From 8b56a82b0ffeea2bb0fe9b42588bf81fc74db27f Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 03:32:27 -0400 Subject: [PATCH 01/11] refactor: state PCP verifier component efficiency plainly Manual-first Classes proposal for456. Only PCPVerifier.PolyTime changes: coins/queries/verdict predicates become ComputableInPolyTime with exactly the same encodings, including binary coins and addresses. Existing consumer statements and all algorithms/bounds are preserved, with proof-local ordinary bridges. Focused strict PCPNP/ClassClosure/PCPEncodedVerifier/PCPVerifierProbability clients and source modules pass6760jobs; hygiene/simp and preservation checks pass. This is not the Classes sweep or a public-boundary completion claim. (cherry picked from commit f4e24754eaa42685b5aa342c1dfbf14efa27dbf6) (cherry picked from commit 6829e280bb1313693a13ef7bcee96d5af1ce2987) --- .../Computability/Complexity/Classes/PCP.lean | 6 +++--- .../Computability/Complexity/Classes/PCP/NP.lean | 8 ++++---- .../Complexity/Classes/PCP/ZeroRandomness.lean | 16 +++++++++------- .../Computability/PCP/Encoded/Verifier.lean | 2 +- .../PCP/Encoded/Verifier/Reduction.lean | 4 +++- .../PCP/Encoded/Verifier/Repetition.lean | 4 +++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/PCP.lean b/Complexity/Computability/Complexity/Classes/PCP.lean index 42cb94d93..a1981caf0 100644 --- a/Complexity/Computability/Complexity/Classes/PCP.lean +++ b/Complexity/Computability/Complexity/Classes/PCP.lean @@ -95,9 +95,9 @@ def accepts (V : PCPVerifier α) (a : α) (π ρ : List Bool) : Bool := number of random bits, its queries and its verdict are computable in polynomial time, the numbers in binary. -/ def PolyTime (enc : α ↪ List Bool) (V : PCPVerifier α) : Prop := - ComputableTidilyInPolyTime V.coins enc encNat ∧ - ComputableTidilyInPolyTime V.queries (encPair enc encBits) (encList encNat) ∧ - ComputableTidilyInPolyTime V.verdict (encPair (encPair enc encBits) encBits) encBool + ComputableInPolyTime V.coins enc encNat ∧ + ComputableInPolyTime V.queries (encPair enc encBits) (encList encNat) ∧ + ComputableInPolyTime V.verdict (encPair (encPair enc encBits) encBits) encBool end PCPVerifier diff --git a/Complexity/Computability/Complexity/Classes/PCP/NP.lean b/Complexity/Computability/Complexity/Classes/PCP/NP.lean index 8afea2794..f3204f423 100644 --- a/Complexity/Computability/Complexity/Classes/PCP/NP.lean +++ b/Complexity/Computability/Complexity/Classes/PCP/NP.lean @@ -64,7 +64,7 @@ variable {V} {enc : α ↪ List Bool} {c : ℕ} private theorem coins_unary (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : ComputableTidilyInPolyTime V.coins enc encUnary := - .binary_to_unary_bounded hV.1 (by fun_prop) hcoins + .binary_to_unary_bounded hV.1.tidy (by fun_prop) hcoins private theorem enum_coins (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : @@ -83,7 +83,7 @@ theorem isPolyTime_queryTable (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : ComputableTidilyInPolyTime V.queryTable enc (encList encNat) := by have he := enum_coins hV hcoins - have hq := hV.2.1 + have hq := hV.2.1.tidy unfold queryTable fun_prop @@ -92,8 +92,8 @@ theorem isPolyTime_tableVerifier (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : ComputableTidilyInPolyTime V.tableVerifier (encPair enc encBits) encBool := by have he := enum_coins hV hcoins - have hq := hV.2.1 - have hv := hV.2.2 + have hq := hV.2.1.tidy + have hv := hV.2.2.tidy have ht := isPolyTime_queryTable hV hcoins unfold tableVerifier polytime diff --git a/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean b/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean index 77f09032d..99fa26d67 100644 --- a/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean +++ b/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean @@ -62,7 +62,7 @@ theorem PCP_zero_zero : PCP (fun _ => 0) (fun _ => 0) enc = P enc := by simp only [mul_zero, nonpos_iff_eq_zero] at hcoins hqs refine ⟨fun a => V.verdict ((a, []), []), ?_, fun a => ?_⟩ · exact .of_tidy <| - hv.comp (g := fun a : α => ((a, ([] : List Bool)), ([] : List Bool))) (by fun_prop) + hv.tidy.comp (g := fun a : α => ((a, ([] : List Bool)), ([] : List Bool))) (by fun_prop) · -- with no random bits there are no queries, so the verdict ignores the proof have key (π : List Bool) : V.accepts a π [] = V.verdict ((a, []), []) := by have h0 : V.queries (a, []) = [] := @@ -81,10 +81,10 @@ theorem PCP_zero_zero : PCP (fun _ => 0) (fun _ => 0) enc = P enc := by simp [key, hv'] at this · rintro ⟨f, hf, hA⟩ refine ⟨⟨fun _ => 0, fun _ => [], fun x => f x.1.1⟩, 0, 0, ⟨?_, ?_, ?_⟩, ?_, ?_, ?_, ?_⟩ - · exact ComputableTidilyInPolyTime.const _ - · exact ComputableTidilyInPolyTime.const _ - · exact hf.tidy.comp ((ComputableTidilyInPolyTime.fst enc encBits).comp - (ComputableTidilyInPolyTime.fst (encPair enc encBits) encBits)) + · exact ComputableInPolyTime.const _ + · exact ComputableInPolyTime.const _ + · exact hf.comp ((ComputableInPolyTime.fst enc encBits).comp + (ComputableInPolyTime.fst (encPair enc encBits) encBits)) · intro a simp · intro a ρ _ @@ -111,8 +111,9 @@ theorem exists_mem_PCP_zero_of_mem_NP {A : Set α} (hA : A ∈ NP enc) : obtain ⟨c, k, hle⟩ := polynomiallyBounded_iff_le.mp (PolynomiallyBounded.polynomial_eval p) refine ⟨k, ⟨fun _ => 0, fun x => List.range (p.eval (enc x.1).length), fun y => V (y.1.1, y.2)⟩, 0, c, ⟨?_, ?_, ?_⟩, ?_, ?_, ?_, ?_⟩ - · exact ComputableTidilyInPolyTime.const _ + · exact ComputableInPolyTime.const _ · -- `x ↦ range (p (|enc x.1|))`, built in unary and converted elementwise to binary + apply ComputableInPolyTime.of_tidy have h1 : ComputableTidilyInPolyTime (fun x : α × List Bool => p.eval (enc x.1).length) (encPair enc encBits) encUnary := (ComputableTidilyInPolyTime.unary_eval p).comp @@ -121,7 +122,8 @@ theorem exists_mem_PCP_zero_of_mem_NP {A : Set α} (hA : A ∈ NP enc) : simpa [Function.comp_def] using (ComputableTidilyInPolyTime.map ComputableTidilyInPolyTime.unary_to_binary).comp (ComputableTidilyInPolyTime.range.comp h1) - · exact hV.comp (((ComputableTidilyInPolyTime.fst enc encBits).comp + · apply ComputableInPolyTime.of_tidy + exact hV.comp (((ComputableTidilyInPolyTime.fst enc encBits).comp (ComputableTidilyInPolyTime.fst (encPair enc encBits) encBits)).pair (ComputableTidilyInPolyTime.snd (encPair enc encBits) encBits)) · intro a diff --git a/Complexity/Computability/PCP/Encoded/Verifier.lean b/Complexity/Computability/PCP/Encoded/Verifier.lean index 7f3b6cb18..ed39bb3e3 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier.lean @@ -231,7 +231,7 @@ theorem polyTime_edgeVerifier (width : ℕ) (decode : (Fin width → Bool) → (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : (edgeVerifier width decode eval).PolyTime (encoding enc) := by - refine ⟨?_, ?_, ?_⟩ + refine ⟨.of_tidy ?_, .of_tidy ?_, .of_tidy ?_⟩ · exact ComputableTidilyInPolyTime.unary_to_binary.comp (by change ComputableTidilyInPolyTime (fun g : Graph C => Nat.clog 2 g.edges.length) (encoding enc) encUnary diff --git a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean index 859d2270a..68e5b0f76 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean @@ -65,7 +65,9 @@ theorem polyTime_reductionVerifier {graph : Input → Graph C} (width repeats : (encPair enc (encPair alphabet alphabet)) encBool) : (reductionVerifier graph width repeats decode eval).PolyTime input := by obtain ⟨hcoins, hqueries, hverdict⟩ := polyTime_repeatedEdgeVerifier width repeats decode heval - exact ⟨hcoins.comp hgraph, hqueries.comp (by fun_prop), hverdict.comp (by fun_prop)⟩ + exact ⟨hcoins.comp (.of_tidy hgraph), + .of_tidy (hqueries.tidy.comp (by fun_prop)), + .of_tidy (hverdict.tidy.comp (by fun_prop))⟩ /-- An efficient well-formed graph reduction with a fixed positive gap gives a PCP using logarithmic randomness and constantly many queries. The alphabet representation precedes the input. -/ diff --git a/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean b/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean index 6efc9f69d..f5ef6ccfe 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean @@ -139,7 +139,9 @@ theorem polyTime_repeatedEdgeVerifier (width repeats : ℕ) (decode : (Fin width (encPair enc (encPair alphabet alphabet)) encBool) : (repeatedEdgeVerifier width repeats decode eval).PolyTime (encoding enc) := by obtain ⟨_, hqueries, hverdict⟩ := polyTime_edgeVerifier width decode heval - refine ⟨?_, ?_, ?_⟩ + have hqueries := hqueries.tidy + have hverdict := hverdict.tidy + refine ⟨.of_tidy ?_, .of_tidy ?_, .of_tidy ?_⟩ · apply ComputableTidilyInPolyTime.unary_to_binary.comp change ComputableTidilyInPolyTime (fun g : Graph C => repeats * Nat.clog 2 g.edges.length) (encoding enc) encUnary From afddb93c989a240987b7fba46460be90fde6bbfb Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 03:36:25 -0400 Subject: [PATCH 02/11] refactor: simplify PCP abstract bridge over plain verifier components Necessary seventh caller for the manual Classes field proposal. Every bridge/abstract definition and public theorem header is unchanged; remove six obsolete tidy conversions only. Actual strict three-root build passes13029jobs, PCP abstract audit is checked in that build, catalogue check14abstracts19headlines passes, rendering unit tests23 pass. Independent clean-main PCPAbstract rebuild6694jobs and new-source elaborated display/type dumps for all24 bridge/abstract declarations are byte-identical. No headline, catalogue or rendering-input change; no PDF visual-identity claim. (cherry picked from commit 440a91c5ea27d411936ad17188a4032bab725126) (cherry picked from commit d1693d2da94e5d670fefa9113a4ed28c3f3c8b6f) --- abstracts/ComplexityAbstracts/PCPBridge.lean | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/abstracts/ComplexityAbstracts/PCPBridge.lean b/abstracts/ComplexityAbstracts/PCPBridge.lean index 4f88d589a..5f6dfb03e 100644 --- a/abstracts/ComplexityAbstracts/PCPBridge.lean +++ b/abstracts/ComplexityAbstracts/PCPBridge.lean @@ -97,15 +97,11 @@ theorem pcp_eq {α : Type} (r q : ℕ → ℕ) (enc : α ↪ List Bool) : constructor · rintro ⟨coins, queries, verdict, c, d, hc, hq, hv, hbound, hquery, hyes, hno⟩ exact ⟨⟨coins, queries, verdict⟩, c, d, - ⟨CookLevinBridge.computableInPolyTime_iff_tidy.mp hc, - CookLevinBridge.computableInPolyTime_iff_tidy.mp hq, - CookLevinBridge.computableInPolyTime_iff_tidy.mp hv⟩, + ⟨hc, hq, hv⟩, hbound, hquery, hyes, hno⟩ · rintro ⟨⟨coins, queries, verdict⟩, c, d, ⟨hc, hq, hv⟩, hbound, hquery, hyes, hno⟩ exact ⟨coins, queries, verdict, c, d, - CookLevinBridge.computableInPolyTime_iff_tidy.mpr hc, - CookLevinBridge.computableInPolyTime_iff_tidy.mpr hq, - CookLevinBridge.computableInPolyTime_iff_tidy.mpr hv, hbound, hquery, hyes, hno⟩ + hc, hq, hv, hbound, hquery, hyes, hno⟩ theorem pcp_theorem {α : Type} (enc : α ↪ List Bool) : NP enc = PCP (fun n => Nat.log 2 n + 1) (fun _ => 1) enc := by From 42656c73d3fc907e51493675903278009bd6bbc5 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 14:00:42 -0400 Subject: [PATCH 03/11] refactor(classes): restate the Classes certificates plainly (tool output) Output of `scripts/tidy_sweep.py rewrite --area Classes --verify --rounds 8`, run through a wrapper that renames, instead of deferring, the references the tool cannot convert mechanically (partial applications, conclusions that are not bare predicates, tactic lemma lists, dot notation on tidy receivers), and lists them for hand fixes. 549 case-2 declarations: 16 deferred, 206 translated, 327 wrapped. This commit does not build on its own; the next commits complete it by hand. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Complexity/AffineDisperser.lean | 2 +- .../Complexity/AffineDisperser/PolyTime.lean | 258 +++++++----- .../Complexity/Classes/AWPP.lean | 9 +- .../Classes/AWPP/Amplification.lean | 14 +- .../Complexity/Classes/AWPP/Lowness.lean | 10 +- .../Classes/AWPP/OracleWeights.lean | 14 +- .../Complexity/Classes/AWPP/WPP.lean | 4 +- .../Complexity/Classes/Alternation/Game.lean | 12 +- .../Classes/Alternation/GuessVerify.lean | 3 +- .../Classes/Alternation/Savitch.lean | 63 +-- .../Complexity/Classes/Alternation/TQBF.lean | 41 +- .../Classes/ArthurMerlin/Amplification.lean | 46 +- .../ArthurMerlin/GraphNonIsomorphism.lean | 8 +- .../Complexity/Classes/ArthurMerlin/PH.lean | 20 +- .../Classes/ArthurMerlin/SetLowerBound.lean | 16 +- .../Complexity/Classes/BPP/Amplification.lean | 14 +- .../Classes/BPP/Derandomization.lean | 11 +- .../BPP/Derandomization/Generator.lean | 139 ++++--- .../Classes/BooleanHierarchy/Kadin.lean | 2 +- .../Complexity/Classes/CeqP.lean | 2 +- .../Complexity/Classes/Constructible.lean | 37 +- .../Complexity/Classes/Counting/Space.lean | 6 +- .../Computability/Complexity/Classes/EXP.lean | 18 +- .../Complexity/Classes/FewP.lean | 16 +- .../Complexity/Classes/Hierarchy.lean | 143 ++++--- .../Classes/Hierarchy/ShortDesc.lean | 49 ++- .../Complexity/Classes/Hierarchy/Space.lean | 105 ++--- .../Complexity/Classes/Hierarchy/Time.lean | 117 +++--- .../Classes/IP/GraphNonIsomorphism.lean | 38 +- .../Complexity/Classes/IP/PSPACE.lean | 7 +- .../Complexity/Classes/IP/Simulation.lean | 28 +- .../Complexity/Classes/IP/TQBF/Verifier.lean | 4 +- .../Complexity/Classes/IP/TQBF/Words.lean | 126 +++--- .../Complexity/Classes/Inclusions.lean | 4 +- .../Complexity/Classes/Ladner.lean | 2 +- .../Complexity/Classes/Ladner/PolyTime.lean | 83 ++-- .../Complexity/Classes/MIP/NEXP.lean | 35 +- .../Complexity/Classes/ModP.lean | 2 +- .../Complexity/Classes/NP/GuessVerify.lean | 6 +- .../Classes/NP/Nondeterministic.lean | 9 +- .../Complexity/Classes/NP/SelfReduction.lean | 27 +- .../Complexity/Classes/NP/Witness.lean | 44 +- .../Complexity/Classes/Oracle.lean | 16 +- .../Classes/Oracle/BakerGillSolovay.lean | 2 +- .../Complexity/Classes/Oracle/Closure.lean | 21 +- .../Complexity/Classes/Oracle/Lowness.lean | 20 +- .../Complexity/Classes/Oracle/PP.lean | 12 +- .../Complexity/Classes/Oracle/Space.lean | 31 +- .../Complexity/Classes/Oracle/TQBF.lean | 17 +- .../Complexity/Classes/P/Slices.lean | 26 +- .../Complexity/Classes/PCP/NP.lean | 12 +- .../Complexity/Classes/PH/Kannan.lean | 4 +- .../Complexity/Classes/PH/KarpLipton.lean | 39 +- .../Complexity/Classes/PH/Projection.lean | 30 +- .../Classes/PH/SipserLautemann.lean | 8 +- .../Complexity/Classes/PP/Bit.lean | 4 +- .../Classes/PP/Characterization.lean | 24 +- .../Complexity/Classes/PP/Oracle.lean | 10 +- .../Complexity/Classes/PP/TruthTable.lean | 38 +- .../Complexity/Classes/Padding.lean | 32 +- .../Complexity/Classes/ParityP.lean | 41 +- .../Complexity/Classes/Promise/Basic.lean | 28 +- .../Computability/Complexity/Classes/RP.lean | 12 +- .../Complexity/Classes/RepeatedTrials.lean | 39 +- .../Computability/Complexity/Classes/SBP.lean | 62 +-- .../Complexity/Classes/SBP/Amplification.lean | 27 +- .../Computability/Complexity/Classes/SPP.lean | 2 +- .../Complexity/Classes/SPP/FewP.lean | 14 +- .../Classes/SharpP/Aggregation.lean | 15 +- .../Classes/SharpP/Characterization.lean | 5 +- .../Complexity/Classes/SharpP/Closure.lean | 13 +- .../Classes/SharpP/Combinators.lean | 4 +- .../Classes/SharpP/Completeness.lean | 2 +- .../Complexity/Classes/SharpP/GapMachine.lean | 11 +- .../Complexity/Classes/SharpP/Lowness.lean | 28 +- .../Complexity/Classes/SharpP/Oracle.lean | 12 +- .../Complexity/Classes/SharpP/PolyTime.lean | 18 +- .../Complexity/Classes/SharpP/Power.lean | 19 +- .../Complexity/Classes/SharpP/Products.lean | 26 +- .../Complexity/Classes/SharpP/Space.lean | 16 +- .../Classes/SharpP/WeightedReplay.lean | 21 +- .../Complexity/Classes/Space/Closure.lean | 93 +++-- .../GeneralizedGeography/Membership.lean | 21 +- .../Space/GeneralizedGeography/Reduction.lean | 87 ++-- .../Complexity/Classes/Space/TM2.lean | 5 +- .../Complexity/Classes/Space/TQBF.lean | 8 +- .../Classes/Space/TQBF/Membership.lean | 137 +++--- .../Classes/Space/TQBF/PolyTime.lean | 276 ++++++------ .../Complexity/Classes/Space/TQBF/Prenex.lean | 23 +- .../Classes/Space/TQBF/Reduction.lean | 2 +- .../Complexity/Classes/TFNP.lean | 57 ++- .../Classes/TFNP/SearchToDecision.lean | 4 +- .../Complexity/Classes/TFNP/Subclasses.lean | 223 +++++----- .../Classes/TFNP/Subclasses/Completeness.lean | 49 ++- .../Complexity/Classes/Time.lean | 77 ++-- .../Complexity/Classes/Toda/Counting.lean | 48 +-- .../Complexity/Classes/Toda/Hierarchy.lean | 89 ++-- .../Complexity/Classes/Toda/Isolation.lean | 10 +- .../Computability/Complexity/Classes/UP.lean | 16 +- .../Computability/Complexity/Classes/US.lean | 2 +- .../Classes/ValiantVazirani/Reduction.lean | 21 +- .../Computability/Complexity/Classes/WPP.lean | 30 +- .../Complexity/Classes/WPP/Bounded.lean | 14 +- .../Complexity/Classes/WPP/Lowness.lean | 26 +- .../Complexity/Classes/WPP/Robustness.lean | 12 +- .../Complexity/Classes/WPP/TruthTable.lean | 28 +- .../Complexity/CookLevin/Clauses.lean | 113 +++-- .../Complexity/CookLevin/Completeness.lean | 2 +- .../Complexity/CookLevin/Counting.lean | 2 +- .../Complexity/CookLevin/Encoding.lean | 64 +-- .../Complexity/CookLevin/Parameters.lean | 6 +- .../Complexity/CookLevin/PolyTime.lean | 18 +- .../Complexity/CookLevin/Reduction.lean | 2 +- .../Complexity/Fagin/Converse.lean | 2 +- .../Complexity/Fagin/StrictVerifier.lean | 8 +- .../Complexity/Fagin/Verifier.lean | 64 +-- .../Computability/Complexity/FineGrained.lean | 21 +- .../Complexity/FineGrained/Assignment.lean | 10 +- .../Complexity/FineGrained/BruteForce.lean | 165 ++++---- .../Complexity/FineGrained/Exponents.lean | 4 +- .../Complexity/FineGrained/GraphProblems.lean | 22 +- .../FineGrained/OrthogonalVectors.lean | 393 +++++++++--------- .../PermutationIndependentSet.lean | 6 +- .../Complexity/FineGrained/Reduction.lean | 13 +- .../FineGrained/Sparsification.lean | 10 +- .../Complexity/HardnessEncoding/PolyTime.lean | 122 +++--- .../Complexity/Parameterized.lean | 113 ++--- .../Parameterized/Kernelization.lean | 7 +- .../Complexity/Parameterized/VertexCover.lean | 148 +++---- .../Parameterized/VertexCover/BussKernel.lean | 79 ++-- .../Complexity/Problems/CircuitSAT.lean | 11 +- .../Complexity/Problems/CircuitValue.lean | 12 +- .../Problems/CircuitValue/Compilation.lean | 65 +-- .../Problems/CircuitValue/Completeness.lean | 77 ++-- .../Problems/CircuitValue/Writer.lean | 10 +- .../Complexity/Problems/Clique.lean | 6 +- .../Complexity/Problems/Coloring.lean | 34 +- .../Complexity/Problems/CountingSAT.lean | 15 +- .../Complexity/Problems/ExactThreeSAT.lean | 18 +- .../Complexity/Problems/Graph.lean | 43 +- .../Complexity/Problems/GraphIsomorphism.lean | 39 +- .../Complexity/Problems/Hamiltonian.lean | 79 ++-- .../Problems/Hamiltonian/Diamond.lean | 48 +-- .../Problems/Hamiltonian/Directed.lean | 36 +- .../Problems/Hamiltonian/Sparse.lean | 54 +-- .../Problems/Hamiltonian/Undirected.lean | 16 +- .../Complexity/Problems/IndependentSet.lean | 26 +- .../Problems/IndependentSet/Sparse.lean | 7 +- .../Problems/IntegerProgramming.lean | 13 +- .../Complexity/Problems/Knapsack.lean | 12 +- .../MonotoneCircuitValue/Completeness.lean | 10 +- .../Complexity/Problems/Partition.lean | 12 +- .../Complexity/Problems/SAT/PolyTime.lean | 61 +-- .../Complexity/Problems/SharpSAT.lean | 20 +- .../Complexity/Problems/SubsetSum.lean | 48 ++- .../Complexity/Problems/SubsetSum/Mask.lean | 8 +- .../Complexity/Problems/TQBF/Closed.lean | 9 +- .../Complexity/Problems/TSP.lean | 29 +- .../Complexity/Problems/ThreeSAT.lean | 23 +- .../Complexity/Problems/VertexCover.lean | 35 +- .../Complexity/Reduction/TruthTable.lean | 8 +- .../Computability/Kolmogorov/MINKT.lean | 3 + Complexity/Computability/MCSP/NP.lean | 17 +- .../MultiTape/Complexity/PolySpace.lean | 2 +- .../Machines/Turing/TM2/Reverse/Transfer.lean | 2 +- .../PCP/Approximation/IndependentSet.lean | 6 +- .../PCP/Approximation/MaxCSP.lean | 2 +- .../PCP/Approximation/MaxExactThreeSAT.lean | 7 +- .../PCP/Approximation/MaxThreeSAT.lean | 7 +- .../Computability/PCP/Completeness.lean | 2 +- .../Computability/PCP/Encoded/AddTrivial.lean | 4 +- .../PCP/Encoded/Amplification.lean | 8 +- .../PCP/Encoded/Amplification/Arithmetic.lean | 13 +- .../Encoded/Amplification/Enumeration.lean | 8 +- .../PCP/Encoded/Amplification/Iteration.lean | 14 +- .../PCP/Encoded/AssignmentTester.lean | 9 +- .../Computability/PCP/Encoded/Basic.lean | 88 ++-- .../Computability/PCP/Encoded/Cloud.lean | 16 +- .../PCP/Encoded/CloudRotation.lean | 8 +- .../PCP/Encoded/Composition.lean | 28 +- .../PCP/Encoded/Composition/Enumeration.lean | 4 +- .../PCP/Encoded/Constraints.lean | 18 +- .../PCP/Encoded/DegreeReduction.lean | 29 +- .../Computability/PCP/Encoded/GapTheorem.lean | 10 +- .../PCP/Encoded/GenericComposition.lean | 43 +- .../GenericComposition/Enumeration.lean | 6 +- .../Computability/PCP/Encoded/Iteration.lean | 4 +- .../Computability/PCP/Encoded/Power.lean | 21 +- .../Computability/PCP/Encoded/Preprocess.lean | 8 +- .../PCP/Encoded/Preprocess/Programs.lean | 44 +- .../PCP/Encoded/SelectedAssignmentTester.lean | 9 +- .../PCP/Encoded/SelectedComposition.lean | 4 +- .../SelectedComposition/Enumeration.lean | 4 +- .../Computability/PCP/Encoded/ThreeSAT.lean | 15 +- .../Computability/PCP/Encoded/Verifier.lean | 21 +- .../PCP/Encoded/Verifier/Reduction.lean | 14 +- .../PCP/Encoded/Verifier/Repetition.lean | 6 +- .../Computability/PCP/Power/Complexity.lean | 10 +- .../TreeEval/Reader/Cert/Machine.lean | 33 +- .../TreeEval/Reader/Cert/Offset.lean | 195 +++++---- .../TreeEval/Reader/Cert/Regs.lean | 160 ++++--- .../TreeEval/Reader/Cert/Residue.lean | 91 ++-- .../TreeEval/Reader/Cert/Step.lean | 141 ++++--- .../TreeEval/Reader/Cert/Weight.lean | 45 +- .../Computability/USTCON/Reader/Cert.lean | 27 +- .../AffineDisperser/Explicit.lean | 2 +- ComplexityTests/AWPPAmplification.lean | 2 +- ComplexityTests/AffineDisperserRuntime.lean | 8 +- ComplexityTests/ApproximateCounting.lean | 8 +- ComplexityTests/Axioms.lean | 76 ++-- ComplexityTests/BasicClasses.lean | 4 +- ComplexityTests/CircuitValueCompleteness.lean | 4 +- ComplexityTests/ClassCorollaries.lean | 2 +- ComplexityTests/CountingAggregation.lean | 6 +- ComplexityTests/CountingGapMachine.lean | 6 +- ComplexityTests/CountingProducts.lean | 14 +- ComplexityTests/CountingSpace.lean | 9 +- ComplexityTests/Derandomization.lean | 12 +- ComplexityTests/ExponentialPadding.lean | 4 +- ComplexityTests/Fagin.lean | 4 +- ComplexityTests/FineGrained.lean | 12 +- .../FineGrained/GraphProblems.lean | 10 +- ComplexityTests/HierarchyTheorems.lean | 4 +- ComplexityTests/InteractiveProofs.lean | 6 +- ComplexityTests/Isolation.lean | 4 +- ComplexityTests/Kannan.lean | 4 +- ComplexityTests/KarpLipton2.lean | 8 +- ComplexityTests/KarpReductions.lean | 20 +- ComplexityTests/Ladner.lean | 4 +- ComplexityTests/MathlibTM2Reverse.lean | 4 +- ComplexityTests/MonotoneCircuitValue.lean | 8 +- ComplexityTests/NPCompleteGraphs.lean | 12 +- ComplexityTests/NPCompleteGraphs/TSP.lean | 12 +- ComplexityTests/NPExistsAppend.lean | 4 +- .../NondeterministicVerifiers.lean | 4 +- ComplexityTests/PCPEncoded.lean | 15 + .../PCPEncodedAssignmentTester.lean | 5 + ComplexityTests/PCPEncodedComposition.lean | 7 + .../PCPEncodedCompositionEnumeration.lean | 7 + ComplexityTests/PCPEncodedConstraints.lean | 9 +- .../PCPEncodedGenericComposition.lean | 3 + ComplexityTests/PCPEncodedIteration.lean | 11 +- ComplexityTests/PCPEncodedPreprocess.lean | 27 +- ComplexityTests/PCPEncodedVerifier.lean | 9 +- ComplexityTests/PCPNP.lean | 7 +- .../PCPSelectedAssignmentTester.lean | 3 + ComplexityTests/PPTruthTable.lean | 6 +- ComplexityTests/Parameterized.lean | 8 +- ComplexityTests/ProofComplexity.lean | 2 +- ComplexityTests/QBFProtocol.lean | 4 +- ComplexityTests/RelativizedCounting.lean | 8 +- ComplexityTests/RepeatedTrials.lean | 7 +- ComplexityTests/ResourceBoundsPlain.lean | 12 +- ComplexityTests/ResourceClasses.lean | 5 +- ComplexityTests/ResourceClasses3.lean | 8 +- ComplexityTests/ResourceClasses4.lean | 3 +- ComplexityTests/SBPAmplification.lean | 4 +- ComplexityTests/SipserLautemann.lean | 3 + ComplexityTests/SpaceHierarchy.lean | 4 +- ComplexityTests/TFNPCompleteness.lean | 4 +- ComplexityTests/TQBF.lean | 12 +- ComplexityTests/TimeHierarchy.lean | 7 +- ComplexityTests/TimeReductions.lean | 3 +- ComplexityTests/VertexCoverKernel.lean | 4 +- ComplexityTests/WPP.lean | 4 +- ComplexityTests/WPPBounded.lean | 14 +- ComplexityTests/WPPLowness.lean | 2 +- ComplexityTests/WPPRobustness.lean | 2 +- ComplexityTests/WPPTruthTable.lean | 10 +- ComplexityTests/WPPTwoSided.lean | 2 +- ComplexityTests/WorstCaseHardness.lean | 8 +- ComplexityTests/ZooCountingHierarchy.lean | 4 +- 272 files changed, 4248 insertions(+), 3479 deletions(-) diff --git a/Complexity/Computability/Complexity/AffineDisperser.lean b/Complexity/Computability/Complexity/AffineDisperser.lean index 1af617bae..4b0f70c71 100644 --- a/Complexity/Computability/Complexity/AffineDisperser.lean +++ b/Complexity/Computability/Complexity/AffineDisperser.lean @@ -118,7 +118,7 @@ theorem slice_explicitDisperserLanguage (N : ℕ) : /-- **The language of the explicit disperser is in `P`**, with words encoded as themselves. -/ theorem explicitDisperserLanguage_mem_P : (explicitDisperserLanguage : Set (List Bool)) ∈ Complexity.P encBits := - Complexity.ofSlices_mem_P computableTidilyInPolyTime_explicitDisperser + Complexity.ofSlices_mem_P computableInPolyTime_explicitDisperser /-- **An explicit function in `P` with `B₂` circuit complexity `3.5 N - O(N / log N)`**, after [MishraSanthanam2026]: some language over `Bool` in `P` (the language of the explicit disperser) diff --git a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean index 38c1a5b0a..4ac3ef05a 100644 --- a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean +++ b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean @@ -21,6 +21,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Na import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Length import Complexity.Tactic.PolyTime import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # The explicit affine disperser in polynomial time @@ -37,13 +38,13 @@ numbers in unary. All runtime sizes are polynomial in the input length `N`: division with remainders computed by repeated multiplication by `X`; * the multiplication table has `n ^ 3` entries, each a product over the prime factors of `n`; * a field multiplication sums at most `n ^ 2` table entries, uniformly in the table - (`Cslib.AffineDisperser.computableTidilyInPolyTime_fieldMul`); the `r` powers take at most + (`Cslib.AffineDisperser.computableInPolyTime_fieldMul`); the `r` powers take at most `2 r` multiplications each, the elementary symmetric polynomial `r t` more, and the trace reads the diagonals of the table. Every loop is certified with a bound on its intermediate states, so the certificate charges the whole computation, including every field operation -(`Cslib.AffineDisperser.computableTidilyInPolyTime_explicitDisperser`). The exponent of the +(`Cslib.AffineDisperser.computableInPolyTime_explicitDisperser`). The exponent of the polynomial is not computed. ## Main definitions @@ -53,12 +54,12 @@ polynomial is not computed. ## Main results -* `Cslib.AffineDisperser.computableTidilyInPolyTime_leastIrreducibleCode`: the search for the +* `Cslib.AffineDisperser.computableInPolyTime_leastIrreducibleCode`: the search for the irreducible polynomials. -* `Cslib.AffineDisperser.computableTidilyInPolyTime_explicitTable`: the multiplication table. -* `Cslib.AffineDisperser.computableTidilyInPolyTime_traceSymCoords`: `traceSym 1 r t` in +* `Cslib.AffineDisperser.computableInPolyTime_explicitTable`: the multiplication table. +* `Cslib.AffineDisperser.computableInPolyTime_traceSymCoords`: `traceSym 1 r t` in coordinates, uniformly in the multiplication table. -* `Cslib.AffineDisperser.computableTidilyInPolyTime_explicitDisperser`: the explicit disperser is +* `Cslib.AffineDisperser.computableInPolyTime_explicitDisperser`: the explicit disperser is computable in polynomial time. * `Cslib.AffineDisperser.setOf_explicitDisperser_mem_P`: it decides a problem in `P`. @@ -78,8 +79,8 @@ open Turing.MultiTapeTM ComputableTidilyInPolyTime Explicit /-- Multiplication by `X` modulo a binary polynomial, on coefficient lists. -/ @[fun_prop] -theorem computableTidilyInPolyTime_mulXMod : - ComputableTidilyInPolyTime (fun p : List Bool × List Bool => mulXMod p.1 p.2) +theorem computableInPolyTime_mulXMod : + ComputableInPolyTime (fun p : List Bool × List Bool => mulXMod p.1 p.2) (encPair encBits encBits) encBits := by unfold mulXMod fun_prop @@ -87,12 +88,14 @@ theorem computableTidilyInPolyTime_mulXMod : private theorem length_mulXMod_le (g r : List Bool) : (mulXMod g r).length ≤ g.length - 1 := List.length_take_le _ _ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The remainder modulo a binary polynomial, by a left fold over the coefficients whose state, the current power of `X` and the partial remainder, never exceeds the degree of the modulus. -/ @[fun_prop] -theorem computableTidilyInPolyTime_modBits : - ComputableTidilyInPolyTime (fun p : List Bool × List Bool => modBits p.1 p.2) +theorem computableInPolyTime_modBits : + ComputableInPolyTime (fun p : List Bool × List Bool => modBits p.1 p.2) (encPair encBits encBits) encBits := by + refine .of_tidy ?_ have hstep : ComputableTidilyInPolyTime (fun q : (List Bool × (List Bool × List Bool)) × Bool => modStep q.1.1 q.1.2 q.2) (encPair (encPair encBits (encPair encBits encBits)) encBool) @@ -119,30 +122,34 @@ theorem computableTidilyInPolyTime_modBits : exact (snd encBits encBits).comp h /-- The binary digits of a unary natural. -/ -theorem computableTidilyInPolyTime_bits_unary : - ComputableTidilyInPolyTime Nat.bits encUnary encBits := - natBits.comp unary_to_binary +theorem computableInPolyTime_bits_unary : + ComputableInPolyTime Nat.bits encUnary encBits := + .of_tidy (natBits.comp unary_to_binary) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The irreducibility test by trial division, on a unary code. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isIrreducibleCode : - ComputableTidilyInPolyTime isIrreducibleCode encUnary encBool := by +theorem computableInPolyTime_isIrreducibleCode : + ComputableInPolyTime isIrreducibleCode encUnary encBool := by + refine .of_tidy ?_ unfold isIrreducibleCode - have := computableTidilyInPolyTime_bits_unary + have := computableInPolyTime_bits_unary.tidy fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The exhaustive search for the least irreducible code below a unary bound. -/ @[fun_prop] -theorem computableTidilyInPolyTime_leastIrreducibleCode : - ComputableTidilyInPolyTime (fun q : ℕ × ℕ => leastIrreducibleCode q.1 q.2) +theorem computableInPolyTime_leastIrreducibleCode : + ComputableInPolyTime (fun q : ℕ × ℕ => leastIrreducibleCode q.1 q.2) (encPair encUnary encUnary) encUnary := by + refine .of_tidy ?_ unfold leastIrreducibleCode fun_prop /-- The remainders of the powers of `X`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_powerTable : - ComputableTidilyInPolyTime powerTable encBits (encList encBits) := by +theorem computableInPolyTime_powerTable : + ComputableInPolyTime powerTable encBits (encList encBits) := by unfold powerTable fun_prop @@ -182,19 +189,21 @@ private theorem computableTidilyInPolyTime_prod_of_le {α : Type} {input : α encoding is that of the list. Restricting to lists of lists keeps this rule away from raw bit strings, which have their own lookup rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_getD_list {α γ : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_getD_list {α γ : Type} {input : α ↪ List Bool} {enc : List γ ↪ List Bool} {L : α → List (List γ)} {i : α → ℕ} - (hL : ComputableTidilyInPolyTime L input (encList enc)) - (hi : ComputableTidilyInPolyTime i input encUnary) (d : List γ) : - ComputableTidilyInPolyTime (fun a => (L a).getD (i a) d) input enc := - (listGetD (encA := enc) (encL := encList enc) d).comp (hL.prod hi) + (hL : ComputableInPolyTime L input (encList enc)) + (hi : ComputableInPolyTime i input encUnary) (d : List γ) : + ComputableInPolyTime (fun a => (L a).getD (i a) d) input enc := by + have hL := hL.tidy + have hi := hi.tidy + exact .of_tidy ((listGetD (encA := enc) (encL := encList enc) d).comp (hL.prod hi)) /-! ### The parameters -/ /-- The primes in `(a, b]`, from unary bounds. -/ @[fun_prop] -theorem computableTidilyInPolyTime_primesIoc : - ComputableTidilyInPolyTime (fun q : ℕ × ℕ => primesIoc q.1 q.2) +theorem computableInPolyTime_primesIoc : + ComputableInPolyTime (fun q : ℕ × ℕ => primesIoc q.1 q.2) (encPair encUnary encUnary) (encList encUnary) := by simp_rw [primesIoc, List.range'_eq_map_range] fun_prop @@ -215,9 +224,10 @@ private theorem foldl_selectStep (T : ℕ) (ps chosen : List ℕ) : /-- The greedy choice of primes below a unary budget. -/ @[fun_prop] -theorem computableTidilyInPolyTime_selectBelow : - ComputableTidilyInPolyTime (fun q : ℕ × List ℕ => selectBelow q.1 q.2) +theorem computableInPolyTime_selectBelow : + ComputableInPolyTime (fun q : ℕ × List ℕ => selectBelow q.1 q.2) (encPair encUnary (encList encUnary)) (encList encUnary) := by + refine .of_tidy ?_ have hstep : ComputableTidilyInPolyTime (fun q : (ℕ × List ℕ) × ℕ => selectStep q.1 q.2) (encPair (encPair encUnary (encList encUnary)) encUnary) @@ -244,15 +254,15 @@ theorem computableTidilyInPolyTime_selectBelow : /-- The prime bound `L = ⌊⌊log₂ N⌋ / 3⌋` of unary `N`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_primeBound : - ComputableTidilyInPolyTime primeBound encUnary encUnary := by +theorem computableInPolyTime_primeBound : + ComputableInPolyTime primeBound encUnary encUnary := by unfold primeBound fun_prop /-- The primes of the field degree on `N` bits, `N` in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_degreePrimes : - ComputableTidilyInPolyTime degreePrimes encUnary (encList encUnary) := by +theorem computableInPolyTime_degreePrimes : + ComputableInPolyTime degreePrimes encUnary (encList encUnary) := by unfold degreePrimes fun_prop @@ -271,24 +281,25 @@ private theorem prod_degreePrimes_le (N : ℕ) : (degreePrimes N).prod ≤ N + 1 /-- The field degree on `N` bits, `N` in unary: a product of at most `N + 1`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_fieldDegree : - ComputableTidilyInPolyTime fieldDegree encUnary encUnary := by - have h := computableTidilyInPolyTime_prod_of_le computableTidilyInPolyTime_degreePrimes +theorem computableInPolyTime_fieldDegree : + ComputableInPolyTime fieldDegree encUnary encUnary := by + refine .of_tidy ?_ + have h := computableTidilyInPolyTime_prod_of_le computableInPolyTime_degreePrimes.tidy (fun N p hp => (prime_of_mem_degreePrimes hp).2.2.pos) (B := fun N => N + 1) (.of_forall_le 1 1 fun N => by simp) prod_degreePrimes_le simpa only [← fieldDegree_eq_prod] using h /-- The number of blocks on `N` bits, `N` in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_numBlocks : - ComputableTidilyInPolyTime numBlocks encUnary encUnary := by +theorem computableInPolyTime_numBlocks : + ComputableInPolyTime numBlocks encUnary encUnary := by unfold numBlocks fun_prop /-- The degree of the elementary symmetric polynomial on `N` bits, `N` in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_symDegree : - ComputableTidilyInPolyTime symDegree encUnary encUnary := by +theorem computableInPolyTime_symDegree : + ComputableInPolyTime symDegree encUnary encUnary := by unfold symDegree fun_prop @@ -307,13 +318,13 @@ theorem codeBound_le (N : ℕ) : codeBound N ≤ 2 * (N + 1) * (N + 1) := by /-- The search range `2 ^ (4 L + 1)` on `N` bits, in unary, from `N` in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_codeBound : - ComputableTidilyInPolyTime codeBound encUnary encUnary := by - have hvalue : ComputableTidilyInPolyTime codeBound encUnary encNat := by +theorem computableInPolyTime_codeBound : + ComputableInPolyTime codeBound encUnary encUnary := by + have hvalue : ComputableInPolyTime codeBound encUnary encNat := by unfold codeBound - have := binary_two_pow + have := ComputableInPolyTime.binary_two_pow fun_prop - exact binary_to_unary_bounded hvalue (bound := fun N => 2 * (N + 1) * (N + 1)) (by fun_prop) + exact ComputableInPolyTime.binary_to_unary_bounded hvalue (bound := fun N => 2 * (N + 1) * (N + 1)) (by fun_prop) codeBound_le /-! ### The multiplication table -/ @@ -321,12 +332,14 @@ theorem computableTidilyInPolyTime_codeBound : /-- The tables of remainders of powers of `X` on `N` bits, `N` in unary: the search for each irreducible polynomial ranges over the `2 ^ (4 L + 1) ≤ 2 (N + 1) ^ 2` codes below `codeBound N`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_explicitPowerTables : - ComputableTidilyInPolyTime explicitPowerTables encUnary (encList (encList encBits)) := by +theorem computableInPolyTime_explicitPowerTables : + ComputableInPolyTime explicitPowerTables encUnary (encList (encList encBits)) := by unfold explicitPowerTables - have := computableTidilyInPolyTime_bits_unary + have := computableInPolyTime_bits_unary fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The mixed-radix digits in the radix of the field degree on `N` bits; every partial product of the radix is at most `N + 1`. -/ private theorem computableTidilyInPolyTime_mixedDigit_degreePrimes : @@ -334,7 +347,7 @@ private theorem computableTidilyInPolyTime_mixedDigit_degreePrimes : (encPair (encPair encUnary encUnary) encUnary) encUnary := by have htake : ComputableTidilyInPolyTime (fun q : (ℕ × ℕ) × ℕ => (degreePrimes q.1.1).take q.2) (encPair (encPair encUnary encUnary) encUnary) (encList encUnary) := - (computableTidilyInPolyTime_take encUnary).comp ((computableTidilyInPolyTime_degreePrimes.comp + (computableTidilyInPolyTime_take encUnary).comp ((computableInPolyTime_degreePrimes.tidy.comp ((fst encUnary encUnary).comp (fst _ _))).prod (snd _ _)) have hprod := computableTidilyInPolyTime_prod_of_le htake (fun q p hp => (prime_of_mem_degreePrimes (List.mem_of_mem_take hp)).2.2.pos) @@ -349,15 +362,20 @@ private theorem computableTidilyInPolyTime_mixedDigit_degreePrimes : /-- Mixed-radix digits in the radix of the field degree, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_mixedDigit_degreePrimes' {α : Type} {input : α ↪ List Bool} - {N u i : α → ℕ} (hN : ComputableTidilyInPolyTime N input encUnary) - (hu : ComputableTidilyInPolyTime u input encUnary) - (hi : ComputableTidilyInPolyTime i input encUnary) : - ComputableTidilyInPolyTime (fun a => mixedDigit (degreePrimes (N a)) (u a) (i a)) input - encUnary := - computableTidilyInPolyTime_mixedDigit_degreePrimes.comp ((hN.prod hu).prod hi) - - +theorem computableInPolyTime_mixedDigit_degreePrimes' {α : Type} {input : α ↪ List Bool} + {N u i : α → ℕ} (hN : ComputableInPolyTime N input encUnary) + (hu : ComputableInPolyTime u input encUnary) + (hi : ComputableInPolyTime i input encUnary) : + ComputableInPolyTime (fun a => mixedDigit (degreePrimes (N a)) (u a) (i a)) input + encUnary := by + have hN := hN.tidy + have hu := hu.tidy + have hi := hi.tidy + exact .of_tidy (computableTidilyInPolyTime_mixedDigit_degreePrimes.comp ((hN.prod hu).prod hi)) + + +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Coordinates of the products of monomials of the explicit field on `N` bits, `N` in unary. -/ private theorem computableTidilyInPolyTime_monomialBit_explicit : ComputableTidilyInPolyTime (fun q : ((ℕ × ℕ) × ℕ) × ℕ => @@ -368,21 +386,25 @@ private theorem computableTidilyInPolyTime_monomialBit_explicit : ComputableTidi /-- Coordinates of the products of monomials of the explicit field, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_monomialBit_explicit' {α : Type} {input : α ↪ List Bool} - {N u w v : α → ℕ} (hN : ComputableTidilyInPolyTime N input encUnary) - (hu : ComputableTidilyInPolyTime u input encUnary) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hv : ComputableTidilyInPolyTime v input encUnary) : - ComputableTidilyInPolyTime +theorem computableInPolyTime_monomialBit_explicit' {α : Type} {input : α ↪ List Bool} + {N u w v : α → ℕ} (hN : ComputableInPolyTime N input encUnary) + (hu : ComputableInPolyTime u input encUnary) + (hw : ComputableInPolyTime w input encUnary) + (hv : ComputableInPolyTime v input encUnary) : + ComputableInPolyTime (fun a => monomialBit (degreePrimes (N a)) (explicitPowerTables (N a)) (u a) (w a) (v a)) - input encBool := - computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv) + input encBool := by + have hN := hN.tidy + have hu := hu.tidy + have hw := hw.tidy + have hv := hv.tidy + exact .of_tidy (computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv)) /-- The multiplication table of the explicit field on `N` bits, `N` in unary: its `n ^ 3` entries, `n ≤ N + 1`, are products over the prime factors of `n`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_explicitTable : - ComputableTidilyInPolyTime explicitTable encUnary (encList (encList encBits)) := by +theorem computableInPolyTime_explicitTable : + ComputableInPolyTime explicitTable encUnary (encList (encList encBits)) := by unfold explicitTable monomialTable simp_rw [← fieldDegree_eq_prod] fun_prop @@ -395,17 +417,17 @@ abbrev encTable : List (List (List Bool)) ↪ List Bool := /-- An entry of a computed multiplication table. -/ @[fun_prop] -theorem computableTidilyInPolyTime_tableEntry {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_tableEntry {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {u w : α → ℕ} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hu : ComputableTidilyInPolyTime u input encUnary) - (hw : ComputableTidilyInPolyTime w input encUnary) : - ComputableTidilyInPolyTime (fun a => tableEntry (tab a) (u a) (w a)) input encBits := - computableTidilyInPolyTime_getD_list (computableTidilyInPolyTime_getD_list htab hu []) hw [] + (htab : ComputableInPolyTime tab input encTable) + (hu : ComputableInPolyTime u input encUnary) + (hw : ComputableInPolyTime w input encUnary) : + ComputableInPolyTime (fun a => tableEntry (tab a) (u a) (w a)) input encBits := + computableInPolyTime_getD_list (computableInPolyTime_getD_list htab hu []) hw [] /-- **Multiplication in coordinates**, uniformly in the multiplication table: the sum of at most `n ^ 2` table entries, `n` the number of rows. -/ -theorem computableTidilyInPolyTime_fieldMul : ComputableTidilyInPolyTime +theorem computableInPolyTime_fieldMul : ComputableInPolyTime (fun p : List (List (List Bool)) × List Bool × List Bool => fieldMul p.1 p.2.1 p.2.2) (encPair encTable (encPair encBits encBits)) encBits := by unfold fieldMul @@ -413,18 +435,20 @@ theorem computableTidilyInPolyTime_fieldMul : ComputableTidilyInPolyTime /-- Multiplication in coordinates, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_fieldMul' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_fieldMul' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {a b : α → List Bool} - (htab : ComputableTidilyInPolyTime tab input encTable) - (ha : ComputableTidilyInPolyTime a input encBits) - (hb : ComputableTidilyInPolyTime b input encBits) : - ComputableTidilyInPolyTime (fun x => fieldMul (tab x) (a x) (b x)) input encBits := - computableTidilyInPolyTime_fieldMul.comp (htab.prod (ha.prod hb)) + (htab : ComputableInPolyTime tab input encTable) + (ha : ComputableInPolyTime a input encBits) + (hb : ComputableInPolyTime b input encBits) : + ComputableInPolyTime (fun x => fieldMul (tab x) (a x) (b x)) input encBits := + computableInPolyTime_fieldMul.comp (htab.prod (ha.prod hb)) theorem length_fieldMul (tab : List (List (List Bool))) (a b : List Bool) : (fieldMul tab a b).length = tab.length := by simp [fieldMul] +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The powers `y ^ (2 ^ (k + 1) - 1)`, by `k` multiplications and squarings; every intermediate power has `n` coordinates. -/ private theorem computableTidilyInPolyTime_powerPred : ComputableTidilyInPolyTime @@ -437,15 +461,21 @@ private theorem computableTidilyInPolyTime_powerPred : ComputableTidilyInPolyTim /-- Powers in coordinates, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_powerPred' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_powerPred' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {y : α → List Bool} {k : α → ℕ} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hy : ComputableTidilyInPolyTime y input encBits) - (hk : ComputableTidilyInPolyTime k input encUnary) : - ComputableTidilyInPolyTime (fun x => powerPred (tab x) (y x) (k x)) input encBits := by + (htab : ComputableInPolyTime tab input encTable) + (hy : ComputableInPolyTime y input encBits) + (hk : ComputableInPolyTime k input encUnary) : + ComputableInPolyTime (fun x => powerPred (tab x) (y x) (k x)) input encBits := by + have htab := htab.tidy + have hy := hy.tidy + have hk := hk.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_powerPred.comp (htab.prod (hy.prod hk)) +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- One step of the dynamic program for the elementary symmetric polynomials. -/ private theorem computableTidilyInPolyTime_esymmStep : ComputableTidilyInPolyTime (fun p : (List (List (List Bool)) × List (List Bool)) × List Bool => @@ -490,19 +520,25 @@ private theorem computableTidilyInPolyTime_esymmCoords : ComputableTidilyInPolyT omega · simp)).1 unfold esymmCoords - exact computableTidilyInPolyTime_getD_list h (by fun_prop) [] + exact (computableInPolyTime_getD_list (.of_tidy h) (.of_tidy (by fun_prop)) []).tidy /-- The elementary symmetric polynomial in coordinates, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_esymmCoords' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_esymmCoords' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {t : α → ℕ} {zs : α → List (List Bool)} - (htab : ComputableTidilyInPolyTime tab input encTable) - (ht : ComputableTidilyInPolyTime t input encUnary) - (hzs : ComputableTidilyInPolyTime zs input (encList encBits)) : - ComputableTidilyInPolyTime (fun x => esymmCoords (tab x) (t x) (zs x)) input encBits := by + (htab : ComputableInPolyTime tab input encTable) + (ht : ComputableInPolyTime t input encUnary) + (hzs : ComputableInPolyTime zs input (encList encBits)) : + ComputableInPolyTime (fun x => esymmCoords (tab x) (t x) (zs x)) input encBits := by + have htab := htab.tidy + have ht := ht.tidy + have hzs := hzs.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_esymmCoords.comp ((htab.prod ht).prod hzs) +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The traces of the basis elements, from the diagonals of the multiplication table. -/ private theorem computableTidilyInPolyTime_traceVector : ComputableTidilyInPolyTime traceVector encTable encBits := by @@ -511,9 +547,11 @@ private theorem computableTidilyInPolyTime_traceVector : /-- The traces of the basis elements, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_traceVector' {α : Type} {input : α ↪ List Bool} - {tab : α → List (List (List Bool))} (htab : ComputableTidilyInPolyTime tab input encTable) : - ComputableTidilyInPolyTime (fun x => traceVector (tab x)) input encBits := by +theorem computableInPolyTime_traceVector' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} (htab : ComputableInPolyTime tab input encTable) : + ComputableInPolyTime (fun x => traceVector (tab x)) input encBits := by + have htab := htab.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_traceVector.comp htab /-- The trace as a bit. -/ @@ -524,18 +562,23 @@ private theorem computableTidilyInPolyTime_traceBit : ComputableTidilyInPolyTime /-- The trace as a bit, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_traceBit' {α : Type} {input : α ↪ List Bool} - {τ a : α → List Bool} (hτ : ComputableTidilyInPolyTime τ input encBits) - (ha : ComputableTidilyInPolyTime a input encBits) : - ComputableTidilyInPolyTime (fun x => traceBit (τ x) (a x)) input encBool := by +theorem computableInPolyTime_traceBit' {α : Type} {input : α ↪ List Bool} + {τ a : α → List Bool} (hτ : ComputableInPolyTime τ input encBits) + (ha : ComputableInPolyTime a input encBits) : + ComputableInPolyTime (fun x => traceBit (τ x) (a x)) input encBool := by + have hτ := hτ.tidy + have ha := ha.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_traceBit.comp (hτ.prod ha) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`traceSym 1 r t` in coordinates**, uniformly in the multiplication table, `r` and `t` in unary, and the input bits. -/ -theorem computableTidilyInPolyTime_traceSymCoords : ComputableTidilyInPolyTime +theorem computableInPolyTime_traceSymCoords : ComputableInPolyTime (fun p : ((List (List (List Bool)) × ℕ) × ℕ) × List Bool => traceSymCoords p.1.1.1 p.1.1.2 p.1.2 p.2) (encPair (encPair (encPair encTable encUnary) encUnary) encBits) encBool := by + refine .of_tidy ?_ unfold traceSymCoords fun_prop @@ -545,20 +588,21 @@ theorem computableTidilyInPolyTime_traceSymCoords : ComputableTidilyInPolyTime private theorem computableTidilyInPolyTime_explicitDisperserProgram : ComputableTidilyInPolyTime explicitDisperserProgram encBits encBool := by unfold explicitDisperserProgram - simpa only [Function.comp_def] using computableTidilyInPolyTime_traceSymCoords.comp - ((((computableTidilyInPolyTime_explicitTable.comp length_bits).prod - (computableTidilyInPolyTime_numBlocks.comp length_bits)).prod - (computableTidilyInPolyTime_symDegree.comp length_bits)).prod id') + simpa only [Function.comp_def] using computableInPolyTime_traceSymCoords.tidy.comp + ((((computableInPolyTime_explicitTable.tidy.comp length_bits).prod + (computableInPolyTime_numBlocks.tidy.comp length_bits)).prod + (computableInPolyTime_symDegree.tidy.comp length_bits)).prod id') /-- **The explicit affine disperser is computable in polynomial time**: on a bit list `x` of length `N`, the value `explicitDisperser N x` is computed by a tidy multi-tape machine in time polynomial in `N`. The certificate charges the whole computation: the parameters, the exhaustive searches for the irreducible polynomials by trial division, the remainders of the powers of `X`, the multiplication table, and every field operation of `traceSym 1 r t`. -/ -theorem computableTidilyInPolyTime_explicitDisperser : - ComputableTidilyInPolyTime +theorem computableInPolyTime_explicitDisperser : + ComputableInPolyTime (fun x : List Bool => explicitDisperser x.length (BitString.ofList x.length x)) encBits encBool := by + refine .of_tidy ?_ rw [← funext explicitDisperserProgram_eq] exact computableTidilyInPolyTime_explicitDisperserProgram @@ -567,6 +611,6 @@ theorem computableTidilyInPolyTime_explicitDisperser : theorem setOf_explicitDisperser_mem_P : {x : List Bool | explicitDisperser x.length (BitString.ofList x.length x) = true} ∈ Cslib.Complexity.P encBits := - ⟨_, .of_tidy computableTidilyInPolyTime_explicitDisperser, fun _ => Iff.rfl⟩ + ⟨_, computableInPolyTime_explicitDisperser, fun _ => Iff.rfl⟩ end Cslib.AffineDisperser diff --git a/Complexity/Computability/Complexity/Classes/AWPP.lean b/Complexity/Computability/Complexity/Classes/AWPP.lean index 2577da995..cf63cf453 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP.lean @@ -116,14 +116,15 @@ theorem AWPP_subset_PP : AWPP enc ⊆ PP enc := by /-- An efficiently computed unary exponent can be padded to a polynomial in input length. Multiplying numerator and denominator by the same power of two preserves the ratio. -/ theorem mem_AWPP_of_polyTime_exponent {g : α → ℤ} {r : α → ℕ} - (hg : g ∈ GapP enc) (hr : ComputableTidilyInPolyTime r enc encUnary) + (hg : g ∈ GapP enc) (hr : ComputableInPolyTime r enc encUnary) (hA : ∀ a, (0 ≤ g a ∧ g a ≤ (2 : ℤ) ^ r a) ∧ (a ∈ A → 2 * (2 : ℤ) ^ r a ≤ 3 * g a) ∧ (a ∉ A → 3 * g a ≤ (2 : ℤ) ^ r a)) : A ∈ AWPP enc := by + have hr := hr.tidy obtain ⟨p, hle⟩ := hr.polyBounded.exists_polynomial have hs : ComputableTidilyInPolyTime (fun a => 2 ^ (p.eval (enc a).length - r a)) enc encNat := by fun_prop - have hsG := SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime hs) + have hsG := SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime (.of_tidy hs)) refine ⟨_, GapP.mul_mem hg hsG, p, fun a => ?_⟩ have he : (2 : ℤ) ^ p.eval (enc a).length = (2 : ℤ) ^ r a * (2 : ℤ) ^ (p.eval (enc a).length - r a) := by @@ -142,8 +143,8 @@ theorem PolyTimeReducible.mem_AWPP {β : Type} {encB : β ↪ List Bool} {B : Se (h : PolyTimeReducible enc encB A B) (hB : B ∈ AWPP encB) : A ∈ AWPP enc := by obtain ⟨r, hr, hAB⟩ := polyTimeReducible_iff_tidy.mp h obtain ⟨g, hg, p, hB⟩ := hB - refine mem_AWPP_of_polyTime_exponent (GapP.comp_mem hg hr) - (r := fun a => p.eval (encB (r a)).length) (by fun_prop) (fun a => ?_) + refine mem_AWPP_of_polyTime_exponent (GapP.comp_mem hg (.of_tidy hr)) + (r := fun a => p.eval (encB (r a)).length) (.of_tidy (by fun_prop)) (fun a => ?_) simpa only [Function.comp_apply, ← hAB a] using hB (r a) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean index 44399c53e..a4717c96a 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean @@ -117,25 +117,25 @@ private theorem card_majority_eq {β : Type} [Fintype β] (V : β → Bool) (R : /-- The majority polynomial is uniformly GapP for polynomial-time unary repetition counts. -/ theorem majorityPolynomial_mem {α : Type} {enc : α ↪ List Bool} {g D : α → ℤ} {r : α → ℕ} (hg : g ∈ GapP enc) (hD : D ∈ GapP enc) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => majorityPolynomial (g a) (D a) (r a)) ∈ GapP enc := by let ones : α × List Bool → ℕ := fun x => x.2.countP id - have hones : ComputableTidilyInPolyTime ones (encPair enc encBits) encUnary := by + have hones : ComputableInPolyTime ones (encPair enc encBits) encUnary := by dsimp [ones] fun_prop - have hR : ComputableTidilyInPolyTime (fun x : α × List Bool => r x.1) + have hR : ComputableInPolyTime (fun x : α × List Bool => r x.1) (encPair enc encBits) encUnary := hr.comp (.fst enc encBits) - have hz : ComputableTidilyInPolyTime (fun x : α × List Bool => 2 * r x.1 - ones x) + have hz : ComputableInPolyTime (fun x : α × List Bool => 2 * r x.1 - ones x) (encPair enc encBits) encUnary := by fun_prop have hg' := GapP.pow_mem_polyTime (GapP.comp_mem hg (.fst enc encBits)) hones have hd' := GapP.pow_mem_polyTime (GapP.comp_mem (GapP.sub_mem' hD hg) (.fst enc encBits)) hz - have htest : ComputableTidilyInPolyTime + have htest : ComputableInPolyTime (fun x : α × List Bool => if r x.1 < ones x then (1 : ℕ) else 0) (encPair enc encBits) encNat := by fun_prop have hweight := GapP.mul_mem (GapP.mul_mem hg' hd') (SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime htest)) have hsum := GapP.sum_bits_mem hweight - (ComputableTidilyInPolyTime.unary_mul.comp ((ComputableTidilyInPolyTime.const 2).prod hr)) + (ComputableInPolyTime.unary_mul.comp ((ComputableInPolyTime.const 2).prod hr)) convert hsum using 1 ext a unfold majorityPolynomial @@ -240,7 +240,7 @@ theorem amplify {α : Type} {enc : α ↪ List Bool} {A : Set α} (0 ≤ G a ∧ G a ≤ D) ∧ (a ∈ A → (2 : ℤ) ^ q.eval (enc a).length * (D - G a) ≤ D) ∧ (a ∉ A → (2 : ℤ) ^ q.eval (enc a).length * G a ≤ D) := by - refine ⟨majorityPolynomial_mem hg (GapP.two_pow_mem p) (by fun_prop), fun a => ?_⟩ + refine ⟨majorityPolynomial_mem hg (GapP.two_pow_mem p) (.of_tidy (by fun_prop)), fun a => ?_⟩ obtain ⟨hb, hy, hn⟩ := hA a have h := majorityPolynomial_bounds (e := q.eval (enc a).length) hb.1 hb.2 have he : (12 * q * p).eval (enc a).length = diff --git a/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean b/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean index 878c73348..d075e0f1f 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean @@ -176,16 +176,16 @@ theorem PPWithOracle_eq_PP_of_mem_AWPP (hA : A ∈ AWPP encBits) (enc : α ↪ L · dsimp [input]; fun_prop · dsimp [T']; fun_prop · dsimp [R']; fun_prop - · exact GapP.comp_mem hH (by fun_prop) + · exact GapP.comp_mem hH (.of_tidy (by fun_prop)) let S : α → ℤ := fun a => ∑ w : Fin (r a) → Bool, F (a, List.ofFn w) - have hS : S ∈ GapP enc := GapP.sum_bits_mem hF hr + have hS : S ∈ GapP enc := GapP.sum_bits_mem hF (.of_tidy hr) let E : α → ℤ := fun a => 2 ^ (R a * T a) - have hE : E ∈ GapP enc := mem_GapP_of_polyTime (by dsimp [E]; fun_prop) + have hE : E ∈ GapP enc := mem_GapP_of_polyTime (.of_tidy (by dsimp [E]; fun_prop)) have hcoef : (fun a => 2 * (2 : ℤ) ^ r a + 1) ∈ GapP enc := - mem_GapP_of_polyTime (by fun_prop) + mem_GapP_of_polyTime (.of_tidy (by fun_prop)) apply mem_PP_iff_exists_GapP.mpr refine ⟨fun a => 4 * S a - (2 * (2 : ℤ) ^ r a + 1) * E a, - GapP.sub_mem' (GapP.mul_mem (mem_GapP_of_polyTime (by fun_prop)) hS) + GapP.sub_mem' (GapP.mul_mem (mem_GapP_of_polyTime (.of_tidy (by fun_prop))) hS) (GapP.mul_mem hcoef hE), fun a => ?_⟩ have herror (w : Fin (r a) → Bool) : (2 : ℤ) ^ (r a + T a + 4) * |F (a, List.ofFn w) - E a * (if V (a, List.ofFn w) then 1 else 0)| ≤ diff --git a/Complexity/Computability/Complexity/Classes/AWPP/OracleWeights.lean b/Complexity/Computability/Complexity/Classes/AWPP/OracleWeights.lean index d21927783..dfbee7740 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/OracleWeights.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/OracleWeights.lean @@ -42,20 +42,20 @@ including arbitrary words occurring in a replay state. The requested error expon computed in unary and may be zero. -/ theorem exists_AWPP_queryWeights {α : Type} {enc : α ↪ List Bool} {A : Set (List Bool)} (hA : A ∈ AWPP encBits) {T e : α → ℕ} - (hT : ComputableTidilyInPolyTime T enc encUnary) - (he : ComputableTidilyInPolyTime e enc encUnary) : + (hT : ComputableInPolyTime T enc encUnary) + (he : ComputableInPolyTime e enc encUnary) : ∃ H ∈ GapP (encPair enc encBits), ∃ R : α → ℕ, - ComputableTidilyInPolyTime R enc encUnary ∧ ∀ a w, + ComputableInPolyTime R enc encUnary ∧ ∀ a w, let D := (2 : ℤ) ^ R a (0 ≤ H (a, w) ∧ H (a, w) ≤ D) ∧ (w.take (T a) ∈ A → (2 : ℤ) ^ e a * (D - H (a, w)) ≤ D) ∧ (w.take (T a) ∉ A → (2 : ℤ) ^ e a * H (a, w) ≤ D) := by obtain ⟨g, hg, p, hA⟩ := hA let query : α × List Bool → List Bool := fun x => x.2.take (T x.1) - have hquery : ComputableTidilyInPolyTime query (encPair enc encBits) encBits := by + have hquery : ComputableInPolyTime query (encPair enc encBits) encBits := by dsimp [query] fun_prop - have he' : ComputableTidilyInPolyTime (fun x : α × List Bool => e x.1) + have he' : ComputableInPolyTime (fun x : α × List Bool => e x.1) (encPair enc encBits) encUnary := he.comp (.fst enc encBits) let H₀ : α × List Bool → ℤ := fun x => AWPPAmplification.majorityPolynomial (g (query x)) ((2 : ℤ) ^ p.eval (query x).length) (6 * e x.1) @@ -66,10 +66,10 @@ theorem exists_AWPP_queryWeights {α : Type} {enc : α ↪ List Bool} {A : Set ( · fun_prop let padding : α × List Bool → ℕ := fun x => 12 * e x.1 * (p.eval (T x.1) - p.eval (query x).length) - have hpadding : ComputableTidilyInPolyTime padding (encPair enc encBits) encUnary := by + have hpadding : ComputableInPolyTime padding (encPair enc encBits) encUnary := by dsimp [padding] fun_prop - have hpow : ComputableTidilyInPolyTime (fun x => 2 ^ padding x) + have hpow : ComputableInPolyTime (fun x => 2 ^ padding x) (encPair enc encBits) encNat := by fun_prop let H : α × List Bool → ℤ := fun x => H₀ x * (2 : ℤ) ^ padding x have hH : H ∈ GapP (encPair enc encBits) := by diff --git a/Complexity/Computability/Complexity/Classes/AWPP/WPP.lean b/Complexity/Computability/Complexity/Classes/AWPP/WPP.lean index 41dc9a8ad..dbd2992a0 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/WPP.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/WPP.lean @@ -50,14 +50,14 @@ theorem WPP_subset_AWPP : WPP enc ⊆ AWPP enc := by let D a : ℤ := 2 ^ r a have hD : D ∈ GapP enc := by have := SharpP.natCast_mem_GapP - (mem_SharpP_of_polyTime (ComputableTidilyInPolyTime.binary_two_pow.comp hr)) + (mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp hr))) simpa only [Function.comp_apply, Nat.cast_pow, Nat.cast_ofNat, D] using this let G := g * g have hG : G ∈ GapP enc := GapP.mul_mem hg hg have hnum := GapP.sub_mem' (GapP.add_mem (GapP.mul_mem hG hD) (GapP.mul_mem hG hD)) (GapP.mul_mem hG hG) refine mem_AWPP_of_polyTime_exponent hnum - (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hr)) (fun a => ?_) + (.of_tidy (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hr))) (fun a => ?_) have hkcast : (k a : ℤ) = f a * f a := Int.toNat_of_nonneg (mul_self_nonneg _) have hkpos : 0 < k a := by have := mul_self_pos.mpr (hf0 a) diff --git a/Complexity/Computability/Complexity/Classes/Alternation/Game.lean b/Complexity/Computability/Complexity/Classes/Alternation/Game.lean index ea7405a9c..f15e5a549 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/Game.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/Game.lean @@ -238,10 +238,12 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} /-- **Every problem in `AP` has a polynomial-time game verifier.** -/ theorem exists_isGameVerifier_of_mem_AP (h : A ∈ AP enc) : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by - obtain ⟨t, ht, k, State, hfinite, atm, hdecides⟩ := h - obtain ⟨c, d, hle⟩ := ht.exists_le - exact ⟨_, atm.gameVerifier enc, atm.computableTidilyInPolyTime_gameVerifier, - (hdecides.mono hle).isGameVerifier⟩ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + obtain ⟨t, ht, k, State, hfinite, atm, hdecides⟩ := h + obtain ⟨c, d, hle⟩ := ht.exists_le + exact ⟨_, atm.gameVerifier enc, atm.computableTidilyInPolyTime_gameVerifier, + (hdecides.mono hle).isGameVerifier⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean b/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean index 760b50f01..fdc74e1c3 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean @@ -187,8 +187,9 @@ variable {α : Type} {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × Li Stockmeyer][ChandraKozenStockmeyer1981]: a problem with a polynomial-time game verifier is decided in polynomial time by the guess-then-verify machine, which writes the moves of the two players, alternately, and then runs the verifier. -/ -theorem IsGameVerifier.mem_AP (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) +theorem IsGameVerifier.mem_AP (hV : Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool) (h : IsGameVerifier enc p V A) : A ∈ AP enc := by + have hV := hV.tidy -- the number of moves, and the word prepared on tape `B` set L : α → ℕ := fun a => 2 * p.eval (enc a).length have hL : ComputableTidilyInPolyTime L enc encUnary := diff --git a/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean b/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean index fb012a949..003ddf5f9 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean @@ -56,7 +56,7 @@ exactly those in `PSPACE` (`Cslib.Complexity.mem_PSPACE_iff_exists_isGameVerifie * `Cslib.Complexity.alternation_append_iff`: trailing moves that do not matter. * `Cslib.Reachability.alternation_midpointGame_iff`: the midpoint game is Savitch's recursion. -* `Cslib.Complexity.computableTidilyInPolyTime_savitchVerifier`: the game is polynomial-time. +* `Cslib.Complexity.computableInPolyTime_savitchVerifier`: the game is polynomial-time. * `Cslib.Complexity.exists_isGameVerifier_of_mem_PSPACE`: every problem in `PSPACE` has a polynomial-time game verifier. * `Cslib.Complexity.PSPACE_subset_AP`, `Cslib.Complexity.AP_eq_PSPACE`: `AP = PSPACE`. @@ -263,8 +263,8 @@ open _root_.Turing _root_.Turing.MultiTapeTM /-- A level of the midpoint game is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_midpointStep : - ComputableTidilyInPolyTime (fun p : ℕ × List Bool × List Bool × List Bool => +theorem computableInPolyTime_midpointStep : + Turing.MultiTapeTM.ComputableInPolyTime (fun p : ℕ × List Bool × List Bool × List Bool => midpointStep p.1 p.2) (encPair encUnary (encPair encBits (encPair encBits encBits))) (encPair encBits (encPair encBits encBits)) := by unfold midpointStep midpointMoves @@ -295,9 +295,10 @@ noncomputable def savitchVerifier (x : α × List Bool) : Bool := (MultiTapeNTM.acceptCode (ntm.codeWidth c d (enc x.1))) x.2 /-- The verifier of the midpoint game is polynomial-time. -/ -theorem computableTidilyInPolyTime_savitchVerifier : - ComputableTidilyInPolyTime (savitchVerifier (enc := enc) ntm c d) (encPair enc encBits) +theorem computableInPolyTime_savitchVerifier : + Turing.MultiTapeTM.ComputableInPolyTime (savitchVerifier (enc := enc) ntm c d) (encPair enc encBits) encBool := by + refine .of_tidy ?_ have hwidth : ComputableTidilyInPolyTime (fun x : α × List Bool => ntm.codeWidth c d (enc x.1)) (encPair enc encBits) encUnary := (MultiTapeNTM.computableTidilyInPolyTime_codeWidth c d).comp @@ -317,7 +318,7 @@ theorem computableTidilyInPolyTime_savitchVerifier : ((MultiTapeNTM.computableTidilyInPolyTime_acceptCode hwidth).prod (ComputableTidilyInPolyTime.snd enc encBits)) have hloop := ComputableTidilyInPolyTime.iterateWith_of_bounded_growth hw hw hinit - computableTidilyInPolyTime_midpointStep + computableInPolyTime_midpointStep.tidy (growth := fun x => 2 * savitchWidth (enc := enc) ntm c d x.1) (ComputableTidilyInPolyTime.polyBounded (by unfold savitchWidth; fun_prop)) fun x s => by unfold midpointStep @@ -345,29 +346,31 @@ space. The game has `2 * ((W + 1) * W)` moves for the width `W` of the codes, pa polynomial number. -/ theorem exists_isGameVerifier_of_mem_PSPACE (h : A ∈ PSPACE enc) : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by - obtain ⟨k, State, _, ntm, s, hs, hA⟩ := PSPACE_subset_NPSPACE h - obtain ⟨c, d, hcd⟩ := hs.exists_le - -- the number of rounds of the game is polynomially bounded - have hrounds : ComputableTidilyInPolyTime - (fun a => (savitchWidth (enc := enc) ntm c d a + 1) * savitchWidth (enc := enc) ntm c d a) - enc encUnary := by - have := MultiTapeNTM.computableTidilyInPolyTime_codeWidth (ntm := ntm) (enc := enc) c d - unfold savitchWidth - fun_prop - obtain ⟨p, hr⟩ := hrounds.polyBounded.exists_polynomial - refine ⟨p, savitchVerifier (enc := enc) ntm c d, - computableTidilyInPolyTime_savitchVerifier ntm c d, fun a => ?_⟩ - set w := savitchWidth (enc := enc) ntm c d a - have hle : 2 * ((w + 1) * w) ≤ 2 * p.eval (enc a).length := - Nat.mul_le_mul_left 2 (hr a) - rw [(hA.recognizesInSpace a).2, - ← MultiTapeNTM.savitchDecide_eq_true_iff (hA.recognizesInSpace a).1 (hcd a), - MultiTapeNTM.savitchDecide, - savitch_eq, ← Nat.add_sub_cancel' hle, List.replicate_add, alternation_append_iff - fun z => by rw [Cslib.Complexity.sum_replicate_one, savitchVerifier, savitchVerifier, - midpointGame_take]] - exact (alternation_midpointGame_iff _ _ _).symm + Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + obtain ⟨k, State, _, ntm, s, hs, hA⟩ := PSPACE_subset_NPSPACE h + obtain ⟨c, d, hcd⟩ := hs.exists_le + -- the number of rounds of the game is polynomially bounded + have hrounds : ComputableTidilyInPolyTime + (fun a => (savitchWidth (enc := enc) ntm c d a + 1) * savitchWidth (enc := enc) ntm c d a) + enc encUnary := by + have := MultiTapeNTM.computableTidilyInPolyTime_codeWidth (ntm := ntm) (enc := enc) c d + unfold savitchWidth + fun_prop + obtain ⟨p, hr⟩ := hrounds.polyBounded.exists_polynomial + refine ⟨p, savitchVerifier (enc := enc) ntm c d, + (computableInPolyTime_savitchVerifier ntm c d).tidy, fun a => ?_⟩ + set w := savitchWidth (enc := enc) ntm c d a + have hle : 2 * ((w + 1) * w) ≤ 2 * p.eval (enc a).length := + Nat.mul_le_mul_left 2 (hr a) + rw [(hA.recognizesInSpace a).2, + ← MultiTapeNTM.savitchDecide_eq_true_iff (hA.recognizesInSpace a).1 (hcd a), + MultiTapeNTM.savitchDecide, + savitch_eq, ← Nat.add_sub_cancel' hle, List.replicate_add, alternation_append_iff + fun z => by rw [Cslib.Complexity.sum_replicate_one, savitchVerifier, savitchVerifier, + midpointGame_take]] + exact (alternation_midpointGame_iff _ _ _).symm + simpa only [Turing.MultiTapeTM.computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- **`PSPACE ⊆ AP`** [Chandra, Kozen and Stockmeyer][ChandraKozenStockmeyer1981]: a problem in `PSPACE` is Savitch's midpoint game on the views of a machine deciding it, which the @@ -384,7 +387,7 @@ theorem AP_eq_PSPACE : AP enc = PSPACE enc := /-- **The problems with polynomial-time game verifiers are exactly those in `PSPACE`.** -/ theorem mem_PSPACE_iff_exists_isGameVerifier : A ∈ PSPACE enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := + Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := ⟨exists_isGameVerifier_of_mem_PSPACE, fun ⟨_, _, hV, h⟩ => h.mem_PSPACE hV⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean index 987e4bd8a..388eebdb7 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean @@ -60,7 +60,7 @@ in particular every problem in `AP` (`Cslib.Complexity.AP_subset_PSPACE`): the i * `Cslib.Complexity.TQBF.eval_gameFormula`, `Cslib.Complexity.TQBF.closed_gameFormula`: the formula of a game. * `Cslib.Complexity.TQBF.gameReduce_mem_TQBF_iff`, - `Cslib.Complexity.TQBF.computableTidilyInPolyTime_gameReduce`: the reduction is correct and + `Cslib.Complexity.TQBF.computableInPolyTime_gameReduce`: the reduction is correct and polynomial-time. * `Cslib.Complexity.IsGameVerifier.mem_PSPACE`: games of polynomially many moves with a polynomial-time winning condition are decided in polynomial space. @@ -351,34 +351,34 @@ variable {γ : Type} {encIn : γ ↪ List Bool} /-- The tokens of a round, from the width and the round in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_roundTokens {w i : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => roundTokens (w x) (i x)) encIn (encList encToken) := by +theorem computableInPolyTime_roundTokens {w i : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => roundTokens (w x) (i x)) encIn (encList encToken) := by unfold roundTokens fun_prop /-- **The formula of a game is polynomial-time** in the tableau and the number of rounds in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_gameFormula {k : ℕ} {State : Type} [Fintype State] +theorem computableInPolyTime_gameFormula {k : ℕ} {State : Type} [Fintype State] {tab : γ → CNF (CookLevin.Var k State)} {w : γ → ℕ} - (htab : ComputableTidilyInPolyTime tab encIn + (htab : Turing.MultiTapeTM.ComputableInPolyTime tab encIn (encList (encList (encPair CookLevin.encVar encBool)))) - (hw : ComputableTidilyInPolyTime w encIn encUnary) : - ComputableTidilyInPolyTime (fun x => gameFormula (tab x) (w x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => gameFormula (tab x) (w x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (List.range (w x)).flatMap (roundTokens (w x)) ++ (baseFormula (tab x) (w x)).tokens) (by fun_prop) fun _ => tokens_gameFormula .. /-- **The reduction of a game is polynomial-time.** -/ -theorem computableTidilyInPolyTime_gameReduce {kV : ℕ} {StateV : Type} [Fintype StateV] +theorem computableInPolyTime_gameReduce {kV : ℕ} {StateV : Type} [Fintype StateV] [DecidableEq StateV] (tmV : MultiTapeTM kV Bool StateV) (cV dV : ℕ) : - ComputableTidilyInPolyTime (gameReduce enc p tmV cV dV) enc encQBF := by - have htab := CookLevin.computableTidilyInPolyTime_tableau tmV - have hframe := bitsFrame enc - have hp : ComputableTidilyInPolyTime (fun a => p.eval (enc a).length) enc encUnary := - (unary_eval p).comp (encoding_length enc) + Turing.MultiTapeTM.ComputableInPolyTime (gameReduce enc p tmV cV dV) enc encQBF := by + have htab := CookLevin.computableInPolyTime_tableau tmV + have hframe := Turing.MultiTapeTM.ComputableInPolyTime.bitsFrame enc + have hp : Turing.MultiTapeTM.ComputableInPolyTime (fun a => p.eval (enc a).length) enc encUnary := + (Turing.MultiTapeTM.ComputableInPolyTime.unary_eval p).comp (Turing.MultiTapeTM.ComputableInPolyTime.encoding_length enc) unfold gameReduce fun_prop @@ -404,15 +404,16 @@ private theorem IsGameVerifier.polyTimeReducible have := Fintype.ofFinite StateV classical exact ⟨TQBF.gameReduce enc p tmV cV dV, - .of_tidy (TQBF.computableTidilyInPolyTime_gameReduce tmV cV dV), + (TQBF.computableInPolyTime_gameReduce tmV cV dV), fun a => (h a).trans (TQBF.gameReduce_mem_TQBF_iff (htmV.mono htV fun _ => le_rfl) a).symm⟩ /-- **Games of polynomially many moves are decided in polynomial space**: a problem with a polynomial-time game verifier is in `PSPACE`. -/ theorem IsGameVerifier.mem_PSPACE - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) - (h : IsGameVerifier enc p V A) : A ∈ PSPACE enc := - (h.polyTimeReducible hV).mem_PSPACE TQBF_mem_PSPACE + (hV : Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool) + (h : IsGameVerifier enc p V A) : A ∈ PSPACE enc := by + have hV := hV.tidy + exact (h.polyTimeReducible hV).mem_PSPACE TQBF_mem_PSPACE /-- **`AP ⊆ PSPACE`** [Chandra, Kozen and Stockmeyer][ChandraKozenStockmeyer1981] [Sipser, Section 10.3][Sipser2013]: a problem decided by an alternating machine within polynomial diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean index c5f3d2933..dac82ff8f 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean @@ -115,9 +115,9 @@ def merlinArthurRepeat (enc : α ↪ List Bool) (q r p : Polynomial ℕ) (V : α /-- Majority votes of a polynomial-time Merlin–Arthur verifier take polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_merlinArthurRepeat {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (q r p : Polynomial ℕ) : - ComputableTidilyInPolyTime (merlinArthurRepeat enc q r p V) (encPair enc encBits) encBool := by +theorem computableInPolyTime_merlinArthurRepeat {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (q r p : Polynomial ℕ) : + ComputableInPolyTime (merlinArthurRepeat enc q r p V) (encPair enc encBits) encBool := by unfold merlinArthurRepeat repeatMajority repeatVotes fun_prop @@ -189,14 +189,16 @@ verifier with proofs of length `q` and error at most `2 ^ (-e(n))`. The proof le before the error, so the error can be made smaller than `2 ^ (-q(n))`. -/ theorem mem_MA_iff_exists_forall_errorExponent : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) - (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by - rw [mem_MA_iff_tidy] - refine ⟨fun ⟨q, p, V, hV, h⟩ => ⟨q, fun e => ⟨12 * e * p, _, - computableTidilyInPolyTime_merlinArthurRepeat hV _ _ _, h.repeatMajority e⟩⟩, - fun ⟨q, h⟩ => ?_⟩ - obtain ⟨p, V, hV, h⟩ := h 2 - exact ⟨q, p, V, hV, h.isMerlinArthurVerifier fun _ => by simp⟩ + have this : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by + rw [mem_MA_iff_tidy] + refine ⟨fun ⟨q, p, V, hV, h⟩ => ⟨q, fun e => ⟨12 * e * p, _, + (computableInPolyTime_merlinArthurRepeat (.of_tidy hV) _ _ _).tidy, h.repeatMajority e⟩⟩, + fun ⟨q, h⟩ => ?_⟩ + obtain ⟨p, V, hV, h⟩ := h 2 + exact ⟨q, p, V, hV, h.isMerlinArthurVerifier fun _ => by simp⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Error reduction for `AM` -/ @@ -228,9 +230,9 @@ def arthurMerlinRepeat (enc : α ↪ List Bool) (r p q : Polynomial ℕ) (V : α /-- Parallel majority votes of a polynomial-time Arthur–Merlin verifier take polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_arthurMerlinRepeat {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (r p q : Polynomial ℕ) : - ComputableTidilyInPolyTime (arthurMerlinRepeat enc r p q V) (encPair enc encBits) encBool := by +theorem computableInPolyTime_arthurMerlinRepeat {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (r p q : Polynomial ℕ) : + ComputableInPolyTime (arthurMerlinRepeat enc r p q V) (encPair enc encBits) encBool := by unfold arthurMerlinRepeat fun_prop @@ -344,13 +346,15 @@ polynomial `e`, it has a polynomial-time Arthur–Merlin verifier with error at `2 ^ (-e(n))`. -/ theorem mem_AM_iff_forall_errorExponent : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by - rw [mem_AM_iff_tidy] - refine ⟨fun ⟨p, q, V, hV, h⟩ e => ⟨12 * e * p, 12 * e * q, _, - computableTidilyInPolyTime_arthurMerlinRepeat hV _ _ _, h.repeatMajority e⟩, fun h => ?_⟩ - obtain ⟨p, q, V, hV, h⟩ := h 2 - exact ⟨p, q, V, hV, h.isArthurMerlinVerifier fun _ => by simp⟩ + have this : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by + rw [mem_AM_iff_tidy] + refine ⟨fun ⟨p, q, V, hV, h⟩ e => ⟨12 * e * p, 12 * e * q, _, + (computableInPolyTime_arthurMerlinRepeat (.of_tidy hV) _ _ _).tidy, h.repeatMajority e⟩, fun h => ?_⟩ + obtain ⟨p, q, V, hV, h⟩ := h 2 + exact ⟨p, q, V, hV, h.isArthurMerlinVerifier fun _ => by simp⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### `MA ⊆ AM` -/ @@ -368,7 +372,7 @@ theorem MA_subset_AM : MA enc ⊆ AM enc := by (ComputableTidilyInPolyTime.unary_eval P).comp (ComputableTidilyInPolyTime.encoding_length enc) refine ⟨P, q, fun x => W (x.1, x.2.drop (P.eval (enc x.1).length) ++ x.2.take (P.eval (enc x.1).length)), ?_, fun a => ?_⟩ - · exact .of_tidy <| (computableTidilyInPolyTime_merlinArthurRepeat hV.tidy _ _ _).comp + · exact .of_tidy <| (computableInPolyTime_merlinArthurRepeat hV _ _ _).tidy.comp ((ComputableTidilyInPolyTime.fst enc encBits).prod (.bitsAppend (.bitsDropWithInput (.snd enc encBits) (hPu.comp (.fst enc encBits))) (.bitsTakeWithInput (.snd enc encBits) (hPu.comp (.fst enc encBits))))) @@ -444,7 +448,7 @@ theorem MA_subset_SBP : MA enc ⊆ SBP enc := by set W := merlinArthurRepeat enc q (6 * (q + 2)) p V with hW set P : Polynomial ℕ := 12 * (q + 2) * p with hP have hf : (fun a => acceptCount W a ((q + P).eval (enc a).length)) ∈ SharpP enc := - ⟨q + P, W, .of_tidy (computableTidilyInPolyTime_merlinArthurRepeat hV.tidy _ _ _), fun _ => rfl⟩ + ⟨q + P, W, (computableInPolyTime_merlinArthurRepeat hV _ _ _), fun _ => rfl⟩ have hd : ComputableTidilyInPolyTime (fun a => 2 ^ P.eval (enc a).length) enc encNat := ComputableTidilyInPolyTime.binary_two_pow.comp ((ComputableTidilyInPolyTime.unary_eval P).comp (.encoding_length enc)) diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean index dca751403..200c29809 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean @@ -352,8 +352,8 @@ def test (N : Polynomial ℕ) (x : (Graph × Graph) × List Bool) : Bool := /-- The test is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_test (N : Polynomial ℕ) : - ComputableTidilyInPolyTime (test N) (encPair (encPair encGraph encGraph) encBits) encBool := by +theorem computableInPolyTime_test (N : Polynomial ℕ) : + ComputableInPolyTime (test N) (encPair (encPair encGraph encGraph) encBits) encBool := by unfold test check dsimp only fun_prop @@ -514,7 +514,7 @@ theorem mem_AM : GraphNonIsomorphism ∈ AM (encPair encGraph encGraph) := by (ComputableTidilyInPolyTime.const 2).binary_mul' (ComputableTidilyInPolyTime.binary_factorial.comp ((ComputableTidilyInPolyTime.length_list encNat).comp - (Graph.computableTidilyInPolyTime_distinctVertices.comp + (Graph.computableInPolyTime_distinctVertices.tidy.comp (ComputableTidilyInPolyTime.fst encGraph encGraph)))) -- the lengths have hlen (G₀ G₁ : Graph) : @@ -545,7 +545,7 @@ theorem mem_AM : GraphNonIsomorphism ∈ AM (encPair encGraph encGraph) := by rw [hset, card_filter_check (by rw [hE]; omega) (by rw [hC]; omega)] rfl refine mem_AM_of_card_certifiedSet (N := N) (c := c) (R := test N) - (computableTidilyInPolyTime_test N) hK (fun a => by positivity) (fun a ha => ?_) + (computableInPolyTime_test N).tidy hK (fun a => by positivity) (fun a ha => ?_) fun a ha => ?_ · obtain ⟨G₀, G₁⟩ := a dsimp only diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean index 229177818..98d4929a4 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean @@ -95,9 +95,9 @@ def sigmaTwoVerifier (enc : α ↪ List Bool) (q k p : Polynomial ℕ) (W : α /-- The `Σ₂` verifier of a polynomial-time Merlin–Arthur verifier takes polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_sigmaTwoVerifier {W : α × List Bool → Bool} - (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) (q k p : Polynomial ℕ) : - ComputableTidilyInPolyTime (sigmaTwoVerifier enc q k p W) (encPair enc encBits) encBool := by +theorem computableInPolyTime_sigmaTwoVerifier {W : α × List Bool → Bool} + (hW : ComputableInPolyTime W (encPair enc encBits) encBool) (q k p : Polynomial ℕ) : + ComputableInPolyTime (sigmaTwoVerifier enc q k p W) (encPair enc encBits) encBool := by unfold sigmaTwoVerifier fun_prop @@ -185,9 +185,9 @@ def piTwoVerifier (enc : α ↪ List Bool) (k p q : Polynomial ℕ) (W : α × L /-- The `Π₂` verifier of a polynomial-time Arthur–Merlin verifier takes polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_piTwoVerifier {W : α × List Bool → Bool} - (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) (k p q : Polynomial ℕ) : - ComputableTidilyInPolyTime (piTwoVerifier enc k p q W) (encPair enc encBits) encBool := by +theorem computableInPolyTime_piTwoVerifier {W : α × List Bool → Bool} + (hW : ComputableInPolyTime W (encPair enc encBits) encBool) (k p q : Polynomial ℕ) : + ComputableInPolyTime (piTwoVerifier enc k p q W) (encPair enc encBits) encBool := by unfold piTwoVerifier fun_prop @@ -284,8 +284,8 @@ theorem MA_subset_SigmaP_two : MA enc ⊆ SigmaP 2 enc := by exact ⟨[q + (12 * p + 1) * (12 * (12 * p + 1) * p), 12 * (12 * p + 1) * p], sigmaTwoVerifier enc q (12 * p + 1) (12 * (12 * p + 1) * p) (merlinArthurRepeat enc q (6 * (12 * p + 1)) p V), rfl, - .of_tidy (computableTidilyInPolyTime_sigmaTwoVerifier - (computableTidilyInPolyTime_merlinArthurRepeat hV.tidy _ _ _) _ _ _), + (computableInPolyTime_sigmaTwoVerifier + (computableInPolyTime_merlinArthurRepeat hV _ _ _) _ _ _), isAlternatingVerifier_sigmaTwoVerifier (h.repeatMajority _) (eval_lt_mul p) fun _ => Nat.lt_two_pow_self⟩ @@ -298,8 +298,8 @@ theorem AM_subset_PiP_two : AM enc ⊆ PiP 2 enc := by 12 * (12 * p + 1) * p + (12 * p + 1) * (12 * (12 * p + 1) * q)], piTwoVerifier enc (12 * p + 1) (12 * (12 * p + 1) * p) (12 * (12 * p + 1) * q) (arthurMerlinRepeat enc (6 * (12 * p + 1)) p q V), rfl, - .of_tidy (computableTidilyInPolyTime_piTwoVerifier - (computableTidilyInPolyTime_arthurMerlinRepeat hV.tidy _ _ _) _ _ _), + (computableInPolyTime_piTwoVerifier + (computableInPolyTime_arthurMerlinRepeat hV _ _ _) _ _ _), isAlternatingVerifier_piTwoVerifier (h.repeatMajority _) (eval_lt_mul p) fun _ => Nat.lt_two_pow_self⟩ diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean index 92229bf44..b82379cdf 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean @@ -161,10 +161,10 @@ def verifier (enc : α ↪ List Bool) (N c m T : Polynomial ℕ) (ℓ : α → /-- The verifier of the set lower bound protocol is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier {N c m T : Polynomial ℕ} {ℓ : α → ℕ} - {R : α × List Bool → Bool} (hℓ : ComputableTidilyInPolyTime ℓ enc encUnary) - (hR : ComputableTidilyInPolyTime R (encPair enc encBits) encBool) : - ComputableTidilyInPolyTime (verifier enc N c m T ℓ R) (encPair enc encBits) encBool := by +theorem computableInPolyTime_verifier {N c m T : Polynomial ℕ} {ℓ : α → ℕ} + {R : α × List Bool → Bool} (hℓ : ComputableInPolyTime ℓ enc encUnary) + (hR : ComputableInPolyTime R (encPair enc encBits) encBool) : + ComputableInPolyTime (verifier enc N c m T ℓ R) (encPair enc encBits) encBool := by unfold verifier dsimp only fun_prop @@ -253,10 +253,12 @@ polynomials, and `K` a polynomial-time threshold in binary with `K a > 0`. If th of `N(n)` bits with a certificate of `c(n)` bits accepted by `R` has at least `K a` elements for every member `a` of `A`, and at most `K a / 2` for every non-member, then `A ∈ AM`. -/ theorem mem_AM_of_card_certifiedSet {N c : Polynomial ℕ} {R : α × List Bool → Bool} {K : α → ℕ} - (hR : ComputableTidilyInPolyTime R (encPair enc encBits) encBool) - (hK : ComputableTidilyInPolyTime K enc encNat) (hKpos : ∀ a, 0 < K a) + (hR : ComputableInPolyTime R (encPair enc encBits) encBool) + (hK : ComputableInPolyTime K enc encNat) (hKpos : ∀ a, 0 < K a) (hmem : ∀ a ∈ A, K a ≤ #(certifiedSet enc N c R a)) (hnot : ∀ a ∉ A, 2 * #(certifiedSet enc N c R a) ≤ K a) : A ∈ AM enc := by + have hR := hR.tidy + have hK := hK.tidy -- normalise the threshold `K a ^ 5` to a power of two set ℓ : α → ℕ := fun a => Nat.log 2 (K a ^ 5) with hℓdef have hℓ : ComputableTidilyInPolyTime ℓ enc encUnary := @@ -266,7 +268,7 @@ theorem mem_AM_of_card_certifiedSet {N c : Polynomial ℕ} {R : α × List Bool set m : Polynomial ℕ := B + 2 with hm set T : Polynomial ℕ := B + 4 with hT refine ⟨m * (5 * N + T) + m, 5 * N + T + 5 * c, verifier enc N c m T ℓ R, - .of_tidy (computableTidilyInPolyTime_verifier hℓ hR), fun a => ?_⟩ + (computableInPolyTime_verifier (.of_tidy hℓ) (.of_tidy hR)), fun a => ?_⟩ have hP : (m * (5 * N + T) + m).eval (enc a).length = m.eval (enc a).length * (5 * N.eval (enc a).length + T.eval (enc a).length) + m.eval (enc a).length := by simp have hQ : (5 * N + T + 5 * c).eval (enc a).length = 5 * N.eval (enc a).length + diff --git a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean index 291137544..e4c1292db 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean @@ -134,13 +134,15 @@ theorem DecidesWithErrorExponent.decidesWithBoundedError {q p : Polynomial ℕ} `2 ^ (-q(n))`. -/ theorem mem_BPP_iff_forall_decidesWithErrorExponent {A : Set α} : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by - rw [mem_BPP_iff_tidy] - refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨12 * q * p, _, - computableTidilyInPolyTime_repeatMajority hV _ _, h.repeatMajority q⟩, fun h => ?_⟩ - obtain ⟨p, V, hV, h⟩ := h 2 - exact ⟨p, V, hV, h.decidesWithBoundedError fun _ => by simp⟩ + have this : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by + rw [mem_BPP_iff_tidy] + refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨12 * q * p, _, + (computableInPolyTime_repeatMajority (.of_tidy hV) _ _).tidy, h.repeatMajority q⟩, fun h => ?_⟩ + obtain ⟨p, V, hV, h⟩ := h 2 + exact ⟨p, V, hV, h.decidesWithBoundedError fun _ => by simp⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Boolean closure of `BPP` -/ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean index aa79f1a61..9a620a50d 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean @@ -17,6 +17,7 @@ import Complexity.Computability.Circuit.Boolean.Substitution import Complexity.Computability.Complexity.Classes.BPP.Derandomization.Generator import Complexity.Foundations.Data.Nat.PolynomialBound.Log import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Derandomizing BPP from average-case hardness @@ -37,7 +38,7 @@ Nisan–Wigderson generator for all `2 ^ ℓ` seeds of `ℓ = (2 ^ (8 c + 1) + 1 majority. The generator uses the greedy design (`Cslib.Crypto.PRG.NisanWigderson.Design.greedy`) with blocks of `n = 4 c t` positions sharing at most `t - 1` of them, and the hard function on `n` bits, evaluated in time `2 ^ O(n)`. Both `2 ^ ℓ` and `2 ^ O(n)` are polynomial in `N`, so the -algorithm runs in polynomial time (`Cslib.Complexity.computableTidilyInPolyTime_nwDecider`). +algorithm runs in polynomial time (`Cslib.Complexity.computableInPolyTime_nwDecider`). For correctness, the verifier with the instance fixed is a circuit of polynomial size in its random string (`Cslib.Circuits.Boolean.PPoly.exists_of_polyTime`), and `t` is chosen so that @@ -131,7 +132,7 @@ theorem BPP_subset_P_of_isAverageCaseHard {L : Language Bool} {c : ℕ} {α : Type} (enc : α ↪ List Bool) : BPP enc ⊆ P enc := by rintro A ⟨p, V, hV, hdec⟩ obtain ⟨k, hL⟩ := mem_E_iff.1 hL - obtain ⟨g, hgL, hg⟩ := exists_computableTidilyInO_of_mem_DTIME hL + obtain ⟨g, hgL, hg⟩ := exists_computableInO_of_mem_DTIME hL have hslice (n : ℕ) : (fun y : Fin n → Bool => g (List.ofFn y)) = L.slice n := by funext y rw [Bool.eq_iff_iff, Language.slice_eq_true_iff, ← hgL] @@ -168,9 +169,9 @@ theorem BPP_subset_P_of_isAverageCaseHard {L : Language Bool} {c : ℕ} fun x => le_of_eq ?_ rw [← pow_add, ht] ring_nf - refine computableTidilyInPolyTime_nwDecider hV.tidy - (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) hg ?_ ?_ ?_ ?_ - (hbudget (b + 1)) ((hbudget (k * (c * 4))).mono fun x => le_of_eq ?_) + refine (computableInPolyTime_nwDecider hV + (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) (.of_tidy hg) (.of_tidy ?_) (.of_tidy ?_) (.of_tidy ?_) (.of_tidy ?_) + (hbudget (b + 1)) ((hbudget (k * (c * 4))).mono fun x => le_of_eq ?_)).tidy · simp only [hseed] fun_prop · simp only [hblock] diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean index 90e204d65..2902029d5 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean @@ -19,6 +19,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Fo import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Length import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Computing the Nisan–Wigderson generator @@ -35,20 +36,20 @@ is only computable in time `T n`, exponential in `n`. The certificates therefore bounds on `2 ^ ℓ` and on `T n` as functions of the instance: * a problem in `Cslib.Complexity.DTIME encBits t` has a Boolean decider tidily computable within - time and space `O(t n)` (`Cslib.Complexity.exists_computableTidilyInO_of_mem_DTIME`); + time and space `O(t n)` (`Cslib.Complexity.exists_computableInO_of_mem_DTIME`); * such a decider, applied to words cut to a computed length `n`, runs in polynomial time when `T n` is polynomially bounded (`Turing.MultiTapeTM.ComputableTidilyInO.computableTidilyInPolyTime_take`); * the greedy design of `Cslib.Crypto.PRG.NisanWigderson.greedyMasks` is a loop over the `2 ^ ℓ` masks of length `ℓ` that keeps at most one more mask per step - (`Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_greedyMasks`); + (`Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks`); * the generator on lists `Cslib.Crypto.PRG.NisanWigderson.listGenerator` reads each block with `Cslib.Crypto.PRG.NisanWigderson.restrictMask` and evaluates the hard function - (`Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_listGenerator`). + (`Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_listGenerator`). The decider `Cslib.Complexity.nwDecider` combines them: it runs a verifier on the output of the generator for each of the `2 ^ ℓ` seeds and takes the strict majority of the answers -(`Cslib.Complexity.computableTidilyInPolyTime_nwDecider`). Its correctness is the subject of +(`Cslib.Complexity.computableInPolyTime_nwDecider`). Its correctness is the subject of `Cslib.Complexity.BPP_subset_P_of_isAverageCaseHard`. ## Main definitions @@ -58,16 +59,16 @@ generator for each of the `2 ^ ℓ` seeds and takes the strict majority of the a ## Main results -* `Cslib.Complexity.exists_computableTidilyInO_of_mem_DTIME`: deterministic time classes have +* `Cslib.Complexity.exists_computableInO_of_mem_DTIME`: deterministic time classes have tidy deciders within the same time bound, up to constant factors. * `Turing.MultiTapeTM.ComputableTidilyInO.computableTidilyInPolyTime_take`: evaluation of a function computable in time `T n` on words of polynomially bounded `T n`. * `Turing.MultiTapeTM.ComputableTidilyInPolyTime.bitsEnumList_of_polyBounded`: enumeration of the words of a computed length `ℓ` when `2 ^ ℓ` is polynomially bounded. -* `Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_greedyMasks`, - `Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_listGenerator`: the greedy design +* `Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks`, + `Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_listGenerator`: the greedy design and the generator in polynomial time, when `2 ^ ℓ` and `T n` are polynomially bounded. -* `Cslib.Complexity.computableTidilyInPolyTime_nwDecider`: the majority over all seeds in +* `Cslib.Complexity.computableInPolyTime_nwDecider`: the majority over all seeds in polynomial time. ## References @@ -85,37 +86,39 @@ namespace Cslib.Complexity /-- **Deterministic time classes have tidy deciders.** A problem decided within time `O(t n)`, by a machine with any space bound, has a Boolean decider tidily computable within time and space `O(t n)`: time bounds space, and the tidy normal form costs a linear overhead. -/ -theorem exists_computableTidilyInO_of_mem_DTIME {A : Set (List Bool)} {t : ℕ → ℕ} +theorem exists_computableInO_of_mem_DTIME {A : Set (List Bool)} {t : ℕ → ℕ} (h : A ∈ DTIME encBits t) : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ - ComputableTidilyInO g encBits encBool (fun y => t y.length) fun y => t y.length := by - obtain ⟨c₁, c₂, s, hA⟩ := h - obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA - obtain ⟨c, hg⟩ := hg.exists_space_linear - obtain ⟨d, hg⟩ := hg.exists_computableTidilyInTimeAndSpace - set K := (2 + 3 * c) * (c₁ + c₂) + 3 * c + d + d * (c * (c₁ + c₂) + c + 1) + 1 with hK - have hx (y : List Bool) : c₁ * t y.length + c₂ ≤ (c₁ + c₂) * (t y.length + 1) := by - nlinarith [Nat.zero_le (c₂ * t y.length)] - have htime (y : List Bool) : 2 * (c₁ * t y.length + c₂) + 3 * (c * (c₁ * t y.length + c₂) + c) + - d ≤ K * (t y.length + 1) := by - have h₁ := Nat.mul_le_mul_left c (hx y) - calc _ ≤ (2 + 3 * c) * ((c₁ + c₂) * (t y.length + 1)) + (3 * c + d) * (t y.length + 1) := by - nlinarith [hx y, Nat.zero_le ((3 * c + d) * t y.length)] - _ ≤ K * (t y.length + 1) := by - rw [hK] - nlinarith [Nat.zero_le ((d * (c * (c₁ + c₂) + c + 1) + 1) * (t y.length + 1))] - have hspace (y : List Bool) : - d * (c * (c₁ * t y.length + c₂) + c + 1) ≤ K * (t y.length + 1) := by - have h₁ := Nat.mul_le_mul_left c (hx y) - calc _ ≤ d * (c * ((c₁ + c₂) * (t y.length + 1)) + (c + 1) * (t y.length + 1)) := by - refine Nat.mul_le_mul_left d ?_ - nlinarith [Nat.zero_le ((c + 1) * t y.length)] - _ = (d * (c * (c₁ + c₂) + c + 1)) * (t y.length + 1) := by ring - _ ≤ K * (t y.length + 1) := Nat.mul_le_mul_right _ (by omega) - refine ⟨g, hgA, ComputableTidilyInO.of_bounds hg K (fun y => htime y) (fun y => hspace y) - fun y => ?_⟩ - simp only [encBool_apply, List.length_singleton] - exact Nat.one_le_iff_ne_zero.2 (Nat.mul_ne_zero (by omega) (by omega)) + ComputableInO g encBits encBool (fun y => t y.length) fun y => t y.length := by + have this : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ ComputableTidilyInO g encBits encBool (fun y => t y.length) fun y => t y.length := by + obtain ⟨c₁, c₂, s, hA⟩ := h + obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA + obtain ⟨c, hg⟩ := hg.exists_space_linear + obtain ⟨d, hg⟩ := hg.exists_computableTidilyInTimeAndSpace + set K := (2 + 3 * c) * (c₁ + c₂) + 3 * c + d + d * (c * (c₁ + c₂) + c + 1) + 1 with hK + have hx (y : List Bool) : c₁ * t y.length + c₂ ≤ (c₁ + c₂) * (t y.length + 1) := by + nlinarith [Nat.zero_le (c₂ * t y.length)] + have htime (y : List Bool) : 2 * (c₁ * t y.length + c₂) + 3 * (c * (c₁ * t y.length + c₂) + c) + + d ≤ K * (t y.length + 1) := by + have h₁ := Nat.mul_le_mul_left c (hx y) + calc _ ≤ (2 + 3 * c) * ((c₁ + c₂) * (t y.length + 1)) + (3 * c + d) * (t y.length + 1) := by + nlinarith [hx y, Nat.zero_le ((3 * c + d) * t y.length)] + _ ≤ K * (t y.length + 1) := by + rw [hK] + nlinarith [Nat.zero_le ((d * (c * (c₁ + c₂) + c + 1) + 1) * (t y.length + 1))] + have hspace (y : List Bool) : + d * (c * (c₁ * t y.length + c₂) + c + 1) ≤ K * (t y.length + 1) := by + have h₁ := Nat.mul_le_mul_left c (hx y) + calc _ ≤ d * (c * ((c₁ + c₂) * (t y.length + 1)) + (c + 1) * (t y.length + 1)) := by + refine Nat.mul_le_mul_left d ?_ + nlinarith [Nat.zero_le ((c + 1) * t y.length)] + _ = (d * (c * (c₁ + c₂) + c + 1)) * (t y.length + 1) := by ring + _ ≤ K * (t y.length + 1) := Nat.mul_le_mul_right _ (by omega) + refine ⟨g, hgA, ComputableTidilyInO.of_bounds hg K (fun y => htime y) (fun y => hspace y) + fun y => ?_⟩ + simp only [encBool_apply, List.length_singleton] + exact Nat.one_le_iff_ne_zero.2 (Nat.mul_ne_zero (by omega) (by omega)) + simpa only [computableInO_iff_computableTidilyInO] using this end Cslib.Complexity @@ -214,13 +217,17 @@ private theorem computableTidilyInPolyTime_greedyStep : ComputableTidilyInPolyTi `block x` and overlap bound `overlap x`, the greedy design is polynomial-time in `x` when `2 ^ seed x` is polynomially bounded: the loop runs over `2 ^ seed x` masks and keeps at most as many. -/ -theorem computableTidilyInPolyTime_greedyMasks {seed block overlap : γ → ℕ} - (hseed : ComputableTidilyInPolyTime seed encIn encUnary) - (hblock : ComputableTidilyInPolyTime block encIn encUnary) - (hoverlap : ComputableTidilyInPolyTime overlap encIn encUnary) +theorem computableInPolyTime_greedyMasks {seed block overlap : γ → ℕ} + (hseed : ComputableInPolyTime seed encIn encUnary) + (hblock : ComputableInPolyTime block encIn encUnary) + (hoverlap : ComputableInPolyTime overlap encIn encUnary) (hbudget : PolyBounded (fun x => (encIn x).length) fun x => 2 ^ seed x) : - ComputableTidilyInPolyTime (fun x => greedyMasks (seed x) (block x) (overlap x)) encIn + ComputableInPolyTime (fun x => greedyMasks (seed x) (block x) (overlap x)) encIn (encList encBits) := by + have hseed := hseed.tidy + have hblock := hblock.tidy + have hoverlap := hoverlap.tidy + refine .of_tidy ?_ unfold greedyMasks refine foldlWith_of_bounded_growth (encA := encBits) (par := fun x => (block x, overlap x)) (step := fun p kept w => greedyStep p.1 p.2 kept w) (growth := fun x => 2 * seed x + 1) @@ -238,16 +245,21 @@ theorem computableTidilyInPolyTime_greedyMasks {seed block overlap : γ → ℕ} space `O(T n)` on words of length `n`, for a monotone `T`. With computed block size `block x`, masks `masks x` and seed `seed x`, the generator on lists is polynomial-time in `x` when `T (block x)` is polynomially bounded. -/ -theorem computableTidilyInPolyTime_listGenerator {g : List Bool → Bool} {T : ℕ → ℕ} +theorem computableInPolyTime_listGenerator {g : List Bool → Bool} {T : ℕ → ℕ} (hT : Monotone T) - (hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length) + (hg : ComputableInO g encBits encBool (fun y => T y.length) fun y => T y.length) {block : γ → ℕ} {masks : γ → List (List Bool)} {seed : γ → List Bool} - (hblock : ComputableTidilyInPolyTime block encIn encUnary) - (hmasks : ComputableTidilyInPolyTime masks encIn (encList encBits)) - (hseed : ComputableTidilyInPolyTime seed encIn encBits) + (hblock : ComputableInPolyTime block encIn encUnary) + (hmasks : ComputableInPolyTime masks encIn (encList encBits)) + (hseed : ComputableInPolyTime seed encIn encBits) (hbudget : PolyBounded (fun x => (encIn x).length) fun x => T (block x)) : - ComputableTidilyInPolyTime (fun x => listGenerator g (block x) (masks x) (seed x)) encIn + ComputableInPolyTime (fun x => listGenerator g (block x) (masks x) (seed x)) encIn encBits := by + have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by simpa only [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] using hg + have hblock := hblock.tidy + have hmasks := hmasks.tidy + have hseed := hseed.tidy + refine .of_tidy ?_ have heval := hg.computableTidilyInPolyTime_take hT (hblock.comp (fst encIn encBits)) (hbudget.comp (PolyBounded.self.mono fun p => by simp [length_frame]; omega)) @@ -283,17 +295,24 @@ def nwDecider (V : α × List Bool → Bool) (g : List Bool → Bool) (seed bloc tidily computable within time and space `O(T n)` on words of length `n`, for a monotone `T`. With polynomial-time unary parameters, `nwDecider` is polynomial-time when `2 ^ seed x` and `T (block x)` are polynomially bounded in the length of the instance. -/ -theorem computableTidilyInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List Bool → Bool} +theorem computableInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List Bool → Bool} {T : ℕ → ℕ} {seed block overlap out : α → ℕ} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (hT : Monotone T) - (hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length) - (hseed : ComputableTidilyInPolyTime seed enc encUnary) - (hblock : ComputableTidilyInPolyTime block enc encUnary) - (hoverlap : ComputableTidilyInPolyTime overlap enc encUnary) - (hout : ComputableTidilyInPolyTime out enc encUnary) + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (hT : Monotone T) + (hg : ComputableInO g encBits encBool (fun y => T y.length) fun y => T y.length) + (hseed : ComputableInPolyTime seed enc encUnary) + (hblock : ComputableInPolyTime block enc encUnary) + (hoverlap : ComputableInPolyTime overlap enc encUnary) + (hout : ComputableInPolyTime out enc encUnary) (hseedBudget : PolyBounded (fun x => (enc x).length) fun x => 2 ^ seed x) (hblockBudget : PolyBounded (fun x => (enc x).length) fun x => T (block x)) : - ComputableTidilyInPolyTime (nwDecider V g seed block overlap out) enc encBool := by + ComputableInPolyTime (nwDecider V g seed block overlap out) enc encBool := by + have hV := hV.tidy + have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] using hg + have hseed := hseed.tidy + have hblock := hblock.tidy + have hoverlap := hoverlap.tidy + have hout := hout.tidy + refine .of_tidy ?_ have hfst : ∀ {u : α → ℕ}, PolyBounded (fun x => (enc x).length) u → PolyBounded (fun p : α × List Bool => (encPair enc encBits p).length) fun p => u p.1 := fun hu => hu.comp (PolyBounded.self.mono fun p => by simp [length_frame]; omega) @@ -301,11 +320,11 @@ theorem computableTidilyInPolyTime_nwDecider {V : α × List Bool → Bool} {g : (fun p : α × List Bool => (greedyMasks (seed p.1) (block p.1) (overlap p.1)).take (out p.1)) (encPair enc encBits) (encList encBits) := listTakeWithInput - (computableTidilyInPolyTime_greedyMasks (hseed.comp (fst enc encBits)) - (hblock.comp (fst enc encBits)) (hoverlap.comp (fst enc encBits)) (hfst hseedBudget)) + (computableInPolyTime_greedyMasks (.of_tidy (hseed.comp (fst enc encBits))) + (.of_tidy (hblock.comp (fst enc encBits))) (.of_tidy (hoverlap.comp (fst enc encBits))) (hfst hseedBudget)).tidy (hout.comp (fst enc encBits)) - have hgen := computableTidilyInPolyTime_listGenerator hT hg (hblock.comp (fst enc encBits)) - hmasks (snd enc encBits) (hfst hblockBudget) + have hgen := (computableInPolyTime_listGenerator hT (.of_tidy hg) (.of_tidy (hblock.comp (fst enc encBits))) + (.of_tidy hmasks) (.of_tidy (snd enc encBits)) (hfst hblockBudget)).tidy have hvote : ComputableTidilyInPolyTime (fun p : α × List Bool => V (p.1, listGenerator g (block p.1) ((greedyMasks (seed p.1) (block p.1) (overlap p.1)).take (out p.1)) p.2)) (encPair enc encBits) encBool := diff --git a/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean b/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean index 82c1fd420..05404a1a1 100644 --- a/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean +++ b/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean @@ -795,7 +795,7 @@ theorem PiP_three_subset_SigmaP_three_of_coBH_subset_BH {k : ℕ} {y | ∃ u₃ : List Bool, u₃.length = p₃.eval (enc y.1).length ∧ (!V (y.1, y.2 ++ u₃)) = true} have hE : E ∈ NP (encPair enc encBits) := mem_NP_setOf_exists_append (V := fun x => !V x) - (ComputableTidilyInPolyTime.bool_not.comp hV.tidy) p₃ + (.of_tidy (ComputableTidilyInPolyTime.bool_not.comp hV.tidy)) p₃ let m := p₁ + p₂ have hLk_compl : (kadinChain enc m E k)ᶜ ∈ BH (encPair enc encBits) k := h (compl_mem_coBH_iff.mpr (kadinChain_mem_BH hE k)) diff --git a/Complexity/Computability/Complexity/Classes/CeqP.lean b/Complexity/Computability/Complexity/Classes/CeqP.lean index d6a11a3f5..438fb60e0 100644 --- a/Complexity/Computability/Complexity/Classes/CeqP.lean +++ b/Complexity/Computability/Complexity/Classes/CeqP.lean @@ -104,7 +104,7 @@ theorem PolyTimeReducible.mem_CeqP {β : Type} {encB : β ↪ List Bool} {B : Se (h : PolyTimeReducible enc encB A B) (hB : B ∈ CeqP encB) : A ∈ CeqP enc := by obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, hf, hB⟩ := hB - exact ⟨f ∘ g, GapP.comp_mem hf hg.tidy, fun a => (hAB a).trans (hB (g a))⟩ + exact ⟨f ∘ g, GapP.comp_mem hf hg, fun a => (hAB a).trans (hB (g a))⟩ /-- The complement class coC=P. See [Fortnow, Classifications 4.8–4.9][Fortnow1997]. -/ def coCeqP (enc : α ↪ List Bool) : Set (Set α) := {A | Aᶜ ∈ CeqP enc} diff --git a/Complexity/Computability/Complexity/Classes/Constructible.lean b/Complexity/Computability/Complexity/Classes/Constructible.lean index f44c4b9e9..edd3df6d5 100644 --- a/Complexity/Computability/Complexity/Classes/Constructible.lean +++ b/Complexity/Computability/Complexity/Classes/Constructible.lean @@ -16,6 +16,8 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Pl import Complexity.Computability.Machines.Turing.MultiTape.Encodings.NatPower import Complexity.Computability.Machines.Turing.MultiTape.Universal.Compose import Cslib.Computability.Machines.Turing.MultiTape.Combinators.AlmostConstant +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Constructible resource bounds @@ -98,9 +100,10 @@ theorem TimeConstructible.computableTidilyInO {t : ℕ → ℕ} (ht : TimeConstr · exact (Nat.le_succ _).trans (Nat.le_mul_of_pos_left _ (by omega)) /-- A tidy computation of `t n` in binary within time `O(t n)` makes `t` time-constructible. -/ -theorem TimeConstructible.of_computableTidilyInO {t : ℕ → ℕ} {T S : List Bool → ℕ} {s : ℕ → ℕ} - (c : ℕ) (h : ComputableTidilyInO (fun x : List Bool => t x.length) encBits encNat T S) +theorem TimeConstructible.of_computableInO {t : ℕ → ℕ} {T S : List Bool → ℕ} {s : ℕ → ℕ} + (c : ℕ) (h : ComputableInO (fun x : List Bool => t x.length) encBits encNat T S) (hT : ∀ x, T x ≤ c * t x.length + c) (hS : ∀ x, S x ≤ s x.length) : TimeConstructible t := by + have h := h.tidy obtain ⟨k, hk, -⟩ := h refine ⟨k * (c + 1), fun n => k * (s n + 1), hk.computableInTimeAndSpace.mono (fun x => ?_) fun x => ?_⟩ @@ -113,9 +116,11 @@ theorem TimeConstructible.of_computableTidilyInO {t : ℕ → ℕ} {T S : List B · simp only [encBits_apply] exact Nat.mul_le_mul_left k (Nat.add_le_add_right (hS x) 1) +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `2 ^ n` is time-constructible: its binary digits are `n` zeros followed by a one. -/ theorem timeConstructible_two_pow : TimeConstructible (2 ^ ·) := - .of_computableTidilyInO 1 (ComputableTidilyInDegree.two_pow_length encBits).inO_one + TimeConstructible.of_computableInO 1 (ComputableTidilyInDegree.two_pow_length encBits).inO_one (s := fun n => n) (fun x => by simp only [encBits_apply] have := Nat.lt_two_pow_self (n := x.length) @@ -133,17 +138,18 @@ private theorem cube_add_le (u v : ℕ) : (u + v) ^ 3 ≤ 8 * (u ^ 3 + v ^ 3) := /-- If `f n` is computed in binary from words of length `n` within time `O((n + 1) * f n)` and `n ≤ f n`, then `(n + 1) * f n` is time-constructible: writing the length of the word in binary takes time `O(n ^ 2)`, and the product time polylogarithmic in the factors. -/ -theorem TimeConstructible.succ_mul_of_computableTidilyInO {f : ℕ → ℕ} {T : List Bool → ℕ} +theorem TimeConstructible.succ_mul_of_computableInO {f : ℕ → ℕ} {T : List Bool → ℕ} {S : ℕ → ℕ} (c : ℕ) - (hf : ComputableTidilyInO (fun x : List Bool => f x.length) encBits encNat T + (hf : ComputableInO (fun x : List Bool => f x.length) encBits encNat T fun x => S x.length) (hT : ∀ x, T x ≤ c * ((x.length + 1) * f x.length) + c) (hn : ∀ n, n ≤ f n) : TimeConstructible fun n => (n + 1) * f n := by + have hf : ComputableTidilyInO (fun x : List Bool => f x.length) encBits encNat T fun x => S x.length := by simpa only [computableInO_iff_computableTidilyInO] using hf have hlen := ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat have h := computableTidilyInDegree_mul.inO.comp (hlen.prod hf) obtain ⟨C, hC⟩ := exists_pow_length_encNat_le 3 obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 - refine .of_computableTidilyInO (150 * C + C₂ + c + 10) h (fun x => ?_) (s := fun n => + refine Complexity.TimeConstructible.of_computableInO (150 * C + C₂ + c + 10) h (fun x => ?_) (s := fun n => n + 1 + ((encNat n).length + 1) + S n + (2 * (encNat (n + 1)).length + 1 + (encNat (f n)).length + 1) ^ 3) fun x => ?_ · simp only [Function.comp_apply, length_encPair] @@ -185,15 +191,17 @@ theorem TimeConstructible.succ_mul_of_computableTidilyInO {f : ℕ → ℕ} {T : /-- If `f` is time-constructible and `n ≤ f n`, then so is `(n + 1) * f n`. -/ theorem TimeConstructible.succ_mul {f : ℕ → ℕ} (hf : TimeConstructible f) (hn : ∀ n, n ≤ f n) : TimeConstructible fun n => (n + 1) * f n := - succ_mul_of_computableTidilyInO 1 hf.computableTidilyInO (fun x => by + Complexity.TimeConstructible.succ_mul_of_computableInO 1 (.of_tidy hf.computableTidilyInO) (fun x => by have : f x.length ≤ (x.length + 1) * f x.length := Nat.le_mul_of_pos_left _ (by omega) omega) hn +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `(n + 1) ^ 2` is time-constructible. -/ theorem timeConstructible_succ_sq : TimeConstructible fun n => (n + 1) ^ 2 := by have hlen := ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 - have h := TimeConstructible.succ_mul_of_computableTidilyInO (f := fun n => n + 1) + have h := TimeConstructible.succ_mul_of_computableInO (f := fun n => n + 1) (S := fun n => n + 1 + ((encNat n).length + 1)) (C₂ + 2) hlen (fun x => by have := hC₂ x.length have e : (C₂ + 2) * ((x.length + 1) * (x.length + 1)) = @@ -248,9 +256,10 @@ theorem TimeConstructible.spaceConstructible {t : ℕ → ℕ} (ht : TimeConstru /-- A tidy computation of `s n` in binary within space `O(s n)` makes `s` space-constructible: it halts within a time bound of `n`, its number of configurations. -/ -theorem SpaceConstructible.of_computableTidilyInO {s : ℕ → ℕ} {T S : List Bool → ℕ} (c : ℕ) - (h : ComputableTidilyInO (fun x : List Bool => s x.length) encBits encNat T S) +theorem SpaceConstructible.of_computableInO {s : ℕ → ℕ} {T S : List Bool → ℕ} (c : ℕ) + (h : ComputableInO (fun x : List Bool => s x.length) encBits encNat T S) (hS : ∀ x, S x ≤ c * s x.length + c) : SpaceConstructible s := by + have h := h.tidy obtain ⟨k, hk, -⟩ := h obtain ⟨t, ht⟩ := ComputableInTimeAndSpace.exists_time_of_length (s := fun n => k * (c * s n + c + 1)) (hk.computableInTimeAndSpace.mono (fun _ => le_rfl) @@ -258,13 +267,17 @@ theorem SpaceConstructible.of_computableTidilyInO {s : ℕ → ℕ} {T S : List exact ⟨k * (c + 1), t, ComputableInTimeAndSpace.mono ht (fun _ => le_rfl) fun x => by dsimp only; nlinarith⟩ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `n` is space-constructible: count the length of the word in binary. -/ theorem spaceConstructible_id : SpaceConstructible fun n => n := - .of_computableTidilyInO 1 ComputableTidilyInO.lengthNat fun x => by omega + SpaceConstructible.of_computableInO 1 ComputableTidilyInO.lengthNat fun x => by omega +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `n + 1` is space-constructible. -/ theorem spaceConstructible_succ : SpaceConstructible fun n => n + 1 := - .of_computableTidilyInO 2 (ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat) + SpaceConstructible.of_computableInO 2 (ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat) fun x => by have := Universal.length_encNat_le x.length; omega /-- Constant bounds are space-constructible, in zero space. -/ diff --git a/Complexity/Computability/Complexity/Classes/Counting/Space.lean b/Complexity/Computability/Complexity/Classes/Counting/Space.lean index ed96daa68..54ef2e00d 100644 --- a/Complexity/Computability/Complexity/Classes/Counting/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Counting/Space.lean @@ -61,7 +61,7 @@ theorem PP_subset_PSPACE : PP enc ⊆ PSPACE enc := by ((ComputableTidilyInPolySpace.of_polyTime hpow).prod ((ComputableTidilyInPolySpace.of_polyTime hdouble).comp (SharpP.computableTidilyInPolySpace hf))) - exact mem_PSPACE_of_computableTidilyInPolySpace htest fun a => by simpa using hA a + exact mem_PSPACE_of_computableInPolySpace htest fun a => by simpa using hA a /-- Testing whether a fixed modulus divides a #P count is in polynomial space. A quotient has at most one more bit than the verifier's certificate length, even for moduli zero and one. -/ @@ -85,12 +85,12 @@ theorem coModP_subset_PSPACE (k : ℕ) : coModP k enc ⊆ PSPACE enc := by (hle.comp ((ComputableTidilyInPolySpace.of_polyTime hright).prod hleft))) have hB : {x : α × List Bool | f x.1 = k * ofBits x.2} ∈ PSPACE (encPair enc encBits) := - mem_PSPACE_of_computableTidilyInPolySpace htest fun x => by + mem_PSPACE_of_computableInPolySpace htest fun x => by simp only [Set.mem_ofPred_eq, Bool.and_eq_true, decide_eq_true_eq] exact le_antisymm_iff have hbound : ComputableTidilyInPolyTime (fun a => p.eval (enc a).length + 1) enc encUnary := by fun_prop - have h := setOf_exists_mem_PSPACE hB hbound + have h := setOf_exists_mem_PSPACE hB (.of_tidy hbound) convert h using 1 ext a rw [hA a] diff --git a/Complexity/Computability/Complexity/Classes/EXP.lean b/Complexity/Computability/Complexity/Classes/EXP.lean index 341523fa7..304bf7108 100644 --- a/Complexity/Computability/Complexity/Classes/EXP.lean +++ b/Complexity/Computability/Complexity/Classes/EXP.lean @@ -12,6 +12,7 @@ public import Complexity.Computability.Complexity.Classes.Time import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Quantitative import Complexity.Foundations.Data.Nat.PolynomialBound.Closure import Complexity.Foundations.Data.Nat.PolynomialBound.Exponential +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Exponential time @@ -34,7 +35,7 @@ is within `2 ^ n ^ 2` from `n = 4` on, and is not in `P` by the diagonal argumen hierarchy theorem [Arora and Barak, Theorem 3.1][AroraBarak09], [Sipser, Theorem 9.10][Sipser2013]. Polynomial-time computation on a bit word `y` paired with unary padding `2 ^ |y|` gives a problem -in `E` (`Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad`), by writing the padding +in `E` (`Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad`), by writing the padding in exponential time and applying the timed-reduction API. ## Main definitions @@ -51,7 +52,7 @@ in exponential time and applying the timed-reduction API. * `Cslib.Complexity.E_subset_NE`, `Cslib.Complexity.EXP_subset_NEXP`: determinism is a special case. * `Cslib.Complexity.P_ssubset_EXP`: polynomial time is strictly within exponential time. -* `Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad`: polynomial time on inputs +* `Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad`: polynomial time on inputs padded to length `2 ^ n` gives `E`. ## References @@ -151,7 +152,7 @@ theorem setOf_diagonal_mem_EXP : {x | diagonal x = true} ∈ EXP encBits := mem_EXP_iff.mpr ⟨2, DTIME_mono_of_eventually_le (t₁ := fun n => 2 ^ (4 * n)) (eventually_atTop.mpr ⟨4, fun n hn => Nat.pow_le_pow_right (by norm_num) (by nlinarith)⟩) - (setOf_mem_DTIME_of_computableTidilyInO computableTidilyInO_diagonal fun _ => le_rfl)⟩ + (setOf_mem_DTIME_of_computableInO computableInO_diagonal.tidy fun _ => le_rfl)⟩ /-- **Polynomial time is strictly within exponential time**, for problems on bit words: the diagonal problem is in `EXP` and not in `P` [Arora and Barak, Theorem 3.1][AroraBarak09]. -/ @@ -165,16 +166,17 @@ theorem P_ssubset_EXP : P encBits ⊂ EXP encBits := unary number, then the words `y` with `Ψ (y, 2 ^ |y|)` form a problem in `E`: the padding `y ↦ (y, 2 ^ |y|)` is written within time `O(4 ^ |y|)`, and the problem decided by `Ψ` is in `DTIME (n ↦ c (n + 1) ^ d)` (`preimage_mem_DTIME`). -/ -theorem setOf_mem_E_of_computableTidilyInPolyTime_pad {Ψ : List Bool × ℕ → Bool} - (hΨ : ComputableTidilyInPolyTime Ψ (encPair encBits encUnary) encBool) : +theorem setOf_mem_E_of_computableInPolyTime_pad {Ψ : List Bool × ℕ → Bool} + (hΨ : ComputableInPolyTime Ψ (encPair encBits encUnary) encBool) : {y : List Bool | Ψ (y, 2 ^ y.length) = true} ∈ E encBits := by + have hΨ := hΨ.tidy obtain ⟨t, s, ht, hs, h⟩ := hΨ obtain ⟨c, d, hcd⟩ := (ht.add hs).exists_le -- the problem decided by `Ψ`, within polynomial time have hB : {x | Ψ x = true} ∈ DTIME (encPair encBits encUnary) fun n => c * (n + 1) ^ d := - setOf_mem_DTIME_of_computableTidilyInO (T := fun x => t x + s x) (S := fun x => t x + s x) - (.of_bounds h 1 (fun _ => by omega) (fun _ => by omega) - fun x => (h.length_le x).trans (by omega)) hcd + setOf_mem_DTIME_of_computableInO (T := fun x => t x + s x) (S := fun x => t x + s x) + (.of_tidy (.of_bounds h 1 (fun _ => by omega) (fun _ => by omega) + fun x => (h.length_le x).trans (by omega))) hcd -- the padding `y ↦ (y, 2 ^ |y|)` have hgO : ComputableTidilyInO (fun y : List Bool => (y, 2 ^ y.length)) encBits (encPair encBits encUnary) (fun y => 3 * 4 ^ y.length) fun y => 3 * 4 ^ y.length := by diff --git a/Complexity/Computability/Complexity/Classes/FewP.lean b/Complexity/Computability/Complexity/Classes/FewP.lean index 8e83bc368..e95105e8d 100644 --- a/Complexity/Computability/Complexity/Classes/FewP.lean +++ b/Complexity/Computability/Complexity/Classes/FewP.lean @@ -59,14 +59,16 @@ def FewP (enc : α ↪ List Bool) : Set (Set α) := /-- A verifier characterization with a separate polynomial bound on its accepting count. -/ theorem mem_FewP : A ∈ FewP enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ q.eval (enc a).length) ∧ ∀ a, a ∈ A ↔ 0 < acceptCount V a (p.eval (enc a).length) := by - constructor - · rintro ⟨f, ⟨p, V, hV, hf⟩, q, hle, hA⟩ - exact ⟨p, q, V, hV.tidy, fun a => hf a ▸ hle a, fun a => by rw [hA a, hf a]⟩ - · rintro ⟨p, q, V, hV, hle, hA⟩ - exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, q, hle, hA⟩ + have this : A ∈ FewP enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ q.eval (enc a).length) ∧ ∀ a, a ∈ A ↔ 0 < acceptCount V a (p.eval (enc a).length) := by + constructor + · rintro ⟨f, ⟨p, V, hV, hf⟩, q, hle, hA⟩ + exact ⟨p, q, V, hV.tidy, fun a => hf a ▸ hle a, fun a => by rw [hA a, hf a]⟩ + · rintro ⟨p, q, V, hV, hle, hA⟩ + exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, q, hle, hA⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- A bound of one is a polynomial ambiguity bound. -/ theorem UP_subset_FewP : UP enc ⊆ FewP enc := by @@ -104,7 +106,7 @@ theorem PolyTimeReducible.mem_FewP {β : Type} {encB : β ↪ List Bool} {B : Se (ComputableTidilyInPolyTime.unary_eval p).comp ((ComputableTidilyInPolyTime.encoding_length encB).comp hg.tidy) obtain ⟨q, hle⟩ := hlen.polyBounded.exists_polynomial - exact ⟨f ∘ g, SharpP.comp_mem hf hg.tidy, q, + exact ⟨f ∘ g, SharpP.comp_mem hf hg, q, fun a => (hp (g a)).trans (hle a), fun a => (hAB a).trans (hB (g a))⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Hierarchy.lean index fce87bbce..7a218209c 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy.lean @@ -14,6 +14,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Universal.PolyT public import Complexity.Computability.Machines.Turing.MultiTape.Encodings.NatPower import Complexity.Computability.Machines.Turing.MultiTape.Plumbing.Tidy.Run import Complexity.Foundations.Data.Nat.PolynomialBound.Exponential +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # A decidable problem outside P @@ -27,7 +28,7 @@ exactly when the described machine has halted with output `[true]` by then. The hierarchy theorem in `Complexity.Computability.Complexity.Classes.Hierarchy.Time`. The diagonal is itself computed, by one fixed machine, within time `O(2 ^ (4 * n))` and space -`O(2 ^ (2 * n))` on inputs of length `n` (`Cslib.Complexity.computableTidilyInO_diagonal`). The +`O(2 ^ (2 * n))` on inputs of length `n` (`Cslib.Complexity.computableInO_diagonal`). The bound charges decoding, converting the input to symbols through the universal input-coding API, writing the clock `2 ^ n` in binary, the universal run and the final test. The universal run dominates, within time polynomial in `n` times @@ -50,7 +51,7 @@ an explicit exponential-time computation is not in `P`. No time-bounded classes ## Main results -* `Cslib.Complexity.computableTidilyInO_diagonal`: the diagonal in exponential time and space. +* `Cslib.Complexity.computableInO_diagonal`: the diagonal in exponential time and space. * `Cslib.Complexity.diagonal_notMem_P`: the diagonal problem is not in `P`. * `Cslib.Complexity.not_computableInTimeAndSpace_diagonal`: no plain machine computes the diagonal within a polynomial time bound. @@ -171,23 +172,25 @@ namespace Diagonal /-! ### The resources of the diagonal -/ /-- The test is within time quadratic and space linear in the encoded result. -/ -theorem computableTidilyInO_verdict : - ComputableTidilyInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) +theorem computableInO_verdict : + ComputableInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) fun r => (eOut r).length := by - have heq := (ComputableTidilyInO.eq (encList encUnary)).comp - ((ComputableTidilyInO.fst (encList encUnary) encBool).prod - (ComputableTidilyInO.const (encMid := encList encUnary) [eBit true])) - have hfin := (ComputableTidilyInDegree.of_finite (encIn := encPair encBool encBool) - (encMid := encBool) fun q : Bool × Bool => !(q.1 && q.2)).inO_one - refine (hfin.comp ((ComputableTidilyInO.snd (encList encUnary) encBool).prod heq)).mono 64 - (fun r => ?_) fun r => ?_ - all_goals - have h₁ := length_le_encPair_left (encList encUnary) encBool r - have h₂ : (encList encUnary [eBit true]).length = 3 := rfl - simp only [Function.comp_apply, length_encPair, encBool_apply, List.length_singleton, - h₂] at h₁ ⊢ - · nlinarith - · omega + have this : ComputableTidilyInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) fun r => (eOut r).length := by + have heq := (ComputableTidilyInO.eq (encList encUnary)).comp + ((ComputableTidilyInO.fst (encList encUnary) encBool).prod + (ComputableTidilyInO.const (encMid := encList encUnary) [eBit true])) + have hfin := (ComputableTidilyInDegree.of_finite (encIn := encPair encBool encBool) + (encMid := encBool) fun q : Bool × Bool => !(q.1 && q.2)).inO_one + refine (hfin.comp ((ComputableTidilyInO.snd (encList encUnary) encBool).prod heq)).mono 64 + (fun r => ?_) fun r => ?_ + all_goals + have h₁ := length_le_encPair_left (encList encUnary) encBool r + have h₂ : (encList encUnary [eBit true]).length = 3 := rfl + simp only [Function.comp_apply, length_encPair, encBool_apply, List.length_singleton, + h₂] at h₁ ⊢ + · nlinarith + · omega + simpa only [computableInO_iff_computableTidilyInO] using this /-- The numeric core of the resources of the diagonal: for an input of length `n`, a decoded description of encoded length `D`, encoded symbols of length `N`, a clock `J ≥ 1` and a result of @@ -257,57 +260,59 @@ open Diagonal in /-- **The diagonal is decidable in exponential time**, within time `O(2 ^ (4 * n))` and space `O(2 ^ (2 * n))` on inputs of length `n`, charging decoding, the symbols, the clock, the universal run and the test. -/ -theorem computableTidilyInO_diagonal : - ComputableTidilyInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) +theorem computableInO_diagonal : + ComputableInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) fun x => 2 ^ (2 * x.length) := by - obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc - have hu : ComputableTidilyInDegree unframe encBits encBits 1 1 := - .of_linear (.of_unframe fun _ => rfl) - have hdesc := (hdec.comp hu).inO - have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one - have hclock := (ComputableTidilyInDegree.two_pow_length encBits).inO_one - have hpre := hdesc.prod (hsym.prod hclock) - have hU := computableTidilyInO_universal.comp hpre - have h := computableTidilyInO_verdict.comp hU - -- the sizes of the decoded description and of the result - obtain ⟨cD, hcD⟩ := hdesc.length_le - obtain ⟨cO, hcO⟩ := hU.length_le - -- one power of two absorbs every polynomial factor - obtain ⟨C, hC⟩ := PolynomiallyBounded.exists_le_mul_two_pow - (p := fun n => (cD * ((n + 1) ^ max 1 (1 * dd) + 1) + (n + 1) ^ max 1 (1 * dd) + 4 * n + 2) ^ 5) - (by fun_prop) - set K := 100100 + 44100 * (cO + 1) ^ 2 with hK - have hbounds (x : List Bool) := by - have hL : (encNat (2 ^ x.length)).length = x.length + 1 := by - rw [encNat_two_pow, List.length_append, List.length_replicate, List.length_singleton] - have hN : (encList encUnary (x.map eBit)).length ≤ 3 * x.length := - (length_encList_le encUnary _ (b := 1) fun s hs => by - obtain ⟨b, -, rfl⟩ := List.mem_map.mp hs - cases b - · exact Nat.zero_le _ - · exact le_rfl).trans (by rw [List.length_map]; omega) - have hE := hcO x - simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at hE - exact bounds_aux - (I := (eIn (decodeDesc (unframe x), x.map eBit, 2 ^ x.length)).length) Nat.one_le_two_pow - (hcD x) hN hL (by rw [length_encPair, length_encPair]; rfl) rfl hK hE - refine h.mono (K * C) (fun x => ?_) fun x => ?_ - · obtain ⟨h₁, -⟩ := hbounds x - simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at h₁ ⊢ - have hJ4 : 2 ^ (4 * x.length) = 2 ^ x.length * (2 ^ x.length) ^ 3 := by - ring - have := hC x.length - calc _ ≤ K * (_ ^ 5 * (2 ^ x.length) ^ 3) := h₁ - _ ≤ K * (C * 2 ^ x.length * (2 ^ x.length) ^ 3) := - Nat.mul_le_mul_left _ (Nat.mul_le_mul_right _ this) - _ ≤ K * C * (2 ^ (4 * x.length) + 1) := by rw [hJ4]; nlinarith - · obtain ⟨-, h₂⟩ := hbounds x - simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at h₂ ⊢ - have hJ2 : 2 ^ (2 * x.length) = 2 ^ x.length * 2 ^ x.length := by rw [two_mul, pow_add] - have := hC x.length - calc _ ≤ K * (_ ^ 5 * 2 ^ x.length) := h₂ - _ ≤ K * (C * 2 ^ x.length * 2 ^ x.length) := - Nat.mul_le_mul_left _ (Nat.mul_le_mul_right _ this) - _ ≤ K * C * (2 ^ (2 * x.length) + 1) := by rw [hJ2]; nlinarith + have this : ComputableTidilyInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) fun x => 2 ^ (2 * x.length) := by + obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc + have hu : ComputableTidilyInDegree unframe encBits encBits 1 1 := + .of_linear (.of_unframe fun _ => rfl) + have hdesc := (hdec.comp hu).inO + have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one + have hclock := (ComputableTidilyInDegree.two_pow_length encBits).inO_one + have hpre := hdesc.prod (hsym.prod hclock) + have hU := computableTidilyInO_universal.comp hpre + have h := computableInO_verdict.tidy.comp hU + -- the sizes of the decoded description and of the result + obtain ⟨cD, hcD⟩ := hdesc.length_le + obtain ⟨cO, hcO⟩ := hU.length_le + -- one power of two absorbs every polynomial factor + obtain ⟨C, hC⟩ := PolynomiallyBounded.exists_le_mul_two_pow + (p := fun n => (cD * ((n + 1) ^ max 1 (1 * dd) + 1) + (n + 1) ^ max 1 (1 * dd) + 4 * n + 2) ^ 5) + (by fun_prop) + set K := 100100 + 44100 * (cO + 1) ^ 2 with hK + have hbounds (x : List Bool) := by + have hL : (encNat (2 ^ x.length)).length = x.length + 1 := by + rw [encNat_two_pow, List.length_append, List.length_replicate, List.length_singleton] + have hN : (encList encUnary (x.map eBit)).length ≤ 3 * x.length := + (length_encList_le encUnary _ (b := 1) fun s hs => by + obtain ⟨b, -, rfl⟩ := List.mem_map.mp hs + cases b + · exact Nat.zero_le _ + · exact le_rfl).trans (by rw [List.length_map]; omega) + have hE := hcO x + simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at hE + exact bounds_aux + (I := (eIn (decodeDesc (unframe x), x.map eBit, 2 ^ x.length)).length) Nat.one_le_two_pow + (hcD x) hN hL (by rw [length_encPair, length_encPair]; rfl) rfl hK hE + refine h.mono (K * C) (fun x => ?_) fun x => ?_ + · obtain ⟨h₁, -⟩ := hbounds x + simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at h₁ ⊢ + have hJ4 : 2 ^ (4 * x.length) = 2 ^ x.length * (2 ^ x.length) ^ 3 := by + ring + have := hC x.length + calc _ ≤ K * (_ ^ 5 * (2 ^ x.length) ^ 3) := h₁ + _ ≤ K * (C * 2 ^ x.length * (2 ^ x.length) ^ 3) := + Nat.mul_le_mul_left _ (Nat.mul_le_mul_right _ this) + _ ≤ K * C * (2 ^ (4 * x.length) + 1) := by rw [hJ4]; nlinarith + · obtain ⟨-, h₂⟩ := hbounds x + simp only [Function.comp_apply, encBits, Function.Embedding.refl_apply] at h₂ ⊢ + have hJ2 : 2 ^ (2 * x.length) = 2 ^ x.length * 2 ^ x.length := by rw [two_mul, pow_add] + have := hC x.length + calc _ ≤ K * (_ ^ 5 * 2 ^ x.length) := h₂ + _ ≤ K * (C * 2 ^ x.length * 2 ^ x.length) := + Nat.mul_le_mul_left _ (Nat.mul_le_mul_right _ this) + _ ≤ K * C * (2 ^ (2 * x.length) + 1) := by rw [hJ2]; nlinarith + simpa only [computableInO_iff_computableTidilyInO] using this end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean index 07d836459..cfaf9cbda 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean @@ -13,6 +13,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Quantitativ import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Frame import Complexity.Computability.Machines.Turing.MultiTape.Universal.Bound import Mathlib.Data.Nat.Size +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Short descriptions @@ -31,7 +32,7 @@ which is `O(|x|)`. Padded descriptions are short. * `Cslib.Complexity.Diagonal.shortDesc_eq_decide`: shortness compares the length of the description with the number of binary digits of the length of the word. -* `Cslib.Complexity.Diagonal.computableTidilyInO_shortDesc`: shortness is decided within quadratic +* `Cslib.Complexity.Diagonal.computableInO_shortDesc`: shortness is decided within quadratic time and linear space. ## References @@ -57,28 +58,30 @@ theorem shortDesc_eq_decide (x : List Bool) : exact decide_eq_decide.mpr (Nat.lt_size.symm.trans Nat.lt_iff_add_one_le) /-- Shortness is decided within quadratic time and linear space. -/ -theorem computableTidilyInO_shortDesc : - ComputableTidilyInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) +theorem computableInO_shortDesc : + ComputableInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) fun x => x.length + 1 := by - have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := - ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) - have ha := ComputableTidilyInDegree.unary_succ.inO_one.comp - (ComputableTidilyInO.lengthUnary.comp hu) - have hb := ComputableTidilyInO.lengthUnary.comp - (ComputableTidilyInO.lengthNat.of_enc_eq (encOut := encBits) - (g := fun x : List Bool => encNat x.length) fun _ => rfl) - have h := ComputableTidilyInO.unaryLe.comp (ha.prod hb) - refine (h.mono 64 (fun x => ?_) fun x => ?_).of_enc_eq fun x => ?_ - · have h₁ := length_unframe_le x - have h₂ := Universal.length_encNat_le x.length - simp only [Function.comp_apply, length_encPair, encUnary_apply, - List.length_replicate] at h₁ h₂ ⊢ - nlinarith - · have h₁ := length_unframe_le x - have h₂ := Universal.length_encNat_le x.length - simp only [Function.comp_apply, length_encPair, encUnary_apply, - List.length_replicate] at h₁ h₂ ⊢ - omega - · simp only [Function.comp_apply, shortDesc_eq_decide] + have this : ComputableTidilyInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) fun x => x.length + 1 := by + have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := + ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) + have ha := ComputableTidilyInDegree.unary_succ.inO_one.comp + (ComputableTidilyInO.lengthUnary.comp hu) + have hb := ComputableTidilyInO.lengthUnary.comp + (ComputableTidilyInO.lengthNat.of_enc_eq (encOut := encBits) + (g := fun x : List Bool => encNat x.length) fun _ => rfl) + have h := ComputableTidilyInO.unaryLe.comp (ha.prod hb) + refine (h.mono 64 (fun x => ?_) fun x => ?_).of_enc_eq fun x => ?_ + · have h₁ := length_unframe_le x + have h₂ := Universal.length_encNat_le x.length + simp only [Function.comp_apply, length_encPair, encUnary_apply, + List.length_replicate] at h₁ h₂ ⊢ + nlinarith + · have h₁ := length_unframe_le x + have h₂ := Universal.length_encNat_le x.length + simp only [Function.comp_apply, length_encPair, encUnary_apply, + List.length_replicate] at h₁ h₂ ⊢ + omega + · simp only [Function.comp_apply, shortDesc_eq_decide] + simpa only [computableInO_iff_computableTidilyInO] using this end Cslib.Complexity.Diagonal diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean index 9c82c73cd..a341d10c2 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean @@ -17,6 +17,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Universal.Space import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Constructible import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain import Complexity.Foundations.Data.Nat.PolynomialBound.Exponential +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The space hierarchy theorem @@ -35,7 +36,7 @@ the configurations of the simulation encoded within `G n` bits. It negates the v test at the end of each pass, within space linear in the description, the budget and the lengths of the clock and of `n` in binary (`Turing.MultiTapeTM.Universal.budgetSpace_le`). The diagonal also holds its input, to test shortness and to convert it to symbols, so it takes space -`O(n + G n)` (`Cslib.Complexity.computableTidilyInO_spaceDiagonal`) and decides a problem in +`O(n + G n)` (`Cslib.Complexity.computableInO_spaceDiagonal`) and decides a problem in `DSPACE G` when `n ≤ G n` (`Cslib.Complexity.setOf_spaceDiagonal_mem_DSPACE`). Let a machine decide the same problem within space `c₁ * f n + c₂`, where every `c * f n + c` is @@ -117,63 +118,65 @@ budget `G n` in unary, the clock `2 ^ G n` in binary, the budgeted universal run description is short, so decoding it takes space `O(n)`, and the budgeted universal run takes space linear in the description, the budget and the lengths of the clock and of `n` in binary (`Turing.MultiTapeTM.Universal.budgetSpace_le`). -/ -theorem computableTidilyInO_spaceDiagonal {G : ℕ → ℕ} (hG : SpaceConstructible G) : - ∃ T, ComputableTidilyInO (spaceDiagonal G) encBits encBool T +theorem computableInO_spaceDiagonal {G : ℕ → ℕ} (hG : SpaceConstructible G) : + ∃ T, ComputableInO (spaceDiagonal G) encBits encBool T fun x => x.length + G x.length := by - obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc - have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := - ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) - have hdesc := hdec.inO.comp hu - have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one - obtain ⟨TG, hGb⟩ := hG.computableTidilyInO - have hGu := ComputableTidilyInO.natToUnary.comp hGb - have hclock := ((ComputableTidilyInDegree.two_pow_length encUnary).inO_one.comp_linear - hGu).of_enc_eq (encOut := encNat) (g := fun x : List Bool => 2 ^ G x.length) fun x => by - simp only [Function.comp_apply, encUnary_apply, List.length_replicate] - have hU := computableTidilyInO_budgetedUniversal.comp (hdesc.prod (hsym.prod (hclock.prod hGu))) - have h := computableTidilyInO_shortDesc.ite (computableTidilyInO_verdict.comp hU) - (ComputableTidilyInO.const (encMid := encBool) false) - obtain ⟨cD, hcD⟩ := hdesc.length_le - obtain ⟨cA, hcA⟩ := PolynomiallyBounded.exists_le_mul_two_pow (p := fun u => (u + 1) ^ dd) - (by fun_prop) - refine exists_computableTidilyInO_of_space h (300 * (cD + 1) * (cA + 1) + 300) - fun x => ?_ - dsimp only [Function.comp_apply, encBits_apply] - have hK : ∀ m, 2 * m ≤ (300 * (cD + 1) * (cA + 1) + 300) * m := fun m => - Nat.mul_le_mul_right _ (by omega) - split_ifs with hs - · have hA : ((unframe x).length + 1) ^ dd ≤ cA * x.length := - (hcA _).trans (Nat.mul_le_mul_left _ (of_decide_eq_true hs)) - have hD := hcD x - have hB := budgetSpace_le (decodeDesc (unframe x)) (x.map eBit) (G x.length) (2 ^ G x.length) - have hO := length_eOut_budgetedUniversal_le (decodeDesc (unframe x)) (x.map eBit) (G x.length) - (2 ^ G x.length) - have hclk : (encNat (2 ^ G x.length)).length = G x.length + 1 := by - rw [encNat_two_pow, List.length_append, List.length_replicate, List.length_singleton] - have hlen : (encNat ((x.map eBit).length + 1)).length ≤ x.length + 1 := by - rw [List.length_map]; exact Universal.length_encNat_le _ - have hmax : (x.map eBit).foldr max 0 ≤ 1 := listMax_le fun b _ => by cases b <;> decide - simp only [descLen, Function.comp_apply, encBits_apply] at hB hD - have e₁ : cD * (x.length + ((unframe x).length + 1) ^ dd + 1) ≤ - cD * (x.length + cA * x.length + 1) := Nat.mul_le_mul_left _ (by omega) - have e₂ : cD * (x.length + cA * x.length + 1) + cA * x.length ≤ - (cD + 1) * (cA + 1) * (x.length + G x.length + 1) := by - have : (cD + 1) * (cA + 1) * (x.length + G x.length + 1) = - cD * (x.length + cA * x.length + 1) + cA * x.length + (cD * cA * G x.length + cD * cA + - cD * G x.length + cA * G x.length + cA + x.length + G x.length + 1) := by ring + have this : ∃ T, ComputableTidilyInO (spaceDiagonal G) encBits encBool T fun x => x.length + G x.length := by + obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc + have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := + ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) + have hdesc := hdec.inO.comp hu + have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one + obtain ⟨TG, hGb⟩ := hG.computableTidilyInO + have hGu := ComputableTidilyInO.natToUnary.comp hGb + have hclock := ((ComputableTidilyInDegree.two_pow_length encUnary).inO_one.comp_linear + hGu).of_enc_eq (encOut := encNat) (g := fun x : List Bool => 2 ^ G x.length) fun x => by + simp only [Function.comp_apply, encUnary_apply, List.length_replicate] + have hU := computableTidilyInO_budgetedUniversal.comp (hdesc.prod (hsym.prod (hclock.prod hGu))) + have h := computableInO_shortDesc.tidy.ite (computableInO_verdict.tidy.comp hU) + (ComputableTidilyInO.const (encMid := encBool) false) + obtain ⟨cD, hcD⟩ := hdesc.length_le + obtain ⟨cA, hcA⟩ := PolynomiallyBounded.exists_le_mul_two_pow (p := fun u => (u + 1) ^ dd) + (by fun_prop) + refine exists_computableTidilyInO_of_space h (300 * (cD + 1) * (cA + 1) + 300) + fun x => ?_ + dsimp only [Function.comp_apply, encBits_apply] + have hK : ∀ m, 2 * m ≤ (300 * (cD + 1) * (cA + 1) + 300) * m := fun m => + Nat.mul_le_mul_right _ (by omega) + split_ifs with hs + · have hA : ((unframe x).length + 1) ^ dd ≤ cA * x.length := + (hcA _).trans (Nat.mul_le_mul_left _ (of_decide_eq_true hs)) + have hD := hcD x + have hB := budgetSpace_le (decodeDesc (unframe x)) (x.map eBit) (G x.length) (2 ^ G x.length) + have hO := length_eOut_budgetedUniversal_le (decodeDesc (unframe x)) (x.map eBit) (G x.length) + (2 ^ G x.length) + have hclk : (encNat (2 ^ G x.length)).length = G x.length + 1 := by + rw [encNat_two_pow, List.length_append, List.length_replicate, List.length_singleton] + have hlen : (encNat ((x.map eBit).length + 1)).length ≤ x.length + 1 := by + rw [List.length_map]; exact Universal.length_encNat_le _ + have hmax : (x.map eBit).foldr max 0 ≤ 1 := listMax_le fun b _ => by cases b <;> decide + simp only [descLen, Function.comp_apply, encBits_apply] at hB hD + have e₁ : cD * (x.length + ((unframe x).length + 1) ^ dd + 1) ≤ + cD * (x.length + cA * x.length + 1) := Nat.mul_le_mul_left _ (by omega) + have e₂ : cD * (x.length + cA * x.length + 1) + cA * x.length ≤ + (cD + 1) * (cA + 1) * (x.length + G x.length + 1) := by + have : (cD + 1) * (cA + 1) * (x.length + G x.length + 1) = + cD * (x.length + cA * x.length + 1) + cA * x.length + (cD * cA * G x.length + cD * cA + + cD * G x.length + cA * G x.length + cA + x.length + G x.length + 1) := by ring + omega + have e₃ : (300 * (cD + 1) * (cA + 1) + 300) * (x.length + G x.length + 1) = + 300 * ((cD + 1) * (cA + 1) * (x.length + G x.length + 1)) + + 300 * (x.length + G x.length + 1) := by ring omega - have e₃ : (300 * (cD + 1) * (cA + 1) + 300) * (x.length + G x.length + 1) = - 300 * ((cD + 1) * (cA + 1) * (x.length + G x.length + 1)) + - 300 * (x.length + G x.length + 1) := by ring - omega - · have := hK (x.length + G x.length + 1) - omega + · have := hK (x.length + G x.length + 1) + omega + simpa only [computableInO_iff_computableTidilyInO] using this /-- **The diagonal within space `G` decides a problem in `DSPACE G`**, for a space-constructible `G` with `n ≤ G n`. -/ theorem setOf_spaceDiagonal_mem_DSPACE {G : ℕ → ℕ} (hG : SpaceConstructible G) (hn : ∀ n, n ≤ G n) : {x | spaceDiagonal G x = true} ∈ DSPACE encBits G := by - obtain ⟨T, c, hc, -⟩ := computableTidilyInO_spaceDiagonal hG + obtain ⟨T, c, hc, -⟩ := computableInO_spaceDiagonal hG refine mem_DSPACE_iff.mpr ⟨2 * c, 2 * c, _, decidableInTimeAndSpace_iff.mpr ⟨spaceDiagonal G, hc.computableInTimeAndSpace.mono (fun _ => le_rfl) fun x => ?_, fun x => Iff.rfl⟩⟩ diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean index 94f975cd4..0b624b6bc 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean @@ -15,6 +15,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Run import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Constructible import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain import Complexity.Foundations.Data.Nat.PolynomialBound.Exponential +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The time hierarchy theorem @@ -221,64 +222,66 @@ open Diagonal in and space `O((n + 1) ^ 5 * (J n + 1) ^ 3)` on inputs of length `n`, for a time-constructible clock `J`, charging the shortness test, decoding, the symbols, the clock, the universal run and the test. -/ -theorem computableTidilyInO_timeDiagonal {J : ℕ → ℕ} (hJ : TimeConstructible J) : - ComputableTidilyInO (timeDiagonal J) encBits encBool +theorem computableInO_timeDiagonal {J : ℕ → ℕ} (hJ : TimeConstructible J) : + ComputableInO (timeDiagonal J) encBits encBool (fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3) fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := by - obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc - have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := - ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) - have hdesc := hdec.inO.comp hu - have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one - have hclock := hJ.computableTidilyInO - have hU := computableTidilyInO_universal.comp (hdesc.prod (hsym.prod hclock)) - have h := computableTidilyInO_shortDesc.ite (computableTidilyInO_verdict.comp hU) - (ComputableTidilyInO.const (encMid := encBool) false) - obtain ⟨cD, hcD⟩ := hdesc.length_le - obtain ⟨cO, hcO⟩ := hU.length_le - obtain ⟨cA, hcA⟩ := PolynomiallyBounded.exists_le_mul_two_pow (p := fun u => (u + 1) ^ dd) - (by fun_prop) - obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 - obtain ⟨K, hK⟩ := clockedBounds_aux cA cD cO C₂ - have hbounds (x : List Bool) (hs : shortDesc x = true) := by - have hA : ((unframe x).length + 1) ^ dd ≤ cA * (x.length + 1) := - (hcA _).trans (Nat.mul_le_mul_left _ ((of_decide_eq_true hs).trans (Nat.le_succ _))) - have hN : (encList encUnary (x.map eBit)).length ≤ 3 * x.length := - (length_encList_le encUnary _ (b := 1) fun s hs => by - obtain ⟨b, -, rfl⟩ := List.mem_map.mp hs - cases b - · exact Nat.zero_le _ - · exact le_rfl).trans (by rw [List.length_map]; omega) - have hD := hcD x - have hE := hcO x - dsimp only [Function.comp_apply, encBits_apply] at hD hE - exact hK (D := descLen (decodeDesc (unframe x))) hA hD hN (hC₂ _) - (by rw [length_encPair, length_encPair]) hE - have hW (x : List Bool) : x.length + 1 ≤ (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := - (Nat.le_self_pow (by norm_num) _).trans (Nat.le_mul_of_pos_right _ (Nat.pow_pos (by omega))) - have hW2 (x : List Bool) : (x.length + 1) ^ 2 ≤ (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := - (Nat.pow_le_pow_right (by omega) (by omega)).trans - (Nat.le_mul_of_pos_right _ (Nat.pow_pos (by omega))) - refine h.mono (K + 2) (fun x => ?_) fun x => ?_ - · have e : (K + 2) * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3 + 1) = - K * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + - 2 * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + K + 2 := by ring - have := hW x - have := hW2 x - dsimp only [Function.comp_apply, encBits_apply] - split_ifs with hs - · have := (hbounds x hs).1 - omega - · omega - · have e : (K + 2) * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3 + 1) = - K * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + - 2 * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + K + 2 := by ring - have := hW x - dsimp only [Function.comp_apply, encBits_apply] - split_ifs with hs - · have := (hbounds x hs).2 - omega - · omega + have this : ComputableTidilyInO (timeDiagonal J) encBits encBool (fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3) fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := by + obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc + have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := + ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) + have hdesc := hdec.inO.comp hu + have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one + have hclock := hJ.computableTidilyInO + have hU := computableTidilyInO_universal.comp (hdesc.prod (hsym.prod hclock)) + have h := computableInO_shortDesc.tidy.ite (computableInO_verdict.tidy.comp hU) + (ComputableTidilyInO.const (encMid := encBool) false) + obtain ⟨cD, hcD⟩ := hdesc.length_le + obtain ⟨cO, hcO⟩ := hU.length_le + obtain ⟨cA, hcA⟩ := PolynomiallyBounded.exists_le_mul_two_pow (p := fun u => (u + 1) ^ dd) + (by fun_prop) + obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 + obtain ⟨K, hK⟩ := clockedBounds_aux cA cD cO C₂ + have hbounds (x : List Bool) (hs : shortDesc x = true) := by + have hA : ((unframe x).length + 1) ^ dd ≤ cA * (x.length + 1) := + (hcA _).trans (Nat.mul_le_mul_left _ ((of_decide_eq_true hs).trans (Nat.le_succ _))) + have hN : (encList encUnary (x.map eBit)).length ≤ 3 * x.length := + (length_encList_le encUnary _ (b := 1) fun s hs => by + obtain ⟨b, -, rfl⟩ := List.mem_map.mp hs + cases b + · exact Nat.zero_le _ + · exact le_rfl).trans (by rw [List.length_map]; omega) + have hD := hcD x + have hE := hcO x + dsimp only [Function.comp_apply, encBits_apply] at hD hE + exact hK (D := descLen (decodeDesc (unframe x))) hA hD hN (hC₂ _) + (by rw [length_encPair, length_encPair]) hE + have hW (x : List Bool) : x.length + 1 ≤ (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := + (Nat.le_self_pow (by norm_num) _).trans (Nat.le_mul_of_pos_right _ (Nat.pow_pos (by omega))) + have hW2 (x : List Bool) : (x.length + 1) ^ 2 ≤ (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := + (Nat.pow_le_pow_right (by omega) (by omega)).trans + (Nat.le_mul_of_pos_right _ (Nat.pow_pos (by omega))) + refine h.mono (K + 2) (fun x => ?_) fun x => ?_ + · have e : (K + 2) * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3 + 1) = + K * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + + 2 * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + K + 2 := by ring + have := hW x + have := hW2 x + dsimp only [Function.comp_apply, encBits_apply] + split_ifs with hs + · have := (hbounds x hs).1 + omega + · omega + · have e : (K + 2) * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3 + 1) = + K * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + + 2 * ((x.length + 1) ^ 5 * (J x.length + 1) ^ 3) + K + 2 := by ring + have := hW x + dsimp only [Function.comp_apply, encBits_apply] + split_ifs with hs + · have := (hbounds x hs).2 + omega + · omega + simpa only [computableInO_iff_computableTidilyInO] using this /-- **The diagonal argument for time.** The problem of the clocked diagonal is not decidable within time `O(f)` when every `c * f n + c` is eventually below the clock: on its own description, padded @@ -322,7 +325,7 @@ theorem setOf_timeDiagonal_notMem_DTIME {f J : ℕ → ℕ} `O((n + 1) ^ 5 * (J n + 1) ^ 3)`. -/ theorem setOf_timeDiagonal_mem_DTIME {J : ℕ → ℕ} (hJ : TimeConstructible J) : {x | timeDiagonal J x = true} ∈ DTIME encBits fun n => (n + 1) ^ 5 * (J n + 1) ^ 3 := - setOf_mem_DTIME_of_computableTidilyInO (computableTidilyInO_timeDiagonal hJ) + setOf_mem_DTIME_of_computableInO (computableInO_timeDiagonal hJ).tidy (t := fun n => (n + 1) ^ 5 * (J n + 1) ^ 3) fun _ => le_rfl /-! ### The time hierarchy theorem -/ diff --git a/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean b/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean index a6dc9d341..61725eafb 100644 --- a/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean +++ b/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean @@ -255,29 +255,33 @@ private theorem natGetD {γ : Type} {input : γ ↪ List Bool} {list : γ → Li (listGetD (encA := encUnary) 0).comp (hlist.prod hindex) @[fun_prop] -theorem computableTidilyInPolyTime_rankOf {γ : Type} {input : γ ↪ List Bool} {n i : γ → ℕ} - {keys : γ → List ℕ} (hn : ComputableTidilyInPolyTime n input encUnary) - (hkeys : ComputableTidilyInPolyTime keys input (encList encUnary)) - (hi : ComputableTidilyInPolyTime i input encUnary) : - ComputableTidilyInPolyTime (fun x => rankOf (n x) (keys x) (i x)) input encUnary := by +theorem computableInPolyTime_rankOf {γ : Type} {input : γ ↪ List Bool} {n i : γ → ℕ} + {keys : γ → List ℕ} (hn : ComputableInPolyTime n input encUnary) + (hkeys : ComputableInPolyTime keys input (encList encUnary)) + (hi : ComputableInPolyTime i input encUnary) : + ComputableInPolyTime (fun x => rankOf (n x) (keys x) (i x)) input encUnary := by + have hn := hn.tidy + have hkeys := hkeys.tidy + have hi := hi.tidy + refine .of_tidy ?_ unfold rankOf fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_orderOf {γ : Type} {input : γ ↪ List Bool} {n : γ → ℕ} - {keys : γ → List ℕ} (hn : ComputableTidilyInPolyTime n input encUnary) - (hkeys : ComputableTidilyInPolyTime keys input (encList encUnary)) : - ComputableTidilyInPolyTime (fun x => orderOf (n x) (keys x)) input (encList encUnary) := by +theorem computableInPolyTime_orderOf {γ : Type} {input : γ ↪ List Bool} {n : γ → ℕ} + {keys : γ → List ℕ} (hn : ComputableInPolyTime n input encUnary) + (hkeys : ComputableInPolyTime keys input (encList encUnary)) : + ComputableInPolyTime (fun x => orderOf (n x) (keys x)) input (encList encUnary) := by unfold orderOf fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_relabel {γ : Type} {input : γ ↪ List Bool} {G : γ → Graph} - {keys : γ → List ℕ} (hG : ComputableTidilyInPolyTime G input encGraph) - (hkeys : ComputableTidilyInPolyTime keys input (encList encUnary)) : - ComputableTidilyInPolyTime (fun x => relabel (G x) (keys x)) input encBits := by - have hn : ComputableTidilyInPolyTime (fun x => (G x).distinctVertices.length) input encUnary := - (length_list encNat).comp (Graph.computableTidilyInPolyTime_distinctVertices.comp hG) +theorem computableInPolyTime_relabel {γ : Type} {input : γ ↪ List Bool} {G : γ → Graph} + {keys : γ → List ℕ} (hG : ComputableInPolyTime G input encGraph) + (hkeys : ComputableInPolyTime keys input (encList encUnary)) : + ComputableInPolyTime (fun x => relabel (G x) (keys x)) input encBits := by + have hn : ComputableInPolyTime (fun x => (G x).distinctVertices.length) input encUnary := + (ComputableInPolyTime.length_list encNat).comp (Graph.computableInPolyTime_distinctVertices.comp hG) unfold relabel simp only [List.flatMap_def] fun_prop @@ -552,7 +556,7 @@ private theorem isPPTOn_relabelMessage {γ : Type} {input : γ ↪ List Bool} {G (hG : ComputableTidilyInPolyTime G input encGraph) : IsPPTOn input encBits (fun x => relabelMessage (G x)) := by have hn : ComputableTidilyInPolyTime (fun x => (G x).distinctVertices.length) input encUnary := - (length_list encNat).comp (Graph.computableTidilyInPolyTime_distinctVertices.comp hG) + (length_list encNat).comp (Graph.computableInPolyTime_distinctVertices.tidy.comp hG) have hsize : ComputableTidilyInPolyTime (fun x => 16 * (G x).distinctVertices.length * (G x).distinctVertices.length) input encUnary := by fun_prop have hw : ComputableTidilyInPolyTime (fun x => keyWidth (G x).distinctVertices.length) input @@ -570,7 +574,7 @@ private theorem isPPTOn_relabelMessage {γ : Type} {input : γ ↪ List Bool} {G (fst (encPair input encBits) encBits))) (snd (encPair input encBits) encBits)) exact IsPPTOn.map_with (f := fun x bits => relabel (G x) (keysOf (G x).distinctVertices.length (keyWidth (G x).distinctVertices.length) bits)) hcount.sampleList - (.of_tidy (computableTidilyInPolyTime_relabel (hG.comp (fst input encBits)) hkeys)) + (computableInPolyTime_relabel (.of_tidy (hG.comp (fst input encBits))) (.of_tidy hkeys)) /-- The verifier is strict oracle PPT. -/ theorem isOraclePPTOn_verifier : diff --git a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean index 1b5c4668e..4ec457ad9 100644 --- a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean +++ b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean @@ -17,6 +17,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Na import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Option import Complexity.Computability.Machines.Turing.MultiTape.Encodings.NatPower +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # `IP ⊆ PSPACE` @@ -48,7 +49,7 @@ values: (`Cslib.Complexity.Interaction.image_decodeWord_iterate_firstCode`, `Cslib.Complexity.Interaction.gameTree_value_eq`). Its leaf values count the accepting coin values, within polynomial space - (`Cslib.Complexity.Interaction.computableTidilyInPolySpace_countAccepts`). + (`Cslib.Complexity.Interaction.computableInPolySpace_countAccepts`). * The explicit-stack evaluator of the game tree (`Cslib.Complexity.Interaction.evaluate`) runs for `2 ^ ((t + 1) * (2 * t + 1))` steps, with at most `t` frames of `O(t)` bits each (`Cslib.Complexity.Interaction.length_encEvalState_iterate_le`), so it computes `W` within @@ -460,7 +461,7 @@ private theorem computableTidilyInPolySpace_leaf [Finite Control] : ComputableTidilyInPolySpace (fun s : EvalState α => min (2 ^ fuel s.1) (leafValue (coinFamily M (fuel s.1) (enc s.1)) (GameTree.history s.2.1))) (encEvalState enc) encNat := by - have hcount := computableTidilyInPolySpace_countAccepts M enc fuel hfuel + have hcount := (computableInPolySpace_countAccepts M enc fuel (.of_tidy hfuel)).tidy have hdec := computableTidilyInPolyTime_decodeHistory have harg : ComputableTidilyInPolyTime (fun s : EvalState α => (s.1, decodeHistory (GameTree.history s.2.1))) (encEvalState enc) @@ -644,7 +645,7 @@ theorem IP_subset_PSPACE (enc : α ↪ List Bool) : IP enc ⊆ PSPACE enc := by exact (ComputableTidilyInPolySpace.of_polyTime hpost).comp ((ComputableTidilyInPolySpace.of_polyTime hcap).prod (computableTidilyInPolySpace_evaluate M hfuel)) - refine mem_PSPACE_of_computableTidilyInPolySpace hdec fun a => ?_ + refine mem_PSPACE_of_computableInPolySpace hdec fun a => ?_ rw [mem_iff_two_pow_lt_value (fun a S oracle s => hreal a S oracle s) hA a, evaluate_eq, decide_eq_true_iff] diff --git a/Complexity/Computability/Complexity/Classes/IP/Simulation.lean b/Complexity/Computability/Complexity/Classes/IP/Simulation.lean index a58f9c0b7..66ca545fa 100644 --- a/Complexity/Computability/Complexity/Classes/IP/Simulation.lean +++ b/Complexity/Computability/Complexity/Classes/IP/Simulation.lean @@ -19,6 +19,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Fo import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Foundations.Data.Nat.PolynomialBound.Closure +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Counting the accepting coins in polynomial space @@ -30,7 +31,7 @@ history, and in exponential time. * A replay keeping only whether it is still live (`Cslib.Complexity.Interaction.aliveStep`) decides whether the program of given coins accepts after a history (`Cslib.Complexity.Interaction.accepts_eq_true_iff`), in polynomial time - (`Cslib.Complexity.Interaction.computableTidilyInPolyTime_accepts`): it folds one instruction per + (`Cslib.Complexity.Interaction.computableInPolyTime_accepts`): it folds one instruction per coin over the configuration of the machine, whose storage grows by a bounded amount per instruction. * The coin values are enumerated by the binary counter of the shared streaming count @@ -38,7 +39,7 @@ history, and in exponential time. (`Cslib.Complexity.Interaction.countAccepts`, `Cslib.Complexity.Interaction.countAccepts_eq_accepted`), within polynomial space (`Turing.MultiTapeTM.ComputableTidilyInPolySpace`, - `Cslib.Complexity.Interaction.computableTidilyInPolySpace_countAccepts`). + `Cslib.Complexity.Interaction.computableInPolySpace_countAccepts`). ## Main definitions @@ -47,9 +48,9 @@ history, and in exponential time. ## Main results -* `Cslib.Complexity.Interaction.computableTidilyInPolyTime_accepts`: acceptance in polynomial time. +* `Cslib.Complexity.Interaction.computableInPolyTime_accepts`: acceptance in polynomial time. * `Cslib.Complexity.Interaction.countAccepts_eq_accepted`: the count of accepting coin values. -* `Cslib.Complexity.Interaction.computableTidilyInPolySpace_countAccepts`: the count in polynomial +* `Cslib.Complexity.Interaction.computableInPolySpace_countAccepts`: the count in polynomial space. ## References @@ -373,10 +374,11 @@ private theorem computableTidilyInPolyTime_aliveRun : omit [Fintype Operation] in include hmatch hpair in /-- **Acceptance is polynomial-time** in the input, the coins and the history. -/ -theorem computableTidilyInPolyTime_accepts [Finite Operation] : - ComputableTidilyInPolyTime (fun p : List Bool × List Bool × List Entry => +theorem computableInPolyTime_accepts [Finite Operation] : + Turing.MultiTapeTM.ComputableInPolyTime (fun p : List Bool × List Bool × List Entry => accepts matchOp entryPair M p.1 p.2.1 p.2.2) (encPair encBits (encPair encBits (encList encEntry))) encBool := by + refine .of_tidy ?_ cases nonempty_fintype Operation have h := computableTidilyInPolyTime_aliveRun matchOp entryPair M (encEntry := encEntry) hmatch hpair @@ -408,20 +410,22 @@ theorem countAccepts_eq_accepted (q : α × History) : /-- **The count of accepting coins within polynomial space**, in the input and the history, for a number of coins computed in polynomial time. -/ -theorem computableTidilyInPolySpace_countAccepts [Finite Control] - (hfuel : ComputableTidilyInPolyTime fuel enc encUnary) : - ComputableTidilyInPolySpace (countAccepts MUnit enc fuel) (encPair enc encHistory) encNat := by +theorem computableInPolySpace_countAccepts [Finite Control] + (hfuel : Turing.MultiTapeTM.ComputableInPolyTime fuel enc encUnary) : + Turing.MultiTapeTM.ComputableInPolySpace (countAccepts MUnit enc fuel) (encPair enc encHistory) encNat := by + have hfuel := hfuel.tidy + refine .of_tidy ?_ have hfuel' : ComputableTidilyInPolyTime (fun q : α × History => fuel q.1) (encPair enc encHistory) encUnary := hfuel.comp (ComputableTidilyInPolyTime.fst _ _) - have hacc := computableTidilyInPolyTime_accepts (fun _ _ => true) id MUnit + have hacc := (computableInPolyTime_accepts (fun _ _ => true) id MUnit (encEntry := encPair encBits encBits) (fun _ => .of_tidy (ComputableTidilyInPolyTime.const true)) - (.of_tidy ComputableTidilyInPolyTime.id') + (.of_tidy ComputableTidilyInPolyTime.id')).tidy have hverify : ComputableTidilyInPolyTime (fun p : (α × History) × List Bool => accepts (fun _ _ => true) id MUnit (enc p.1.1) p.2 p.1.2) (encPair (encPair enc encHistory) encBits) encBool := by fun_prop - exact (computableTidilyInPolySpace_acceptCount hverify hfuel').congr fun q => + exact (computableInPolySpace_acceptCount (.of_tidy hverify) (.of_tidy hfuel')).tidy.congr fun q => (streamAcceptCount_eq_acceptCount _ q _).symm end Count diff --git a/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean b/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean index fb9d86387..c52221d0c 100644 --- a/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean +++ b/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean @@ -314,7 +314,7 @@ private lemma opCont_pt (o : ArithQBF.Operator) : unfold opCont have hsample : IsOraclePPTOn (Operation := Unit) (encPair encStepData encBits) encUnary (fun pair : StepData × List Bool => ProbOracleComp.sample (sampleMod pair.1.modulus)) := - (isPPTOn_sampleMod (by fun_prop)).isOraclePPTOn + (isPPTOn_sampleMod (.of_tidy (by fun_prop))).isOraclePPTOn exact IsOraclePPTOn.cond (opCheck_pt o) (hsample.map_with opNext_pt) ((ComputableTidilyInPolyTime.isOraclePPTOn (f := fun pair : StepData × List Bool => reject pair.1) (by fun_prop))) @@ -574,7 +574,7 @@ private lemma loopInput_pt : ComputableTidilyInPolyTime loopInput encQBF encLoop realizes it against every stateful prover. -/ theorem isOraclePPTOn_verifier : IsOraclePPTOn encQBF encBool verifier := by unfold verifier - exact IsOraclePPTOn.cond computableTidilyInPolyTime_decide_closed + exact IsOraclePPTOn.cond computableInPolyTime_decide_closed.tidy ((isOraclePPTOn_loop.preprocess loopInput_pt).map (by fun_prop)) (ComputableTidilyInPolyTime.isOraclePPTOn (f := fun _ : QBF ℕ => false) (const false)) diff --git a/Complexity/Computability/Complexity/Classes/IP/TQBF/Words.lean b/Complexity/Computability/Complexity/Classes/IP/TQBF/Words.lean index a3fb98144..de2ebf11f 100644 --- a/Complexity/Computability/Complexity/Classes/IP/TQBF/Words.lean +++ b/Complexity/Computability/Complexity/Classes/IP/TQBF/Words.lean @@ -342,35 +342,39 @@ open ComputableTidilyInPolyTime variable {γ : Type} {encIn : γ ↪ List Bool} @[fun_prop] -theorem computableTidilyInPolyTime_subMod {p a b : γ → ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (ha : ComputableTidilyInPolyTime a encIn encUnary) - (hb : ComputableTidilyInPolyTime b encIn encUnary) : - ComputableTidilyInPolyTime (fun x => subMod (p x) (a x) (b x)) encIn encUnary := by +theorem computableInPolyTime_subMod {p a b : γ → ℕ} + (hp : ComputableInPolyTime p encIn encUnary) + (ha : ComputableInPolyTime a encIn encUnary) + (hb : ComputableInPolyTime b encIn encUnary) : + ComputableInPolyTime (fun x => subMod (p x) (a x) (b x)) encIn encUnary := by unfold subMod fun_prop -theorem computableTidilyInPolyTime_connectiveMod (o : ArithQBF.Connective) {p a b : γ → ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (ha : ComputableTidilyInPolyTime a encIn encUnary) - (hb : ComputableTidilyInPolyTime b encIn encUnary) : - ComputableTidilyInPolyTime (fun x => connectiveMod (p x) o (a x) (b x)) encIn encUnary := by +theorem computableInPolyTime_connectiveMod (o : ArithQBF.Connective) {p a b : γ → ℕ} + (hp : ComputableInPolyTime p encIn encUnary) + (ha : ComputableInPolyTime a encIn encUnary) + (hb : ComputableInPolyTime b encIn encUnary) : + ComputableInPolyTime (fun x => connectiveMod (p x) o (a x) (b x)) encIn encUnary := by cases o <;> simp only [connectiveMod] <;> fun_prop -theorem computableTidilyInPolyTime_operatorMod (o : ArithQBF.Operator) {p t a b : γ → ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (ht : ComputableTidilyInPolyTime t encIn encUnary) - (ha : ComputableTidilyInPolyTime a encIn encUnary) - (hb : ComputableTidilyInPolyTime b encIn encUnary) : - ComputableTidilyInPolyTime (fun x => operatorMod (p x) o (t x) (a x) (b x)) encIn encUnary := by +theorem computableInPolyTime_operatorMod (o : ArithQBF.Operator) {p t a b : γ → ℕ} + (hp : ComputableInPolyTime p encIn encUnary) + (ht : ComputableInPolyTime t encIn encUnary) + (ha : ComputableInPolyTime a encIn encUnary) + (hb : ComputableInPolyTime b encIn encUnary) : + ComputableInPolyTime (fun x => operatorMod (p x) o (t x) (a x) (b x)) encIn encUnary := by cases o <;> simp only [operatorMod] <;> fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_hornerMod {p z : γ → ℕ} {l : γ → List ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (hz : ComputableTidilyInPolyTime z encIn encUnary) - (hl : ComputableTidilyInPolyTime l encIn (encList encUnary)) : - ComputableTidilyInPolyTime (fun x => hornerMod (p x) (z x) (l x)) encIn encUnary := by +theorem computableInPolyTime_hornerMod {p z : γ → ℕ} {l : γ → List ℕ} + (hp : ComputableInPolyTime p encIn encUnary) + (hz : ComputableInPolyTime z encIn encUnary) + (hl : ComputableInPolyTime l encIn (encList encUnary)) : + ComputableInPolyTime (fun x => hornerMod (p x) (z x) (l x)) encIn encUnary := by + have hp := hp.tidy + have hz := hz.tidy + have hl := hl.tidy + refine .of_tidy ?_ unfold hornerMod refine foldlWithInput_of_bounded_growth (encA := encUnary) (encL := encList encUnary) (const 0) ⟨by fun_prop, by fun_prop, inferInstance, inferInstance⟩ @@ -380,74 +384,88 @@ theorem computableTidilyInPolyTime_hornerMod {p z : γ → ℕ} {l : γ → List omega @[fun_prop] -theorem computableTidilyInPolyTime_lookupPt {pt : γ → List (ℕ × ℕ)} {w : γ → ℕ} - (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) - (hw : ComputableTidilyInPolyTime w encIn encNat) : - ComputableTidilyInPolyTime (fun x => lookupPt (pt x) (w x)) encIn encUnary := by +theorem computableInPolyTime_lookupPt {pt : γ → List (ℕ × ℕ)} {w : γ → ℕ} + (hpt : ComputableInPolyTime pt encIn (encList (encPair encNat encUnary))) + (hw : ComputableInPolyTime w encIn encNat) : + ComputableInPolyTime (fun x => lookupPt (pt x) (w x)) encIn encUnary := by + have hpt := hpt.tidy + have hw := hw.tidy + refine .of_tidy ?_ unfold lookupPt have htest : ComputableTidilyInPolyTime (fun q : γ × (ℕ × ℕ) => q.2.1 == w q.1) (encPair encIn (encPair encNat encUnary)) encBool := by fun_prop exact optionElimWithInput (findWithInput hpt htest) (const 0) (by fun_prop) @[fun_prop] -theorem computableTidilyInPolyTime_normPt {p : γ → ℕ} {xs : γ → List ℕ} - {pt : γ → List (ℕ × ℕ)} (hp : ComputableTidilyInPolyTime p encIn encUnary) - (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) - (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) : - ComputableTidilyInPolyTime (fun x => normPt (p x) (xs x) (pt x)) encIn +theorem computableInPolyTime_normPt {p : γ → ℕ} {xs : γ → List ℕ} + {pt : γ → List (ℕ × ℕ)} (hp : ComputableInPolyTime p encIn encUnary) + (hxs : ComputableInPolyTime xs encIn (encList encNat)) + (hpt : ComputableInPolyTime pt encIn (encList (encPair encNat encUnary))) : + ComputableInPolyTime (fun x => normPt (p x) (xs x) (pt x)) encIn (encList (encPair encNat encUnary)) := by unfold normPt fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] -theorem computableTidilyInPolyTime_updatePt {p : γ → ℕ} {xs : γ → List ℕ} - {pt : γ → List (ℕ × ℕ)} {v z : γ → ℕ} (hp : ComputableTidilyInPolyTime p encIn encUnary) - (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) - (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) - (hv : ComputableTidilyInPolyTime v encIn encNat) - (hz : ComputableTidilyInPolyTime z encIn encUnary) : - ComputableTidilyInPolyTime (fun x => updatePt (p x) (xs x) (pt x) (v x) (z x)) encIn +theorem computableInPolyTime_updatePt {p : γ → ℕ} {xs : γ → List ℕ} + {pt : γ → List (ℕ × ℕ)} {v z : γ → ℕ} (hp : ComputableInPolyTime p encIn encUnary) + (hxs : ComputableInPolyTime xs encIn (encList encNat)) + (hpt : ComputableInPolyTime pt encIn (encList (encPair encNat encUnary))) + (hv : ComputableInPolyTime v encIn encNat) + (hz : ComputableInPolyTime z encIn encUnary) : + ComputableInPolyTime (fun x => updatePt (p x) (xs x) (pt x) (v x) (z x)) encIn (encList (encPair encNat encUnary)) := by + have hp := hp.tidy + have hxs := hxs.tidy + have hpt := hpt.tidy + have hv := hv.tidy + have hz := hz.tidy + refine .of_tidy ?_ unfold updatePt fun_prop /-- An entry of a computed list of unary numbers, `0` outside the list. -/ @[fun_prop] -theorem computableTidilyInPolyTime_getD_zero {l : γ → List ℕ} {i : γ → ℕ} - (hl : ComputableTidilyInPolyTime l encIn (encList encUnary)) - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => (l x).getD (i x) 0) encIn encUnary := by +theorem computableInPolyTime_getD_zero {l : γ → List ℕ} {i : γ → ℕ} + (hl : ComputableInPolyTime l encIn (encList encUnary)) + (hi : ComputableInPolyTime i encIn encUnary) : + ComputableInPolyTime (fun x => (l x).getD (i x) 0) encIn encUnary := by + have hl := hl.tidy + have hi := hi.tidy + refine .of_tidy ?_ simp only [List.getD_eq_getElem?_getD] exact optionGetDWithInput (getElem? hl hi) (const 0) @[fun_prop] -theorem computableTidilyInPolyTime_width {p : γ → ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) : - ComputableTidilyInPolyTime (fun x => width (p x)) encIn encUnary := by +theorem computableInPolyTime_width {p : γ → ℕ} + (hp : ComputableInPolyTime p encIn encUnary) : + ComputableInPolyTime (fun x => width (p x)) encIn encUnary := by unfold width fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_replyLimit {p D : γ → ℕ} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (hD : ComputableTidilyInPolyTime D encIn encUnary) : - ComputableTidilyInPolyTime (fun x => replyLimit (p x) (D x)) encIn encUnary := by +theorem computableInPolyTime_replyLimit {p D : γ → ℕ} + (hp : ComputableInPolyTime p encIn encUnary) + (hD : ComputableInPolyTime D encIn encUnary) : + ComputableInPolyTime (fun x => replyLimit (p x) (D x)) encIn encUnary := by unfold replyLimit fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_decodeReply {p D : γ → ℕ} {word : γ → List Bool} - (hp : ComputableTidilyInPolyTime p encIn encUnary) - (hD : ComputableTidilyInPolyTime D encIn encUnary) - (hword : ComputableTidilyInPolyTime word encIn encBits) : - ComputableTidilyInPolyTime (fun x => decodeReply (p x) (D x) (word x)) encIn +theorem computableInPolyTime_decodeReply {p D : γ → ℕ} {word : γ → List Bool} + (hp : ComputableInPolyTime p encIn encUnary) + (hD : ComputableInPolyTime D encIn encUnary) + (hword : ComputableInPolyTime word encIn encBits) : + ComputableInPolyTime (fun x => decodeReply (p x) (D x) (word x)) encIn (encList encUnary) := by unfold decodeReply fun_prop /-- The samples are strict PPT in a unary modulus. -/ -theorem isPPTOn_sampleMod {p : γ → ℕ} (hp : ComputableTidilyInPolyTime p encIn encUnary) : +theorem isPPTOn_sampleMod {p : γ → ℕ} (hp : ComputableInPolyTime p encIn encUnary) : IsPPTOn encIn encUnary (fun x => sampleMod (p x)) := by + have hp := hp.tidy unfold sampleMod exact IsPPTOn.map_with (f := fun x i => i % p x) (isPPTOn_sampleDyadicIndex hp) (by fun_prop) diff --git a/Complexity/Computability/Complexity/Classes/Inclusions.lean b/Complexity/Computability/Complexity/Classes/Inclusions.lean index e58de7786..b68d6343b 100644 --- a/Complexity/Computability/Complexity/Classes/Inclusions.lean +++ b/Complexity/Computability/Complexity/Classes/Inclusions.lean @@ -172,7 +172,7 @@ theorem PSPACE_subset_EXP : PSPACE enc ⊆ EXP enc := by (Q := fun n => (B n + 2) * (B n + 1)) (R := fun n => ((B n + 1) * (B n + B n + 1) + L + 1) ^ 2 + cE * (2 * L + 3 * B n + 3) ^ dE) (by fun_prop) (by simp only [B]; fun_prop) (by simp only [B]; fun_prop) - have hmem := setOf_mem_DTIME_of_computableTidilyInO h + have hmem := setOf_mem_DTIME_of_computableInO h (t := fun n => cT * (n + 1) ^ dT + 2 ^ ((B n + 2) * (B n + 1)) * (((B n + 1) * (B n + B n + 1) + L + 1) ^ 2 + cE * (2 * L + 3 * B n + 3) ^ dE)) fun a => by @@ -229,7 +229,7 @@ private theorem alternationSet_mem_PSPACE (ps : List (Polynomial ℕ)) : (encPair enc encBits) encUnary := ((ComputableTidilyInPolyTime.unary_eval p).comp (ComputableTidilyInPolyTime.encoding_length enc)).comp (.fst _ _) - convert setOf_exists_mem_PSPACE hB hℓ using 1 + convert setOf_exists_mem_PSPACE hB (.of_tidy hℓ) using 1 ext x simp only [alternationSet, List.map_cons, alternation_true_cons, Set.mem_ofPred_eq, List.append_assoc] diff --git a/Complexity/Computability/Complexity/Classes/Ladner.lean b/Complexity/Computability/Complexity/Classes/Ladner.lean index 6b6db48d8..6b04611e0 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner.lean @@ -337,7 +337,7 @@ theorem SAT_mem_P_of_reducible_of_tendsto (hR : PolyTimeReducible encCNF encBits -- the polynomial-time certificate of a round have hshrink : ComputableTidilyInPolyTime (shrink R N) encCNF encCNF := by have hH' : ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => H p.2) (encPair encCNF encUnary) - encUnary := computableTidilyInPolyTime_H.comp (ComputableTidilyInPolyTime.snd _ _) + encUnary := computableInPolyTime_H.tidy.comp (ComputableTidilyInPolyTime.snd _ _) unfold shrink fun_prop -- the rounds preserve satisfiability and shorten the formula to below `N` diff --git a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean index f759157cf..ebf20e519 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean @@ -20,7 +20,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Op # Ladner's language in polynomial time and in NP The exponent function `Cslib.Complexity.Ladner.H` of Ladner's language is tidily computable in -polynomial time on unary numbers (`Cslib.Complexity.Ladner.computableTidilyInPolyTime_H`), and +polynomial time on unary numbers (`Cslib.Complexity.Ladner.computableInPolyTime_H`), and Ladner's language is in `NP` (`Cslib.Complexity.Ladner.SATH_mem_NP`), with a verifier that reads the padded formula and evaluates it under the assignment the certificate describes. @@ -36,9 +36,9 @@ value is polynomial in `n`, and the polynomial-time calculus certifies the compo The certificate rests on general tools: a total decoder for formulas (`Cslib.Complexity.cnfDecoder`, built from `Turing.MultiTapeTM.Decoder.nat` and `Turing.MultiTapeTM.Decoder.bool`), capped powers on unary numbers -(`Cslib.Complexity.Ladner.computableTidilyInPolyTime_capPow`), the universal function with its +(`Cslib.Complexity.Ladner.computableInPolyTime_capPow`), the universal function with its number of steps in unary (`Turing.MultiTapeTM.Universal.computableTidilyInPolyTime_universal`), and -the words by index (`Cslib.Complexity.Ladner.computableTidilyInPolyTime_word`). Decoding machine +the words by index (`Cslib.Complexity.Ladner.computableInPolyTime_word`). Decoding machine descriptions and coding their input bits use the shared polynomial-time rules in `Complexity.Computability.Machines.Turing.MultiTape.Universal.PolyTime`. @@ -53,12 +53,12 @@ descriptions and coding their input bits use the shared polynomial-time rules in ## Main results -* `Cslib.Complexity.Ladner.computableTidilyInPolyTime_capPow`: capped powers in unary. +* `Cslib.Complexity.Ladner.computableInPolyTime_capPow`: capped powers in unary. * `Cslib.Complexity.Ladner.mem_padSAT_iff`: membership in a padded language through `padCheck`. -* `Cslib.Complexity.Ladner.computableTidilyInPolyTime_padCheck`: `padCheck` is polynomial-time for a +* `Cslib.Complexity.Ladner.computableInPolyTime_padCheck`: `padCheck` is polynomial-time for a polynomial-time exponent function. * `Cslib.Complexity.Ladner.hstepB_eq`: the search computes the step. -* `Cslib.Complexity.Ladner.computableTidilyInPolyTime_H`: `H` is polynomial-time. +* `Cslib.Complexity.Ladner.computableInPolyTime_H`: `H` is polynomial-time. * `Cslib.Complexity.Ladner.SATH_mem_NP`: Ladner's language is in `NP`. ## References @@ -83,10 +83,10 @@ theorem decodeCNF_encCNF (φ : CNF ℕ) : decodeCNF (encCNF φ) = φ := Complexity.cnfDecoder.decode_enc φ @[fun_prop] -theorem computableTidilyInPolyTime_decodeCNF : - ComputableTidilyInPolyTime decodeCNF encBits encCNF := - let ⟨_, _, h⟩ := Complexity.cnfDecoder.computable - h.computableTidilyInPolyTime +theorem computableInPolyTime_decodeCNF : + ComputableInPolyTime decodeCNF encBits encCNF := + .of_tidy (let ⟨_, _, h⟩ := Complexity.cnfDecoder.computable + h.computableTidilyInPolyTime) /-! ### Capped powers -/ @@ -127,18 +127,21 @@ private theorem computableTidilyInPolyTime_capPow_pair : simpa only [iterate_min_mul, one_mul, capPow] using h @[fun_prop] -theorem computableTidilyInPolyTime_capPow {α : Type} {input : α ↪ List Bool} - {base exp cap : α → ℕ} (hbase : ComputableTidilyInPolyTime base input encUnary) - (hexp : ComputableTidilyInPolyTime exp input encUnary) - (hcap : ComputableTidilyInPolyTime cap input encUnary) : - ComputableTidilyInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := - computableTidilyInPolyTime_capPow_pair.comp (hbase.prod (hexp.prod hcap)) +theorem computableInPolyTime_capPow {α : Type} {input : α ↪ List Bool} + {base exp cap : α → ℕ} (hbase : ComputableInPolyTime base input encUnary) + (hexp : ComputableInPolyTime exp input encUnary) + (hcap : ComputableInPolyTime cap input encUnary) : + ComputableInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := by + have hbase := hbase.tidy + have hexp := hexp.tidy + have hcap := hcap.tidy + exact .of_tidy (computableTidilyInPolyTime_capPow_pair.comp (hbase.prod (hexp.prod hcap))) /-! ### Words by index -/ /-- The word with a given index is polynomial-time in the index in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_word : ComputableTidilyInPolyTime word encUnary encBits := by +theorem computableInPolyTime_word : ComputableInPolyTime word encUnary encBits := by have h : word = fun j => (encNat (j + 1)).take ((encNat (j + 1)).length - 1) := by funext j simp [word, encNat_apply, List.dropLast_eq_take] @@ -201,8 +204,9 @@ private theorem computableTidilyInPolyTime_idxOf_false_reverse : /-- Splitting a padded word is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_unpad : - ComputableTidilyInPolyTime unpad encBits (encPair encBits encUnary) := by +theorem computableInPolyTime_unpad : + ComputableInPolyTime unpad encBits (encPair encBits encUnary) := by + refine .of_tidy ?_ have hk := computableTidilyInPolyTime_idxOf_false_reverse unfold unpad fun_prop @@ -218,12 +222,15 @@ private theorem computableTidilyInPolyTime_padCheckAt : /-- Reading the formula padded along a computed exponent function is polynomial-time. The exponent function may capture the input. -/ @[fun_prop] -theorem computableTidilyInPolyTime_padCheck {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_padCheck {α : Type} {input : α ↪ List Bool} {e : α → ℕ → ℕ} {y : α → List Bool} - (he : ComputableTidilyInPolyTime (fun p : α × ℕ => e p.1 p.2) (encPair input encUnary) + (he : ComputableInPolyTime (fun p : α × ℕ => e p.1 p.2) (encPair input encUnary) encUnary) - (hy : ComputableTidilyInPolyTime y input encBits) : - ComputableTidilyInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := by + (hy : ComputableInPolyTime y input encBits) : + ComputableInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := by + have he := he.tidy + have hy := hy.tidy + refine .of_tidy ?_ have h := computableTidilyInPolyTime_padCheckAt unfold padCheck fun_prop @@ -249,10 +256,10 @@ theorem bruteSAT_iff {n : ℕ} {φ : CNF ℕ} (h : 2 ^ ((encCNF φ).length + 1) exact List.any_eq_true.mpr ⟨index w, List.mem_range.mpr (by omega), by rwa [word_index]⟩ @[fun_prop] -theorem computableTidilyInPolyTime_bruteSAT {α : Type} {input : α ↪ List Bool} - {n : α → ℕ} {φ : α → CNF ℕ} (hn : ComputableTidilyInPolyTime n input encUnary) - (hφ : ComputableTidilyInPolyTime φ input encCNF) : - ComputableTidilyInPolyTime (fun x => bruteSAT (n x) (φ x)) input encBool := by +theorem computableInPolyTime_bruteSAT {α : Type} {input : α ↪ List Bool} + {n : α → ℕ} {φ : α → CNF ℕ} (hn : ComputableInPolyTime n input encUnary) + (hφ : ComputableInPolyTime φ input encCNF) : + ComputableInPolyTime (fun x => bruteSAT (n x) (φ x)) input encBool := by unfold bruteSAT fun_prop @@ -335,12 +342,12 @@ theorem hstepB_eq (T : List ℕ) : hstepB T = Hstep T := by /-- The run of an indexed machine, with the number of steps in unary, is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_runIndexed {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_runIndexed {α : Type} {input : α ↪ List Bool} {i : α → ℕ} {w : α → List Bool} {t : α → ℕ} - (hi : ComputableTidilyInPolyTime i input encUnary) - (hw : ComputableTidilyInPolyTime w input encBits) - (ht : ComputableTidilyInPolyTime t input encUnary) : - ComputableTidilyInPolyTime (fun x => runIndexed (i x) (w x) (t x)) input eOut := by + (hi : ComputableInPolyTime i input encUnary) + (hw : ComputableInPolyTime w input encBits) + (ht : ComputableInPolyTime t input encUnary) : + ComputableInPolyTime (fun x => runIndexed (i x) (w x) (t x)) input eOut := by unfold runIndexed fun_prop @@ -376,8 +383,9 @@ theorem Htable_eq_iterate (n : ℕ) : Htable n = (fun T => T ++ [hstepB T])^[n] | succ n ih => rw [Htable, Function.iterate_succ_apply', ← ih, hstepB_eq] /-- The tables of `H` are polynomial-time in their length, in unary. -/ -theorem computableTidilyInPolyTime_Htable : - ComputableTidilyInPolyTime Htable encUnary (encList encUnary) := by +theorem computableInPolyTime_Htable : + ComputableInPolyTime Htable encUnary (encList encUnary) := by + refine .of_tidy ?_ have hs := computableTidilyInPolyTime_hstepB have h := iterate (encIn := encUnary) (encState := encList encUnary) (count := fun n => n) (init := fun _ => []) (step := fun T => T ++ [hstepB T]) (by fun_prop) (by fun_prop) @@ -395,8 +403,9 @@ theorem computableTidilyInPolyTime_Htable : /-- **`H` is polynomial-time** on unary numbers. -/ @[fun_prop] -theorem computableTidilyInPolyTime_H : ComputableTidilyInPolyTime H encUnary encUnary := by - have h := computableTidilyInPolyTime_hstepB.comp computableTidilyInPolyTime_Htable +theorem computableInPolyTime_H : ComputableInPolyTime H encUnary encUnary := by + refine .of_tidy ?_ + have h := computableTidilyInPolyTime_hstepB.comp computableInPolyTime_Htable.tidy have heq : hstepB ∘ Htable = H := funext fun n => hstepB_eq _ rwa [heq] at h @@ -411,7 +420,7 @@ private theorem computableTidilyInPolyTime_verifier : ComputableTidilyInPolyTime verifier (encPair encBits encBits) encBool := by have hH : ComputableTidilyInPolyTime (fun p : (List Bool × List Bool) × ℕ => H p.2) (encPair (encPair encBits encBits) encUnary) encUnary := - computableTidilyInPolyTime_H.comp (snd _ _) + computableInPolyTime_H.tidy.comp (snd _ _) unfold verifier fun_prop diff --git a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean index 3b791e5fc..cd727cd41 100644 --- a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean +++ b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean @@ -43,7 +43,7 @@ $$\mathsf{MIP}_2 \subseteq \mathsf{MIP} \subseteq \mathsf{NEXP}.$$ `aliveRun M x r th` specializes `Cslib.Complexity.Interaction.aliveRun` to execute `M` for `t` steps, consuming `th` from the front whenever `M` issues an oracle query `(op, m)` and checking that the entry matches `(op.val, m)`. By - `Cslib.Complexity.Interaction.computableTidilyInPolyTime_accepts`, `accepts` is computable tidily + `Cslib.Complexity.Interaction.computableInPolyTime_accepts`, `accepts` is computable tidily in polynomial time. 2. **Correspondence with deterministic prover families (`acceptFrom_eq_one_of_accepts`, `acceptFrom_eq_ite_accepts_canonicalTrace`)**: @@ -139,8 +139,8 @@ theorem projHistory_cons_of_ne {i j : ℕ} (hne : j ≠ i) (my : List Bool × Li /-- Projecting a tagged history onto channel `i` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_projHistory : - ComputableTidilyInPolyTime (fun p : ℕ × TaggedHistory => projHistory p.1 p.2) +theorem computableInPolyTime_projHistory : + Turing.MultiTapeTM.ComputableInPolyTime (fun p : ℕ × TaggedHistory => projHistory p.1 p.2) (encPair encUnary encTaggedHistory) encHistory := by unfold projHistory fun_prop @@ -198,9 +198,10 @@ theorem consistentHistStep_suffix {h₂ : History} {s : History × Bool × Bool} /-- `consistentHist` is computable tidily in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_consistentHist : - ComputableTidilyInPolyTime (fun p : History × History => consistentHist p.1 p.2) +theorem computableInPolyTime_consistentHist : + Turing.MultiTapeTM.ComputableInPolyTime (fun p : History × History => consistentHist p.1 p.2) (encPair encHistory encHistory) encBool := by + refine .of_tidy ?_ have hstep : ComputableTidilyInPolyTime (fun q : (History × Bool × Bool) × (List Bool × List Bool) => consistentHistStep q.1 q.2) (encPair (encPair encHistory (encPair encBool encBool)) (encPair encBits encBits)) @@ -255,12 +256,12 @@ abbrev accepts (x r : List Bool) (th : TaggedHistory) : Bool := /-- Multi-channel replay acceptance is polynomial-time in the input, coins, and tagged history. -/ @[fun_prop] -theorem computableTidilyInPolyTime_accepts [Finite Control] : - ComputableTidilyInPolyTime (fun q : List Bool × List Bool × TaggedHistory => +theorem computableInPolyTime_accepts [Finite Control] : + Turing.MultiTapeTM.ComputableInPolyTime (fun q : List Bool × List Bool × TaggedHistory => accepts M q.1 q.2.1 q.2.2) (encPair encBits (encPair encBits encTaggedHistory)) encBool := - Interaction.computableTidilyInPolyTime_accepts matchTaggedOp Prod.snd M - (fun op => .of_tidy (by unfold matchTaggedOp; fun_prop)) (.of_tidy (snd _ _)) + (Interaction.computableInPolyTime_accepts matchTaggedOp Prod.snd M + (fun op => .of_tidy (by unfold matchTaggedOp; fun_prop)) (.of_tidy (snd _ _))) /-! ### Correspondence between `accepts` and `coinProgram` against deterministic provers -/ @@ -601,9 +602,10 @@ variable [Finite Control] /-- `checkCert` is computable tidily in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_checkCert (c d : ℕ) : - ComputableTidilyInPolyTime (fun q : List Bool × Cert => checkCert M c d q.1 q.2) +theorem computableInPolyTime_checkCert (c d : ℕ) : + Turing.MultiTapeTM.ComputableInPolyTime (fun q : List Bool × Cert => checkCert M c d q.1 q.2) (encPair encBits encCert) encBool := by + refine .of_tidy ?_ have ht : ComputableTidilyInPolyTime (fun q : List Bool × Cert => c * (q.1.length + 1) ^ d) (encPair encBits encCert) encUnary := by @@ -651,8 +653,9 @@ theorem computableTidilyInPolyTime_checkCert (c d : ℕ) : /-- `checkPaddedCert` is computable tidily in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_checkPaddedCert (c d : ℕ) : - ComputableTidilyInPolyTime (checkPaddedCert M c d) (encPair encBits encCert) encBool := by +theorem computableInPolyTime_checkPaddedCert (c d : ℕ) : + Turing.MultiTapeTM.ComputableInPolyTime (checkPaddedCert M c d) (encPair encBits encCert) encBool := by + refine .of_tidy ?_ have hunframe : ComputableTidilyInPolyTime unframe encBits encBits := .of_linear (.of_unframe fun _ => rfl) have hlen : ComputableTidilyInPolyTime @@ -660,13 +663,13 @@ theorem computableTidilyInPolyTime_checkPaddedCert (c d : ℕ) : (encPair encBits encCert) encBool := unary_le' ((encoding_length encCert).comp (snd encBits encCert)) (length_bits.comp (fst encBits encCert)) - exact bool_and' hlen ((computableTidilyInPolyTime_checkCert M c d).comp + exact bool_and' hlen ((computableInPolyTime_checkCert M c d).tidy.comp ((hunframe.comp (fst encBits encCert)).prod (snd encBits encCert))) /-- The padded multiprover language `paddedMIP M c d` belongs to `NP encBits`. -/ theorem paddedMIP_mem_NP (c d : ℕ) : paddedMIP M c d ∈ NP encBits := by refine mem_NP_of_witness certDecoder (p := Polynomial.X) - (computableTidilyInPolyTime_checkPaddedCert M c d) (fun _ _ => Iff.rfl) ?_ + (computableInPolyTime_checkPaddedCert M c d) (fun _ _ => Iff.rfl) ?_ intro w cert h refine ⟨cert, h, ?_⟩ simp only [checkPaddedCert, Bool.and_eq_true, decide_eq_true_eq] at h @@ -1011,7 +1014,7 @@ theorem MIP_subset_NEXP : MIP enc ⊆ NEXP enc := by natCast_div_le_natCast_div_iff hpos (by norm_num)] at hineq lia rw [hpre] - exact preimage_pad_mem_NEXP hNP hf hn + exact preimage_pad_mem_NEXP hNP (.of_tidy hf) hn /-- **`MIP₂ ⊆ NEXP`**: every problem with a two-prover interactive proof is decidable in nondeterministic exponential time. -/ diff --git a/Complexity/Computability/Complexity/Classes/ModP.lean b/Complexity/Computability/Complexity/Classes/ModP.lean index 5ba53c8e4..94f2716d0 100644 --- a/Complexity/Computability/Complexity/Classes/ModP.lean +++ b/Complexity/Computability/Complexity/Classes/ModP.lean @@ -97,7 +97,7 @@ theorem PolyTimeReducible.mem_ModP {β : Type} {encB : β ↪ List Bool} {B : Se (h : PolyTimeReducible enc encB A B) (hB : B ∈ ModP k encB) : A ∈ ModP k enc := by obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, hf, hB⟩ := hB - exact ⟨f ∘ g, SharpP.comp_mem hf hg.tidy, fun a => (hAB a).trans (hB (g a))⟩ + exact ⟨f ∘ g, SharpP.comp_mem hf hg, fun a => (hAB a).trans (hB (g a))⟩ /-- Prime divisibility of a product gives intersection closure. -/ theorem inter_mem_ModP (hk : k.Prime) (hA : A ∈ ModP k enc) (hB : B ∈ ModP k enc) : diff --git a/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean b/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean index fce7c79b2..38cffef4f 100644 --- a/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean +++ b/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean @@ -13,6 +13,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Machine.Nondete import Complexity.Computability.Probabilistic.PPT.Capture import Complexity.Computability.Probabilistic.PPT.Clock import Complexity.Computability.Probabilistic.Sampling +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Guess and verify @@ -59,10 +60,11 @@ machine whose nondeterministic machine decides the problem within the explicit p `c * ((enc a).length + 1) ^ d`. That machine is never stuck, so its branches actually halt within the bound. -/ theorem IsVerifier.exists_decidesInTime - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (hA : IsVerifier enc p V A) : + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (hA : IsVerifier enc p V A) : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePTM k Bool State) (c d : ℕ), machine.toNTM.DecidesInTime enc A (fun a => c * ((enc a).length + 1) ^ d) ∧ ∀ input (cfg : Cfg k Bool State input), ∃ cfg', machine.toNTM.Step cfg cfg' := by + have hV := hV.tidy -- guess a certificate of the required length, then verify it let program (a : α) : ProbComp Bool := (fun w => V (a, w)) <$> BitString.sampleList (p.eval (enc a).length) @@ -88,6 +90,8 @@ theorem IsVerifier.exists_decidesInTime · rintro ⟨b, ⟨w, hw, hV⟩, rfl⟩ exact ⟨w, hw, hV⟩ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Problems in `NP` are decidable in polynomial time by nondeterministic machines with a binary alphabet and finitely many states. -/ theorem decidableInPolyTime_of_mem_NP (h : A ∈ NP enc) : diff --git a/Complexity/Computability/Complexity/Classes/NP/Nondeterministic.lean b/Complexity/Computability/Complexity/Classes/NP/Nondeterministic.lean index c65e39a0b..fdf2b95a0 100644 --- a/Complexity/Computability/Complexity/Classes/NP/Nondeterministic.lean +++ b/Complexity/Computability/Complexity/Classes/NP/Nondeterministic.lean @@ -40,7 +40,7 @@ the verifier needs no machine built by hand. ## Main results -* `Turing.MultiTapeNTM.computableTidilyInPolyTime_checkChoices`: the verifier is polynomial-time. +* `Turing.MultiTapeNTM.computableInPolyTime_checkChoices`: the verifier is polynomial-time. * `Turing.MultiTapeNTM.DecidesInTime.mem_iff_exists_checkChoices`: accepting computations have certificates of every length at least the action count times the time bound. * `Turing.MultiTapeNTM.DecidesInTime.isVerifier`: a machine deciding a problem within @@ -72,8 +72,9 @@ noncomputable def checkChoices (ntm : MultiTapeNTM k Bool State) (enc : α ↪ L /-- Checking an encoded computation is polynomial-time: it replays a fixed finite fair-coin table. -/ @[fun_prop] -theorem computableTidilyInPolyTime_checkChoices (ntm : MultiTapeNTM k Bool State) : - ComputableTidilyInPolyTime (ntm.checkChoices enc) (encPair enc encBits) encBool := by +theorem computableInPolyTime_checkChoices (ntm : MultiTapeNTM k Bool State) : + ComputableInPolyTime (ntm.checkChoices enc) (encPair enc encBits) encBool := by + refine .of_tidy ?_ have hswap : ComputableTidilyInPolyTime (fun x : α × List Bool => (x.2, enc x.1)) (encPair enc encBits) (encPair encBits encBits) := (ComputableTidilyInPolyTime.snd enc encBits).prod @@ -134,7 +135,7 @@ theorem mem_NP_of_decidableInPolyTime (h : MultiTapeNTM.DecidableInPolyTime A en A ∈ NP enc := by obtain ⟨t, ht, k, State, hfinite, ntm, hdecides⟩ := h obtain ⟨c, d, hle⟩ := ht.exists_le - exact ⟨_, ntm.checkChoices enc, .of_tidy ntm.computableTidilyInPolyTime_checkChoices, + exact ⟨_, ntm.checkChoices enc, (ntm.computableInPolyTime_checkChoices), (hdecides.mono hle).isVerifier⟩ /-- **`NP` is nondeterministic polynomial time** [Arora and Barak, Theorem 2.6][AroraBarak09]: diff --git a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean index 7c2eec106..a7f815c14 100644 --- a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean +++ b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean @@ -33,7 +33,7 @@ one bit for each literal occurrence. The self-reduction makes one query for each literal occurrence, so it runs in polynomial time when the queries are answered in polynomial time -(`Cslib.Complexity.SAT.computableTidilyInPolyTime_search`). In particular, if `SAT` is in `P`, +(`Cslib.Complexity.SAT.computableInPolyTime_search`). In particular, if `SAT` is in `P`, satisfying assignments can be found in polynomial time (`Cslib.Complexity.SAT.exists_search`). ## Main definitions @@ -46,7 +46,7 @@ satisfying assignments can be found in polynomial time (`Cslib.Complexity.SAT.ex * `Cslib.Complexity.SAT.verifier_search`: with answers correct up to `queryBound`, the self-reduction finds a satisfying assignment of every satisfiable formula. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_search`: the self-reduction is polynomial-time +* `Cslib.Complexity.SAT.computableInPolyTime_search`: the self-reduction is polynomial-time when the queries are answered in polynomial time. * `Cslib.Complexity.SAT.exists_search`: if `SAT ∈ P`, satisfying assignments are found in polynomial time. @@ -233,14 +233,17 @@ open ComputableTidilyInPolyTime /-- **The self-reduction is polynomial-time** when its queries are answered in polynomial time, with a procedure `D x` that may depend on the input `x`. -/ -theorem computableTidilyInPolyTime_search {γ : Type} {encIn : γ ↪ List Bool} +theorem computableInPolyTime_search {γ : Type} {encIn : γ ↪ List Bool} {D : γ → CNF ℕ → Bool} {φ : γ → CNF ℕ} - (hD : ComputableTidilyInPolyTime (fun p : γ × CNF ℕ => D p.1 p.2) (encPair encIn encCNF) + (hD : ComputableInPolyTime (fun p : γ × CNF ℕ => D p.1 p.2) (encPair encIn encCNF) encBool) - (hφ : ComputableTidilyInPolyTime φ encIn encCNF) : - ComputableTidilyInPolyTime (fun x => search (D x) (φ x)) encIn encBits := by + (hφ : ComputableInPolyTime φ encIn encCNF) : + ComputableInPolyTime (fun x => search (D x) (φ x)) encIn encBits := by + have hD := hD.tidy + have hφ := hφ.tidy + refine .of_tidy ?_ have hvars : ComputableTidilyInPolyTime (fun x => (φ x).vars) encIn (encList encNat) := - computableTidilyInPolyTime_vars.comp hφ + computableInPolyTime_vars.tidy.comp hφ have hquery : ComputableTidilyInPolyTime (fun p : (γ × List (Literal ℕ)) × ℕ => φ p.1.1 ++ units p.1.2 ++ [[(p.2, true)]]) (encPair (encPair encIn (encList (encPair encNat encBool))) encNat) encCNF := by @@ -270,10 +273,12 @@ theorem computableTidilyInPolyTime_search {γ : Type} {encIn : γ ↪ List Bool} /-- **Search reduces to decision for `SAT`**: if `SAT` is in `P`, a polynomial-time function finds a satisfying assignment of every satisfiable formula, as a certificate for `SAT.verifier`. -/ theorem exists_search (h : SAT ∈ P encCNF) : - ∃ g : CNF ℕ → List Bool, ComputableTidilyInPolyTime g encCNF encBits ∧ + ∃ g : CNF ℕ → List Bool, ComputableInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by - obtain ⟨D, hD, hSAT⟩ := mem_P_iff_tidy.mp h - exact ⟨search D, computableTidilyInPolyTime_search (D := fun _ => D) (hD.comp (snd _ _)) id', - fun φ => verifier_search_iff fun ψ _ => (hSAT ψ).symm⟩ + have this : ∃ g : CNF ℕ → List Bool, ComputableTidilyInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by + obtain ⟨D, hD, hSAT⟩ := mem_P_iff_tidy.mp h + exact ⟨search D, (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (snd _ _))) (.of_tidy id')).tidy, + fun φ => verifier_search_iff fun ψ _ => (hSAT ψ).symm⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this end Cslib.Complexity.SAT diff --git a/Complexity/Computability/Complexity/Classes/NP/Witness.lean b/Complexity/Computability/Complexity/Classes/NP/Witness.lean index 157a4f168..1b9ecc0f5 100644 --- a/Complexity/Computability/Complexity/Classes/NP/Witness.lean +++ b/Complexity/Computability/Complexity/Classes/NP/Witness.lean @@ -143,9 +143,11 @@ theorem isVerifier_witnessVerifier (D : Decoder encW) {check : α × β → Bool /-- The verifier of a witness relation is polynomial-time when its check is. -/ @[fun_prop] -theorem computableTidilyInPolyTime_witnessVerifier (D : Decoder encW) {check : α × β → Bool} - (hcheck : ComputableTidilyInPolyTime check (encPair enc encW) encBool) : - ComputableTidilyInPolyTime (witnessVerifier D check) (encPair enc encBits) encBool := by +theorem computableInPolyTime_witnessVerifier (D : Decoder encW) {check : α × β → Bool} + (hcheck : ComputableInPolyTime check (encPair enc encW) encBool) : + ComputableInPolyTime (witnessVerifier D check) (encPair enc encBits) encBool := by + have hcheck := hcheck.tidy + refine .of_tidy ?_ obtain ⟨_, _, hD⟩ := D.computable have hdecode : ComputableTidilyInPolyTime (fun x : α × List Bool => D.decode (unframe x.2)) (encPair enc encBits) encW := @@ -159,12 +161,13 @@ If `check` decides the relation `R` in polynomial time, the witness encoding has every member has a witness whose encoding has length at most `p (enc a).length`, then `{a | ∃ b, R a b}` is in `NP`. -/ theorem mem_NP_of_witness (D : Decoder encW) {check : α × β → Bool} {R : α → β → Prop} - (hcheck : ComputableTidilyInPolyTime check (encPair enc encW) encBool) + (hcheck : ComputableInPolyTime check (encPair enc encW) encBool) (hR : ∀ a b, check (a, b) = true ↔ R a b) (hp : ∀ a b, R a b → ∃ b', R a b' ∧ (encW b').length ≤ p.eval (enc a).length) : - {a | ∃ b, R a b} ∈ NP enc := - mem_NP_iff_tidy.mpr - ⟨_, _, computableTidilyInPolyTime_witnessVerifier D hcheck, isVerifier_witnessVerifier D hR hp⟩ + {a | ∃ b, R a b} ∈ NP enc := by + have hcheck := hcheck.tidy + exact mem_NP_iff_tidy.mpr + ⟨_, _, (computableInPolyTime_witnessVerifier D (.of_tidy hcheck)).tidy, isVerifier_witnessVerifier D hR hp⟩ end Witness @@ -191,8 +194,8 @@ private theorem toFinset_selectDistinct_map_append {l : List γ} {S : Finset γ} /-- Selecting the entries of a list from a mask is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_selectDistinct (encγ : γ ↪ List Bool) : - ComputableTidilyInPolyTime (fun x : List γ × List Bool => selectDistinct x.1 x.2) +theorem computableInPolyTime_selectDistinct (encγ : γ ↪ List Bool) : + ComputableInPolyTime (fun x : List γ × List Bool => selectDistinct x.1 x.2) (encPair (encList encγ) encBits) (encList encγ) := by unfold selectDistinct fun_prop @@ -223,25 +226,27 @@ theorem isVerifier_subsetVerifier {vs : α → List γ} /-- The verifier of a subset problem is polynomial-time when the candidates and the check are. -/ @[fun_prop] -theorem computableTidilyInPolyTime_subsetVerifier {encγ : γ ↪ List Bool} {vs : α → List γ} - (hvs : ComputableTidilyInPolyTime vs enc (encList encγ)) {check : α × List γ → Bool} - (hcheck : ComputableTidilyInPolyTime check (encPair enc (encList encγ)) encBool) : - ComputableTidilyInPolyTime (subsetVerifier vs check) (encPair enc encBits) encBool := - hcheck.comp ((fst enc encBits).prod ((computableTidilyInPolyTime_selectDistinct encγ).comp - ((hvs.comp (fst enc encBits)).prod (snd enc encBits)))) +theorem computableInPolyTime_subsetVerifier {encγ : γ ↪ List Bool} {vs : α → List γ} + (hvs : ComputableInPolyTime vs enc (encList encγ)) {check : α × List γ → Bool} + (hcheck : ComputableInPolyTime check (encPair enc (encList encγ)) encBool) : + ComputableInPolyTime (subsetVerifier vs check) (encPair enc encBits) encBool := + hcheck.comp ((ComputableInPolyTime.fst enc encBits).prod ((computableInPolyTime_selectDistinct encγ).comp + ((hvs.comp (ComputableInPolyTime.fst enc encBits)).prod (ComputableInPolyTime.snd enc encBits)))) /-- **NP membership of subset problems.** If the candidates `vs a` and the check of the selected candidates are polynomial-time, and `check` decides `P a` on duplicate-free lists of candidates, then having a set `S` of candidates with `P a S` is in `NP`. -/ theorem mem_NP_of_subsetWitness {encγ : γ ↪ List Bool} {vs : α → List γ} - (hvs : ComputableTidilyInPolyTime vs enc (encList encγ)) {check : α × List γ → Bool} - (hcheck : ComputableTidilyInPolyTime check (encPair enc (encList encγ)) encBool) + (hvs : ComputableInPolyTime vs enc (encList encγ)) {check : α × List γ → Bool} + (hcheck : ComputableInPolyTime check (encPair enc (encList encγ)) encBool) {P : α → Finset γ → Prop} (hP : ∀ a l, l.Nodup → (∀ v ∈ l, v ∈ vs a) → (check (a, l) = true ↔ P a l.toFinset)) : {a | ∃ S : Finset γ, (∀ v ∈ S, v ∈ vs a) ∧ P a S} ∈ NP enc := by + have hvs := hvs.tidy + have hcheck := hcheck.tidy obtain ⟨p, hle⟩ := hvs.polyBounded_length.exists_polynomial refine mem_NP_iff_tidy.mpr ⟨p, _, - computableTidilyInPolyTime_subsetVerifier hvs hcheck, + (computableInPolyTime_subsetVerifier (.of_tidy hvs) (.of_tidy hcheck)).tidy, isVerifier_subsetVerifier (fun a => ?_) hP⟩ exact (length_le_length_encList encγ (vs a)).trans (hle a) @@ -282,9 +287,10 @@ theorem PolyTimeReducible.mem_coNP {encB : β ↪ List Bool} {B : Set β} `(a, u)` for which `V` accepts `(a, u ++ v)` for some `v` of length `q (enc a).length` form a problem in `NP`, for the encoding of pairs. -/ theorem mem_NP_setOf_exists_append {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (q : Polynomial ℕ) : + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (q : Polynomial ℕ) : {y : α × List Bool | ∃ v : List Bool, v.length = q.eval (enc y.1).length ∧ V (y.1, y.2 ++ v) = true} ∈ NP (encPair enc encBits) := by + have hV := hV.tidy refine mem_NP_iff_tidy.mpr ⟨q, fun z => V (z.1.1, z.1.2 ++ z.2.take (q.eval (enc z.1.1).length)), ?_, fun y => ?_⟩ · exact hV.comp ((fst _ _).fst'.prod (bitsAppend (fst _ _).snd' (bitsTakeWithInput (snd _ _) diff --git a/Complexity/Computability/Complexity/Classes/Oracle.lean b/Complexity/Computability/Complexity/Classes/Oracle.lean index 752cf34e3..c405128b9 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle.lean @@ -10,6 +10,7 @@ module public import Complexity.Computability.Complexity.Classes.NP public import Complexity.Computability.Complexity.Classes.P public import Complexity.Computability.Probabilistic.Oracle +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Polynomial time relative to an oracle language @@ -61,7 +62,7 @@ oracle constructions rest. ## Main results * `Cslib.OracleComp.interpret_id_congr`: answers to requests that are not made do not matter. -* `Turing.MultiTapeTM.ComputableTidilyInPolyTime.computableInPolyTimeWithOracle`: polynomial time +* `Turing.MultiTapeTM.ComputableInPolyTime.computableInPolyTimeWithOracle`: polynomial time is polynomial time relative to every oracle. * `Cslib.Complexity.PolyTimeOracleProgram.of_polyTime`, `Cslib.Complexity.PolyTimeOracleProgram.exists_computableInPolyTimeWithOracle`, @@ -184,11 +185,12 @@ def ComputableInPolyTimeWithOracle (A : Set (List Bool)) (f : α → β) (input /-- A polynomial-time computation makes no request, so it is polynomial time relative to every oracle. -/ @[fun_prop] -theorem _root_.Turing.MultiTapeTM.ComputableTidilyInPolyTime.computableInPolyTimeWithOracle +theorem _root_.Turing.MultiTapeTM.ComputableInPolyTime.computableInPolyTimeWithOracle {f : α → β} {input : α ↪ List Bool} {output : β ↪ List Bool} - (h : ComputableTidilyInPolyTime f input output) (A : Set (List Bool)) : - ComputableInPolyTimeWithOracle A f input output := - ⟨fun a => pure (f a), h.isOraclePPTOn, fun _ => rfl⟩ + (h : ComputableInPolyTime f input output) (A : Set (List Bool)) : + ComputableInPolyTimeWithOracle A f input output := by + have h := h.tidy + exact ⟨fun a => pure (f a), h.isOraclePPTOn, fun _ => rfl⟩ /-- One deterministic polynomial-time oracle program whose function against every oracle language satisfying `Admissible` satisfies `Spec`. The program is fixed before the oracle language, so @@ -264,11 +266,15 @@ theorem mem_NPWithOracle {A : Set (List Bool)} {enc : α ↪ List Bool} {L : Set ComputableInPolyTimeWithOracle A V (encPair enc encBits) encBool ∧ IsVerifier enc p V L := Iff.rfl +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Every problem in `P` is in `P` relative to every oracle. -/ theorem P_subset_PWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : P enc ⊆ PWithOracle A enc := fun _ ⟨f, hf, h⟩ => ⟨f, hf.tidy.computableInPolyTimeWithOracle A, h⟩ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Every problem in `NP` is in `NP` relative to every oracle. -/ theorem NP_subset_NPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : NP enc ⊆ NPWithOracle A enc := fun _ ⟨p, V, hV, h⟩ => diff --git a/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean b/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean index 6d6b49273..cb17b8328 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean @@ -171,7 +171,7 @@ theorem unaryLengthLanguage_mem_NPWithOracle (B : Set (List Bool)) : unaryLengthLanguage B ∈ NPWithOracle B encBits := by refine ⟨Polynomial.X, fun xu : List Bool × List Bool => xu.1.all id && decide (xu.2 ∈ B), ((computableInPolyTimeWithOracle_mem B).preprocess - (ComputableTidilyInPolyTime.snd encBits encBits)).map_with + (.of_tidy (ComputableTidilyInPolyTime.snd encBits encBits))).map_with (g := fun (xu : List Bool × List Bool) b => xu.1.all id && b) BakerGillSolovay.computableTidilyInPolyTime_all_and, fun x => ?_⟩ · simp only [unaryLengthLanguage, Set.mem_ofPred_eq, Polynomial.eval_X, encBits, diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean index 2944f3184..88b3d149e 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean @@ -65,16 +65,18 @@ namespace ComputableInPolyTimeWithOracle /-- Polynomial-time preprocessing of the argument. -/ theorem preprocess {f : β → γ} {g : α → β} (hf : ComputableInPolyTimeWithOracle A f middle output) - (hg : ComputableTidilyInPolyTime g input middle) : - ComputableInPolyTimeWithOracle A (fun a => f (g a)) input output := - let ⟨program, hprogram, heq⟩ := hf - ⟨fun a => program (g a), hprogram.preprocess hg, fun a => heq (g a)⟩ + (hg : Turing.MultiTapeTM.ComputableInPolyTime g input middle) : + ComputableInPolyTimeWithOracle A (fun a => f (g a)) input output := by + have hg := hg.tidy + exact let ⟨program, hprogram, heq⟩ := hf + ⟨fun a => program (g a), hprogram.preprocess hg, fun a => heq (g a)⟩ /-- Polynomial-time postprocessing of the result, which may also use the argument. -/ theorem map_with {f : α → β} {g : α → β → γ} (hf : ComputableInPolyTimeWithOracle A f input middle) - (hg : ComputableTidilyInPolyTime (fun pair => g pair.1 pair.2) (encPair input middle) output) : + (hg : Turing.MultiTapeTM.ComputableInPolyTime (fun pair => g pair.1 pair.2) (encPair input middle) output) : ComputableInPolyTimeWithOracle A (fun a => g a (f a)) input output := by + have hg := hg.tidy obtain ⟨program, hprogram, heq⟩ := hf refine ⟨fun a => g a <$> program a, ?_, fun a => ?_⟩ · simpa only [OracleComp.interpret_map] using hprogram.map_with hg @@ -83,8 +85,9 @@ theorem map_with {f : α → β} {g : α → β → γ} /-- Polynomial-time postprocessing of the result. -/ theorem map {f : α → β} {g : β → γ} (hf : ComputableInPolyTimeWithOracle A f input middle) - (hg : ComputableTidilyInPolyTime g middle output) : + (hg : Turing.MultiTapeTM.ComputableInPolyTime g middle output) : ComputableInPolyTimeWithOracle A (fun a => g (f a)) input output := by + have hg := hg.tidy obtain ⟨program, hprogram, heq⟩ := hf refine ⟨fun a => g <$> program a, ?_, fun a => ?_⟩ · simpa only [OracleComp.interpret_map] using hprogram.map hg @@ -145,7 +148,7 @@ theorem mem_PWithOracle_self (A : Set (List Bool)) : A ∈ PWithOracle A encBits certificate. -/ theorem PWithOracle_subset_NPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : PWithOracle A enc ⊆ NPWithOracle A enc := fun _ ⟨f, hf, h⟩ => - ⟨0, fun aw => f aw.1, hf.preprocess (ComputableTidilyInPolyTime.fst enc encBits), fun a => by + ⟨0, fun aw => f aw.1, hf.preprocess (.of_tidy (ComputableTidilyInPolyTime.fst enc encBits)), fun a => by simp only [Polynomial.eval_zero, List.length_eq_zero_iff, exists_eq_left, h]⟩ /-- **`P` relative to an oracle is closed under polynomial-time many-one reductions.** -/ @@ -154,7 +157,7 @@ theorem PolyTimeReducible.mem_PWithOracle {encA : α ↪ List Bool} {encB : β (hL' : L' ∈ PWithOracle A encB) : L ∈ PWithOracle A encA := let ⟨g, hg, hL⟩ := h let ⟨f, hf, hL'⟩ := hL' - ⟨fun a => f (g a), hf.preprocess hg.tidy, fun a => (hL a).trans (hL' (g a))⟩ + ⟨fun a => f (g a), hf.preprocess hg, fun a => (hL a).trans (hL' (g a))⟩ /-- **`NP` relative to an oracle is closed under polynomial-time many-one reductions.** The certificates are padded to a polynomial of the instance length; the verifier reads the prefix of @@ -172,7 +175,7 @@ theorem PolyTimeReducible.mem_NPWithOracle {encA : α ↪ List Bool} {encB : β exact p.eval_mono (hlen a) refine ⟨q, fun aw => V (g aw.1, aw.2.take (p.eval (encB (g aw.1)).length)), hV.preprocess (f := V) (g := fun aw : α × List Bool => - (g aw.1, aw.2.take (p.eval (encB (g aw.1)).length))) (by fun_prop), fun a => ?_⟩ + (g aw.1, aw.2.take (p.eval (encB (g aw.1)).length))) (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [hL a, hL' (g a)] constructor · rintro ⟨w, hw, hV⟩ diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean b/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean index b1387285d..b5ff6ed76 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean @@ -96,7 +96,7 @@ variable {α β : Type} {enc : α ↪ List Bool} {output : β ↪ List Bool} {A theorem compl_mem_PWithOracle {L : Set α} (hL : L ∈ PWithOracle A enc) : Lᶜ ∈ PWithOracle A enc := by obtain ⟨f, hf, hL⟩ := hL - refine ⟨fun a => !f a, hf.map (by fun_prop), fun a => ?_⟩ + refine ⟨fun a => !f a, hf.map (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [Set.mem_compl_iff, hL a] cases h : f a <;> simp [h] @@ -105,7 +105,7 @@ theorem inter_mem_PWithOracle {L₁ L₂ : Set α} (h₁ : L₁ ∈ PWithOracle (h₂ : L₂ ∈ PWithOracle A enc) : L₁ ∩ L₂ ∈ PWithOracle A enc := by obtain ⟨f₁, hf₁, hL₁⟩ := h₁ obtain ⟨f₂, hf₂, hL₂⟩ := h₂ - refine ⟨fun a => f₁ a && f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 && p.2) (by fun_prop), + refine ⟨fun a => f₁ a && f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 && p.2) (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [Set.mem_inter_iff, hL₁ a, hL₂ a, Bool.and_eq_true] @@ -114,7 +114,7 @@ theorem union_mem_PWithOracle {L₁ L₂ : Set α} (h₁ : L₁ ∈ PWithOracle (h₂ : L₂ ∈ PWithOracle A enc) : L₁ ∪ L₂ ∈ PWithOracle A enc := by obtain ⟨f₁, hf₁, hL₁⟩ := h₁ obtain ⟨f₂, hf₂, hL₂⟩ := h₂ - refine ⟨fun a => f₁ a || f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 || p.2) (by fun_prop), + refine ⟨fun a => f₁ a || f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 || p.2) (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [Set.mem_union, hL₁ a, hL₂ a, Bool.or_eq_true] @@ -186,9 +186,9 @@ private theorem replayStepFactor_mem_SharpP [Finite Control] [Finite Operation] have hbit : ComputableTidilyInPolyTime (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop - exact SharpP.ite_mem hquery - (SharpP.ite_mem hbit (SharpP.comp_mem hYes hreq) (SharpP.comp_mem hNo hreq)) - (SharpP.ite_mem hbit SharpP.zero_mem SharpP.one_mem) + exact SharpP.ite_mem (.of_tidy hquery) + (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) (SharpP.comp_mem hNo (.of_tidy hreq))) + (SharpP.ite_mem (.of_tidy hbit) SharpP.zero_mem SharpP.one_mem) private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] (machine : MultiTapePTM k Bool Control Operation) {input : α → List Bool} @@ -197,7 +197,7 @@ private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] (hYes : fYes ∈ SharpP encBits) (hNo : fNo ∈ SharpP encBits) : replayPathCount machine input fYes fNo ∈ SharpP (encPair enc encBits) := SharpP.prod_range_mem (replayStepFactor_mem_SharpP machine hinput hYes hNo) - (r := fun x : α × List Bool => x.2.length) (by fun_prop) + (r := fun x : α × List Bool => x.2.length) (.of_tidy (by fun_prop)) private theorem replayAcceptCount_mem_SharpP [Finite Control] [Finite Operation] (machine : MultiTapePTM k Bool Control Operation) {input : α → List Bool} @@ -219,8 +219,8 @@ private theorem replayAcceptCount_mem_SharpP [Finite Control] [Finite Operation] have hmask : (fun x : α × List Bool => if P (x.1, machine.replayOutput (input x.1) x.2) then 1 else 0) ∈ SharpP (encPair enc encBits) := - SharpP.ite_mem hout SharpP.one_mem SharpP.zero_mem - exact SharpP.sum_bits_mem (SharpP.mul_mem hpath hmask) hT + SharpP.ite_mem (.of_tidy hout) SharpP.one_mem SharpP.zero_mem + exact SharpP.sum_bits_mem (SharpP.mul_mem hpath hmask) (.of_tidy hT) private theorem replayStepFactor_pos_iff (machine : MultiTapePTM k Bool Control Operation) (input : α → List Bool) {fYes fNo : List Bool → ℕ} {g : List Bool → Bool} @@ -475,7 +475,7 @@ theorem NPWithOracle_subset_NP_of_PWithOracle_subset_NP have hFV' (x : α × List Bool) : 0 < F x ↔ V x = true := (hFV x).symm have hr : ComputableTidilyInPolyTime (fun a : α => p.eval (enc a).length) enc encUnary := by fun_prop - refine mem_NP_iff_exists_SharpP.mpr ⟨_, SharpP.sum_bits_mem hF hr, fun a => ?_⟩ + refine mem_NP_iff_exists_SharpP.mpr ⟨_, SharpP.sum_bits_mem hF (.of_tidy hr), fun a => ?_⟩ rw [Finset.sum_pos_iff, hL a] simp only [mem_univ, true_and, hFV'] constructor diff --git a/Complexity/Computability/Complexity/Classes/Oracle/PP.lean b/Complexity/Computability/Complexity/Classes/Oracle/PP.lean index 9a92e8228..ad5f5216b 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/PP.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/PP.lean @@ -147,8 +147,8 @@ theorem exists_mem_PP_mem_PWithOracle_image (hL : L ∈ PWithPPOracle enc) : theorem setOf_le_mem_PP {f : α → ℕ} (hf : f ∈ SharpP enc) : {x : α × ℕ | x.2 ≤ f x.1} ∈ PP (encPair enc encNat) := by refine mem_PP_iff_exists_GapP.2 ⟨fun x => ((f x.1 + 1 : ℕ) : ℤ) - (x.2 : ℕ), - ⟨_, SharpP.add_one_mem (SharpP.comp_mem hf (ComputableTidilyInPolyTime.fst enc encNat)), _, - mem_SharpP_of_polyTime (ComputableTidilyInPolyTime.snd enc encNat), fun _ => rfl⟩, + ⟨_, SharpP.add_one_mem (SharpP.comp_mem hf (.of_tidy (ComputableTidilyInPolyTime.fst enc encNat))), _, + mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.snd enc encNat)), fun _ => rfl⟩, fun x => ?_⟩ simp only [Set.mem_ofPred_eq, sub_pos, Nat.cast_lt] omega @@ -247,10 +247,12 @@ theorem interpret_id_search {F N : ℕ} {A : Set (List Bool)} {u : List Bool} one request and reading one reply bit, on states of a binary number below `2 ^ N` and a unary counter. -/ theorem isOraclePPTOn_search {input : α ↪ List Bool} {u : α → List Bool} {N : α → ℕ} - (hu : ComputableTidilyInPolyTime u input encBits) - (hN : ComputableTidilyInPolyTime N input encUnary) : + (hu : ComputableInPolyTime u input encBits) + (hN : ComputableInPolyTime N input encUnary) : IsOraclePPTOn input encNat (fun a => OracleComp.interpret ProbOracleComp.query (search (u a) (N a))) := by + have hu := hu.tidy + have hN := hN.tidy simp only [search, OracleComp.interpret_map, OracleComp.interpret_iterate] have hinit : ComputableTidilyInPolyTime (fun a => ((0 : ℕ), N a)) input (encPair encNat encUnary) := @@ -375,7 +377,7 @@ theorem PWithSharpPOracle_subset_PWithPPOracle : PWithSharpPOracle enc ⊆ PWith OracleComp.interpret ProbOracleComp.query (bitQuery r ((), w))) := by simp only [bitQuery, OracleComp.interpret_map] exact (isOraclePPTOn_search (u := unframe) (N := fun w => r.eval w.length + 1) - (by fun_prop) (by fun_prop)).map_with hlast + (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop))).map_with hlast have hhandler : IsOraclePPTOn (encPair enc (encPair (encPair (encFinEnum Unit) encBits) (encFinEnum Unit))) (encPair encBits (encFinEnum Unit)) diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean index 795740537..b66983fad 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean @@ -14,6 +14,7 @@ import Complexity.Computability.Complexity.Classes.Oracle.Deterministic import Complexity.Computability.Complexity.Classes.Space.Closure import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Probabilistic.Replay.Simulation +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Polynomial time relative to an oracle in polynomial space @@ -37,8 +38,8 @@ bounded existential quantification (`Cslib.Complexity.setOf_exists_mem_PSPACE`). ## Main results -* `Cslib.Complexity.exists_computableTidilyInO_of_mem_PSPACE`, - `Cslib.Complexity.mem_PSPACE_of_computableTidilyInO`: `PSPACE` in terms of tidy computability +* `Cslib.Complexity.exists_computableInO_of_mem_PSPACE`, + `Cslib.Complexity.mem_PSPACE_of_computableInO`: `PSPACE` in terms of tidy computability within explicit bounds. * `Cslib.Complexity.mem_PSPACE_of_isVerifier`: certificate search within polynomial space. * `Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableTidilyInO`: polynomial time @@ -62,17 +63,17 @@ variable {α β : Type} {enc : α ↪ List Bool} /-- A problem in `PSPACE` has a tidy decider within explicit bounds, the space polynomial in the length of the encoded instance. -/ -theorem exists_computableTidilyInO_of_mem_PSPACE {L : Set α} (hL : L ∈ PSPACE enc) : +theorem exists_computableInO_of_mem_PSPACE {L : Set α} (hL : L ∈ PSPACE enc) : ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ - ∃ f : α → Bool, ComputableTidilyInO f enc encBool T S ∧ ∀ a, a ∈ L ↔ f a = true := - let ⟨f, T, S, hf, hS, hL⟩ := mem_PSPACE_iff_computableTidilyInO.mp hL + ∃ f : α → Bool, Turing.MultiTapeTM.ComputableInO f enc encBool T S ∧ ∀ a, a ∈ L ↔ f a = true := + let ⟨f, T, S, hf, hS, hL⟩ := mem_PSPACE_iff_computableInO.mp hL ⟨T, S, hS, f, hf, hL⟩ /-- A tidy decider within polynomial space puts a problem in `PSPACE`. -/ -theorem mem_PSPACE_of_computableTidilyInO {L : Set α} {f : α → Bool} {T S : α → ℕ} - (hf : ComputableTidilyInO f enc encBool T S) (hS : PolyBounded (fun a => (enc a).length) S) +theorem mem_PSPACE_of_computableInO {L : Set α} {f : α → Bool} {T S : α → ℕ} + (hf : Turing.MultiTapeTM.ComputableInO f enc encBool T S) (hS : PolyBounded (fun a => (enc a).length) S) (hL : ∀ a, a ∈ L ↔ f a = true) : L ∈ PSPACE enc := - mem_PSPACE_iff_computableTidilyInO.mpr ⟨f, T, S, hf, hS, hL⟩ + mem_PSPACE_iff_computableInO.mpr ⟨f, T, S, hf, hS, hL⟩ /-! ### Certificate search -/ @@ -80,13 +81,13 @@ theorem mem_PSPACE_of_computableTidilyInO {L : Set α} {f : α → Bool} {T S : polynomial space and certificates of polynomial length is in `PSPACE`, by closure of `PSPACE` under polynomially bounded existential quantification (`Cslib.Complexity.setOf_exists_mem_PSPACE`). -/ theorem mem_PSPACE_of_isVerifier {p : Polynomial ℕ} {V : α × List Bool → Bool} {L : Set α} - {T S : α × List Bool → ℕ} (hV : ComputableTidilyInO V (encPair enc encBits) encBool T S) + {T S : α × List Bool → ℕ} (hV : Turing.MultiTapeTM.ComputableInO V (encPair enc encBits) encBool T S) (hS : PolyBounded (fun x => (encPair enc encBits x).length) S) (hL : IsVerifier enc p V L) : L ∈ PSPACE enc := by have hB : {x | V x = true} ∈ PSPACE (encPair enc encBits) := - mem_PSPACE_of_computableTidilyInO hV hS fun _ => Iff.rfl - have hℓ : ComputableTidilyInPolyTime (fun a : α => p.eval (enc a).length) enc encUnary := - (ComputableTidilyInPolyTime.unary_eval p).comp (.encoding_length enc) + mem_PSPACE_of_computableInO hV hS fun _ => Iff.rfl + have hℓ : Turing.MultiTapeTM.ComputableInPolyTime (fun a : α => p.eval (enc a).length) enc encUnary := + (Turing.MultiTapeTM.ComputableInPolyTime.unary_eval p).comp (.encoding_length enc) have hEq : L = {x | ∃ w : List Bool, w.length = p.eval (enc x).length ∧ (x, w) ∈ {x : α × List Bool | V x = true}} := Set.ext fun a => hL a @@ -102,7 +103,7 @@ theorem ComputableInPolyTimeWithOracle.exists_computableTidilyInO {A : Set (List {f : α → β} {output : β ↪ List Bool} (hA : A ∈ PSPACE encBits) (hf : ComputableInPolyTimeWithOracle A f enc output) : ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ ComputableTidilyInO f enc output T S := by - obtain ⟨TA, SA, hSA, g, hg, hgA⟩ := exists_computableTidilyInO_of_mem_PSPACE hA + obtain ⟨TA, SA, hSA, g, hg, hgA⟩ := exists_computableInO_of_mem_PSPACE hA have hg' : g = fun w => decide (w ∈ A) := funext fun w => Bool.eq_iff_iff.mpr ⟨fun h => decide_eq_true ((hgA w).mpr h), fun h => (hgA w).mp (of_decide_eq_true h)⟩ @@ -119,7 +120,7 @@ theorem ComputableInPolyTimeWithOracle.exists_computableTidilyInO {A : Set (List theorem PWithOracle_subset_PSPACE {A : Set (List Bool)} (hA : A ∈ PSPACE encBits) : PWithOracle A enc ⊆ PSPACE enc := fun _ ⟨_, hf, hL⟩ => let ⟨_, _, hS, h⟩ := hf.exists_computableTidilyInO hA - mem_PSPACE_of_computableTidilyInO h hS hL + mem_PSPACE_of_computableInO (.of_tidy h) hS hL /-- **`NP` relative to an oracle in `PSPACE` is within `PSPACE`** [Arora and Barak, Theorem 3.7][AroraBarak09]: the verifier runs within polynomial space, and its certificates are searched @@ -127,6 +128,6 @@ within polynomial space. -/ theorem NPWithOracle_subset_PSPACE {A : Set (List Bool)} (hA : A ∈ PSPACE encBits) : NPWithOracle A enc ⊆ PSPACE enc := fun _ ⟨_, _, hV, hL⟩ => let ⟨_, _, hS, h⟩ := hV.exists_computableTidilyInO hA - mem_PSPACE_of_isVerifier h hS hL + mem_PSPACE_of_isVerifier (.of_tidy h) hS hL end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean b/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean index 8a1155e83..f8a9f4a12 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean @@ -275,7 +275,8 @@ theorem isCode_iff (w : List Bool) : isCode w = true ↔ ∃ φ, encQBF φ = w : exact ⟨⟨φ, rfl⟩, rfl⟩ /-- Whether a word encodes a formula is decidable in polynomial time. -/ -theorem isCode_pt : ComputableTidilyInPolyTime isCode encBits encBool := by +theorem isCode_pt : Turing.MultiTapeTM.ComputableInPolyTime isCode encBits encBool := by + refine .of_tidy ?_ obtain ⟨d, e, hD⟩ := tokensDecoder.computable have hD := hD.computableTidilyInPolyTime have hre : ComputableTidilyInPolyTime (fun w => encList encToken (tokensDecoder.decode w)) @@ -299,9 +300,9 @@ private theorem encQBF_decodeQBF (w : List Bool) : · rfl /-- `decodeQBF` is polynomial-time. -/ -theorem decodeQBF_pt : ComputableTidilyInPolyTime decodeQBF encBits encQBF := - (ComputableTidilyInPolyTime.ite' isCode_pt ComputableTidilyInPolyTime.id' - (ComputableTidilyInPolyTime.const (encQBF .bot))).of_enc_eq fun w => encQBF_decodeQBF w +theorem decodeQBF_pt : Turing.MultiTapeTM.ComputableInPolyTime decodeQBF encBits encQBF := + .of_tidy ((ComputableTidilyInPolyTime.ite' isCode_pt.tidy ComputableTidilyInPolyTime.id' + (ComputableTidilyInPolyTime.const (encQBF .bot))).of_enc_eq fun w => encQBF_decodeQBF w) private theorem decodeQBF_encQBF (φ : QBF ℕ) : decodeQBF (encQBF φ) = φ := encQBF.injective (by simp [encQBF_decodeQBF, (isCode_iff _).mpr ⟨φ, rfl⟩]) @@ -327,11 +328,11 @@ theorem mem_image_TQBF_iff (w : List Bool) : /-- **The words encoding true closed formulas are decided within polynomial space**: a word is tested for encoding a formula in polynomial time, and then evaluated. -/ theorem image_TQBF_mem_PSPACE : encQBF '' TQBF ∈ PSPACE encBits := by - obtain ⟨e, he⟩ := exists_computableTidilyInO_evaluate - obtain ⟨dc, _, hc⟩ := isCode_pt.exists_degree - obtain ⟨dd, _, hd⟩ := decodeQBF_pt.exists_degree + obtain ⟨e, he⟩ := exists_computableInO_evaluate + obtain ⟨dc, _, hc⟩ := isCode_pt.tidy.exists_degree + obtain ⟨dd, _, hd⟩ := decodeQBF_pt.tidy.exists_degree have h := hc.inO.ite (he.comp hd.inO) (ComputableTidilyInO.const false) - refine mem_PSPACE_of_computableTidilyInO (h.mono_le (T' := _) (S' := fun w => + refine mem_PSPACE_of_computableInO (h.mono_le (T' := _) (S' := fun w => (w.length + 1) ^ dc + ((w.length + 1) ^ dd + (w.length + (encQBF .bot).length + 1) ^ e + w.length)) (fun _ => le_rfl) fun w => ?_) ?_ fun w => ?_ diff --git a/Complexity/Computability/Complexity/Classes/P/Slices.lean b/Complexity/Computability/Complexity/Classes/P/Slices.lean index 8c2984e04..085c7eea4 100644 --- a/Complexity/Computability/Complexity/Classes/P/Slices.lean +++ b/Complexity/Computability/Complexity/Classes/P/Slices.lean @@ -55,23 +55,27 @@ theorem ofSlices_eq_setOf_ofList (f : ∀ N, BitString N → Bool) : /-- If `fun x => f x.length (BitString.ofList x.length x)` is tidily computable in polynomial time, then `Language.ofSlices f` belongs to `P encBits`. -/ theorem ofSlices_mem_P {f : ∀ n, BitString n → Bool} - (hf : ComputableTidilyInPolyTime + (hf : ComputableInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool) : - (Language.ofSlices f : Set (List Bool)) ∈ P encBits := - ⟨_, .of_tidy hf, mem_ofSlices_iff f⟩ + (Language.ofSlices f : Set (List Bool)) ∈ P encBits := by + have hf := hf.tidy + exact ⟨_, .of_tidy hf, mem_ofSlices_iff f⟩ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`Language.ofSlices f` is in `P`** if and only if its list evaluator `fun x => f x.length (BitString.ofList x.length x)` is tidily computable in polynomial time. -/ theorem ofSlices_mem_P_iff {f : ∀ N, BitString N → Bool} : (Language.ofSlices f : Set (List Bool)) ∈ P encBits ↔ - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool := by - constructor - · rintro ⟨g, hg, hiff⟩ - have heq : (fun x : List Bool => f x.length (BitString.ofList x.length x)) = g := by - funext x - exact Bool.eq_iff_iff.mpr ((mem_ofSlices_iff f x).symm.trans (hiff x)) - exact heq ▸ hg.tidy - · exact ofSlices_mem_P + have this : (Language.ofSlices f : Set (List Bool)) ∈ P encBits ↔ ComputableTidilyInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool := by + constructor + · rintro ⟨g, hg, hiff⟩ + have heq : (fun x : List Bool => f x.length (BitString.ofList x.length x)) = g := by + funext x + exact Bool.eq_iff_iff.mpr ((mem_ofSlices_iff f x).symm.trans (hiff x)) + exact heq ▸ hg.tidy + · exact ofSlices_mem_P + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/PCP/NP.lean b/Complexity/Computability/Complexity/Classes/PCP/NP.lean index f3204f423..657220dfa 100644 --- a/Complexity/Computability/Complexity/Classes/PCP/NP.lean +++ b/Complexity/Computability/Complexity/Classes/PCP/NP.lean @@ -81,7 +81,8 @@ private theorem enum_coins (hV : V.PolyTime enc) /-- The complete address table charges every enumerated word and binary address. -/ theorem isPolyTime_queryTable (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : - ComputableTidilyInPolyTime V.queryTable enc (encList encNat) := by + ComputableInPolyTime V.queryTable enc (encList encNat) := by + refine .of_tidy ?_ have he := enum_coins hV hcoins have hq := hV.2.1.tidy unfold queryTable @@ -90,11 +91,12 @@ theorem isPolyTime_queryTable (hV : V.PolyTime enc) /-- Exhaustive verification is polynomial time for every table, including short inputs. -/ theorem isPolyTime_tableVerifier (hV : V.PolyTime enc) (hcoins : ∀ a, V.coins a ≤ c * (Nat.log 2 (enc a).length + 1)) : - ComputableTidilyInPolyTime V.tableVerifier (encPair enc encBits) encBool := by + ComputableInPolyTime V.tableVerifier (encPair enc encBits) encBool := by + refine .of_tidy ?_ have he := enum_coins hV hcoins have hq := hV.2.1.tidy have hv := hV.2.2.tidy - have ht := isPolyTime_queryTable hV hcoins + have ht := (isPolyTime_queryTable hV hcoins).tidy unfold tableVerifier polytime @@ -151,10 +153,10 @@ theorem PCP_log_subset_NP (q : ℕ → ℕ) : PCP (fun n => Nat.log 2 n + 1) q enc ⊆ NP enc := by rintro A ⟨V, c, d, hV, hcoins, hqueries, hcomplete, hsound⟩ obtain ⟨p, hlength⟩ := - (PCPVerifier.isPolyTime_queryTable hV hcoins).polyBounded_length.exists_polynomial + (PCPVerifier.isPolyTime_queryTable hV hcoins).tidy.polyBounded_length.exists_polynomial have hbound (a : α) : (V.queryTable a).length ≤ p.eval (enc a).length := by exact (length_le_length_encList encNat (V.queryTable a)).trans (hlength a) - refine ⟨p, V.tableVerifier, .of_tidy (PCPVerifier.isPolyTime_tableVerifier hV hcoins), + refine ⟨p, V.tableVerifier, (PCPVerifier.isPolyTime_tableVerifier hV hcoins), fun a => ?_⟩ constructor · intro ha diff --git a/Complexity/Computability/Complexity/Classes/PH/Kannan.lean b/Complexity/Computability/Complexity/Classes/PH/Kannan.lean index 5e9202011..468d8ee0a 100644 --- a/Complexity/Computability/Complexity/Classes/PH/Kannan.lean +++ b/Complexity/Computability/Complexity/Classes/PH/Kannan.lean @@ -484,11 +484,11 @@ private theorem computableTidilyInPolyTime_verifier (k : ℕ) : exact bitsGetDWithInput hT (bitsBoundedBinaryValueWithInput (length_bits.comp hT) (bitsReverse.comp (bitsTakeWithInput (fst _ _) hm))) false unfold verifier - exact bool_and' (bool_and' (bool_not.comp (MCSP.computableTidilyInPolyTime_tableVerifier.comp + exact bool_and' (bool_and' (bool_not.comp (MCSP.computableInPolyTime_tableVerifier.tidy.comp ((hT.prod hs).prod hc))) (bool_or.comp ((bool_not.comp (binary_lt' (computableTidilyInPolyTime_binaryValue.comp hT') (computableTidilyInPolyTime_binaryValue.comp hT))).prod - (MCSP.computableTidilyInPolyTime_tableVerifier.comp ((hT'.prod hs).prod hc'))))) hval + (MCSP.computableInPolyTime_tableVerifier.tidy.comp ((hT'.prod hs).prod hc'))))) hval /-- **Kannan's language is in `Σ₃`.** -/ theorem language_mem_SigmaP_three (k : ℕ) : diff --git a/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean b/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean index eba04afd2..7dc7d1be3 100644 --- a/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean +++ b/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean @@ -73,7 +73,7 @@ Furthermore, `P/poly` preimages are closed under polynomial-time many-one reduct * `Cslib.Circuits.Boolean.evalAdvice_familyAdvice`: evaluation from the advice string of a family is evaluation of its circuits. -* `Cslib.Circuits.Boolean.computableTidilyInPolyTime_evalAdvice`: evaluation from advice strings is +* `Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice`: evaluation from advice strings is polynomial-time. * `Cslib.Complexity.PiP_two_subset_SigmaP_two_of_SAT`: if `SAT` has circuits of polynomial size, then `Π₂ ⊆ Σ₂`. @@ -180,13 +180,18 @@ open ComputableTidilyInPolyTime /-- **Evaluation from advice strings is polynomial-time**, for the number of gates and the block width in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_evalAdvice {γ : Type} {encIn : γ ↪ List Bool} - {s width : γ → ℕ} {w x : γ → List Bool} (hs : ComputableTidilyInPolyTime s encIn encUnary) - (hwidth : ComputableTidilyInPolyTime width encIn encUnary) - (hw : ComputableTidilyInPolyTime w encIn encBits) - (hx : ComputableTidilyInPolyTime x encIn encBits) : - ComputableTidilyInPolyTime (fun a => evalAdvice (s a) (width a) (w a) (x a)) encIn +theorem computableInPolyTime_evalAdvice {γ : Type} {encIn : γ ↪ List Bool} + {s width : γ → ℕ} {w x : γ → List Bool} (hs : ComputableInPolyTime s encIn encUnary) + (hwidth : ComputableInPolyTime width encIn encUnary) + (hw : ComputableInPolyTime w encIn encBits) + (hx : ComputableInPolyTime x encIn encBits) : + ComputableInPolyTime (fun a => evalAdvice (s a) (width a) (w a) (x a)) encIn encBool := by + have hs := hs.tidy + have hwidth := hwidth.tidy + have hw := hw.tidy + have hx := hx.tidy + refine .of_tidy ?_ have hm : ComputableTidilyInPolyTime (fun a => (x a).length) encIn encUnary := length_bits.comp hx have hc := (computableInPolyTime_readCertificate (.of_tidy hm) (.of_tidy hs) (.of_tidy (bitsDropWithInput hw (unary_mul.comp (hm.prod hwidth))))).tidy @@ -236,11 +241,11 @@ private theorem computableTidilyInPolyTime_verifier {f : α × List Bool → CNF (p.1.2.take (P.eval (enc p.1.1).length)) (encCNF p.2)) (encPair (encPair enc encBits) encCNF) encBool := by have hn' := hn.comp (fst (encPair enc encBits) encCNF) - exact computableTidilyInPolyTime_evalAdvice ((unary_eval S).comp hn') - ((unary_eval W).comp hn') (bitsTakeWithInput (fst _ _).snd' ((unary_eval P).comp hn')) - ((encode encCNF).comp (snd _ _)) - exact SAT.computableTidilyInPolyTime_verifier.comp - (hφ.prod (SAT.computableTidilyInPolyTime_search hD hφ)) + exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn')) + (.of_tidy ((unary_eval W).comp hn')) (.of_tidy (bitsTakeWithInput (fst _ _).snd' ((unary_eval P).comp hn'))) + (.of_tidy ((encode encCNF).comp (snd _ _)))).tidy + exact SAT.computableInPolyTime_verifier.tidy.comp + (hφ.prod (SAT.computableInPolyTime_search (.of_tidy hD) (.of_tidy hφ)).tidy) end KarpLipton @@ -252,7 +257,7 @@ theorem PiP_two_subset_SigmaP_two_of_SAT (hSAT : ∃ L ∈ PPoly, ∀ φ, φ ∈ (enc : α ↪ List Bool) : PiP 2 enc ⊆ SigmaP 2 enc := by rintro A ⟨ps, V, hlen, hV, hA⟩ obtain ⟨p, q, rfl⟩ := List.length_eq_two.1 hlen - obtain ⟨f, hf, hfB⟩ := CookLevin.SAT_npHard _ _ (mem_NP_setOf_exists_append hV.tidy q) + obtain ⟨f, hf, hfB⟩ := CookLevin.SAT_npHard _ _ (mem_NP_setOf_exists_append hV q) obtain ⟨L, hL, hSAT⟩ := hSAT obtain ⟨C, s, hs, hC⟩ := mem_PPoly_iff_exists_circuits.1 hL obtain ⟨c, d, hcd⟩ := polynomiallyBounded_iff_le.1 hs @@ -375,8 +380,8 @@ theorem PolyTimeReducible.exists_mem_PPoly {β : Type} {encB : β ↪ List Bool} have hn : ComputableTidilyInPolyTime (fun x : List Bool × α => (enc x.2).length) (encPair encBits enc) encUnary := (encoding_length enc).comp (snd _ _) - exact computableTidilyInPolyTime_evalAdvice ((unary_eval S).comp hn) - ((unary_eval W).comp hn) (fst _ _) ((encode encB).comp (hf.tidy.comp (snd _ _))) + exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn)) + (.of_tidy ((unary_eval W).comp hn)) (.of_tidy (fst _ _)) (.of_tidy ((encode encB).comp (hf.tidy.comp (snd _ _))))).tidy obtain ⟨M, hM, hgM⟩ := PPoly.exists_of_polyTime (.of_tidy hg) let α_adv : ℕ → List Bool := fun n => familyAdvice (N.eval n) (S.eval n) C have hα : PolynomiallyBounded fun n => (α_adv n).length := by @@ -443,8 +448,8 @@ theorem mem_PPoly_of_exists_frame_append (fun z : List Bool × List Bool => z.2.take (p.eval (dropFrame z.1).length)) (encPair encBits encBits) encBits := bitsTakeWithInput (snd _ _) ((unary_eval p).comp hn) - exact computableTidilyInPolyTime_evalAdvice ((unary_eval S).comp hn) - ((unary_eval W).comp hn) hu (bitsAppend ((bitsFrame encBits).comp hx) hw) + exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn)) + (.of_tidy ((unary_eval W).comp hn)) (.of_tidy hu) (.of_tidy (bitsAppend ((bitsFrame encBits).comp hx) hw))).tidy let D : Language Bool := {z : List Bool | ∃ w : List Bool, w.length = p.eval z.length ∧ V (z, w) = true} have hD : D ∈ PPoly := hNP D ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩ diff --git a/Complexity/Computability/Complexity/Classes/PH/Projection.lean b/Complexity/Computability/Complexity/Classes/PH/Projection.lean index 1534660f7..53e16b9ff 100644 --- a/Complexity/Computability/Complexity/Classes/PH/Projection.lean +++ b/Complexity/Computability/Complexity/Classes/PH/Projection.lean @@ -34,7 +34,7 @@ of `B` therefore reads longer blocks and cuts each to its first bits * `Cslib.Complexity.alternation_truncateBlocks`: cutting longer blocks does not change alternating quantifiers. -* `Cslib.Complexity.computableTidilyInPolyTime_truncateBlocks`: cutting blocks is polynomial-time. +* `Cslib.Complexity.computableInPolyTime_truncateBlocks`: cutting blocks is polynomial-time. * `Cslib.Complexity.exists_mem_PiP_of_mem_SigmaP_succ`: a problem in `Σₖ₊₁` is the projection of a problem in `Πₖ` on pairs. @@ -107,20 +107,20 @@ theorem alternation_truncateBlocks {ps : List (Polynomial ℕ)} {n m : ℕ} (h : /-- Cutting blocks is polynomial-time, for a fixed list of polynomials and lengths `n`, `m` computed in unary. -/ -theorem computableTidilyInPolyTime_truncateBlocks {γ : Type} {encIn : γ ↪ List Bool} +theorem computableInPolyTime_truncateBlocks {γ : Type} {encIn : γ ↪ List Bool} (ps : List (Polynomial ℕ)) {N M : γ → ℕ} - (hN : ComputableTidilyInPolyTime N encIn encUnary) - (hM : ComputableTidilyInPolyTime M encIn encUnary) {W : γ → List Bool} - (hW : ComputableTidilyInPolyTime W encIn encBits) : - ComputableTidilyInPolyTime (fun x => truncateBlocks ps (N x) (M x) (W x)) encIn encBits := by + (hN : ComputableInPolyTime N encIn encUnary) + (hM : ComputableInPolyTime M encIn encUnary) {W : γ → List Bool} + (hW : ComputableInPolyTime W encIn encBits) : + ComputableInPolyTime (fun x => truncateBlocks ps (N x) (M x) (W x)) encIn encBits := by induction ps generalizing W with | nil => exact .const [] | cons p ps ih => - exact ComputableTidilyInPolyTime.bitsAppend - (ComputableTidilyInPolyTime.bitsTakeWithInput hW - ((ComputableTidilyInPolyTime.unary_eval p).comp hN)) - (ih (ComputableTidilyInPolyTime.bitsDropWithInput hW - ((ComputableTidilyInPolyTime.unary_eval p).comp hM))) + exact ComputableInPolyTime.bitsAppend + (ComputableInPolyTime.bitsTakeWithInput hW + ((ComputableInPolyTime.unary_eval p).comp hN)) + (ih (ComputableInPolyTime.bitsDropWithInput hW + ((ComputableInPolyTime.unary_eval p).comp hM))) /-! ### Peeling off the first quantifier -/ @@ -147,10 +147,10 @@ theorem exists_mem_PiP_of_mem_SigmaP_succ {k : ℕ} {A : Set α} (hA : A ∈ Sig · have hfst := (ComputableTidilyInPolyTime.fst (encPair enc encBits) encBits) exact .of_tidy <| hV.tidy.comp (((ComputableTidilyInPolyTime.fst _ _).comp hfst).prod (ComputableTidilyInPolyTime.bitsAppend ((ComputableTidilyInPolyTime.snd _ _).comp hfst) - (computableTidilyInPolyTime_truncateBlocks ps - ((ComputableTidilyInPolyTime.encoding_length enc).comp - ((ComputableTidilyInPolyTime.fst _ _).comp hfst)) - ((ComputableTidilyInPolyTime.encoding_length _).comp hfst) (.snd _ _)))) + (computableInPolyTime_truncateBlocks ps + (.of_tidy ((ComputableTidilyInPolyTime.encoding_length enc).comp + ((ComputableTidilyInPolyTime.fst _ _).comp hfst))) + (.of_tidy ((ComputableTidilyInPolyTime.encoding_length _).comp hfst)) (.of_tidy (.snd _ _))).tidy)) · exact (alternation_truncateBlocks (hle y) (P := fun w => V (y.1, y.2 ++ w) = true)).symm end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean b/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean index bede5cfba..f84dddb0e 100644 --- a/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean +++ b/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean @@ -347,8 +347,10 @@ def verifier (enc : α ↪ List Bool) (p : Polynomial ℕ) (V : α × List Bool `verifier enc p V`. -/ @[fun_prop] theorem verifier_polyTime {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : - ComputableTidilyInPolyTime (verifier enc p V) (encPair enc encBits) encBool := by + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : + ComputableInPolyTime (verifier enc p V) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ unfold verifier shiftAccepts trialSeed shifts runs halfRuns fun_prop @@ -452,7 +454,7 @@ theorem BPP_subset_SigmaP_two : BPP enc ⊆ SigmaP 2 enc := by rintro A ⟨p, V, hV, hA⟩ exact ⟨[SipserLautemann.witnessPoly p, SipserLautemann.seedPoly p], SipserLautemann.verifier enc p V, rfl, - .of_tidy (SipserLautemann.verifier_polyTime hV.tidy), + (SipserLautemann.verifier_polyTime hV), SipserLautemann.isAlternatingVerifier_verifier hA⟩ /-- **The Sipser–Gács–Lautemann theorem (`Π₂` form)**: every problem in `BPP` lies in `Π₂`, diff --git a/Complexity/Computability/Complexity/Classes/PP/Bit.lean b/Complexity/Computability/Complexity/Classes/PP/Bit.lean index 6337fec2b..071a4615a 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Bit.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Bit.lean @@ -64,9 +64,9 @@ theorem exists_SharpP_testBit_of_mem_PP {α : Type} {enc : α ↪ List Bool} {A let count := fun a => acceptCount V a (p.eval (enc a).length) have hcount : count ∈ SharpP enc := ⟨p, V, hV, fun _ => rfl⟩ have hshift : (fun a => 2 ^ p.eval (enc a).length - 1) ∈ SharpP enc := - mem_SharpP_of_polyTime ((ComputableTidilyInPolyTime.binary_two_pow.comp + mem_SharpP_of_polyTime (.of_tidy ((ComputableTidilyInPolyTime.binary_two_pow.comp (by fun_prop : ComputableTidilyInPolyTime - (fun a => p.eval (enc a).length) enc encUnary)).binary_sub' (.const 1)) + (fun a => p.eval (enc a).length) enc encUnary)).binary_sub' (.const 1))) refine ⟨count + count + (fun a => 2 ^ p.eval (enc a).length - 1), SharpP.add_mem (SharpP.add_mem hcount hcount) hshift, p + 1, fun a => ?_⟩ rw [h a] diff --git a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean index 7fc7e3ac4..126c1b8d6 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean @@ -98,18 +98,20 @@ verifier accepts the members of the problem, and only them, on at least half of strings. -/ theorem mem_PP_iff_decidesByNonstrictMajority {A : Set α} : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p V A := by - constructor - · intro hA - obtain ⟨p, V, hV, h⟩ := mem_PP_iff_tidy.mp (compl_mem_PP hA) - refine ⟨p, fun x => !V x, ComputableTidilyInPolyTime.bool_not.comp hV, ?_⟩ - simpa using decidesByMajority_iff_decidesByNonstrictMajority_compl.1 h - · rintro ⟨p, V, hV, h⟩ - have h' : DecidesByMajority enc p (fun x => !V x) Aᶜ := by - rw [decidesByMajority_iff_decidesByNonstrictMajority_compl] - simpa using h - simpa using compl_mem_PP ⟨p, _, .of_tidy (ComputableTidilyInPolyTime.bool_not.comp hV), h'⟩ + have this : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p V A := by + constructor + · intro hA + obtain ⟨p, V, hV, h⟩ := mem_PP_iff_tidy.mp (compl_mem_PP hA) + refine ⟨p, fun x => !V x, ComputableTidilyInPolyTime.bool_not.comp hV, ?_⟩ + simpa using decidesByMajority_iff_decidesByNonstrictMajority_compl.1 h + · rintro ⟨p, V, hV, h⟩ + have h' : DecidesByMajority enc p (fun x => !V x) Aᶜ := by + rw [decidesByMajority_iff_decidesByNonstrictMajority_compl] + simpa using h + simpa using compl_mem_PP ⟨p, _, .of_tidy (ComputableTidilyInPolyTime.bool_not.comp hV), h'⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Reductions -/ diff --git a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean index f90032c01..9885a6e6b 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean @@ -84,7 +84,7 @@ theorem mem_PPWithOracle_iff_exists_GapPWithOracle {L : Set α} : let f₂ a := acceptCount (fun x => !V x) a (p.eval (enc a).length) refine ⟨fun a => (f₁ a : ℤ) - f₂ a, ⟨f₁, ⟨p, V, hV, fun _ => rfl⟩, - f₂, ⟨p, _, hV.map ComputableTidilyInPolyTime.bool_not, fun _ => rfl⟩, + f₂, ⟨p, _, hV.map (.of_tidy ComputableTidilyInPolyTime.bool_not), fun _ => rfl⟩, fun _ => rfl⟩, fun a => ?_⟩ have htotal := acceptCount_add_acceptCount_not V a (p.eval (enc a).length) rw [hL a] @@ -95,14 +95,14 @@ theorem mem_PPWithOracle_iff_exists_GapPWithOracle {L : Set α} : let W₂ := andVerifier (fun a => q.eval (enc a).length) V₂ allFalseVerifier have hfalse : ComputableInPolyTimeWithOracle A (allFalseVerifier (α := α)) (encPair enc encBits) encBool := - computableTidilyInPolyTime_allFalseVerifier.computableInPolyTimeWithOracle A + computableInPolyTime_allFalseVerifier.tidy.computableInPolyTimeWithOracle A have hW₁ : ComputableInPolyTimeWithOracle A W₁ (encPair enc encBits) encBool := - computableInPolyTimeWithOracle_andVerifier (by fun_prop) h₁ hfalse + computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) h₁ hfalse have hW₂ : ComputableInPolyTimeWithOracle A W₂ (encPair enc encBits) encBool := - computableInPolyTimeWithOracle_andVerifier (by fun_prop) h₂ hfalse + computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) h₂ hfalse refine ⟨p + q + 1, selectVerifier W₁ (fun x => !W₂ x), computableInPolyTimeWithOracle_selectVerifier hW₁ - (hW₂.map ComputableTidilyInPolyTime.bool_not), fun a => ?_⟩ + (hW₂.map (.of_tidy ComputableTidilyInPolyTime.bool_not)), fun a => ?_⟩ have hc₁ : acceptCount W₁ a ((p + q).eval (enc a).length) = f₁ a := by simpa only [W₁, Polynomial.eval_add, hf₁ a] using acceptCount_andVerifier_allFalseVerifier (fun a => p.eval (enc a).length) diff --git a/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean b/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean index 6f000655b..49f11275a 100644 --- a/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean +++ b/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean @@ -156,13 +156,13 @@ private theorem newmanAmp_mem_GapP {M r : α → ℕ} {h : α × ℕ → ℤ} GapP.add_mem GapP.one_mem GapP.one_mem have hpow2 : (fun p : (α × ℕ) × ℕ => (2 : ℤ) ^ p.2) ∈ GapP (encPair (encPair enc encUnary) encUnary) := - GapP.pow_mem_polyTime htwo (.snd (encPair enc encUnary) encUnary) + GapP.pow_mem_polyTime htwo (.of_tidy (.snd (encPair enc encUnary) encUnary)) have hbody : (fun p : (α × ℕ) × ℕ => (2 : ℤ) ^ p.2 + h p.1) ∈ GapP (encPair (encPair enc encUnary) encUnary) := - GapP.add_mem hpow2 (GapP.comp_mem hh (.fst (encPair enc encUnary) encUnary)) + GapP.add_mem hpow2 (GapP.comp_mem hh (.of_tidy (.fst (encPair enc encUnary) encUnary))) have hprod : (fun x : α × ℕ => newmanPoly (M x.1) (h x)) ∈ GapP (encPair enc encUnary) := - GapP.prod_range_mem hbody (by fun_prop) - exact GapP.pow_mem_polyTime hprod (by fun_prop) + GapP.prod_range_mem hbody (.of_tidy (by fun_prop)) + exact GapP.pow_mem_polyTime hprod (.of_tidy (by fun_prop)) /-! ### Word weights and truth-table gap construction -/ @@ -193,11 +193,11 @@ private theorem ppTruthTableGap_mem {M r : α → ℕ} {g : α × ℕ → ℤ} { else newmanAmp (M x.1.1) (r x.1.1 + 1) (-g (x.1.1, x.2))) ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.ite_mem (by fun_prop) (GapP.comp_mem hpos hq) (GapP.comp_mem hneg hq) - have hp := GapP.prod_range_mem hs (hr.comp (.fst enc encBits)) + GapP.ite_mem (.of_tidy (by fun_prop)) (GapP.comp_mem hpos (.of_tidy hq)) (GapP.comp_mem hneg (.of_tidy hq)) + have hp := GapP.prod_range_mem hs (.of_tidy (hr.comp (.fst enc encBits))) have hw : ComputableTidilyInPolyTime (fun x => if d x then (1 : ℤ) else -1) (encPair enc encBits) encIntBin := by fun_prop - exact GapP.sum_bits_mem (GapP.mul_mem (mem_GapP_of_polyTime hw) hp) hr + exact GapP.sum_bits_mem (GapP.mul_mem (mem_GapP_of_polyTime (.of_tidy hw)) hp) (.of_tidy hr) private theorem ppWordWeight_eq_prod_univ (M r : α → ℕ) (g : α × ℕ → ℤ) (a : α) (w : Fin (r a) → Bool) : @@ -296,9 +296,11 @@ variable {A : Set (α × ℕ)} {r : α → ℕ} {d : α × List Bool → Bool} polynomial-time unary query count `r`, and a polynomial-time Boolean combiner `d`, the language `{a | d (a, truthTableAnswers A r a) = true}` belongs to `PP enc`. -/ theorem truthTable_mem_PP (hA : A ∈ PP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) - (hd : ComputableTidilyInPolyTime d (encPair enc encBits) encBool) : + (hr : ComputableInPolyTime r enc encUnary) + (hd : ComputableInPolyTime d (encPair enc encBits) encBool) : {a | d (a, truthTableAnswers A r a) = true} ∈ PP enc := by + have hr := hr.tidy + have hd := hd.tidy classical obtain ⟨g₀, hg₀, hAg₀⟩ := mem_PP_iff_exists_GapP.mp hA let g : α × ℕ → ℤ := fun x => (g₀ x + g₀ x) - 1 @@ -347,7 +349,7 @@ theorem PolyTimeTruthTableReducible.mem_PP {β : Type} {encB : β ↪ List Bool} obtain ⟨r, q, d, hr, hq, hd, hL⟩ := h have hqB : q ⁻¹' B ∈ PP (encPair enc encUnary) := PolyTimeReducible.mem_PP ⟨q, hq, fun _ => Iff.rfl⟩ hB - convert truthTable_mem_PP hqB hr.tidy hd.tidy using 1 + convert truthTable_mem_PP hqB hr hd using 1 ext a exact hL a @@ -355,25 +357,27 @@ theorem PolyTimeTruthTableReducible.mem_PP {β : Type} {encB : β ↪ List Bool} /-- `PP` is closed under polynomial-time bounded universal quantification. -/ theorem forall_lt_mem_PP (hA : A ∈ PP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∀ i < r a, (a, i) ∈ A} ∈ PP enc := by + have hr := hr.tidy have hd : ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.all id) (encPair enc encBits) encBool := ComputableTidilyInPolyTime.allWithEncoding (encP := encBool) (encA := encBool) (encL := encBits) (test := fun p : Bool × Bool => p.2) (by fun_prop) (.const false) (.snd enc encBits) - convert truthTable_mem_PP hA hr hd using 1 + convert truthTable_mem_PP hA (.of_tidy hr) (.of_tidy hd) using 1 ext a simp [truthTableAnswers, List.all_eq_true, Fin.forall_iff] /-- `PP` is closed under polynomial-time bounded existential quantification. -/ theorem exists_lt_mem_PP (hA : A ∈ PP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∃ i < r a, (a, i) ∈ A} ∈ PP enc := by + have hr := hr.tidy have hd : ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.any id) (encPair enc encBits) encBool := ComputableTidilyInPolyTime.anyWithEncoding (encP := encBool) (encA := encBool) (encL := encBits) (test := fun p : Bool × Bool => p.2) (by fun_prop) (.const false) (.snd enc encBits) - convert truthTable_mem_PP hA hr hd using 1 + convert truthTable_mem_PP hA (.of_tidy hr) (.of_tidy hd) using 1 ext a simp [truthTableAnswers, List.any_eq_true, Fin.exists_iff] @@ -387,13 +391,13 @@ theorem inter_mem_PP {A B : Set α} (hA : A ∈ PP enc) (hB : B ∈ PP enc) : let C : Set (α × ℕ) := {x | if x.2 = 0 then x.1 ∈ A else x.1 ∈ B} have hC : C ∈ PP (encPair enc encUnary) := by refine mem_PP_iff_exists_GapP.mpr ⟨fun x => if decide (x.2 = 0) then gA x.1 else gB x.1, - GapP.ite_mem (by fun_prop) (GapP.comp_mem hgA (.fst enc encUnary)) - (GapP.comp_mem hgB (.fst enc encUnary)), fun x => ?_⟩ + GapP.ite_mem (.of_tidy (by fun_prop)) (GapP.comp_mem hgA (.of_tidy (.fst enc encUnary))) + (GapP.comp_mem hgB (.of_tidy (.fst enc encUnary))), fun x => ?_⟩ by_cases h : x.2 = 0 <;> simp [C, h, hAg x.1, hBg x.1] have hd : ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.getD 0 false && x.2.getD 1 false) (encPair enc encBits) encBool := by fun_prop - convert truthTable_mem_PP (r := fun _ => 2) hC (by fun_prop) hd using 1 + convert truthTable_mem_PP (r := fun _ => 2) hC (.of_tidy (by fun_prop)) (.of_tidy hd) using 1 ext a simp [C, truthTableAnswers] diff --git a/Complexity/Computability/Complexity/Classes/Padding.lean b/Complexity/Computability/Complexity/Classes/Padding.lean index d87f526b6..6d250d4af 100644 --- a/Complexity/Computability/Complexity/Classes/Padding.lean +++ b/Complexity/Computability/Complexity/Classes/Padding.lean @@ -20,6 +20,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Ba import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain import Complexity.Foundations.Data.Nat.PolynomialBound.Exponential +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Padding @@ -37,7 +38,7 @@ The general timed-reduction API lives in `Cslib.Complexity.preimage_mem_DTIME` computes a reduction and then tidily decides its output; the padding arguments below apply this API to their padded instances. The unconditional deterministic exponential-padding lemma -`Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad` lives in +`Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad` lives in `Complexity.Computability.Complexity.Classes.EXP`. ## The padded problem @@ -115,11 +116,12 @@ noncomputable def checkPadded (ntm : MultiTapeNTM k Bool State) (x : List Bool /-- Checking a padded instance is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_checkPadded (ntm : MultiTapeNTM k Bool State) : - ComputableTidilyInPolyTime ntm.checkPadded (encPair encBits encBits) encBool := by +theorem computableInPolyTime_checkPadded (ntm : MultiTapeNTM k Bool State) : + ComputableInPolyTime ntm.checkPadded (encPair encBits encBits) encBool := by + refine .of_tidy ?_ have hunframe : ComputableTidilyInPolyTime unframe encBits encBits := .of_linear (.of_unframe fun _ => rfl) - exact ntm.computableTidilyInPolyTime_checkChoices.comp + exact (ntm.computableInPolyTime_checkChoices).tidy.comp ((hunframe.comp (.fst encBits encBits)).prod (.snd encBits encBits)) /-- **The padded problem** of `ntm`: the bit words `x` such that some `c * |x|` coins encode an @@ -131,7 +133,7 @@ def padded (ntm : MultiTapeNTM k Bool State) (c : ℕ) : Set (List Bool) := theorem padded_mem_NP (ntm : MultiTapeNTM k Bool State) (c : ℕ) : ntm.padded c ∈ Cslib.Complexity.NP encBits := ⟨Polynomial.C c * Polynomial.X, ntm.checkPadded, - .of_tidy ntm.computableTidilyInPolyTime_checkPadded, + (ntm.computableInPolyTime_checkPadded), fun x => by simp [padded]⟩ /-- **Padded instances.** If `ntm` decides `A` within `t`, then the padded word @@ -162,9 +164,10 @@ nondeterministic machine within time `O(t n)` is decidable deterministically wit `P`, and the padding is written within time `O(n + T n)`. -/ theorem NTIME_subset_iUnion_DTIME_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) {t T : ℕ → ℕ} {S : List Bool → ℕ} - (hpad : ComputableTidilyInO (fun x : List Bool => t x.length) encBits encUnary + (hpad : Turing.MultiTapeTM.ComputableInO (fun x : List Bool => t x.length) encBits encUnary (fun x => T x.length) S) : NTIME enc t ⊆ ⋃ d, DTIME enc fun n => (n + T n + 1) ^ d := by + have hpad := hpad.tidy rintro A ⟨c₁, c₂, k, State, hfinite, ntm, hA⟩ set c := Nat.card (Turing.Action k Bool State) * (c₁ + c₂) obtain ⟨d, hd⟩ := mem_P_iff_exists_mem_DTIME.mp (hNP (ntm.padded_mem_NP c)) @@ -213,8 +216,9 @@ unary in polynomial time with `n ≤ f n`, then every problem decidable by a non within time `O(2 ^ f n)` is decidable deterministically within time `O(2 ^ (d * f n))` for some `d`. -/ theorem NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) - {f : ℕ → ℕ} (hf : ComputableTidilyInPolyTime f encUnary encUnary) (hn : ∀ n, n ≤ f n) : + {f : ℕ → ℕ} (hf : Turing.MultiTapeTM.ComputableInPolyTime f encUnary encUnary) (hn : ∀ n, n ≤ f n) : NTIME enc (fun n => 2 ^ f n) ⊆ ⋃ d, DTIME enc fun n => 2 ^ (d * f n) := by + have hf := hf.tidy intro A hA obtain ⟨d, e, hd⟩ := hf.exists_degree have hpad := ComputableTidilyInO.unary_two_pow.comp (hd.inO.comp ComputableTidilyInO.lengthUnary) @@ -223,7 +227,7 @@ theorem NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P (hNP : NP encBits ⊆ P fun x => x.length + (x.length + 1) ^ d + 2 ^ f x.length := hpad.mono_le (fun x => by simp [encUnary_apply]) fun x => by simp [encUnary_apply] obtain ⟨D, hD⟩ := Set.mem_iUnion.mp (NTIME_subset_iUnion_DTIME_of_NP_subset_P hNP - (T := fun n => n + (n + 1) ^ d + (f n + 1) * 2 ^ f n) hpad' hA) + (T := fun n => n + (n + 1) ^ d + (f n + 1) * 2 ^ f n) (.of_tidy hpad') hA) obtain ⟨C₀, hC₀⟩ := (PolynomiallyBounded.of_forall_le 1 d fun n => by simp only [one_mul]; exact le_rfl).exists_le_mul_two_pow (p := fun n => (n + 1) ^ d) refine Set.mem_iUnion.mpr ⟨2 * D, DTIME_mono_of_le_mul_add (C := (C₀ + 3) ^ D) @@ -254,7 +258,7 @@ theorem NE_subset_E_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) : NE enc ⊆ NTIME_mono (fun n => Nat.pow_le_pow_right (by norm_num) (Nat.mul_le_mul_right n (Nat.le_succ k))) hk obtain ⟨d, hd⟩ := Set.mem_iUnion.mp (NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P hNP - (f := fun n => (k + 1) * n) (by fun_prop) (fun n => Nat.le_mul_of_pos_left n (Nat.succ_pos k)) + (f := fun n => (k + 1) * n) (.of_tidy (by fun_prop)) (fun n => Nat.le_mul_of_pos_left n (Nat.succ_pos k)) hk') exact mem_E_iff.mpr ⟨d * (k + 1), by simpa only [Nat.mul_assoc] using hd⟩ @@ -266,7 +270,7 @@ theorem NEXP_subset_EXP_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) : NEXP e NTIME_mono_of_eventually_le (Filter.eventually_atTop.mpr ⟨1, fun n hn => Nat.pow_le_pow_right (by norm_num) (Nat.pow_le_pow_right hn (Nat.le_succ k))⟩) hk obtain ⟨d, hd⟩ := Set.mem_iUnion.mp (NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P hNP - (ComputableTidilyInPolyTime.unary_pow (k + 1)) (fun n => Nat.le_self_pow (by omega) n) hk') + (.of_tidy (ComputableTidilyInPolyTime.unary_pow (k + 1))) (fun n => Nat.le_self_pow (by omega) n) hk') refine mem_EXP_iff.mpr ⟨k + 2, DTIME_mono_of_eventually_le (Filter.eventually_atTop.mpr ⟨d, fun n hn => Nat.pow_le_pow_right (by norm_num) ?_⟩) hd⟩ rw [pow_succ' n (k + 1)] @@ -299,8 +303,9 @@ some `d`: a deterministic machine writes `g a` to a buffer tape and hands off to fair-coin certificate verifier for `B`. -/ theorem preimage_mem_NTIME_of_mem_NP {B : Set (List Bool)} {g : α → List Bool} {T₀ : ℕ → ℕ} {S : α → ℕ} (hB : B ∈ NP encBits) - (hg : ComputableTidilyInO g enc encBits (fun a => T₀ (enc a).length) S) : + (hg : Turing.MultiTapeTM.ComputableInO g enc encBits (fun a => T₀ (enc a).length) S) : ∃ d, g ⁻¹' B ∈ NTIME enc fun n => (T₀ n + 1) ^ d := by + have hg := hg.tidy obtain ⟨c₀, ⟨k₀, State₀, hfinite₀, tm, htm⟩, -⟩ := hg set t₁ : α → ℕ := fun a => c₀ * (T₀ (enc a).length + 1) have htm_run (a : α) : @@ -397,9 +402,10 @@ theorem preimage_mem_NTIME_of_mem_NP {B : Set (List Bool)} {g : α → List Bool `a ↦ frame (enc a) ++ List.replicate (2 ^ f (enc a).length) true`, where `f` is polynomial-time in unary with `n ≤ f n`, gives a problem in `NEXP enc`. -/ theorem preimage_pad_mem_NEXP {B : Set (List Bool)} (hB : B ∈ NP encBits) {f : ℕ → ℕ} - (hf : ComputableTidilyInPolyTime f encUnary encUnary) (hn : ∀ n, n ≤ f n) : + (hf : Turing.MultiTapeTM.ComputableInPolyTime f encUnary encUnary) (hn : ∀ n, n ≤ f n) : (fun a : α => frame (enc a) ++ List.replicate (2 ^ f (enc a).length) true) ⁻¹' B ∈ NEXP enc := by + have hf := hf.tidy obtain ⟨d₀, e₀, hd₀⟩ := hf.exists_degree have hpad := ComputableTidilyInO.unary_two_pow.comp (hd₀.inO.comp ComputableTidilyInO.lengthUnary) have hpad' : ComputableTidilyInO (fun x : List Bool => 2 ^ f x.length) encBits encUnary @@ -413,7 +419,7 @@ theorem preimage_pad_mem_NEXP {B : Set (List Bool)} (hB : B ∈ NP encBits) {f : 2 ^ f (enc a).length)) := (ComputableTidilyInO.of_linear (.of_frame (f := id) (encOut := encFramed enc) fun _ => rfl)).append (hpad'.comp_enc enc) fun _ => rfl - obtain ⟨D, hD⟩ := preimage_mem_NTIME_of_mem_NP hB hg + obtain ⟨D, hD⟩ := preimage_mem_NTIME_of_mem_NP hB (.of_tidy hg) obtain ⟨C₀, hC₀⟩ := (PolynomiallyBounded.of_forall_le 1 d₀ fun n => by simp only [one_mul]; exact le_rfl).exists_le_mul_two_pow (p := fun n => (n + 1) ^ d₀) obtain ⟨c_f, d_f, hf_le⟩ := hf.polyBounded_length.exists_le diff --git a/Complexity/Computability/Complexity/Classes/ParityP.lean b/Complexity/Computability/Complexity/Classes/ParityP.lean index 6d5650ee2..7062dd290 100644 --- a/Complexity/Computability/Complexity/Classes/ParityP.lean +++ b/Complexity/Computability/Complexity/Classes/ParityP.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.Complexity.Classes.Operators import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Foundations.Data.BitString.WordCount +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # The class parity-P @@ -101,20 +102,20 @@ end Counting /-- `succTest` is polynomial-time, with a test that may use the input. -/ @[fun_prop] -theorem computableTidilyInPolyTime_succTest {γ : Type} {input : γ ↪ List Bool} +theorem computableInPolyTime_succTest {γ : Type} {input : γ ↪ List Bool} {g : γ → List Bool → Bool} {w : γ → List Bool} - (hg : ComputableTidilyInPolyTime (fun p : γ × List Bool => g p.1 p.2) (encPair input encBits) + (hg : ComputableInPolyTime (fun p : γ × List Bool => g p.1 p.2) (encPair input encBits) encBool) - (hw : ComputableTidilyInPolyTime w input encBits) : - ComputableTidilyInPolyTime (fun x => succTest (g x) (w x)) input encBool := by + (hw : ComputableInPolyTime w input encBits) : + ComputableInPolyTime (fun x => succTest (g x) (w x)) input encBool := by unfold succTest fun_prop /-- `succVerifier V` is polynomial-time when `V` is. -/ @[fun_prop] -theorem computableTidilyInPolyTime_succVerifier {enc : α ↪ List Bool} - {V : α × List Bool → Bool} (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : - ComputableTidilyInPolyTime (succVerifier V) (encPair enc encBits) encBool := by +theorem computableInPolyTime_succVerifier {enc : α ↪ List Bool} + {V : α × List Bool → Bool} (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : + ComputableInPolyTime (succVerifier V) (encPair enc encBits) encBool := by unfold succVerifier fun_prop @@ -131,17 +132,21 @@ variable {enc : α ↪ List Bool} {L : Set α} /-- **`⊕P` through verifiers.** -/ theorem mem_ParityP : L ∈ ParityP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ ∀ a, a ∈ L ↔ Odd (acceptCount V a (p.eval (enc a).length)) := by - classical - constructor - · rintro ⟨p, L', ⟨f, hf, hL'⟩, h⟩ - refine ⟨p, f, hf.tidy, fun a => (h a).trans ?_⟩ - rw [acceptCount_congr (W := f) fun w => by simp [hL' (a, w)]] - · rintro ⟨p, V, hV, h⟩ - refine ⟨p, {x | V x = true}, ⟨V, .of_tidy hV, fun _ => Iff.rfl⟩, fun a => (h a).trans ?_⟩ - exact Iff.of_eq (congrArg Odd (acceptCount_congr (W := V) (fun w => by simp) _).symm) - + have this : L ∈ ParityP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a, a ∈ L ↔ Odd (acceptCount V a (p.eval (enc a).length)) := by + classical + constructor + · rintro ⟨p, L', ⟨f, hf, hL'⟩, h⟩ + refine ⟨p, f, hf.tidy, fun a => (h a).trans ?_⟩ + rw [acceptCount_congr (W := f) fun w => by simp [hL' (a, w)]] + · rintro ⟨p, V, hV, h⟩ + refine ⟨p, {x | V x = true}, ⟨V, .of_tidy hV, fun _ => Iff.rfl⟩, fun a => (h a).trans ?_⟩ + exact Iff.of_eq (congrArg Odd (acceptCount_congr (W := V) (fun w => by simp) _).symm) + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this + +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`⊕P` through `#P`**: a problem is in `⊕P` exactly when it is the set of instances where some function in `#P` is odd. -/ theorem mem_ParityP_iff_exists_SharpP : @@ -160,6 +165,8 @@ theorem compl_mem_ParityP (hL : L ∈ ParityP enc) : Lᶜ ∈ ParityP enc := by rw [Set.mem_compl_iff, h a, Polynomial.eval_add, Polynomial.eval_one, odd_acceptCount_succVerifier_iff] +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`P ⊆ ⊕P`**: a decider accepts the empty string or nothing. -/ theorem P_subset_ParityP : P enc ⊆ ParityP enc := by rintro L ⟨f, hf, h⟩ diff --git a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean index fb66a6c13..d7122b471 100644 --- a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean +++ b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean @@ -191,8 +191,10 @@ def PromiseP (enc : α ↪ List Bool) : Set (PromiseProblem α) := promiseClass /-- **Goldreich's definition of promise-P**: a promise problem is in `PromiseP` when a polynomial-time function solves it. -/ theorem mem_PromiseP_iff : - Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableTidilyInPolyTime f enc encBool ∧ Q.SolvedBy f := - mem_promiseClass_iff_solvedBy fun _ => mem_P_iff_tidy + Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableInPolyTime f enc encBool ∧ Q.SolvedBy f := by + have this : Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableTidilyInPolyTime f enc encBool ∧ Q.SolvedBy f := + mem_promiseClass_iff_solvedBy fun _ => mem_P_iff_tidy + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this @[simp] theorem ofSet_mem_PromiseP {A : Set α} : ofSet A ∈ PromiseP enc ↔ A ∈ P enc := ofSet_mem_promiseClass @@ -211,18 +213,20 @@ def PromiseNP (enc : α ↪ List Bool) : Set (PromiseProblem α) := promiseClass polynomial-time verifier accepts some certificate for every yes-instance and none for any no-instance. -/ theorem mem_PromiseNP_iff : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a ∈ Q.yes, ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true) ∧ ∀ a ∈ Q.no, ∀ w : List Bool, w.length = p.eval (enc a).length → V (a, w) = false := by - constructor - · rintro ⟨A, ⟨p, V, hV, h⟩, hyes, hno⟩ - refine ⟨p, V, hV.tidy, fun a ha => (h a).1 (hyes ha), fun a ha w hw => ?_⟩ - rw [← Bool.not_eq_true] - exact fun hVw => Set.disjoint_right.1 hno ha ((h a).2 ⟨w, hw, hVw⟩) - · rintro ⟨p, V, hV, hyes, hno⟩ - refine ⟨{a | ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true}, - ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩, hyes, Set.disjoint_right.2 fun a ha ⟨w, hw, hVw⟩ => ?_⟩ - simp [hno a ha w hw] at hVw + have this : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a ∈ Q.yes, ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true) ∧ ∀ a ∈ Q.no, ∀ w : List Bool, w.length = p.eval (enc a).length → V (a, w) = false := by + constructor + · rintro ⟨A, ⟨p, V, hV, h⟩, hyes, hno⟩ + refine ⟨p, V, hV.tidy, fun a ha => (h a).1 (hyes ha), fun a ha w hw => ?_⟩ + rw [← Bool.not_eq_true] + exact fun hVw => Set.disjoint_right.1 hno ha ((h a).2 ⟨w, hw, hVw⟩) + · rintro ⟨p, V, hV, hyes, hno⟩ + refine ⟨{a | ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true}, + ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩, hyes, Set.disjoint_right.2 fun a ha ⟨w, hw, hVw⟩ => ?_⟩ + simp [hno a ha w hw] at hVw + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this @[simp] theorem ofSet_mem_PromiseNP {A : Set α} : ofSet A ∈ PromiseNP enc ↔ A ∈ NP enc := ofSet_mem_promiseClass diff --git a/Complexity/Computability/Complexity/Classes/RP.lean b/Complexity/Computability/Complexity/Classes/RP.lean index 39be6e195..a5e44e3e3 100644 --- a/Complexity/Computability/Complexity/Classes/RP.lean +++ b/Complexity/Computability/Complexity/Classes/RP.lean @@ -211,12 +211,14 @@ exactly when, for every polynomial `q`, it is decided in polynomial time with on most `2 ^ (-q(n))`. -/ theorem mem_RP_iff_forall_decidesWithOneSidedErrorExponent {A : Set α} : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent enc q p V A := by - refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨q * p, _, - computableTidilyInPolyTime_repeatAny hV.tidy _ _, h.repeatAny q⟩, fun h => ?_⟩ - obtain ⟨p, V, hV, h⟩ := h 1 - exact ⟨p, V, .of_tidy hV, h.decidesWithOneSidedError fun _ => by simp⟩ + have this : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent enc q p V A := by + refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨q * p, _, + (computableInPolyTime_repeatAny hV _ _).tidy, h.repeatAny q⟩, fun h => ?_⟩ + obtain ⟨p, V, hV, h⟩ := h 1 + exact ⟨p, V, .of_tidy hV, h.decidesWithOneSidedError fun _ => by simp⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- **`RP ⊆ BPP`** [Arora and Barak, Chapter 7][AroraBarak09]: two runs of a one-sided-error decider reject a member with probability at most `1 / 4`. -/ diff --git a/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean b/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean index 8c9d2e0f1..53df0b00c 100644 --- a/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean +++ b/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Poly public import Mathlib.Algebra.Polynomial.Eval.Defs import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Foundations.Data.List.OfFn +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # Deterministic computations on repeated random-tape blocks @@ -33,9 +34,9 @@ the separate probabilistic-program interface for independently sampled runs. ## Main results * `Cslib.Complexity.repeatVotes_ofFn`: votes on a full tape agree with finite block evaluation. -* `Cslib.Complexity.computableTidilyInPolyTime_repeatVotes`: producing votes takes polynomial time. -* `Cslib.Complexity.computableTidilyInPolyTime_repeatAny`, - `Cslib.Complexity.computableTidilyInPolyTime_repeatMajority`: efficient aggregation. +* `Cslib.Complexity.computableInPolyTime_repeatVotes`: producing votes takes polynomial time. +* `Cslib.Complexity.computableInPolyTime_repeatAny`, + `Cslib.Complexity.computableInPolyTime_repeatMajority`: efficient aggregation. ## References @@ -74,13 +75,17 @@ theorem repeatVotes_ofFn {trials width : ℕ} {V : α × List Bool → Bool} (a /-- Producing votes takes polynomial time when the verifier and the unary dimensions do. The dimensions may depend on the complete input, and output uses the raw bit-list encoding. -/ @[fun_prop] -theorem computableTidilyInPolyTime_repeatVotes {enc : α ↪ List Bool} +theorem computableInPolyTime_repeatVotes {enc : α ↪ List Bool} {V : α × List Bool → Bool} {trials width : α × List Bool → ℕ} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) - (htrials : ComputableTidilyInPolyTime trials (encPair enc encBits) encUnary) - (hwidth : ComputableTidilyInPolyTime width (encPair enc encBits) encUnary) : - ComputableTidilyInPolyTime (fun input => repeatVotes (trials input) (width input) V input) + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) + (htrials : ComputableInPolyTime trials (encPair enc encBits) encUnary) + (hwidth : ComputableInPolyTime width (encPair enc encBits) encUnary) : + ComputableInPolyTime (fun input => repeatVotes (trials input) (width input) V input) (encPair enc encBits) encBits := by + have hV := hV.tidy + have htrials := htrials.tidy + have hwidth := hwidth.tidy + refine .of_tidy ?_ unfold repeatVotes fun_prop @@ -95,11 +100,14 @@ def repeatMajority (enc : α ↪ List Bool) (r p : Polynomial ℕ) (V : α × Li variable {enc : α ↪ List Bool} +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Majority votes of a polynomial-time decider take polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_repeatMajority {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (r p : Polynomial ℕ) : - ComputableTidilyInPolyTime (repeatMajority enc r p V) (encPair enc encBits) encBool := by +theorem computableInPolyTime_repeatMajority {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (r p : Polynomial ℕ) : + ComputableInPolyTime (repeatMajority enc r p V) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ unfold repeatMajority fun_prop @@ -122,11 +130,14 @@ def repeatAny (enc : α ↪ List Bool) (q p : Polynomial ℕ) (V : α × List Bo variable {enc : α ↪ List Bool} +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Repeating a polynomial-time decider takes polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_repeatAny {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (q p : Polynomial ℕ) : - ComputableTidilyInPolyTime (repeatAny enc q p V) (encPair enc encBits) encBool := by +theorem computableInPolyTime_repeatAny {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (q p : Polynomial ℕ) : + ComputableInPolyTime (repeatAny enc q p V) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ unfold repeatAny fun_prop diff --git a/Complexity/Computability/Complexity/Classes/SBP.lean b/Complexity/Computability/Complexity/Classes/SBP.lean index a8d646cd4..0302c6f29 100644 --- a/Complexity/Computability/Complexity/Classes/SBP.lean +++ b/Complexity/Computability/Complexity/Classes/SBP.lean @@ -78,24 +78,26 @@ theorem mem_SBP_iff_tidy : A ∈ SBP enc ↔ /-- Replacing `(f, k)` by `(2f + 1, 2k + 1)` makes the threshold positive. -/ theorem mem_SBP_iff_exists_pos_threshold : A ∈ SBP enc ↔ - ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by - rw [mem_SBP_iff_tidy] - constructor - · rintro ⟨f, hf, k, hk, hA⟩ - refine ⟨f + f + 1, SharpP.add_mem (SharpP.add_mem hf hf) SharpP.one_mem, - fun a => k a + k a + 1, by fun_prop, - fun a => by positivity, fun a => ?_⟩ - simp only [Pi.add_apply, Pi.one_apply] + have this : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by + rw [mem_SBP_iff_tidy] constructor - · intro ha - have := (hA a).1 ha - lia - · intro ha - have := (hA a).2 ha - lia - · rintro ⟨f, hf, k, hk, -, hA⟩ - exact ⟨f, hf, k, hk, hA⟩ + · rintro ⟨f, hf, k, hk, hA⟩ + refine ⟨f + f + 1, SharpP.add_mem (SharpP.add_mem hf hf) SharpP.one_mem, + fun a => k a + k a + 1, by fun_prop, + fun a => by positivity, fun a => ?_⟩ + simp only [Pi.add_apply, Pi.one_apply] + constructor + · intro ha + have := (hA a).1 ha + lia + · intro ha + have := (hA a).2 ha + lia + · rintro ⟨f, hf, k, hk, -, hA⟩ + exact ⟨f, hf, k, hk, hA⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- Threshold one recognizes precisely the positive #P counts. -/ theorem NP_subset_SBP : NP enc ⊆ SBP enc := by @@ -132,7 +134,7 @@ theorem BPP_subset_SBP : BPP enc ⊆ SBP enc := by theorem SBP_subset_PP : SBP enc ⊆ PP enc := by rintro A ⟨f, hf, k, hk, hA⟩ have hg := GapP.sub_mem' (SharpP.natCast_mem_GapP (SharpP.add_mem hf hf)) - (SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime hk.tidy)) + (SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime hk)) refine mem_PP_iff_exists_GapP.mpr ⟨_, GapP.add_mem hg GapP.one_mem, fun a => ?_⟩ change a ∈ A ↔ 0 < ((f a + f a : ℕ) : ℤ) - (k a : ℤ) + 1 by_cases ha : a ∈ A @@ -148,15 +150,15 @@ theorem PolyTimeReducible.mem_SBP {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ SBP encB) : A ∈ SBP enc := by obtain ⟨r, hr, hAB⟩ := h obtain ⟨f, hf, k, hk, hB⟩ := hB - exact ⟨f ∘ r, SharpP.comp_mem hf hr.tidy, k ∘ r, hk.comp hr, fun a => by + exact ⟨f ∘ r, SharpP.comp_mem hf hr, k ∘ r, hk.comp hr, fun a => by simpa only [Function.comp_apply, ← hAB a] using hB (r a)⟩ /-- Normalize two positive thresholds by cross multiplication, then square and add the counts. -/ theorem union_mem_SBP (hA : A ∈ SBP enc) (hB : B ∈ SBP enc) : A ∪ B ∈ SBP enc := by obtain ⟨f, hf, k, hk, hkpos, hA⟩ := mem_SBP_iff_exists_pos_threshold.mp hA obtain ⟨g, hg, l, hl, hlpos, hB⟩ := mem_SBP_iff_exists_pos_threshold.mp hB - have hfl := SharpP.mul_mem hf (mem_SharpP_of_polyTime hl) - have hgk := SharpP.mul_mem hg (mem_SharpP_of_polyTime hk) + have hfl := SharpP.mul_mem hf (mem_SharpP_of_polyTime (.of_tidy hl)) + have hgk := SharpP.mul_mem hg (mem_SharpP_of_polyTime (.of_tidy hk)) refine ⟨_, SharpP.add_mem (SharpP.pow_mem hfl 2) (SharpP.pow_mem hgk 2), fun a => (k a * l a) ^ 2, by fun_prop, fun a => ?_⟩ change (a ∈ A ∪ B → (k a * l a) ^ 2 ≤ (f a * l a) ^ 2 + (g a * k a) ^ 2) ∧ @@ -185,17 +187,19 @@ closure under input-dependent powers; see `Complexity/Computability/Complexity/Classes/SBP/Amplification.lean` for the uniform theorem. See [Watson, Section 1.1][Watson2012]. -/ theorem exists_SBP_gap_pow (hA : A ∈ SBP enc) {m : ℕ} (hm : 0 < m) : - ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by - obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA - refine ⟨f ^ m, SharpP.pow_mem hf m, fun a => k a ^ m, - hk.binary_pow' (.const m), fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ - · intro ha - exact Nat.pow_le_pow_left ((h a).1 ha) m - · intro ha - simpa only [Pi.pow_apply, mul_pow] using - Nat.pow_lt_pow_left ((h a).2 ha) (Nat.ne_of_gt hm) + have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by + obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA + refine ⟨f ^ m, SharpP.pow_mem hf m, fun a => k a ^ m, + hk.binary_pow' (.const m), fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ + · intro ha + exact Nat.pow_le_pow_left ((h a).1 ha) m + · intro ha + simpa only [Pi.pow_apply, mul_pow] using + Nat.pow_lt_pow_left ((h a).2 ha) (Nat.ne_of_gt hm) + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- Intersecting an SBP language with a BPP language preserves SBP. Square the SBP gap, amplify BPP beyond the exponential bound on that count, diff --git a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean index 232316422..dbf0150e3 100644 --- a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean @@ -44,18 +44,21 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} /-- Uniform SBP gap strengthening by positive, polynomial-time unary powers. Both the #P numerator and the positive binary-output threshold are raised to the same input-dependent power. -/ theorem exists_SBP_gap_pow_polyTime (hA : A ∈ SBP enc) {r : α → ℕ} - (hr : ComputableTidilyInPolyTime r enc encUnary) (hpos : ∀ a, 0 < r a) : - ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + (hr : ComputableInPolyTime r enc encUnary) (hpos : ∀ a, 0 < r a) : + ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by - obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA - refine ⟨_, SharpP.pow_mem_polyTime hf hr, fun a => k a ^ r a, - hk.binary_pow' hr, fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ - · intro ha - exact Nat.pow_le_pow_left ((h a).1 ha) (r a) - · intro ha - simpa only [mul_pow] using - Nat.pow_lt_pow_left ((h a).2 ha) (Nat.ne_of_gt (hpos a)) + have hr := hr.tidy + have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by + obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA + refine ⟨_, SharpP.pow_mem_polyTime hf (.of_tidy hr), fun a => k a ^ r a, + hk.binary_pow' hr, fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ + · intro ha + exact Nat.pow_le_pow_left ((h a).1 ha) (r a) + · intro ha + simpa only [mul_pow] using + Nat.pow_lt_pow_left ((h a).2 ha) (Nat.ne_of_gt (hpos a)) + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- **Uniform SBP amplification.** One #P witness and one positive polynomial-time binary threshold achieve gap `2 ^ r(a)` for every polynomially bounded requested exponent. The request @@ -63,12 +66,12 @@ need not be computable: the proof uses a fixed length polynomial dominating it, ensure positive repetition even when the request is zero. -/ theorem exists_SBP_gap_pow_polyBounded (hA : A ∈ SBP enc) (r : α → ℕ) (hr : PolyBounded (fun a => (enc a).length) r) : - ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by obtain ⟨c, d, hb⟩ := hr.exists_le let q : Polynomial ℕ := Polynomial.C c * (Polynomial.X + 1) ^ d + 1 - have hq : ComputableTidilyInPolyTime (fun a => q.eval (enc a).length) enc encUnary := by + have hq : ComputableInPolyTime (fun a => q.eval (enc a).length) enc encUnary := by fun_prop have hpos (a : α) : 0 < q.eval (enc a).length := by simp [q] obtain ⟨f, hf, k, hk, hkpos, h⟩ := exists_SBP_gap_pow_polyTime hA hq hpos diff --git a/Complexity/Computability/Complexity/Classes/SPP.lean b/Complexity/Computability/Complexity/Classes/SPP.lean index 5361296e3..866c80dd7 100644 --- a/Complexity/Computability/Complexity/Classes/SPP.lean +++ b/Complexity/Computability/Complexity/Classes/SPP.lean @@ -115,6 +115,6 @@ theorem PolyTimeReducible.mem_SPP {β : Type} {encB : β ↪ List Bool} {B : Set (h : PolyTimeReducible enc encB A B) (hB : B ∈ SPP encB) : A ∈ SPP enc := by obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, hf, hr, hB⟩ := hB - exact ⟨f ∘ g, GapP.comp_mem hf hg.tidy, fun a => hr (g a), fun a => (hAB a).trans (hB (g a))⟩ + exact ⟨f ∘ g, GapP.comp_mem hf hg, fun a => hr (g a), fun a => (hAB a).trans (hB (g a))⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/SPP/FewP.lean b/Complexity/Computability/Complexity/Classes/SPP/FewP.lean index 0a0dbf2e6..95738d282 100644 --- a/Complexity/Computability/Complexity/Classes/SPP/FewP.lean +++ b/Complexity/Computability/Complexity/Classes/SPP/FewP.lean @@ -53,7 +53,7 @@ exactly when `c` is the largest certificate above the last one listed. ## Main results * `Cslib.Complexity.SortedSubsets.signedSum_eq`: the signed count of the listings. -* `Cslib.Complexity.SortedSubsets.computableTidilyInPolyTime_verifier`: the verifier is +* `Cslib.Complexity.SortedSubsets.computableInPolyTime_verifier`: the verifier is polynomial-time. * `Cslib.Complexity.FewP_subset_SPP`: **`FewP ⊆ SPP`**. @@ -321,10 +321,12 @@ private theorem length_encState_step (acc : List Bool → Bool) (s : State) (slo List.length_tail] <;> omega /-- **The verifiers are polynomial-time.** -/ -theorem computableTidilyInPolyTime_verifier {enc : α ↪ List Bool} {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (p q : Polynomial ℕ) +theorem computableInPolyTime_verifier {enc : α ↪ List Bool} {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (p q : Polynomial ℕ) (b : Bool) : - ComputableTidilyInPolyTime (verifier enc p q V b) (encPair enc encBits) encBool := by + ComputableInPolyTime (verifier enc p q V b) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ have hP : ComputableTidilyInPolyTime (fun x : α × List Bool => p.eval (enc x.1).length + 1) (encPair enc encBits) encUnary := by fun_prop have hQ : ComputableTidilyInPolyTime (fun x : α × List Bool => q.eval (enc x.1).length) @@ -370,9 +372,9 @@ theorem FewP_subset_SPP : FewP enc ⊆ SPP enc := by set O : α → ℕ := fun a => acceptCount (verifier enc p q V true) a ((q * (p + 1)).eval (enc a).length) with hO_def have hE : E ∈ SharpP enc := - ⟨q * (p + 1), _, .of_tidy (computableTidilyInPolyTime_verifier hV.tidy p q false), fun _ => rfl⟩ + ⟨q * (p + 1), _, (computableInPolyTime_verifier hV p q false), fun _ => rfl⟩ have hO : O ∈ SharpP enc := - ⟨q * (p + 1), _, .of_tidy (computableTidilyInPolyTime_verifier hV.tidy p q true), fun _ => rfl⟩ + ⟨q * (p + 1), _, (computableInPolyTime_verifier hV p q true), fun _ => rfl⟩ have hdiff (a : α) : (E a : ℤ) - O a = if 0 < f a then 0 else 1 := by have hsum : (E a : ℤ) - O a = signedSum (fun c => V (a, c)) (p.eval (enc a).length) (q.eval (enc a).length) init := by diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean index bf818c27e..5ad4f59af 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean @@ -47,14 +47,15 @@ variable {α : Type} {enc : α ↪ List Bool} /-- Summing a uniform #P family over all words of a polynomial-time unary length preserves #P. -/ theorem SharpP.sum_bits_mem {f : α × List Bool → ℕ} {r : α → ℕ} (hf : f ∈ SharpP (encPair enc encBits)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∑ w : Fin (r a) → Bool, f (a, List.ofFn w)) ∈ SharpP enc := by + have hr := hr.tidy obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf let q : α → ℕ := fun a => p.eval (2 * (enc a).length + 1 + r a) let W : α × List Bool → Bool := fun x => V ((x.1, x.2.take (r x.1)), x.2.drop (r x.1)) have hq : ComputableTidilyInPolyTime q enc encUnary := by dsimp [q]; fun_prop have hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool := by dsimp [W]; fun_prop - convert mem_SharpP_of_polyTime_length hW (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hq)) + convert mem_SharpP_of_polyTime_length (.of_tidy hW) (.of_tidy (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hq))) using 1 ext a change _ = acceptCount W a (r a + q a) @@ -69,7 +70,7 @@ theorem SharpP.sum_bits_mem {f : α × List Bool → ℕ} {r : α → ℕ} /-- GapP is closed under summing over all words of a polynomial-time unary length. -/ theorem GapP.sum_bits_mem {g : α × List Bool → ℤ} {r : α → ℕ} (hg : g ∈ GapP (encPair enc encBits)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∑ w : Fin (r a) → Bool, g (a, List.ofFn w)) ∈ GapP enc := by obtain ⟨f₁, h₁, f₂, h₂, hg⟩ := hg refine ⟨_, SharpP.sum_bits_mem h₁ hr, _, SharpP.sum_bits_mem h₂ hr, fun a => ?_⟩ @@ -158,10 +159,12 @@ theorem count_sub (r k : α → ℕ) (V W : α × List Bool → Bool) (a : α) : end SignedProduct +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A GapP function raised to an input-dependent polynomial-time unary exponent is in GapP. -/ theorem GapP.pow_mem_polyTime {g : α → ℤ} {r : α → ℕ} (hg : g ∈ GapP enc) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => g a ^ r a) ∈ GapP enc := by + have hr := hr.tidy obtain ⟨f₁, ⟨p₁, V₁, hV₁, hf₁⟩, f₂, ⟨p₂, V₂, hV₂, hf₂⟩, hg⟩ := hg replace hV₁ := hV₁.tidy replace hV₂ := hV₂.tidy @@ -173,8 +176,8 @@ theorem GapP.pow_mem_polyTime {g : α → ℤ} {r : α → ℕ} (hg : g ∈ GapP have hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool := by dsimp [W]; fun_prop have hlength := ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk) refine ⟨_, - mem_SharpP_of_polyTime_length (SignedProduct.polyTime_verifier hr hk hV hW false) hlength, - _, mem_SharpP_of_polyTime_length (SignedProduct.polyTime_verifier hr hk hV hW true) hlength, + mem_SharpP_of_polyTime_length (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW false)) (.of_tidy hlength), + _, mem_SharpP_of_polyTime_length (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW true)) (.of_tidy hlength), fun a => ?_⟩ change g a ^ r a = (acceptCount (SignedProduct.verifier r k V W false) a (r a * k a) : ℤ) - diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Characterization.lean b/Complexity/Computability/Complexity/Classes/SharpP/Characterization.lean index 43acec1e6..c7c3730e6 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Characterization.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Characterization.lean @@ -49,7 +49,7 @@ variable {α : Type} Preparation, framing, buffers and tidy restoration are included in the polynomial clock. -/ theorem exists_verifier_counting_machine (enc : α ↪ List Bool) (p : Polynomial ℕ) (verifier : α × List Bool → Bool) - (hverify : ComputableTidilyInPolyTime verifier (encPair enc encBits) encBool) : + (hverify : ComputableInPolyTime verifier (encPair enc encBits) encBool) : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) (clock : Polynomial ℕ), machine.Nonblocking ∧ ∀ a, machine.HaltsWithin (clock.eval (enc a).length) (Cfg.init machine.initial (enc a)) ∧ @@ -58,6 +58,7 @@ theorem exists_verifier_counting_machine (enc : α ↪ List Bool) (p : Polynomia machine.rejectCount (clock.eval (enc a).length) (Cfg.init machine.initial (enc a)) = 2 ^ (p.eval (enc a).length) - Complexity.acceptCount verifier a (p.eval (enc a).length) := by + have hverify := hverify.tidy obtain ⟨k, State, hfinite, machine, clock, hnon, hm⟩ := exists_verifier_machine enc p verifier hverify refine ⟨k, State, hfinite, machine, clock, hnon, fun a => ?_⟩ @@ -109,7 +110,7 @@ theorem mem_SharpP_iff_exists_machine : constructor · rintro ⟨p, verifier, hverify, hf⟩ obtain ⟨k, State, hfinite, machine, clock, hnon, hm⟩ := - MultiTapeCTM.exists_verifier_counting_machine enc p verifier hverify.tidy + MultiTapeCTM.exists_verifier_counting_machine enc p verifier hverify exact ⟨k, State, hfinite, machine, clock, hnon, fun a => ⟨(hm a).1, (hm a).2.1.trans (hf a).symm⟩⟩ · rintro ⟨k, State, hfinite, machine, clock, _, hm⟩ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean b/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean index 9c6082ca0..1bc14d5f1 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean @@ -235,9 +235,11 @@ end GapP /-- A polynomial-time unary certificate length can be padded without changing the count. -/ theorem mem_SharpP_of_polyTime_length {V : α × List Bool → Bool} {r : α → ℕ} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) + (hr : ComputableInPolyTime r enc encUnary) : (fun a => acceptCount V a (r a)) ∈ SharpP enc := by + have hV := hV.tidy + have hr := hr.tidy obtain ⟨p, hle⟩ := hr.polyBounded.exists_polynomial refine ⟨p, andVerifier r V allFalseVerifier, by fun_prop, fun a => ?_⟩ obtain ⟨k, hk⟩ := Nat.exists_eq_add_of_le (hle a) @@ -246,18 +248,19 @@ theorem mem_SharpP_of_polyTime_length {V : α × List Bool → Bool} {r : α → /-- Polynomial-time precomposition preserves the exact accepting count. Padding bits are required to be false, so they do not multiply the number of witnesses. -/ theorem SharpP.comp_mem {β : Type} {encB : β ↪ List Bool} {f : β → ℕ} {g : α → β} - (hf : f ∈ SharpP encB) (hg : ComputableTidilyInPolyTime g enc encB) : + (hf : f ∈ SharpP encB) (hg : ComputableInPolyTime g enc encB) : f ∘ g ∈ SharpP enc := by + have hg := hg.tidy obtain ⟨q, W, hW, hWB⟩ := mem_SharpP_iff_tidy.mp hf have h := mem_SharpP_of_polyTime_length (V := fun x => W (g x.1, x.2)) - (r := fun a => q.eval (encB (g a)).length) (by fun_prop) (by fun_prop) + (r := fun a => q.eval (encB (g a)).length) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) change (fun a => acceptCount W (g a) (q.eval (encB (g a)).length)) ∈ SharpP enc at h simpa only [← hWB, Function.comp_def] using h /-- `GapP` is closed under polynomial-time precomposition. -/ theorem GapP.comp_mem {β : Type} {encB : β ↪ List Bool} {f : β → ℤ} {g : α → β} - (hf : f ∈ GapP encB) (hg : ComputableTidilyInPolyTime g enc encB) : + (hf : f ∈ GapP encB) (hg : ComputableInPolyTime g enc encB) : f ∘ g ∈ GapP enc := by obtain ⟨f₁, h₁, f₂, h₂, h⟩ := hf exact ⟨f₁ ∘ g, SharpP.comp_mem h₁ hg, f₂ ∘ g, SharpP.comp_mem h₂ hg, fun a => h (g a)⟩ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean b/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean index ad6133316..db6f33b4e 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean @@ -80,8 +80,8 @@ theorem acceptCount_allFalseVerifier (a : α) (n : ℕ) : acceptCount allFalseVe /-- `allFalseVerifier` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_allFalseVerifier {enc : α ↪ List Bool} : - ComputableTidilyInPolyTime allFalseVerifier (encPair enc encBits) encBool := by +theorem computableInPolyTime_allFalseVerifier {enc : α ↪ List Bool} : + ComputableInPolyTime allFalseVerifier (encPair enc encBits) encBool := by unfold allFalseVerifier fun_prop diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean b/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean index a3ab7849b..2044384de 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean @@ -106,7 +106,7 @@ theorem ParsimoniousReducible.trans (hfg : ParsimoniousReducible encA encB f g) theorem ParsimoniousReducible.mem_SharpP (hfg : ParsimoniousReducible encA encB f g) (hg : g ∈ SharpP encB) : f ∈ SharpP encA := by obtain ⟨r, hr, hfg⟩ := parsimoniousReducible_iff_tidy.mp hfg - have h := SharpP.comp_mem hg hr + have h := SharpP.comp_mem hg (.of_tidy hr) rwa [show g ∘ r = f from funext fun a => (hfg a).symm] at h /-- `#P`-hardness transfers along a parsimonious reduction. -/ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/GapMachine.lean b/Complexity/Computability/Complexity/Classes/SharpP/GapMachine.lean index 8343fbae6..fbcac449c 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/GapMachine.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/GapMachine.lean @@ -50,7 +50,7 @@ variable {α : Type} for the positive sign and `(N-f, N)` for the negative sign. Routing and buffering are charged. -/ theorem exists_signed_verifier_machine (enc : α ↪ List Bool) (p : Polynomial ℕ) (verifier : α × List Bool → Bool) - (hverify : ComputableTidilyInPolyTime verifier (encPair enc encBits) encBool) (sign : Bool) : + (hverify : ComputableInPolyTime verifier (encPair enc encBits) encBool) (sign : Bool) : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) (clock : Polynomial ℕ), machine.Nonblocking ∧ ∀ a, machine.HaltsWithin (clock.eval (enc a).length) (Cfg.init machine.initial (enc a)) ∧ @@ -61,6 +61,7 @@ theorem exists_signed_verifier_machine (enc : α ↪ List Bool) (p : Polynomial (if sign then 2 ^ p.eval (enc a).length - Complexity.acceptCount verifier a (p.eval (enc a).length) else 2 ^ p.eval (enc a).length) := by + have hverify := hverify.tidy obtain ⟨k, State, hfinite, source, sourceClock, hnon, hm⟩ := exists_verifier_machine enc p verifier hverify let machine := (verdictMachine sign).comp source true @@ -116,8 +117,8 @@ theorem exists_signed_verifier_machine (enc : α ↪ List Bool) (p : Polynomial witness lengths. Its signed difference is exact; halted branches acquire no padding choices. -/ theorem exists_verifier_difference_machine (enc : α ↪ List Bool) (p q : Polynomial ℕ) (positive negative : α × List Bool → Bool) - (hpositive : ComputableTidilyInPolyTime positive (encPair enc encBits) encBool) - (hnegative : ComputableTidilyInPolyTime negative (encPair enc encBits) encBool) : + (hpositive : ComputableInPolyTime positive (encPair enc encBits) encBool) + (hnegative : ComputableInPolyTime negative (encPair enc encBits) encBool) : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) (clock : Polynomial ℕ), machine.Nonblocking ∧ ∀ a, machine.HaltsWithin (clock.eval (enc a).length) (Cfg.init machine.initial (enc a)) ∧ @@ -199,8 +200,8 @@ theorem mem_GapP_iff_exists_machine : constructor · rintro ⟨f₁, ⟨p, positive, hpositive, hf₁⟩, f₂, ⟨q, negative, hnegative, hf₂⟩, hg⟩ obtain ⟨k, State, hfinite, machine, clock, hnon, hm⟩ := - MultiTapeCTM.exists_verifier_difference_machine enc p q positive negative hpositive.tidy - hnegative.tidy + MultiTapeCTM.exists_verifier_difference_machine enc p q positive negative hpositive + hnegative refine ⟨k, State, hfinite, machine, clock, hnon, fun a => ⟨(hm a).1, ?_⟩⟩ rw [(hm a).2, hg a, hf₁ a, hf₂ a] · rintro ⟨k, State, hfinite, machine, clock, _, hm⟩ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean b/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean index 8c3214f12..cd9a8ec7c 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean @@ -197,9 +197,9 @@ private theorem replayStepFactor_mem_SharpP [Finite Control] [Finite Operation] have hbit : ComputableTidilyInPolyTime (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop - exact SharpP.ite_mem hquery - (SharpP.ite_mem hbit (SharpP.comp_mem hYes hreq) (SharpP.comp_mem hNo hreq)) - (SharpP.ite_mem hbit SharpP.zero_mem SharpP.one_mem) + exact SharpP.ite_mem (.of_tidy hquery) + (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) (SharpP.comp_mem hNo (.of_tidy hreq))) + (SharpP.ite_mem (.of_tidy hbit) SharpP.zero_mem SharpP.one_mem) private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] (machine : MultiTapePTM tapes Bool Control Operation) {input : α → List Bool} @@ -208,7 +208,7 @@ private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] (hYes : fYes ∈ SharpP encBits) (hNo : fNo ∈ SharpP encBits) : replayPathCount machine input fYes fNo ∈ SharpP (encPair enc encBits) := SharpP.prod_range_mem (replayStepFactor_mem_SharpP machine hinput hYes hNo) - (r := fun x : α × List Bool => x.2.length) (by fun_prop) + (r := fun x : α × List Bool => x.2.length) (.of_tidy (by fun_prop)) private theorem replayWeightedSum_mem_SharpP [Finite Control] [Finite Operation] (machine : MultiTapePTM tapes Bool Control Operation) {input : α → List Bool} @@ -224,9 +224,9 @@ private theorem replayWeightedSum_mem_SharpP [Finite Control] [Finite Operation] (encPair enc encBits) (encPair encBits encBits) := by fun_prop have hout : (fun x : α × List Bool => F (x.1, machine.replayOutput (input x.1) x.2)) ∈ SharpP (encPair enc encBits) := - SharpP.comp_mem hF ((ComputableTidilyInPolyTime.fst enc encBits).prod - (machine.replayOutput_pt.comp hpair)) - exact SharpP.sum_bits_mem (SharpP.mul_mem hpath hout) hT + SharpP.comp_mem hF (.of_tidy ((ComputableTidilyInPolyTime.fst enc encBits).prod + (machine.replayOutput_pt.comp hpair))) + exact SharpP.sum_bits_mem (SharpP.mul_mem hpath hout) (.of_tidy hT) private theorem replayStepFactor_pos_iff (machine : MultiTapePTM tapes Bool Control Operation) (input : α → List Bool) {fYes fNo : List Bool → ℕ} {g : List Bool → Bool} @@ -395,7 +395,7 @@ theorem SharpP.comp_mem_of_computableInPolyTimeWithOracle (hF : F ∈ SharpP encBits) : (F ∘ f) ∈ SharpP enc := SharpP.encoded_comp_mem_of_computableInPolyTimeWithOracle hA_up hA_coup hf - (SharpP.comp_mem hF (.snd enc encBits)) + (SharpP.comp_mem hF (.of_tidy (.snd enc encBits))) /-- **`GapP` precomposition with encoded `FP^(UP ∩ coUP)` outputs.** -/ theorem GapP.encoded_comp_mem_of_computableInPolyTimeWithOracle @@ -417,7 +417,7 @@ theorem GapP.comp_mem_of_computableInPolyTimeWithOracle (hG : G ∈ GapP encBits) : (G ∘ f) ∈ GapP enc := GapP.encoded_comp_mem_of_computableInPolyTimeWithOracle hA_up hA_coup hf - (GapP.comp_mem hG (.snd enc encBits)) + (GapP.comp_mem hG (.of_tidy (.snd enc encBits))) /-! ### Exact characterization of `#P` oracle lowness (`Low(#P) = UP ∩ coUP`) -/ @@ -435,7 +435,7 @@ theorem SharpPWithOracle_eq_SharpP_of_mem_UP_of_mem_coUP (encPair (encPair enc encBits) encBits) encBool := by fun_prop have hF_ind : (fun x : (α × List Bool) × List Bool => if x.2.headD false then 1 else 0) ∈ SharpP (encPair (encPair enc encBits) encBits) := - SharpP.ite_mem hbit SharpP.one_mem SharpP.zero_mem + SharpP.ite_mem (.of_tidy hbit) SharpP.one_mem SharpP.zero_mem have hV_sharp : (fun x : α × List Bool => if V x then 1 else 0) ∈ SharpP (encPair enc encBits) := by convert SharpP.encoded_comp_mem_of_computableInPolyTimeWithOracle hA_up hA_coup hV hF_ind @@ -444,7 +444,7 @@ theorem SharpPWithOracle_eq_SharpP_of_mem_UP_of_mem_coUP simp [encBool_apply] have hr : ComputableTidilyInPolyTime (fun a : α => p.eval (enc a).length) enc encUnary := by fun_prop - have hsum := SharpP.sum_bits_mem hV_sharp hr + have hsum := SharpP.sum_bits_mem hV_sharp (.of_tidy hr) convert hsum using 1 funext a simp only [hf a, acceptCount, card_filter] @@ -461,7 +461,7 @@ zero-bit witness length `p = 0`. -/ theorem indicator_mem_SharpPWithOracle_self (A : Set (List Bool)) : (fun q : List Bool => if q ∈ A then 1 else 0) ∈ SharpPWithOracle A encBits := by obtain ⟨fA, hfA, hA_iff⟩ := mem_PWithOracle_self A - refine ⟨0, fun x => fA x.1, hfA.preprocess (by fun_prop), fun q => ?_⟩ + refine ⟨0, fun x => fA x.1, hfA.preprocess (.of_tidy (by fun_prop)), fun q => ?_⟩ simp only [Polynomial.eval_zero, acceptCount_zero, hA_iff q] open Classical in @@ -469,7 +469,7 @@ open Classical in theorem indicator_compl_mem_SharpPWithOracle_self (A : Set (List Bool)) : (fun q : List Bool => if q ∉ A then 1 else 0) ∈ SharpPWithOracle A encBits := by obtain ⟨fA, hfA, hA_iff⟩ := mem_PWithOracle_self A - refine ⟨0, fun x => !fA x.1, (hfA.preprocess (by fun_prop)).map (by fun_prop), fun q => ?_⟩ + refine ⟨0, fun x => !fA x.1, (hfA.preprocess (.of_tidy (by fun_prop))).map (.of_tidy (by fun_prop)), fun q => ?_⟩ simp only [Polynomial.eval_zero, acceptCount_zero, hA_iff q] cases fA q <;> simp @@ -604,7 +604,7 @@ theorem SBP_subset_SBPWithFixedTarget (A : Set (List Bool)) (enc : α ↪ List B theorem PWithOracle_subset_UPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : PWithOracle A enc ⊆ UPWithOracle A enc := by rintro L ⟨f, hf, hL⟩ - refine mem_UPWithOracle.mpr ⟨0, fun x => f x.1, hf.preprocess (by fun_prop), ?_, ?_⟩ + refine mem_UPWithOracle.mpr ⟨0, fun x => f x.1, hf.preprocess (.of_tidy (by fun_prop)), ?_, ?_⟩ · intro a simp only [Polynomial.eval_zero, acceptCount_zero] split <;> omega diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean index ca7f1e9bb..c3ec3d0de 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean @@ -97,7 +97,7 @@ theorem GapPWithOracle_eq_GapP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : /-- Oracle verifiers can run on disjoint parts of a witness and conjoin their results. -/ theorem computableInPolyTimeWithOracle_andVerifier {k : α → ℕ} - {V₁ V₂ : α × List Bool → Bool} (hk : ComputableTidilyInPolyTime k enc encUnary) + {V₁ V₂ : α × List Bool → Bool} (hk : ComputableInPolyTime k enc encUnary) (h₁ : ComputableInPolyTimeWithOracle A V₁ (encPair enc encBits) encBool) (h₂ : ComputableInPolyTimeWithOracle A V₂ (encPair enc encBits) encBool) : ComputableInPolyTimeWithOracle A (andVerifier k V₁ V₂) (encPair enc encBits) encBool := by @@ -118,7 +118,7 @@ theorem computableInPolyTimeWithOracle_selectVerifier {V₀ V₁ : α × List Bo exact (((h₀.prod h₁).preprocess (input := encPair enc encBits) (g := fun x : α × List Bool => (x.1, x.2.tail))) (by fun_prop)).map_with (g := fun x b => if x.2.headD false then b.2 else b.1) - (output := encBool) (by fun_prop) + (output := encBool) (.of_tidy (by fun_prop)) namespace SharpPWithOracle @@ -135,13 +135,13 @@ theorem add_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpPWithOracle A enc obtain ⟨p₂, V₂, hV₂, hf₂⟩ := h₂ have hfalse : ComputableInPolyTimeWithOracle A (allFalseVerifier (α := α)) (encPair enc encBits) encBool := - computableTidilyInPolyTime_allFalseVerifier.computableInPolyTimeWithOracle A + computableInPolyTime_allFalseVerifier.tidy.computableInPolyTimeWithOracle A refine ⟨p₁ + p₂ + 1, selectVerifier (andVerifier (fun a => p₁.eval (enc a).length) V₁ allFalseVerifier) (andVerifier (fun a => p₂.eval (enc a).length) V₂ allFalseVerifier), computableInPolyTimeWithOracle_selectVerifier - (computableInPolyTimeWithOracle_andVerifier (by fun_prop) hV₁ hfalse) - (computableInPolyTimeWithOracle_andVerifier (by fun_prop) hV₂ hfalse), + (computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) hV₁ hfalse) + (computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) hV₂ hfalse), fun a => ?_⟩ have e₁ := acceptCount_andVerifier_allFalseVerifier (fun a => p₁.eval (enc a).length) V₁ a (p₂.eval (enc a).length) @@ -159,7 +159,7 @@ theorem mul_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpPWithOracle A enc obtain ⟨p₁, V₁, hV₁, hf₁⟩ := h₁ obtain ⟨p₂, V₂, hV₂, hf₂⟩ := h₂ refine ⟨p₁ + p₂, andVerifier (fun a => p₁.eval (enc a).length) V₁ V₂, - computableInPolyTimeWithOracle_andVerifier (by fun_prop) hV₁ hV₂, + computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) hV₁ hV₂, fun a => ?_⟩ rw [Pi.mul_apply, hf₁ a, hf₂ a, Polynomial.eval_add, acceptCount_andVerifier] diff --git a/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean b/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean index 8a634389f..055a6b91b 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean @@ -42,8 +42,9 @@ open Turing.MultiTapeTM variable {α : Type} {enc : α ↪ List Bool} /-- A polynomial-time function with binary natural output is a #P function. -/ -theorem mem_SharpP_of_polyTime {f : α → ℕ} (hf : ComputableTidilyInPolyTime f enc encNat) : +theorem mem_SharpP_of_polyTime {f : α → ℕ} (hf : ComputableInPolyTime f enc encNat) : f ∈ SharpP enc := by + have hf := hf.tidy obtain ⟨p, hb⟩ := hf.polyBounded_length.exists_polynomial refine ⟨p, fun x => decide (BitString.binaryValue x.2 < f x.1), ?_, fun a => ?_⟩ · exact .of_tidy <| ComputableTidilyInPolyTime.binary_lt.comp @@ -58,25 +59,26 @@ theorem mem_SharpP_of_polyTime {f : α → ℕ} (hf : ComputableTidilyInPolyTime exact (Nat.lt_size_self _).le.trans (Nat.pow_le_pow_right (by lia) hsize) /-- A polynomial-time function with binary integer output is a GapP function. -/ -theorem mem_GapP_of_polyTime {f : α → ℤ} (hf : ComputableTidilyInPolyTime f enc encIntBin) : +theorem mem_GapP_of_polyTime {f : α → ℤ} (hf : ComputableInPolyTime f enc encIntBin) : f ∈ GapP enc := by - have hp := mem_SharpP_of_polyTime (ComputableTidilyInPolyTime.intBin_toNat.comp hf) + have hf := hf.tidy + have hp := mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.intBin_toNat.comp hf)) have hn := mem_SharpP_of_polyTime - (ComputableTidilyInPolyTime.intBin_toNat.comp (ComputableTidilyInPolyTime.intBin_neg.comp hf)) + (.of_tidy (ComputableTidilyInPolyTime.intBin_toNat.comp (ComputableTidilyInPolyTime.intBin_neg.comp hf))) exact ⟨_, hp, _, hn, fun a => by simp only [Function.comp_apply]; lia⟩ /-- A polynomial-time Boolean test may select between two #P functions on the same input. Its two Boolean masks are polynomial-time functions; multiplication and addition select the corresponding count exactly. -/ theorem SharpP.ite_mem {c : α → Bool} {f g : α → ℕ} - (hc : ComputableTidilyInPolyTime c enc encBool) + (hc : ComputableInPolyTime c enc encBool) (hf : f ∈ SharpP enc) (hg : g ∈ SharpP enc) : (fun a => if c a then f a else g a) ∈ SharpP enc := by have htrue : (fun a => (c a).toNat) ∈ SharpP enc := - mem_SharpP_of_polyTime ((ComputableTidilyInPolyTime.of_finite Bool.toNat).comp hc) + mem_SharpP_of_polyTime ((ComputableInPolyTime.of_finite Bool.toNat).comp hc) have hfalse : (fun a => (!c a).toNat) ∈ SharpP enc := mem_SharpP_of_polyTime - ((ComputableTidilyInPolyTime.of_finite (fun b : Bool => (!b).toNat)).comp hc) + ((ComputableInPolyTime.of_finite (fun b : Bool => (!b).toNat)).comp hc) convert SharpP.add_mem (SharpP.mul_mem htrue hf) (SharpP.mul_mem hfalse hg) using 1 funext a cases h : c a <;> simp [h] @@ -84,7 +86,7 @@ theorem SharpP.ite_mem {c : α → Bool} {f g : α → ℕ} /-- A polynomial-time Boolean test may select between two GapP functions on the same input. Apply #P selection to the positive and negative counting functions of each branch. -/ theorem GapP.ite_mem {c : α → Bool} {f g : α → ℤ} - (hc : ComputableTidilyInPolyTime c enc encBool) + (hc : ComputableInPolyTime c enc encBool) (hf : f ∈ GapP enc) (hg : g ∈ GapP enc) : (fun a => if c a then f a else g a) ∈ GapP enc := by obtain ⟨f₁, hf₁, f₂, hf₂, hf⟩ := hf diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Power.lean b/Complexity/Computability/Complexity/Classes/SharpP/Power.lean index a7b00e42f..cd896c1bd 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Power.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Power.lean @@ -48,10 +48,14 @@ def powerVerifier (r k : α → ℕ) (V : α × List Bool → Bool) (x : α × L /-- A row count and width computed in unary give a polynomial-time repeated verifier. -/ @[fun_prop] theorem polyTime_powerVerifier {r k : α → ℕ} {V : α × List Bool → Bool} - (hr : ComputableTidilyInPolyTime r enc encUnary) - (hk : ComputableTidilyInPolyTime k enc encUnary) - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : - ComputableTidilyInPolyTime (powerVerifier r k V) (encPair enc encBits) encBool := by + (hr : ComputableInPolyTime r enc encUnary) + (hk : ComputableInPolyTime k enc encUnary) + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : + ComputableInPolyTime (powerVerifier r k V) (encPair enc encBits) encBool := by + have hr := hr.tidy + have hk := hk.tidy + have hV := hV.tidy + refine .of_tidy ?_ unfold powerVerifier fun_prop @@ -67,13 +71,14 @@ theorem acceptCount_powerVerifier (r k : α → ℕ) (V : α × List Bool → Bo /-- A #P function raised to an input-dependent polynomial-time unary exponent remains in #P. -/ theorem pow_mem_polyTime {f : α → ℕ} {r : α → ℕ} (hf : f ∈ SharpP enc) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => f a ^ r a) ∈ SharpP enc := by + have hr := hr.tidy obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf let k : α → ℕ := fun a => p.eval (enc a).length have hk : ComputableTidilyInPolyTime k enc encUnary := by dsimp [k]; fun_prop - convert mem_SharpP_of_polyTime_length (polyTime_powerVerifier hr hk hV) - (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk)) using 1 + convert mem_SharpP_of_polyTime_length (polyTime_powerVerifier (.of_tidy hr) (.of_tidy hk) (.of_tidy hV)) + (.of_tidy (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk))) using 1 ext a change f a ^ r a = acceptCount (powerVerifier r k V) a (r a * k a) rw [acceptCount_powerVerifier, hf] diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean index bcc3ec0a3..5c5e5d3eb 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean @@ -59,10 +59,14 @@ def indexedProductVerifier (r k : α → ℕ) (V : (α × ℕ) × List Bool → /-- Uniform row counts, widths and indexed tests give a polynomial-time product verifier. -/ @[fun_prop] theorem polyTime_indexedProductVerifier {r k : α → ℕ} {V : (α × ℕ) × List Bool → Bool} - (hr : ComputableTidilyInPolyTime r enc encUnary) - (hk : ComputableTidilyInPolyTime k enc encUnary) - (hV : ComputableTidilyInPolyTime V (encPair (encPair enc encUnary) encBits) encBool) : - ComputableTidilyInPolyTime (indexedProductVerifier r k V) (encPair enc encBits) encBool := by + (hr : ComputableInPolyTime r enc encUnary) + (hk : ComputableInPolyTime k enc encUnary) + (hV : ComputableInPolyTime V (encPair (encPair enc encUnary) encBits) encBool) : + ComputableInPolyTime (indexedProductVerifier r k V) (encPair enc encBits) encBool := by + have hr := hr.tidy + have hk := hk.tidy + have hV := hV.tidy + refine .of_tidy ?_ unfold indexedProductVerifier fun_prop @@ -86,13 +90,15 @@ theorem acceptCount_indexedProductVerifier (r k : α → ℕ) simpa only [BitString.listRow_eq_ofFn (k a) ⟨i, hi⟩, BitString.ofList_ofFn, BitString.blocksEquiv_apply] using h ⟨i, hi⟩ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A jointly uniform #P family on an instance and unary index may be multiplied over a polynomial-time unary range. If the original certificate polynomial is `p`, a common row width is `p(2|a|+1+r(a))`, and the unpadded total length is `r(a)` times that width. -/ theorem prod_range_mem {f : α × ℕ → ℕ} {r : α → ℕ} (hf : f ∈ SharpP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∏ i ∈ range (r a), f (a, i)) ∈ SharpP enc := by + have hr := hr.tidy obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf let width : α × ℕ → ℕ := fun x => p.eval ((encPair enc encUnary) x).length let k : α → ℕ := fun a => p.eval (2 * (enc a).length + 1 + r a) @@ -100,8 +106,8 @@ theorem prod_range_mem {f : α × ℕ → ℕ} {r : α → ℕ} have hk : ComputableTidilyInPolyTime k enc encUnary := by dsimp [k]; fun_prop have hW : ComputableTidilyInPolyTime W (encPair (encPair enc encUnary) encBits) encBool := by dsimp [W, width]; fun_prop - convert mem_SharpP_of_polyTime_length (polyTime_indexedProductVerifier hr hk hW) - (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk)) using 1 + convert mem_SharpP_of_polyTime_length (polyTime_indexedProductVerifier (.of_tidy hr) (.of_tidy hk) (.of_tidy hW)) + (.of_tidy (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk))) using 1 ext a change _ = acceptCount (indexedProductVerifier r k W) a (r a * k a) rw [acceptCount_indexedProductVerifier] @@ -147,18 +153,18 @@ polynomial-time unary range. Boolean expansion uses certified #P products and a parity sign, so no general GapP product closure is assumed. -/ theorem GapP.prod_range_mem {g : α × ℕ → ℤ} {r : α → ℕ} (hg : g ∈ GapP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∏ i ∈ range (r a), g (a, i)) ∈ GapP enc := by obtain ⟨f₁, h₁, f₂, h₂, hg⟩ := hg let select : (α × List Bool) × ℕ → ℕ := fun x => if x.1.2.getD x.2 false then f₂ (x.1.1, x.2) else f₁ (x.1.1, x.2) - have hreindex : ComputableTidilyInPolyTime + have hreindex : ComputableInPolyTime (fun x : (α × List Bool) × ℕ => (x.1.1, x.2)) (encPair (encPair enc encBits) encUnary) (encPair enc encUnary) := by fun_prop have hselect : select ∈ SharpP (encPair (encPair enc encBits) encUnary) := SharpP.ite_mem (by fun_prop) (SharpP.comp_mem h₂ hreindex) (SharpP.comp_mem h₁ hreindex) have hprod := SharpP.prod_range_mem hselect (hr.comp (.fst enc encBits)) - have hsign : ComputableTidilyInPolyTime + have hsign : ComputableInPolyTime (fun x : α × List Bool => (-1 : ℤ) ^ x.2.countP id) (encPair enc encBits) encIntBin := by fun_prop have hsum := GapP.sum_bits_mem diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean index 04898d3ae..05466485d 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean @@ -18,6 +18,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Na import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Int.Binary import Complexity.Foundations.Data.Nat.PolynomialBound.Closure import Mathlib.Data.Nat.Size +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Exact counting in polynomial space @@ -36,7 +37,7 @@ its accepting coins with the same counter (`Cslib.Complexity.Interaction.countAc ## Main results * `Cslib.Complexity.streamAcceptCount_eq_acceptCount`: the streaming count is `acceptCount`. -* `Cslib.Complexity.computableTidilyInPolySpace_acceptCount`: count accepted certificates of a +* `Cslib.Complexity.computableInPolySpace_acceptCount`: count accepted certificates of a polynomial-time unary length, with binary output. * `Cslib.Complexity.SharpP.computableTidilyInPolySpace`: every #P function is computable within polynomial space, with binary output. @@ -126,10 +127,13 @@ theorem streamAcceptCount_eq_acceptCount (V : α × List Bool → Bool) (a : α) /-- Count the accepted certificates of a polynomial-time unary length in polynomial space. The result uses binary natural-number output, including when the certificate length is zero. -/ -theorem computableTidilyInPolySpace_acceptCount {V : α × List Bool → Bool} {r : α → ℕ} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) - (hr : ComputableTidilyInPolyTime r enc encUnary) : - ComputableTidilyInPolySpace (fun a => acceptCount V a (r a)) enc encNat := by +theorem computableInPolySpace_acceptCount {V : α × List Bool → Bool} {r : α → ℕ} + (hV : Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool) + (hr : Turing.MultiTapeTM.ComputableInPolyTime r enc encUnary) : + Turing.MultiTapeTM.ComputableInPolySpace (fun a => acceptCount V a (r a)) enc encNat := by + have hV := hV.tidy + have hr := hr.tidy + refine .of_tidy ?_ classical rcases isEmpty_or_nonempty α with hα | hα · exact (ComputableTidilyInPolySpace.of_polyTime @@ -173,7 +177,7 @@ theorem computableTidilyInPolySpace_acceptCount {V : α × List Bool → Bool} { theorem SharpP.computableTidilyInPolySpace {f : α → ℕ} (hf : f ∈ SharpP enc) : ComputableTidilyInPolySpace f enc encNat := by obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf - exact (computableTidilyInPolySpace_acceptCount hV (by fun_prop)).congr fun a => (hf a).symm + exact (computableInPolySpace_acceptCount (.of_tidy hV) (.of_tidy (by fun_prop))).tidy.congr fun a => (hf a).symm /-- Every GapP function is computable in polynomial space with binary sign-magnitude output. -/ theorem GapP.computableTidilyInPolySpace {g : α → ℤ} (hg : g ∈ GapP enc) : diff --git a/Complexity/Computability/Complexity/Classes/SharpP/WeightedReplay.lean b/Complexity/Computability/Complexity/Classes/SharpP/WeightedReplay.lean index 99825a01b..00169ee55 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/WeightedReplay.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/WeightedReplay.lean @@ -63,11 +63,14 @@ positivity assumption on the numerators is needed. -/ theorem GapP.weightedReplay_mem [Finite Control] [Finite Operation] (machine : MultiTapePTM k Bool Control Operation) {input : α → List Bool} {T R : α → ℕ} {H : α × List Bool → ℤ} - (hinput : ComputableTidilyInPolyTime input enc encBits) - (hT : ComputableTidilyInPolyTime T enc encUnary) - (hR : ComputableTidilyInPolyTime R enc encUnary) + (hinput : Turing.MultiTapeTM.ComputableInPolyTime input enc encBits) + (hT : Turing.MultiTapeTM.ComputableInPolyTime T enc encUnary) + (hR : Turing.MultiTapeTM.ComputableInPolyTime R enc encUnary) (hH : H ∈ GapP (encPair enc encBits)) : weightedReplay machine input T R H ∈ GapP enc := by + have hinput := hinput.tidy + have hT := hT.tidy + have hR := hR.tidy let _ := Fintype.ofFinite Operation let cfg : (α × List Bool) × ℕ → FiniteConfig k Bool Control Operation := fun x => machine.replayPrefix (input x.1.1) x.1.2 x.2 @@ -90,16 +93,16 @@ theorem GapP.weightedReplay_mem [Finite Control] [Finite Operation] let p : (α × List Bool) × ℕ → ℤ := fun x => if (machine.pendingQuery (cfg x)).isSome then H (x.1.1, machine.pendingRequest (cfg x)) else 0 have hp : p ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.ite_mem hquery (GapP.comp_mem hH hrequest) GapP.zero_mem + GapP.ite_mem (.of_tidy hquery) (GapP.comp_mem hH (.of_tidy hrequest)) GapP.zero_mem have hdenom : (fun x : (α × List Bool) × ℕ => (2 : ℤ) ^ R x.1.1) ∈ GapP (encPair (encPair enc encBits) encUnary) := - mem_GapP_of_polyTime (by fun_prop) + mem_GapP_of_polyTime (.of_tidy (by fun_prop)) have hbit : ComputableTidilyInPolyTime (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop - have hfactor := GapP.ite_mem hbit hp (GapP.sub_mem' hdenom hp) + have hfactor := GapP.ite_mem (.of_tidy hbit) hp (GapP.sub_mem' hdenom hp) have hprod := GapP.prod_range_mem hfactor - (r := fun x : α × List Bool => x.2.length) (by fun_prop) + (r := fun x : α × List Bool => x.2.length) (.of_tidy (by fun_prop)) have hout : ComputableTidilyInPolyTime (fun x : α × List Bool => (machine.replayOutput (input x.1) x.2).headD false) (encPair enc encBits) encBool := by @@ -110,8 +113,8 @@ theorem GapP.weightedReplay_mem [Finite Control] [Finite Operation] (machine.replayOutput_pt.comp hreindex) have hmask : (fun x : α × List Bool => if (machine.replayOutput (input x.1) x.2).headD false then (1 : ℤ) else 0) ∈ - GapP (encPair enc encBits) := GapP.ite_mem hout GapP.one_mem GapP.zero_mem - have hsum := GapP.sum_bits_mem (GapP.mul_mem hprod hmask) hT + GapP (encPair enc encBits) := GapP.ite_mem (.of_tidy hout) GapP.one_mem GapP.zero_mem + have hsum := GapP.sum_bits_mem (GapP.mul_mem hprod hmask) (.of_tidy hT) convert hsum using 1 funext a rw [weightedReplay, acceptWeight_eq_sum] diff --git a/Complexity/Computability/Complexity/Classes/Space/Closure.lean b/Complexity/Computability/Complexity/Classes/Space/Closure.lean index 477983622..8a9ec3296 100644 --- a/Complexity/Computability/Complexity/Classes/Space/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Space/Closure.lean @@ -17,14 +17,16 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Bi import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Foundations.Data.Nat.PolynomialBound.Closure +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Characterizations and closure properties of `PSPACE` A problem is in `PSPACE` exactly when a Boolean function deciding it is tidily computable within some time and space polynomial in the length of the encoded instance -(`Cslib.Complexity.mem_PSPACE_iff_computableTidilyInO`, -`Cslib.Complexity.mem_PSPACE_iff_computableTidilyInPolySpace`). `PSPACE` is closed under +(`Cslib.Complexity.mem_PSPACE_iff_computableInO`, +`Cslib.Complexity.mem_PSPACE_iff_computableInPolySpace`). `PSPACE` is closed under complement, under polynomial-time reductions, and under polynomially bounded existential quantification [Arora and Barak, Chapter 4][AroraBarak09]. The existential quantifier over the words `w` of length `ℓ` is reachability within two steps from the all-zero word to the all-one word @@ -34,9 +36,9 @@ in place and reusing the space of the decider for each. ## Main results -* `Cslib.Complexity.mem_PSPACE_iff_computableTidilyInO`: `PSPACE` in the quantitative calculus. -* `Cslib.Complexity.mem_PSPACE_iff_computableTidilyInPolySpace`, - `Cslib.Complexity.mem_PSPACE_of_computableTidilyInPolySpace`: `PSPACE` within polynomial space. +* `Cslib.Complexity.mem_PSPACE_iff_computableInO`: `PSPACE` in the quantitative calculus. +* `Cslib.Complexity.mem_PSPACE_iff_computableInPolySpace`, + `Cslib.Complexity.mem_PSPACE_of_computableInPolySpace`: `PSPACE` within polynomial space. * `Cslib.Complexity.compl_mem_PSPACE`, `Cslib.Complexity.inter_mem_PSPACE`, `Cslib.Complexity.union_mem_PSPACE`, `Cslib.Complexity.diff_mem_PSPACE`, `Cslib.Complexity.symmDiff_mem_PSPACE`, `Cslib.Complexity.PSPACE.booleanSubalgebra`, @@ -61,55 +63,64 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} /-- **`PSPACE` in the quantitative calculus**: a problem is in `PSPACE` exactly when a Boolean function deciding it is tidily computable within some time and within space polynomial in the length of the encoded instance. -/ -theorem mem_PSPACE_iff_computableTidilyInO : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), - ComputableTidilyInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ +theorem mem_PSPACE_iff_computableInO : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), + Turing.MultiTapeTM.ComputableInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ ∀ a, a ∈ A ↔ f a = true := by - constructor - · rintro ⟨f, ⟨t, s, hs, hf⟩, hA⟩ - obtain ⟨c, hc⟩ := ComputableInTimeAndSpace.exists_computableTidilyInTimeAndSpace hf - exact ⟨f, fun a => 2 * t a + 3 * s a + c, s, .of_bounds hc (c + 1) (fun a => by nlinarith) - (fun a => by nlinarith) fun a => by - simp only [encBool_apply, List.length_singleton] - exact Nat.mul_pos (Nat.succ_pos c) (Nat.succ_pos (s a)), - hs, hA⟩ - · rintro ⟨f, T, S, ⟨c, hc, -⟩, hS, hA⟩ - exact ⟨f, ⟨_, _, (PolyBounded.const c).mul (hS.add (.const 1)), hc.computableInTimeAndSpace⟩, - hA⟩ + have this : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), ComputableTidilyInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ ∀ a, a ∈ A ↔ f a = true := by + constructor + · rintro ⟨f, ⟨t, s, hs, hf⟩, hA⟩ + obtain ⟨c, hc⟩ := ComputableInTimeAndSpace.exists_computableTidilyInTimeAndSpace hf + exact ⟨f, fun a => 2 * t a + 3 * s a + c, s, .of_bounds hc (c + 1) (fun a => by nlinarith) + (fun a => by nlinarith) fun a => by + simp only [encBool_apply, List.length_singleton] + exact Nat.mul_pos (Nat.succ_pos c) (Nat.succ_pos (s a)), + hs, hA⟩ + · rintro ⟨f, T, S, ⟨c, hc, -⟩, hS, hA⟩ + exact ⟨f, ⟨_, _, (PolyBounded.const c).mul (hS.add (.const 1)), hc.computableInTimeAndSpace⟩, + hA⟩ + simpa only [Turing.MultiTapeTM.computableInO_iff_computableTidilyInO] using this +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in /-- **`PSPACE` within polynomial space**: a problem is in `PSPACE` exactly when a Boolean function deciding it is tidily computable within space polynomial in the length of the encoded instance (`Turing.MultiTapeTM.ComputableTidilyInPolySpace`). -/ -theorem mem_PSPACE_iff_computableTidilyInPolySpace : A ∈ PSPACE enc ↔ - ∃ f : α → Bool, ComputableTidilyInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by - rw [mem_PSPACE_iff_computableTidilyInO] - constructor - · rintro ⟨f, T, S, hf, hS, hA⟩ - exact ⟨f, ⟨T, S, hS, hf⟩, hA⟩ - · rintro ⟨f, ⟨T, S, hS, hf⟩, hA⟩ - exact ⟨f, T, S, hf, hS, hA⟩ +theorem mem_PSPACE_iff_computableInPolySpace : A ∈ PSPACE enc ↔ + ∃ f : α → Bool, Turing.MultiTapeTM.ComputableInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by + have this : A ∈ PSPACE enc ↔ ∃ f : α → Bool, ComputableTidilyInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by + rw [mem_PSPACE_iff_computableInO] + constructor + · rintro ⟨f, T, S, hf, hS, hA⟩ + exact ⟨f, ⟨T, S, hS, hf⟩, hA⟩ + · rintro ⟨f, ⟨T, S, hS, hf⟩, hA⟩ + exact ⟨f, T, S, hf, hS, hA⟩ + simpa only [Turing.MultiTapeTM.computableInPolySpace_iff_computableTidilyInPolySpace] using this /-- A Boolean function computable within polynomial space decides a problem in `PSPACE`. -/ -theorem mem_PSPACE_of_computableTidilyInPolySpace {f : α → Bool} - (hf : ComputableTidilyInPolySpace f enc encBool) (hA : ∀ a, a ∈ A ↔ f a = true) : +theorem mem_PSPACE_of_computableInPolySpace {f : α → Bool} + (hf : Turing.MultiTapeTM.ComputableInPolySpace f enc encBool) (hA : ∀ a, a ∈ A ↔ f a = true) : A ∈ PSPACE enc := - mem_PSPACE_iff_computableTidilyInPolySpace.mpr ⟨f, hf, hA⟩ + mem_PSPACE_iff_computableInPolySpace.mpr ⟨f, hf, hA⟩ +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **`PSPACE` is closed under complement**: negate the answer. -/ theorem compl_mem_PSPACE (hA : A ∈ PSPACE enc) : Aᶜ ∈ PSPACE enc := by - obtain ⟨f, T, S, hf, hS, hA⟩ := mem_PSPACE_iff_computableTidilyInO.mp hA + obtain ⟨f, T, S, hf, hS, hA⟩ := mem_PSPACE_iff_computableInO.mp hA have hnot := (ComputableTidilyInDegree.of_finite (encIn := encBool) (encMid := encBool) Bool.not).inO_one.comp_linear hf - refine mem_PSPACE_iff_computableTidilyInO.mpr ⟨_, T, S, hnot, hS, fun a => ?_⟩ + refine mem_PSPACE_iff_computableInO.mpr ⟨_, T, S, hnot, hS, fun a => ?_⟩ simp [hA a] open scoped symmDiff +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **`PSPACE` is closed under intersection.** -/ theorem inter_mem_PSPACE {B : Set α} (hA : A ∈ PSPACE enc) (hB : B ∈ PSPACE enc) : A ∩ B ∈ PSPACE enc := by - obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableTidilyInPolySpace.mp hA - obtain ⟨g, hg, hB⟩ := mem_PSPACE_iff_computableTidilyInPolySpace.mp hB - exact mem_PSPACE_of_computableTidilyInPolySpace + obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp hA + obtain ⟨g, hg, hB⟩ := mem_PSPACE_iff_computableInPolySpace.mp hB + exact mem_PSPACE_of_computableInPolySpace ((ComputableTidilyInPolySpace.of_polyTime ComputableTidilyInPolyTime.bool_and).comp (hf.prod hg)) fun a => by simp [hA a, hB a] @@ -142,13 +153,15 @@ theorem symmDiff_mem_PSPACE {B : Set α} (hA : A ∈ PSPACE enc) (hB : B ∈ PSP A ∆ B ∈ PSPACE enc := (PSPACE.booleanSubalgebra enc).symmDiff_mem hA hB +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **`PSPACE` is closed under polynomial-time reductions.** -/ theorem PolyTimeReducible.mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ PSPACE encB) : A ∈ PSPACE enc := by obtain ⟨g, hg, hAB⟩ := h - obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableTidilyInO.mp hB + obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableInO.mp hB obtain ⟨Tg, Sg, hSg, hgO⟩ := ComputableTidilyInPolySpace.of_polyTime hg.tidy - exact mem_PSPACE_iff_computableTidilyInO.mpr ⟨f ∘ g, _, _, hf.comp hgO, + exact mem_PSPACE_iff_computableInO.mpr ⟨f ∘ g, _, _, hf.comp hgO, hSg.add (hS.comp hg.polyBounded_length), fun a => (hAB a).trans (hB (g a))⟩ /-- The edges of the graph on words of width `n + 1` whose reachability within two steps from the @@ -184,6 +197,7 @@ private theorem savitch_existsEdge {β : Type} (f : β × List Bool → Bool) (x · simp [existsEdge, List.replicate_succ, hf] · simp [existsEdge, List.replicate_succ] +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **`PSPACE` is closed under polynomially bounded existential quantification**: if `B ⊆ β × List Bool` is in `PSPACE` and `ℓ` is polynomial-time, then so is the set of the `x` for which some word `w` of length `ℓ x` has `(x, w) ∈ B`. The candidates are enumerated in place: this is reachability @@ -192,9 +206,10 @@ decides at depth `1`, reusing the space of the decider of `B` for every candidat (`Cslib.Reachability.computableTidilyInO_savitch`). -/ theorem setOf_exists_mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set (β × List Bool)} {ℓ : β → ℕ} (hB : B ∈ PSPACE (encPair encB encBits)) - (hℓ : ComputableTidilyInPolyTime ℓ encB encUnary) : + (hℓ : Turing.MultiTapeTM.ComputableInPolyTime ℓ encB encUnary) : {x | ∃ w : List Bool, w.length = ℓ x ∧ (x, w) ∈ B} ∈ PSPACE encB := by - obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableTidilyInO.mp hB + have hℓ := hℓ.tidy + obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableInO.mp hB set encQ := encPair encB (encPair encBits encBits) -- the edge test: polynomial-time tests around one call of the decider of `B` have hg : ComputableTidilyInPolyTime (fun q : β × List Bool × List Bool => (q.1, q.2.2.tail)) @@ -253,7 +268,7 @@ theorem setOf_exists_mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set ( fun x => cE * (2 * (encB x).length + 3 * ℓ x + 6) ^ dE := PolyBounded.comp (size' := id) (v := fun n => cE * n ^ dE) (PolyBounded.of_polynomiallyBounded (bound := fun n => cE * n ^ dE) id (by fun_prop)) hG - refine mem_PSPACE_iff_computableTidilyInO.mpr ⟨_, _, _, h, ?_, fun x => ?_⟩ + refine mem_PSPACE_iff_computableInO.mpr ⟨_, _, _, h, ?_, fun x => ?_⟩ · refine (((hSi.add ((PolyBounded.const 2).mul (hℓ'.add (.const 3)))).add .self).add hpow).mono fun x => ?_ have hmax : Cslib.Reachability.edgeMax (fun q : β × List Bool × List Bool => diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean index 234561e14..9f8f565f2 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean @@ -59,7 +59,7 @@ whose state grows by at most one vertex per block, polynomial-time in the graph Generalized Geography. * `Cslib.Complexity.GeneralizedGeography.length_encPlay_step_le`: a block adds at most one vertex to a play. -* `Cslib.Complexity.GeneralizedGeography.computableTidilyInPolyTime_verifier`: the replay is +* `Cslib.Complexity.GeneralizedGeography.computableInPolyTime_verifier`: the replay is polynomial-time. * `Cslib.Complexity.GeneralizedGeography_mem_PSPACE`: Generalized Geography is in `PSPACE`. @@ -435,11 +435,11 @@ variable {γ : Type} {encIn : γ ↪ List Bool} /-- The bits of a move are polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_moverBits {B : γ → ℕ} {first : γ → Bool} - {z : γ → List Bool} (hB : ComputableTidilyInPolyTime B encIn encUnary) - (hfirst : ComputableTidilyInPolyTime first encIn encBool) - (hz : ComputableTidilyInPolyTime z encIn encBits) : - ComputableTidilyInPolyTime (fun x => moverBits (B x) (first x) (z x)) encIn +theorem computableInPolyTime_moverBits {B : γ → ℕ} {first : γ → Bool} + {z : γ → List Bool} (hB : ComputableInPolyTime B encIn encUnary) + (hfirst : ComputableInPolyTime first encIn encBool) + (hz : ComputableInPolyTime z encIn encBits) : + ComputableInPolyTime (fun x => moverBits (B x) (first x) (z x)) encIn (encList encBool) := by unfold moverBits fun_prop @@ -532,8 +532,9 @@ private abbrev encStep : (((Graph × ℕ) × List Bool) × Play) × List Bool /-- **The replay is polynomial-time**: a fold over the blocks whose state grows by at most one vertex per block. -/ -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := by + refine .of_tidy ?_ have hG : ComputableTidilyInPolyTime (fun x : (Graph × ℕ) × List Bool => x.1.1) encInput encGraph := by fun_prop have hB : ComputableTidilyInPolyTime (fun x : (Graph × ℕ) × List Bool => x.1.1.2.length) encInput @@ -564,7 +565,7 @@ theorem computableTidilyInPolyTime_verifier : (fun p : ((((Graph × ℕ) × List Bool) × Play) × List Bool) => moverBits p.1.1.1.1.2.length p.1.2.2.1 p.2) encStep (encList encBool) := - computableTidilyInPolyTime_moverBits (hB.comp hX) (by fun_prop) (snd _ _) + (computableInPolyTime_moverBits (.of_tidy (hB.comp hX)) (.of_tidy (by fun_prop)) (.of_tidy (snd _ _))).tidy have hpair : ComputableTidilyInPolyTime (fun p : ((((Graph × ℕ) × List Bool) × Play) × List Bool) => ((p.1.1.1.1, p.1.2), moverBits p.1.1.1.1.2.length p.1.2.2.1 p.2)) @@ -606,6 +607,6 @@ open GeneralizedGeography Turing.MultiTapeTM /-- **Generalized Geography is in `PSPACE`** [Sipser, Theorem 8.14][Sipser2013]: it is a game of polynomially many moves whose winning condition is polynomial-time. -/ theorem GeneralizedGeography_mem_PSPACE : GeneralizedGeography ∈ PSPACE (encPair encGraph encNat) := - isGameVerifier_verifier.mem_PSPACE computableTidilyInPolyTime_verifier + isGameVerifier_verifier.mem_PSPACE computableInPolyTime_verifier.tidy end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean index 191206127..b6ea4cb6e 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean @@ -60,7 +60,7 @@ mapped to a graph without arcs, where the first player loses * `Cslib.Complexity.GeneralizedGeography.updates_eq_getD_lastIdx`: a variable takes the value of its last quantifier. * `Cslib.Complexity.GeneralizedGeography.reduce_mem_iff`, - `Cslib.Complexity.GeneralizedGeography.computableTidilyInPolyTime_reduce`: the reduction is + `Cslib.Complexity.GeneralizedGeography.computableInPolyTime_reduce`: the reduction is correct and polynomial-time. * `Cslib.Complexity.polyTimeReducible_TQBFCNF_GeneralizedGeography`, `Cslib.Complexity.GeneralizedGeography_pspaceHard`: Generalized Geography is `PSPACE`-hard. @@ -547,56 +547,61 @@ open ComputableTidilyInPolyTime variable {γ : Type} {encIn : γ ↪ List Bool} @[fun_prop] -theorem computableTidilyInPolyTime_topNode {j : γ → ℕ} - (hj : ComputableTidilyInPolyTime j encIn encUnary) : - ComputableTidilyInPolyTime (fun x => topNode (j x)) encIn encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 0 (j x)) _ _ by - fun_prop) +theorem computableInPolyTime_topNode {j : γ → ℕ} + (hj : ComputableInPolyTime j encIn encUnary) : + ComputableInPolyTime (fun x => topNode (j x)) encIn encNat := by + have hj := hj.tidy + exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 0 (j x)) _ _ by + fun_prop)) @[fun_prop] -theorem computableTidilyInPolyTime_valueNode {j : γ → ℕ} {b : γ → Bool} - (hj : ComputableTidilyInPolyTime j encIn encUnary) - (hb : ComputableTidilyInPolyTime b encIn encBool) : - ComputableTidilyInPolyTime (fun x => valueNode (j x) (b x)) encIn encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime - (fun x => Nat.pair 1 (Nat.pair (j x) (b x).toNat)) _ _ by fun_prop) +theorem computableInPolyTime_valueNode {j : γ → ℕ} {b : γ → Bool} + (hj : ComputableInPolyTime j encIn encUnary) + (hb : ComputableInPolyTime b encIn encBool) : + ComputableInPolyTime (fun x => valueNode (j x) (b x)) encIn encNat := by + have hj := hj.tidy + have hb := hb.tidy + exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime + (fun x => Nat.pair 1 (Nat.pair (j x) (b x).toNat)) _ _ by fun_prop)) @[fun_prop] -theorem computableTidilyInPolyTime_bottomNode {j : γ → ℕ} - (hj : ComputableTidilyInPolyTime j encIn encUnary) : - ComputableTidilyInPolyTime (fun x => bottomNode (j x)) encIn encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 2 (j x)) _ _ by - fun_prop) +theorem computableInPolyTime_bottomNode {j : γ → ℕ} + (hj : ComputableInPolyTime j encIn encUnary) : + ComputableInPolyTime (fun x => bottomNode (j x)) encIn encNat := by + have hj := hj.tidy + exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 2 (j x)) _ _ by + fun_prop)) @[fun_prop] -theorem computableTidilyInPolyTime_clauseNode {i : γ → ℕ} - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => clauseNode (i x)) encIn encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 4 (i x)) _ _ by - fun_prop) +theorem computableInPolyTime_clauseNode {i : γ → ℕ} + (hi : ComputableInPolyTime i encIn encUnary) : + ComputableInPolyTime (fun x => clauseNode (i x)) encIn encNat := by + have hi := hi.tidy + exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 4 (i x)) _ _ by + fun_prop)) @[fun_prop] -theorem computableTidilyInPolyTime_diamondArcs {j : γ → ℕ} - (hj : ComputableTidilyInPolyTime j encIn encUnary) : - ComputableTidilyInPolyTime (fun x => diamondArcs (j x)) encIn +theorem computableInPolyTime_diamondArcs {j : γ → ℕ} + (hj : ComputableInPolyTime j encIn encUnary) : + ComputableInPolyTime (fun x => diamondArcs (j x)) encIn (encList (encPair encNat encNat)) := by unfold diamondArcs fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_lastIdx {xs : γ → List ℕ} {v : γ → ℕ} - (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) - (hv : ComputableTidilyInPolyTime v encIn encNat) : - ComputableTidilyInPolyTime (fun x => lastIdx (xs x) (v x)) encIn encUnary := by +theorem computableInPolyTime_lastIdx {xs : γ → List ℕ} {v : γ → ℕ} + (hxs : ComputableInPolyTime xs encIn (encList encNat)) + (hv : ComputableInPolyTime v encIn encNat) : + ComputableInPolyTime (fun x => lastIdx (xs x) (v x)) encIn encUnary := by unfold lastIdx fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_literalArcs {xs : γ → List ℕ} {i : γ → ℕ} - {c : γ → Clause ℕ} (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) - (hi : ComputableTidilyInPolyTime i encIn encUnary) - (hc : ComputableTidilyInPolyTime c encIn (encList (encPair encNat encBool))) : - ComputableTidilyInPolyTime (fun x => literalArcs (xs x) (i x) (c x)) encIn +theorem computableInPolyTime_literalArcs {xs : γ → List ℕ} {i : γ → ℕ} + {c : γ → Clause ℕ} (hxs : ComputableInPolyTime xs encIn (encList encNat)) + (hi : ComputableInPolyTime i encIn encUnary) + (hc : ComputableInPolyTime c encIn (encList (encPair encNat encBool))) : + ComputableInPolyTime (fun x => literalArcs (xs x) (i x) (c x)) encIn (encList (encPair encNat encNat)) := by unfold literalArcs simp only [List.decide_mem_eq_any] @@ -604,17 +609,17 @@ theorem computableTidilyInPolyTime_literalArcs {xs : γ → List ℕ} {i : γ /-- The graph of a formula is polynomial-time in its quantified variables and its clauses. -/ @[fun_prop] -theorem computableTidilyInPolyTime_formulaGraph {xs : γ → List ℕ} {ψ : γ → CNF ℕ} - (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) - (hψ : ComputableTidilyInPolyTime ψ encIn encCNF) : - ComputableTidilyInPolyTime (fun x => formulaGraph (xs x) (ψ x)) encIn encGraph := by +theorem computableInPolyTime_formulaGraph {xs : γ → List ℕ} {ψ : γ → CNF ℕ} + (hxs : ComputableInPolyTime xs encIn (encList encNat)) + (hψ : ComputableInPolyTime ψ encIn encCNF) : + ComputableInPolyTime (fun x => formulaGraph (xs x) (ψ x)) encIn encGraph := by unfold formulaGraph formulaArcs encGraph unfold encCNF at hψ fun_prop /-- **The reduction is polynomial-time.** -/ -theorem computableTidilyInPolyTime_reduce : - ComputableTidilyInPolyTime reduce encPrenexCNF (encPair encGraph encNat) := by +theorem computableInPolyTime_reduce : + ComputableInPolyTime reduce encPrenexCNF (encPair encGraph encNat) := by unfold reduce QBF.roundVars encPrenexCNF simp only [List.decide_mem_eq_any] unfold encCNF @@ -630,7 +635,7 @@ open GeneralizedGeography Turing.MultiTapeTM [LichtensteinSipser1980]. -/ theorem polyTimeReducible_TQBFCNF_GeneralizedGeography : PolyTimeReducible encPrenexCNF (encPair encGraph encNat) TQBFCNF GeneralizedGeography := - ⟨reduce, .of_tidy computableTidilyInPolyTime_reduce, fun x => (reduce_mem_iff x).symm⟩ + ⟨reduce, computableInPolyTime_reduce, fun x => (reduce_mem_iff x).symm⟩ /-- **Generalized Geography is `PSPACE`-hard** [Sipser, Theorem 8.14][Sipser2013] [LichtensteinSipser1980]. -/ diff --git a/Complexity/Computability/Complexity/Classes/Space/TM2.lean b/Complexity/Computability/Complexity/Classes/Space/TM2.lean index 236df0726..1c2134088 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TM2.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TM2.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.Machines.Turing.TM2.PolySpace public import Complexity.Computability.Complexity.Classes.Space.Closure +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Polynomial-space Mathlib stack machines decide problems in PSPACE @@ -52,7 +53,7 @@ theorem mem_PSPACE_of_tm2 {α αΓ βΓ : Type} [Finite αΓ] [Finite βΓ] have hf := h.computableTidilyInPolySpace ha hb hspace hstacks have hbool := ComputableTidilyInPolyTime.of_finite (id : Bool → Bool) (encA := (⟨eb, hb⟩ : Bool ↪ List βΓ).trans (encList (encFinite βΓ))) (encB := encBool) - exact mem_PSPACE_of_computableTidilyInPolySpace - ((ComputableTidilyInPolySpace.of_polyTime hbool).comp hf) hA + exact mem_PSPACE_of_computableInPolySpace + (.of_tidy ((ComputableTidilyInPolySpace.of_polyTime hbool).comp hf)) hA end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF.lean index 7cfb8552b..b8ff5cc61 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF.lean @@ -29,9 +29,9 @@ problem [Sipser, Theorem 8.9][Sipser2013] [Arora and Barak, Theorem 4.13][AroraB Acceptance is reachability between the codes of its finite views (`Turing.MultiTapeNTM.savitchDecide_eq_true_iff`), which Savitch's formula expresses with a polynomial number of tokens (`Cslib.Complexity.TQBF.reduce_mem_TQBF_iff`), constructed in - polynomial time (`Cslib.Complexity.TQBF.computableTidilyInPolyTime_reduce`). Its formula of level + polynomial time (`Cslib.Complexity.TQBF.computableInPolyTime_reduce`). Its formula of level `0` is the Cook–Levin tableau of a polynomial-time machine testing one step or none between codes - (`Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest`). + (`Cslib.Complexity.TQBF.computableInPolyTime_edgeTest`). The reduction maps every instance to a closed formula: the quantified variables of the formula of level `0` are odd, those of the blocks of the midpoint recursion even, and the source and target @@ -72,12 +72,12 @@ theorem TQBF_pspaceHard : PSPACEHard encQBF TQBF := by obtain ⟨k, State, hfinite, ntm, s, hs, hA⟩ := PSPACE_subset_NPSPACE hA obtain ⟨c, d, hcd⟩ := hs.exists_le obtain ⟨tV, sV, htV, -, kV, StateV, hfiniteV, tmV, htmV⟩ := - TQBF.computableTidilyInPolyTime_edgeTest (enc := enc) (ntm := ntm) (c := c) (d := d) + TQBF.computableInPolyTime_edgeTest.tidy (enc := enc) (ntm := ntm) (c := c) (d := d) obtain ⟨cV, dV, htV⟩ := htV.exists_le have := Fintype.ofFinite StateV classical refine ⟨TQBF.reduce enc ntm c d tmV cV dV, - .of_tidy (TQBF.computableTidilyInPolyTime_reduce tmV cV dV), fun a => ?_⟩ + (TQBF.computableInPolyTime_reduce tmV cV dV), fun a => ?_⟩ rw [TQBF.reduce_mem_TQBF_iff (htmV.mono htV fun _ => le_rfl) (hA.recognizesInSpace a).1 (hcd a)] exact (hA.recognizesInSpace a).2 diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean index 6b71729b7..4ae6f77bc 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean @@ -16,6 +16,8 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Ba import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Finite import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Option +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # `TQBF` is in polynomial space @@ -27,7 +29,7 @@ and space in the quantitative calculus of tidy computability the rounds and every copy. The states of the machine are encoded by framed tuples (`Cslib.Complexity.TQBF.encState`). A step -is polynomial-time in the encoded state (`Cslib.Complexity.TQBF.computableTidilyInPolyTime_step`): +is polynomial-time in the encoded state (`Cslib.Complexity.TQBF.computableInPolyTime_step`): it branches on whether a value is being returned, on the kind of the next token or of the top frame, and looks variables up in the stack. Along a run on a formula with encoding of length `L`, the stack holds at most `L` frames, each storing a token and a suffix of the tokens of the formula, @@ -36,7 +38,7 @@ so every state has an encoding of length `O((L + 1) ^ 2)` `L + 1` digits, from `2 ^ L` written in linear time (`Turing.MultiTapeTM.ComputableTidilyInDegree.two_pow_length`), so the evaluator runs in space polynomial in `L` and in time `2 ^ L` times a polynomial in `L` -(`Cslib.Complexity.TQBF.exists_computableTidilyInO_evaluate`). Hence `TQBF ∈ PSPACE` +(`Cslib.Complexity.TQBF.exists_computableInO_evaluate`). Hence `TQBF ∈ PSPACE` [Sipser, Theorem 8.9][Sipser2013] [Arora and Barak, Theorem 4.13][AroraBarak09]. ## Main definitions @@ -45,9 +47,9 @@ polynomial in `L` and in time `2 ^ L` times a polynomial in `L` ## Main results -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_step`: a step is polynomial-time. +* `Cslib.Complexity.TQBF.computableInPolyTime_step`: a step is polynomial-time. * `Cslib.Complexity.TQBF.length_encState_le`: the states of a run are of quadratic size. -* `Cslib.Complexity.TQBF.exists_computableTidilyInO_evaluate`: the time and space of the evaluator. +* `Cslib.Complexity.TQBF.exists_computableInO_evaluate`: the time and space of the evaluator. * `Cslib.Complexity.TQBF_mem_PSPACE`: `TQBF` is in polynomial space. ## References @@ -261,7 +263,8 @@ private lemma retStep_pt (k : QBF.Kind) (second : Bool) : cases k <;> cases second <;> unfold retStep <;> fun_prop /-- **A step of the evaluator is polynomial-time** in the encoded state. -/ -theorem computableTidilyInPolyTime_step : ComputableTidilyInPolyTime step encState encState := by +theorem computableInPolyTime_step : ComputableInPolyTime step encState encState := by + refine .of_tidy ?_ rw [show step = _ from funext step_eq] refine cond (optionIsSome value_pt) (cond (listIsEmpty' encFrame |>.comp stack_pt) id' ?_) (cond (listIsEmpty' encToken |>.comp input_pt) (by fun_prop) ?_) @@ -333,67 +336,69 @@ some fixed `e`. The space charges the input, the stack of at most `L` frames, ea and a suffix of the tokens, the value, the flag, the counter of the `2 ^ L` rounds in binary, and the polynomial space of a step; the time charges every round [Sipser, Theorem 8.9][Sipser2013] [Arora and Barak, Theorem 4.13][AroraBarak09]. -/ -theorem exists_computableTidilyInO_evaluate : ∃ e, ComputableTidilyInO evaluate encQBF encBool +theorem exists_computableInO_evaluate : ∃ e, ComputableInO evaluate encQBF encBool (fun φ => 2 ^ (encQBF φ).length * ((encQBF φ).length + 1) ^ e) fun φ => ((encQBF φ).length + 1) ^ e := by - obtain ⟨d, e, hstep⟩ := computableTidilyInPolyTime_step.exists_degree - obtain ⟨d₀, e₀, hinit⟩ := init_pt.exists_degree - obtain ⟨d₁, e₁, hans⟩ := answer_pt.exists_degree - have hn := (ComputableTidilyInDegree.two_pow_length encQBF).inO_one - have hiter := ComputableTidilyInO.iterate hn hinit.inO hstep.inO - (R := fun φ => (16 * ((encQBF φ).length + 1) ^ 2 + 1) ^ d) - (Q := fun φ => (16 * ((encQBF φ).length + 1) ^ 2 + 1) ^ d) - (B := fun φ => 16 * ((encQBF φ).length + 1) ^ 2) - (fun φ k _ => Nat.pow_le_pow_left (Nat.add_le_add_right - (length_encState_le (good_iterate_step φ k)) 1) d) - (fun φ k _ => Nat.pow_le_pow_left (Nat.add_le_add_right - (length_encState_le (good_iterate_step φ k)) 1) d) - (fun φ k _ => length_encState_le (good_iterate_step φ k)) - have h := hans.inO.comp hiter - refine ⟨2 * (d + d₀ + d₁) + 2, ?_⟩ - refine (h.mono (17 ^ (d + d₁) * 64) (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => rfl - all_goals - simp only [encNat_two_pow, List.length_append, List.length_replicate, - List.length_singleton] - have hgood := length_encState_le (good_iterate_step φ (2 ^ (encQBF φ).length)) - generalize step^[2 ^ (encQBF φ).length] (init φ) = s at hgood ⊢ - generalize (encQBF φ).length = L at hgood ⊢ - set E := 2 * (d + d₀ + d₁) + 2 - have hP : 1 ≤ L + 1 := by omega - have hpow (a : ℕ) (ha : a ≤ E / 2) : - (16 * (L + 1) ^ 2 + 1) ^ a ≤ 17 ^ a * (L + 1) ^ E := by - calc (16 * (L + 1) ^ 2 + 1) ^ a ≤ (17 * (L + 1) ^ 2) ^ a := - Nat.pow_le_pow_left (by nlinarith [Nat.one_le_pow 2 (L + 1) hP]) a - _ = 17 ^ a * (L + 1) ^ (2 * a) := by rw [Nat.mul_pow, ← pow_mul] - _ ≤ 17 ^ a * (L + 1) ^ E := Nat.mul_le_mul_left _ (pow_le_pow_of_le hP (by omega)) - have hR := hpow d (by omega) - have hA : ((encState s).length + 1) ^ d₁ ≤ 17 ^ d₁ * (L + 1) ^ E := - (Nat.pow_le_pow_left (by omega) d₁).trans (hpow d₁ (by omega)) - have hM1 : L + 1 ≤ (L + 1) ^ E := by - simpa using pow_le_pow_of_le hP (show 1 ≤ E by omega) - have hM2 : (L + 1) ^ 2 ≤ (L + 1) ^ E := pow_le_pow_of_le hP (by omega) - have hM0 : (L + 1) ^ d₀ ≤ (L + 1) ^ E := pow_le_pow_of_le hP (by omega) - have hK : 17 ^ d ≤ 17 ^ (d + d₁) := Nat.pow_le_pow_right (by norm_num) (by omega) - have hK₁ : 17 ^ d₁ ≤ 17 ^ (d + d₁) := Nat.pow_le_pow_right (by norm_num) (by omega) - have hN : 1 ≤ 2 ^ L := Nat.one_le_two_pow - have hsq : (L + 1 + 1) ^ 2 ≤ 4 * (L + 1) ^ 2 := by nlinarith - generalize (16 * (L + 1) ^ 2 + 1) ^ d = X at * - generalize ((encState s).length + 1) ^ d₁ = A at * - generalize (L + 1) ^ E = M at * - generalize (L + 1) ^ 2 = Q at * - generalize (L + 1) ^ d₀ = D at * - generalize 17 ^ (d + d₁) = K at * - generalize 2 ^ L = N at * - have hX : X ≤ K * M := hR.trans (Nat.mul_le_mul_right _ hK) - have hA' : A ≤ K * M := hA.trans (Nat.mul_le_mul_right _ hK₁) - have hK1 : 1 ≤ K := le_trans (Nat.one_le_pow _ _ (by norm_num)) hK - have hKM : M ≤ K * M := Nat.le_mul_of_pos_left _ hK1 - · have hround : X + 16 * Q + (L + 1 + 1) ^ 2 ≤ 21 * (K * M) := by omega - have hrounds := Nat.mul_le_mul_left (N + 1) hround - have hNM : K * M ≤ N * (K * M) := Nat.le_mul_of_pos_left _ hN - nlinarith - · have : K * 64 * (M + 1) = 64 * (K * M) + 64 * K := by ring - omega + have this : ∃ e, ComputableTidilyInO evaluate encQBF encBool (fun φ => 2 ^ (encQBF φ).length * ((encQBF φ).length + 1) ^ e) fun φ => ((encQBF φ).length + 1) ^ e := by + obtain ⟨d, e, hstep⟩ := computableInPolyTime_step.tidy.exists_degree + obtain ⟨d₀, e₀, hinit⟩ := init_pt.exists_degree + obtain ⟨d₁, e₁, hans⟩ := answer_pt.exists_degree + have hn := (ComputableTidilyInDegree.two_pow_length encQBF).inO_one + have hiter := ComputableTidilyInO.iterate hn hinit.inO hstep.inO + (R := fun φ => (16 * ((encQBF φ).length + 1) ^ 2 + 1) ^ d) + (Q := fun φ => (16 * ((encQBF φ).length + 1) ^ 2 + 1) ^ d) + (B := fun φ => 16 * ((encQBF φ).length + 1) ^ 2) + (fun φ k _ => Nat.pow_le_pow_left (Nat.add_le_add_right + (length_encState_le (good_iterate_step φ k)) 1) d) + (fun φ k _ => Nat.pow_le_pow_left (Nat.add_le_add_right + (length_encState_le (good_iterate_step φ k)) 1) d) + (fun φ k _ => length_encState_le (good_iterate_step φ k)) + have h := hans.inO.comp hiter + refine ⟨2 * (d + d₀ + d₁) + 2, ?_⟩ + refine (h.mono (17 ^ (d + d₁) * 64) (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => rfl + all_goals + simp only [encNat_two_pow, List.length_append, List.length_replicate, + List.length_singleton] + have hgood := length_encState_le (good_iterate_step φ (2 ^ (encQBF φ).length)) + generalize step^[2 ^ (encQBF φ).length] (init φ) = s at hgood ⊢ + generalize (encQBF φ).length = L at hgood ⊢ + set E := 2 * (d + d₀ + d₁) + 2 + have hP : 1 ≤ L + 1 := by omega + have hpow (a : ℕ) (ha : a ≤ E / 2) : + (16 * (L + 1) ^ 2 + 1) ^ a ≤ 17 ^ a * (L + 1) ^ E := by + calc (16 * (L + 1) ^ 2 + 1) ^ a ≤ (17 * (L + 1) ^ 2) ^ a := + Nat.pow_le_pow_left (by nlinarith [Nat.one_le_pow 2 (L + 1) hP]) a + _ = 17 ^ a * (L + 1) ^ (2 * a) := by rw [Nat.mul_pow, ← pow_mul] + _ ≤ 17 ^ a * (L + 1) ^ E := Nat.mul_le_mul_left _ (pow_le_pow_of_le hP (by omega)) + have hR := hpow d (by omega) + have hA : ((encState s).length + 1) ^ d₁ ≤ 17 ^ d₁ * (L + 1) ^ E := + (Nat.pow_le_pow_left (by omega) d₁).trans (hpow d₁ (by omega)) + have hM1 : L + 1 ≤ (L + 1) ^ E := by + simpa using pow_le_pow_of_le hP (show 1 ≤ E by omega) + have hM2 : (L + 1) ^ 2 ≤ (L + 1) ^ E := pow_le_pow_of_le hP (by omega) + have hM0 : (L + 1) ^ d₀ ≤ (L + 1) ^ E := pow_le_pow_of_le hP (by omega) + have hK : 17 ^ d ≤ 17 ^ (d + d₁) := Nat.pow_le_pow_right (by norm_num) (by omega) + have hK₁ : 17 ^ d₁ ≤ 17 ^ (d + d₁) := Nat.pow_le_pow_right (by norm_num) (by omega) + have hN : 1 ≤ 2 ^ L := Nat.one_le_two_pow + have hsq : (L + 1 + 1) ^ 2 ≤ 4 * (L + 1) ^ 2 := by nlinarith + generalize (16 * (L + 1) ^ 2 + 1) ^ d = X at * + generalize ((encState s).length + 1) ^ d₁ = A at * + generalize (L + 1) ^ E = M at * + generalize (L + 1) ^ 2 = Q at * + generalize (L + 1) ^ d₀ = D at * + generalize 17 ^ (d + d₁) = K at * + generalize 2 ^ L = N at * + have hX : X ≤ K * M := hR.trans (Nat.mul_le_mul_right _ hK) + have hA' : A ≤ K * M := hA.trans (Nat.mul_le_mul_right _ hK₁) + have hK1 : 1 ≤ K := le_trans (Nat.one_le_pow _ _ (by norm_num)) hK + have hKM : M ≤ K * M := Nat.le_mul_of_pos_left _ hK1 + · have hround : X + 16 * Q + (L + 1 + 1) ^ 2 ≤ 21 * (K * M) := by omega + have hrounds := Nat.mul_le_mul_left (N + 1) hround + have hNM : K * M ≤ N * (K * M) := Nat.le_mul_of_pos_left _ hN + nlinarith + · have : K * 64 * (M + 1) = 64 * (K * M) + 64 * K := by ring + omega + simpa only [computableInO_iff_computableTidilyInO] using this end Cslib.Complexity.TQBF @@ -401,11 +406,13 @@ namespace Cslib.Complexity open Turing.MultiTapeTM +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`TQBF` is in polynomial space** [Sipser, Theorem 8.9][Sipser2013] [Arora and Barak, Theorem 4.13][AroraBarak09]: the explicit-stack evaluator decides it within space polynomial in the length of the encoded formula. -/ theorem TQBF_mem_PSPACE : TQBF ∈ PSPACE encQBF := by - obtain ⟨e, c, h, -⟩ := TQBF.exists_computableTidilyInO_evaluate + obtain ⟨e, c, h, -⟩ := TQBF.exists_computableInO_evaluate refine ⟨TQBF.evaluate, ⟨_, _, ?_, h.computableInTimeAndSpace⟩, fun φ => TQBF.evaluate_eq_true_iff.symm⟩ refine PolyBounded.of_forall_le (2 * c) e fun φ => ?_ diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean index 1160cfc28..2d1f7f643 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean @@ -20,7 +20,7 @@ import Complexity.Logics.Propositional.CNF.PolyTime A formula is encoded by the list of its tokens in prefix order (`Cslib.Complexity.encQBF`), so a formula is computed in polynomial time as soon as its tokens are -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_of_tokens`). The connectives of +(`Cslib.Complexity.TQBF.computableInPolyTime_of_tokens`). The connectives of `Cslib.Logic.PL.QBF` and the derived connectives of the midpoint formulas (blocks of quantifiers, conjunctions of lists, implication, equivalence, literals, formulas in conjunctive normal form) get composition rules for `fun_prop`, with their tokens written out explicitly @@ -32,28 +32,28 @@ index `j` below the width `w`, so they are computed in unary, where their size i (`Cslib.Complexity.TQBF.tokens_midpoint`): the levels from `d` down to `1`, each with `O(w)` tokens, then the formula of level `0`. So Savitch's formula is polynomial-time in the width and depth in unary, the two words, and the formula of level `0` -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_savitchFormula`). +(`Cslib.Complexity.TQBF.computableInPolyTime_savitchFormula`). The formula of level `0` numbers the variables of a Cook–Levin tableau by odd numbers -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_tabVar`), and is polynomial-time in the tableau. +(`Cslib.Complexity.TQBF.computableInPolyTime_tabVar`), and is polynomial-time in the tableau. Composed with the polynomial-time width and codes of the views (`Turing.MultiTapeNTM.computableTidilyInPolyTime_codeWidth`) and the polynomial-time Cook–Levin -tableau (`Cslib.Complexity.CookLevin.computableTidilyInPolyTime_tableau`), the reduction +tableau (`Cslib.Complexity.CookLevin.computableInPolyTime_tableau`), the reduction `Cslib.Complexity.TQBF.reduce` is polynomial-time, for every machine standing for the test of one step or none and every polynomial time bound -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_reduce`). That test is itself polynomial-time -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest`), which provides the machine. +(`Cslib.Complexity.TQBF.computableInPolyTime_reduce`). That test is itself polynomial-time +(`Cslib.Complexity.TQBF.computableInPolyTime_edgeTest`), which provides the machine. ## Main results -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_of_tokens`: formulas from their tokens. -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_savitchFormula`: Savitch's formula is +* `Cslib.Complexity.TQBF.computableInPolyTime_of_tokens`: formulas from their tokens. +* `Cslib.Complexity.TQBF.computableInPolyTime_savitchFormula`: Savitch's formula is polynomial-time. -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_baseFormula`: a tableau as the formula of +* `Cslib.Complexity.TQBF.computableInPolyTime_baseFormula`: a tableau as the formula of level `0` is polynomial-time. -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest`: the test of one step or none is +* `Cslib.Complexity.TQBF.computableInPolyTime_edgeTest`: the test of one step or none is polynomial-time. -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_reduce`: the reduction is polynomial-time. +* `Cslib.Complexity.TQBF.computableInPolyTime_reduce`: the reduction is polynomial-time. ## References @@ -73,112 +73,113 @@ variable {γ : Type} {encIn : γ ↪ List Bool} /-- The tokens of an encoded formula, the identity on encoded values. -/ @[fun_prop] -theorem computableTidilyInPolyTime_tokens : - ComputableTidilyInPolyTime QBF.tokens encQBF (encList encToken) := - of_eq fun _ => rfl +theorem computableInPolyTime_tokens : + Turing.MultiTapeTM.ComputableInPolyTime QBF.tokens encQBF (encList encToken) := + Turing.MultiTapeTM.ComputableInPolyTime.of_eq fun _ => rfl /-- A formula is polynomial-time when its tokens are. -/ -theorem computableTidilyInPolyTime_of_tokens {f : γ → QBF ℕ} {l : γ → List (QBF.Kind × ℕ)} - (hl : ComputableTidilyInPolyTime l encIn (encList encToken)) (h : ∀ x, (f x).tokens = l x) : - ComputableTidilyInPolyTime f encIn encQBF := - hl.of_enc_eq fun x => by rw [encQBF_apply, h] +theorem computableInPolyTime_of_tokens {f : γ → QBF ℕ} {l : γ → List (QBF.Kind × ℕ)} + (hl : Turing.MultiTapeTM.ComputableInPolyTime l encIn (encList encToken)) (h : ∀ x, (f x).tokens = l x) : + Turing.MultiTapeTM.ComputableInPolyTime f encIn encQBF := by + have hl := hl.tidy + exact .of_tidy (hl.of_enc_eq fun x => by rw [encQBF_apply, h]) /-- A variable, from its number in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_var {v : γ → ℕ} - (hv : ComputableTidilyInPolyTime v encIn encNat) : - ComputableTidilyInPolyTime (fun x => QBF.var (v x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens (l := fun x => [(.var, v x)]) (by fun_prop) fun _ => rfl +theorem computableInPolyTime_var {v : γ → ℕ} + (hv : Turing.MultiTapeTM.ComputableInPolyTime v encIn encNat) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.var (v x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => [(.var, v x)]) (by fun_prop) fun _ => rfl /-- Negation. -/ @[fun_prop] -theorem computableTidilyInPolyTime_not {φ : γ → QBF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => (φ x).not) encIn encQBF := - computableTidilyInPolyTime_of_tokens (l := fun x => (.not, 0) :: (φ x).tokens) (by fun_prop) +theorem computableInPolyTime_not {φ : γ → QBF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => (φ x).not) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (.not, 0) :: (φ x).tokens) (by fun_prop) fun _ => rfl /-- Conjunction. -/ @[fun_prop] -theorem computableTidilyInPolyTime_and {φ ψ : γ → QBF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) - (hψ : ComputableTidilyInPolyTime ψ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => (φ x).and (ψ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens (l := fun x => (.and, 0) :: ((φ x).tokens ++ (ψ x).tokens)) +theorem computableInPolyTime_and {φ ψ : γ → QBF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) + (hψ : Turing.MultiTapeTM.ComputableInPolyTime ψ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => (φ x).and (ψ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (.and, 0) :: ((φ x).tokens ++ (ψ x).tokens)) (by fun_prop) fun _ => rfl /-- Disjunction. -/ @[fun_prop] -theorem computableTidilyInPolyTime_or {φ ψ : γ → QBF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) - (hψ : ComputableTidilyInPolyTime ψ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => (φ x).or (ψ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens (l := fun x => (.or, 0) :: ((φ x).tokens ++ (ψ x).tokens)) +theorem computableInPolyTime_or {φ ψ : γ → QBF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) + (hψ : Turing.MultiTapeTM.ComputableInPolyTime ψ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => (φ x).or (ψ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (.or, 0) :: ((φ x).tokens ++ (ψ x).tokens)) (by fun_prop) fun _ => rfl /-- A block of existential quantifiers, over a list of variables in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_exs {vs : γ → List ℕ} {φ : γ → QBF ℕ} - (hvs : ComputableTidilyInPolyTime vs encIn (encList encNat)) - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => QBF.exs (vs x) (φ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens +theorem computableInPolyTime_exs {vs : γ → List ℕ} {φ : γ → QBF ℕ} + (hvs : Turing.MultiTapeTM.ComputableInPolyTime vs encIn (encList encNat)) + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.exs (vs x) (φ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (vs x).map (fun v => (QBF.Kind.ex, v)) ++ (φ x).tokens) (by fun_prop) fun _ => QBF.tokens_exs .. /-- A block of universal quantifiers, over a list of variables in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_alls {vs : γ → List ℕ} {φ : γ → QBF ℕ} - (hvs : ComputableTidilyInPolyTime vs encIn (encList encNat)) - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => QBF.alls (vs x) (φ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens +theorem computableInPolyTime_alls {vs : γ → List ℕ} {φ : γ → QBF ℕ} + (hvs : Turing.MultiTapeTM.ComputableInPolyTime vs encIn (encList encNat)) + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.alls (vs x) (φ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (vs x).map (fun v => (QBF.Kind.all, v)) ++ (φ x).tokens) (by fun_prop) fun _ => QBF.tokens_alls .. /-- The conjunction of a list of formulas. -/ @[fun_prop] -theorem computableTidilyInPolyTime_conj {l : γ → List (QBF ℕ)} - (hl : ComputableTidilyInPolyTime l encIn (encList encQBF)) : - ComputableTidilyInPolyTime (fun x => QBF.conj (l x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens +theorem computableInPolyTime_conj {l : γ → List (QBF ℕ)} + (hl : Turing.MultiTapeTM.ComputableInPolyTime l encIn (encList encQBF)) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.conj (l x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (l x).flatMap (fun φ => (QBF.Kind.and, 0) :: φ.tokens) ++ [(.top, 0)]) (by fun_prop) fun _ => QBF.tokens_conj .. /-- Implication. -/ @[fun_prop] -theorem computableTidilyInPolyTime_imp {φ ψ : γ → QBF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) - (hψ : ComputableTidilyInPolyTime ψ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => QBF.imp (φ x) (ψ x)) encIn encQBF := by +theorem computableInPolyTime_imp {φ ψ : γ → QBF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) + (hψ : Turing.MultiTapeTM.ComputableInPolyTime ψ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.imp (φ x) (ψ x)) encIn encQBF := by unfold QBF.imp fun_prop /-- Equivalence. -/ @[fun_prop] -theorem computableTidilyInPolyTime_iff {φ ψ : γ → QBF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) - (hψ : ComputableTidilyInPolyTime ψ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => QBF.iff (φ x) (ψ x)) encIn encQBF := by +theorem computableInPolyTime_iff {φ ψ : γ → QBF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) + (hψ : Turing.MultiTapeTM.ComputableInPolyTime ψ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.iff (φ x) (ψ x)) encIn encQBF := by unfold QBF.iff fun_prop /-- A literal, from its variable in binary and its sign. -/ @[fun_prop] -theorem computableTidilyInPolyTime_lit {v : γ → ℕ} {b : γ → Bool} - (hv : ComputableTidilyInPolyTime v encIn encNat) - (hb : ComputableTidilyInPolyTime b encIn encBool) : - ComputableTidilyInPolyTime (fun x => QBF.lit (v x) (b x)) encIn encQBF := by +theorem computableInPolyTime_lit {v : γ → ℕ} {b : γ → Bool} + (hv : Turing.MultiTapeTM.ComputableInPolyTime v encIn encNat) + (hb : Turing.MultiTapeTM.ComputableInPolyTime b encIn encBool) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.lit (v x) (b x)) encIn encQBF := by unfold QBF.lit fun_prop /-- A formula in conjunctive normal form, from its clauses in the encoding of `Cslib.Complexity.encCNF`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_ofCNF {φ : γ → CNF ℕ} - (hφ : ComputableTidilyInPolyTime φ encIn (encList (encList (encPair encNat encBool)))) : - ComputableTidilyInPolyTime (fun x => QBF.ofCNF (φ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens (l := fun x => (φ x).flatMap (fun c => (QBF.Kind.and, 0) :: +theorem computableInPolyTime_ofCNF {φ : γ → CNF ℕ} + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn (encList (encList (encPair encNat encBool)))) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.ofCNF (φ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (φ x).flatMap (fun c => (QBF.Kind.and, 0) :: (c.flatMap (fun l => (QBF.Kind.or, 0) :: (QBF.lit l.1 l.2).tokens) ++ [(QBF.Kind.bot, 0)])) ++ [(QBF.Kind.top, 0)]) (by fun_prop) fun _ => QBF.tokens_ofCNF _ @@ -186,11 +187,15 @@ theorem computableTidilyInPolyTime_ofCNF {φ : γ → CNF ℕ} /-- A block variable, from its kind, level and index in unary, in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_blockVar {kind i j : γ → ℕ} - (hkind : ComputableTidilyInPolyTime kind encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) - (hj : ComputableTidilyInPolyTime j encIn encUnary) : - ComputableTidilyInPolyTime (fun x => blockVar (kind x) (i x) (j x)) encIn encNat := by +theorem computableInPolyTime_blockVar {kind i j : γ → ℕ} + (hkind : Turing.MultiTapeTM.ComputableInPolyTime kind encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) + (hj : Turing.MultiTapeTM.ComputableInPolyTime j encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => blockVar (kind x) (i x) (j x)) encIn encNat := by + have hkind := hkind.tidy + have hi := hi.tidy + have hj := hj.tidy + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun x => blockVar (kind x) (i x) (j x)) encIn encUnary := by unfold blockVar fun_prop @@ -198,79 +203,79 @@ theorem computableTidilyInPolyTime_blockVar {kind i j : γ → ℕ} /-- The variables of a block, from the width, kind and level in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_blockVars {w kind i : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hkind : ComputableTidilyInPolyTime kind encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => blockVars (w x) (kind x) (i x)) encIn +theorem computableInPolyTime_blockVars {w kind i : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hkind : Turing.MultiTapeTM.ComputableInPolyTime kind encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => blockVars (w x) (kind x) (i x)) encIn (encList encNat) := by unfold blockVars fun_prop /-- The equality of two blocks. -/ @[fun_prop] -theorem computableTidilyInPolyTime_eqBlock {w k i k' i' : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hk : ComputableTidilyInPolyTime k encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) - (hk' : ComputableTidilyInPolyTime k' encIn encUnary) - (hi' : ComputableTidilyInPolyTime i' encIn encUnary) : - ComputableTidilyInPolyTime (fun x => eqBlock (w x) (k x) (i x) (k' x) (i' x)) encIn encQBF := by +theorem computableInPolyTime_eqBlock {w k i k' i' : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hk : Turing.MultiTapeTM.ComputableInPolyTime k encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) + (hk' : Turing.MultiTapeTM.ComputableInPolyTime k' encIn encUnary) + (hi' : Turing.MultiTapeTM.ComputableInPolyTime i' encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => eqBlock (w x) (k x) (i x) (k' x) (i' x)) encIn encQBF := by unfold eqBlock fun_prop /-- A block holding a word. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isBlock {w k i : γ → ℕ} {u : γ → List Bool} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hk : ComputableTidilyInPolyTime k encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) - (hu : ComputableTidilyInPolyTime u encIn encBits) : - ComputableTidilyInPolyTime (fun x => isBlock (w x) (k x) (i x) (u x)) encIn encQBF := by +theorem computableInPolyTime_isBlock {w k i : γ → ℕ} {u : γ → List Bool} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hk : Turing.MultiTapeTM.ComputableInPolyTime k encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) + (hu : Turing.MultiTapeTM.ComputableInPolyTime u encIn encBits) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => isBlock (w x) (k x) (i x) (u x)) encIn encQBF := by unfold isBlock fun_prop /-- The hypothesis of a level. -/ @[fun_prop] -theorem computableTidilyInPolyTime_halves {w i : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => halves (w x) (i x)) encIn encQBF := by +theorem computableInPolyTime_halves {w i : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => halves (w x) (i x)) encIn encQBF := by unfold halves fun_prop /-- The tokens a level adds to the midpoint formula. -/ @[fun_prop] -theorem computableTidilyInPolyTime_levelTokens {w i : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hi : ComputableTidilyInPolyTime i encIn encUnary) : - ComputableTidilyInPolyTime (fun x => levelTokens (w x) (i x)) encIn (encList encToken) := by +theorem computableInPolyTime_levelTokens {w i : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => levelTokens (w x) (i x)) encIn (encList encToken) := by unfold levelTokens fun_prop /-- The midpoint formula of level `d`, from the width and level in unary and the formula of level `0`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_midpoint {w d : γ → ℕ} {base : γ → QBF ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hbase : ComputableTidilyInPolyTime base encIn encQBF) - (hd : ComputableTidilyInPolyTime d encIn encUnary) : - ComputableTidilyInPolyTime (fun x => midpoint (w x) (base x) (d x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens +theorem computableInPolyTime_midpoint {w d : γ → ℕ} {base : γ → QBF ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hbase : Turing.MultiTapeTM.ComputableInPolyTime base encIn encQBF) + (hd : Turing.MultiTapeTM.ComputableInPolyTime d encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => midpoint (w x) (base x) (d x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (List.range (d x)).reverse.flatMap (levelTokens (w x)) ++ (base x).tokens) (by fun_prop) fun _ => tokens_midpoint .. /-- **Savitch's formula is polynomial-time** in the width and depth in unary, the formula of level `0`, and the two words. -/ @[fun_prop] -theorem computableTidilyInPolyTime_savitchFormula {w d : γ → ℕ} {base : γ → QBF ℕ} +theorem computableInPolyTime_savitchFormula {w d : γ → ℕ} {base : γ → QBF ℕ} {u v : γ → List Bool} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hd : ComputableTidilyInPolyTime d encIn encUnary) - (hbase : ComputableTidilyInPolyTime base encIn encQBF) - (hu : ComputableTidilyInPolyTime u encIn encBits) - (hv : ComputableTidilyInPolyTime v encIn encBits) : - ComputableTidilyInPolyTime (fun x => savitchFormula (w x) (d x) (base x) (u x) (v x)) encIn + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hd : Turing.MultiTapeTM.ComputableInPolyTime d encIn encUnary) + (hbase : Turing.MultiTapeTM.ComputableInPolyTime base encIn encQBF) + (hu : Turing.MultiTapeTM.ComputableInPolyTime u encIn encBits) + (hv : Turing.MultiTapeTM.ComputableInPolyTime v encIn encBits) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => savitchFormula (w x) (d x) (base x) (u x) (v x)) encIn encQBF := by unfold savitchFormula fun_prop @@ -289,8 +294,9 @@ private theorem computableTidilyInPolyTime_index_unary : /-- The numbering of the tableau variables by odd numbers, in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_tabVar : - ComputableTidilyInPolyTime (tabVar (k := k) (State := State)) CookLevin.encVar encNat := by +theorem computableInPolyTime_tabVar : + Turing.MultiTapeTM.ComputableInPolyTime (tabVar (k := k) (State := State)) CookLevin.encVar encNat := by + refine .of_tidy ?_ have := computableTidilyInPolyTime_index_unary (k := k) (State := State) have h : ComputableTidilyInPolyTime (fun v => tabVar (k := k) (State := State) v) CookLevin.encVar encUnary := by @@ -298,30 +304,38 @@ theorem computableTidilyInPolyTime_tabVar : fun_prop exact unary_to_binary.comp h +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- The block variable holding a certificate bit, from the width and the index in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_certVar {w j : γ → ℕ} - (hw : ComputableTidilyInPolyTime w encIn encUnary) - (hj : ComputableTidilyInPolyTime j encIn encUnary) : - ComputableTidilyInPolyTime (fun x => certVar (w x) (j x)) encIn encNat := by +theorem computableInPolyTime_certVar {w j : γ → ℕ} + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) + (hj : Turing.MultiTapeTM.ComputableInPolyTime j encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => certVar (w x) (j x)) encIn encNat := by + have hw := hw.tidy + have hj := hj.tidy + refine .of_tidy ?_ unfold certVar fun_prop +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **A tableau as the formula of level `0` is polynomial-time** in the tableau and the width in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_baseFormula {tab : γ → CNF (CookLevin.Var k State)} +theorem computableInPolyTime_baseFormula {tab : γ → CNF (CookLevin.Var k State)} {w : γ → ℕ} - (htab : ComputableTidilyInPolyTime tab encIn + (htab : Turing.MultiTapeTM.ComputableInPolyTime tab encIn (encList (encList (encPair CookLevin.encVar encBool)))) - (hw : ComputableTidilyInPolyTime w encIn encUnary) : - ComputableTidilyInPolyTime (fun x => baseFormula (tab x) (w x)) encIn encQBF := by + (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => baseFormula (tab x) (w x)) encIn encQBF := by + have htab := htab.tidy + have hw := hw.tidy + refine .of_tidy ?_ have hvars : ComputableTidilyInPolyTime (fun x => (tab x).vars) encIn (encList CookLevin.encVar) := (CNF.computableInPolyTime_vars CookLevin.encVar).tidy.comp htab have hrelabel : ComputableTidilyInPolyTime (fun x => CNF.relabel tabVar (tab x)) encIn (encList (encList (encPair encNat encBool))) := - (CNF.computableInPolyTime_relabel (.of_tidy computableTidilyInPolyTime_tabVar)).tidy.comp htab + (CNF.computableInPolyTime_relabel computableInPolyTime_tabVar).tidy.comp htab unfold baseFormula baseVars certLinks fun_prop @@ -336,19 +350,21 @@ variable {α : Type} {enc : α ↪ List Bool} {k : ℕ} {State : Type} [Finite S /-- The width of the words of the reduction, in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_width : - ComputableTidilyInPolyTime (width enc ntm c d) enc encUnary := by +theorem computableInPolyTime_width : + Turing.MultiTapeTM.ComputableInPolyTime (width enc ntm c d) enc encUnary := by + refine .of_tidy ?_ have := MultiTapeNTM.computableTidilyInPolyTime_codeWidth (ntm := ntm) (enc := enc) c d unfold width fun_prop /-- **The test of one step or none between codes is polynomial-time**, on the instance and the concatenation of the two codes. -/ -theorem computableTidilyInPolyTime_edgeTest : - ComputableTidilyInPolyTime (edgeTest enc ntm c d) (encPair enc encBits) encBool := by +theorem computableInPolyTime_edgeTest : + Turing.MultiTapeTM.ComputableInPolyTime (edgeTest enc ntm c d) (encPair enc encBits) encBool := by + refine .of_tidy ?_ have hw : ComputableTidilyInPolyTime (fun p : α × List Bool => width enc ntm c d p.1) (encPair enc encBits) encUnary := - computableTidilyInPolyTime_width.comp (fst _ _) + computableInPolyTime_width.tidy.comp (fst _ _) have hx : ComputableTidilyInPolyTime (fun p : α × List Bool => p.2.take (width enc ntm c d p.1)) (encPair enc encBits) encBits := by fun_prop have hy : ComputableTidilyInPolyTime (fun p : α × List Bool => p.2.drop (width enc ntm c d p.1)) @@ -358,15 +374,17 @@ theorem computableTidilyInPolyTime_edgeTest : simp only [Cslib.Reachability.reach] fun_prop +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **The reduction to `TQBF` is polynomial-time**, for every machine `tmV` standing for the test of one step or none and every time bound `cV * (n + 1) ^ dV` allowed to it. -/ -theorem computableTidilyInPolyTime_reduce {kV : ℕ} {StateV : Type} [Fintype StateV] +theorem computableInPolyTime_reduce {kV : ℕ} {StateV : Type} [Fintype StateV] [DecidableEq StateV] (tmV : MultiTapeTM kV Bool StateV) (cV dV : ℕ) : - ComputableTidilyInPolyTime (reduce enc ntm c d tmV cV dV) enc encQBF := by + Turing.MultiTapeTM.ComputableInPolyTime (reduce enc ntm c d tmV cV dV) enc encQBF := by + refine .of_tidy ?_ have hW := MultiTapeNTM.computableTidilyInPolyTime_codeWidth (ntm := ntm) (enc := enc) c d have hinit := ntm.computableTidilyInPolyTime_viewCode_initView hW (.encode enc) have hacc := MultiTapeNTM.computableTidilyInPolyTime_acceptCode hW - have htab := CookLevin.computableTidilyInPolyTime_tableau tmV + have htab := (CookLevin.computableInPolyTime_tableau tmV).tidy have hframe := bitsFrame enc unfold reduce edgeTime fun_prop diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean index cd0253f46..b56f25bc6 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean @@ -51,7 +51,7 @@ which does not change the value (`Cslib.Logic.PL.QBF.eval_rounds_map_pair`). * `Cslib.Complexity.TQBF.eval_prenex`, `Cslib.Complexity.TQBF.closed_prenex`: the normal form of the formula of a game has its value and is closed. * `Cslib.Complexity.TQBF.prenexReduce_mem_TQBFCNF_iff`, - `Cslib.Complexity.TQBF.computableTidilyInPolyTime_prenexReduce`: the normal form is correct and + `Cslib.Complexity.TQBF.computableInPolyTime_prenexReduce`: the normal form is correct and polynomial-time. * `Cslib.Complexity.TQBFCNF_mem_PSPACE`, `Cslib.Complexity.TQBFCNF_pspaceHard`, `Cslib.Complexity.TQBFCNF_pspaceComplete`: `TQBFCNF` is `PSPACE`-complete. @@ -86,11 +86,11 @@ variable {γ : Type} {encIn : γ ↪ List Bool} /-- Rounds of quantifiers are polynomial-time in the rounds and the body. -/ @[fun_prop] -theorem computableTidilyInPolyTime_rounds {ps : γ → List (ℕ × ℕ)} {φ : γ → QBF ℕ} - (hps : ComputableTidilyInPolyTime ps encIn (encList (encPair encNat encNat))) - (hφ : ComputableTidilyInPolyTime φ encIn encQBF) : - ComputableTidilyInPolyTime (fun x => QBF.rounds (ps x) (φ x)) encIn encQBF := - computableTidilyInPolyTime_of_tokens +theorem computableInPolyTime_rounds {ps : γ → List (ℕ × ℕ)} {φ : γ → QBF ℕ} + (hps : Turing.MultiTapeTM.ComputableInPolyTime ps encIn (encList (encPair encNat encNat))) + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn encQBF) : + Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.rounds (ps x) (φ x)) encIn encQBF := + computableInPolyTime_of_tokens (l := fun x => (ps x).flatMap (fun p => [(QBF.Kind.ex, p.1), (QBF.Kind.all, p.2)]) ++ (φ x).tokens) (by fun_prop) fun _ => QBF.tokens_rounds .. @@ -238,10 +238,11 @@ theorem prenexReduce_mem_TQBFCNF_iff {kV : ℕ} {StateV : Type} [Fintype StateV] rfl /-- **The reduction of a game to `TQBFCNF` is polynomial-time.** -/ -theorem computableTidilyInPolyTime_prenexReduce {kV : ℕ} {StateV : Type} [Fintype StateV] +theorem computableInPolyTime_prenexReduce {kV : ℕ} {StateV : Type} [Fintype StateV] [DecidableEq StateV] (tmV : MultiTapeTM kV Bool StateV) (cV dV : ℕ) : - ComputableTidilyInPolyTime (prenexReduce enc p tmV cV dV) enc encPrenexCNF := by - have htab := CookLevin.computableTidilyInPolyTime_tableau tmV + Turing.MultiTapeTM.ComputableInPolyTime (prenexReduce enc p tmV cV dV) enc encPrenexCNF := by + refine .of_tidy ?_ + have htab := (CookLevin.computableInPolyTime_tableau tmV).tidy have hframe := bitsFrame enc have hp : ComputableTidilyInPolyTime (fun a => p.eval (enc a).length) enc encUnary := (unary_eval p).comp (encoding_length enc) @@ -252,7 +253,7 @@ theorem computableTidilyInPolyTime_prenexReduce {kV : ℕ} {StateV : Type} [Fint have hrelabel : ComputableTidilyInPolyTime (CNF.relabel (tabVar (k := kV) (State := StateV))) (encList (encList (encPair CookLevin.encVar encBool))) (encList (encList (encPair encNat encBool))) := - (CNF.computableInPolyTime_relabel (.of_tidy computableTidilyInPolyTime_tabVar)).tidy + (CNF.computableInPolyTime_relabel computableInPolyTime_tabVar).tidy unfold prenexReduce gameTableau prenexPairs prenexMatrix gamePairs baseVars certLinkCNF encPrenexCNF encCNF fun_prop @@ -279,7 +280,7 @@ theorem TQBFCNF_pspaceHard : PSPACEHard encPrenexCNF TQBFCNF := by have := Fintype.ofFinite StateV classical exact ⟨TQBF.prenexReduce enc p tmV cV dV, - .of_tidy (TQBF.computableTidilyInPolyTime_prenexReduce tmV cV dV), + (TQBF.computableInPolyTime_prenexReduce tmV cV dV), fun a => (h a).trans ((TQBF.gameReduce_mem_TQBF_iff (htmV.mono htV fun _ => le_rfl) a).symm.trans (TQBF.prenexReduce_mem_TQBFCNF_iff tmV cV dV a).symm)⟩ diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Reduction.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Reduction.lean index 0668c192c..1f57e2648 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Reduction.lean @@ -27,7 +27,7 @@ besides those of its formula of level `0`; it is computed in polynomial time in `Cslib.Computability.Complexity.Classes.Space.TQBF.PolyTime`. Its formula of level `0` must express one step or none between the words held by two blocks. The -step test of codes is polynomial-time (`Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest`), +step test of codes is polynomial-time (`Cslib.Complexity.TQBF.computableInPolyTime_edgeTest`), so some tidy machine computes, on `encPair enc encBits (a, x ++ y)`, the Boolean `Cslib.Reachability.reach e w 0 x y` for the edge test `e` of the codes, within a polynomial time bound `T`. Its Cook–Levin tableau (`Cslib.Complexity.CookLevin.tableau`) on the inputs diff --git a/Complexity/Computability/Complexity/Classes/TFNP.lean b/Complexity/Computability/Complexity/Classes/TFNP.lean index 24d7711ac..558b4a6c0 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP.lean @@ -13,6 +13,7 @@ import Complexity.Computability.Complexity.Classes.NP.Witness import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Option +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Search problems: FNP, FP and TFNP @@ -222,33 +223,40 @@ of the candidate solutions of length at most `p (enc a).length` accepted by a po verifier. -/ theorem mem_FNP_iff_exists_bounded : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by - rw [mem_FNP_iff_tidy] - constructor - · rintro ⟨⟨p, hp⟩, V, hV, hR⟩ - exact ⟨p, V, hV, fun a w => ⟨fun h => ⟨hp a w h, (hR a w).1 h⟩, fun h => (hR a w).2 h.2⟩⟩ - · rintro ⟨p, V, hV, hR⟩ - refine ⟨⟨p, fun a w h => ((hR a w).1 h).1⟩, - fun x => decide (x.2.length ≤ p.eval (enc x.1).length) && V x, ?_, fun a w => ?_⟩ - · exact bool_and' (unary_le' (length_bits.comp (snd enc encBits)) - ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV - · simp only [hR a w, Bool.and_eq_true, decide_eq_true_eq] + have this : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by + rw [mem_FNP_iff_tidy] + constructor + · rintro ⟨⟨p, hp⟩, V, hV, hR⟩ + exact ⟨p, V, hV, fun a w => ⟨fun h => ⟨hp a w h, (hR a w).1 h⟩, fun h => (hR a w).2 h.2⟩⟩ + · rintro ⟨p, V, hV, hR⟩ + refine ⟨⟨p, fun a w h => ((hR a w).1 h).1⟩, + fun x => decide (x.2.length ≤ p.eval (enc x.1).length) && V x, ?_, fun a w => ?_⟩ + · exact bool_and' (unary_le' (length_bits.comp (snd enc encBits)) + ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV + · simp only [hR a w, Bool.and_eq_true, decide_eq_true_eq] + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- A polynomial-time solver of a total relation in `FNP` puts it in `FPSearch`. -/ theorem mem_FPSearch_of_total (hR : R ∈ FNP enc) {g : α → List Bool} - (hg : ComputableTidilyInPolyTime g enc encBits) (h : ∀ a, R a (g a)) : R ∈ FPSearch enc := - ⟨hR, _, .of_tidy ((optionSome encBits).comp hg), solvesSearch_some h⟩ + (hg : ComputableInPolyTime g enc encBits) (h : ∀ a, R a (g a)) : R ∈ FPSearch enc := by + have hg := hg.tidy + exact ⟨hR, _, .of_tidy ((optionSome encBits).comp hg), solvesSearch_some h⟩ /-- A total relation in `FPSearch` has a polynomial-time function returning a solution. -/ theorem exists_total_of_mem_FPSearch (hR : R ∈ FPSearch enc) (htot : IsTotalSearch R) : - ∃ g : α → List Bool, ComputableTidilyInPolyTime g enc encBits ∧ ∀ a, R a (g a) := - let ⟨_, f, hf, hsolve⟩ := hR - ⟨fun a => (f a).getD [], optionGetDWithInput hf.tidy (const []), - fun a => hsolve.rel_getD htot a []⟩ + ∃ g : α → List Bool, ComputableInPolyTime g enc encBits ∧ ∀ a, R a (g a) := by + have this : ∃ g : α → List Bool, ComputableTidilyInPolyTime g enc encBits ∧ ∀ a, R a (g a) := + let ⟨_, f, hf, hsolve⟩ := hR + ⟨fun a => (f a).getD [], optionGetDWithInput hf.tidy (const []), + fun a => hsolve.rel_getD htot a []⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Domains and `NP` -/ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **Domains of `FNP` relations are in `NP`**: a solution, framed and padded, is a certificate. -/ theorem searchDomain_mem_NP (hR : R ∈ FNP enc) : searchDomain R ∈ NP enc := by obtain ⟨⟨p, hp⟩, V, hV, hR⟩ := mem_FNP_iff_tidy.mp hR @@ -262,8 +270,9 @@ def verifierSearch (enc : α ↪ List Bool) (p : Polynomial ℕ) (V : α × List /-- The search problem of a polynomial-time verifier is in `FNP`. -/ theorem verifierSearch_mem_FNP {p : Polynomial ℕ} {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : verifierSearch enc p V ∈ FNP enc := by + have hV := hV.tidy refine mem_FNP_iff_tidy.mpr ⟨⟨p, fun a w h => h.1.le⟩, fun x => decide (x.2.length = p.eval (enc x.1).length) && V x, ?_, fun a w => ?_⟩ · exact bool_and' (decide_eq' (length_bits.comp (snd enc encBits)) @@ -277,7 +286,7 @@ theorem IsVerifier.searchDomain_eq {p : Polynomial ℕ} {V : α × List Bool → /-- **`NP` is the class of domains of `FNP` relations.** -/ theorem mem_NP_iff_exists_FNP {A : Set α} : A ∈ NP enc ↔ ∃ R ∈ FNP enc, searchDomain R = A := - ⟨fun ⟨_, _, hV, hA⟩ => ⟨_, verifierSearch_mem_FNP hV.tidy, hA.searchDomain_eq⟩, + ⟨fun ⟨_, _, hV, hA⟩ => ⟨_, verifierSearch_mem_FNP hV, hA.searchDomain_eq⟩, fun ⟨_, hR, hA⟩ => hA ▸ searchDomain_mem_NP hR⟩ /-- **Domains of `FPSearch` relations are in `P`**: test whether the solver finds a solution. -/ @@ -452,10 +461,12 @@ variable {encA : α ↪ List Bool} {encB : β ↪ List Bool} {encC : γ ↪ List /-- For a total target, the one-way condition on solutions suffices for a search reduction. -/ theorem SearchReducible.of_isTotalSearch (hT : IsTotalSearch T) {f : α → β} - {g : α × List Bool → List Bool} (hf : ComputableTidilyInPolyTime f encA encB) - (hg : ComputableTidilyInPolyTime g (encPair encA encBits) encBits) - (h : ∀ a w, T (f a) w → R a (g (a, w))) : SearchReducible encA encB R T := - ⟨f, g, .of_tidy hf, .of_tidy hg, fun a _ => hT (f a), h⟩ + {g : α × List Bool → List Bool} (hf : ComputableInPolyTime f encA encB) + (hg : ComputableInPolyTime g (encPair encA encBits) encBits) + (h : ∀ a w, T (f a) w → R a (g (a, w))) : SearchReducible encA encB R T := by + have hf := hf.tidy + have hg := hg.tidy + exact ⟨f, g, .of_tidy hf, .of_tidy hg, fun a _ => hT (f a), h⟩ /-- Every search problem reduces to itself. -/ @[refl] diff --git a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean index 2a073a89e..0322f93e5 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean @@ -260,7 +260,7 @@ def searchRel (φ : Logic.PL.CNF ℕ) (w : List Bool) : Prop := /-- The search problem of `SAT` is in `FNP`. -/ theorem searchRel_mem_FNP : searchRel ∈ FNP encCNF := - mem_FNP_iff_exists_bounded.2 ⟨Polynomial.X, verifier, computableTidilyInPolyTime_verifier, + mem_FNP_iff_exists_bounded.2 ⟨Polynomial.X, verifier, computableInPolyTime_verifier.tidy, fun _ _ => by simp [searchRel]⟩ /-- The formulas with a solution in `SAT.searchRel` are the satisfiable ones. -/ @@ -276,7 +276,7 @@ theorem searchRel_mem_FPSearch_iff : searchRel ∈ FPSearch encCNF ↔ SAT ∈ P refine ⟨fun h => searchDomain_searchRel ▸ searchDomain_mem_P h, fun h => ?_⟩ obtain ⟨D, hD, hSAT⟩ := mem_P_iff_tidy.mp h have hsearch : ComputableTidilyInPolyTime (search D) encCNF encBits := - computableTidilyInPolyTime_search (D := fun _ => D) (hD.comp (snd _ _)) id' + (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (snd _ _))) (.of_tidy id')).tidy refine mem_FPSearch_iff_tidy.mpr ⟨searchRel_mem_FNP, fun φ => if D φ then some (search D φ) else none, cond hD ((optionSome encBits).comp hsearch) (const none), fun φ => ⟨fun w hw => ?_, ?_⟩⟩ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean index 406d8f1d5..9a00daa31 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean @@ -123,10 +123,11 @@ private theorem computableTidilyInPolyTime_zeroVertex : simpa only [heq] using h @[fun_prop] -theorem computableTidilyInPolyTime_zeroVertex_comp {encIn : α ↪ List Bool} {n : α → ℕ} - (hn : ComputableTidilyInPolyTime n encIn encUnary) : - ComputableTidilyInPolyTime (fun a => zeroVertex (n a)) encIn encBits := - computableTidilyInPolyTime_zeroVertex.comp hn +theorem computableInPolyTime_zeroVertex_comp {encIn : α ↪ List Bool} {n : α → ℕ} + (hn : ComputableInPolyTime n encIn encUnary) : + ComputableInPolyTime (fun a => zeroVertex (n a)) encIn encBits := by + have hn := hn.tidy + exact .of_tidy (computableTidilyInPolyTime_zeroVertex.comp hn) /-- One step of converting a most-significant-first bit string to `Nat.bits` (`encNat`): strip leading `false` bits and prepend significant bits. -/ @@ -170,65 +171,66 @@ private theorem computableTidilyInPolyTime_binaryValue : exact hfold.of_enc_eq fun w => (foldl_binaryBitsStep w).symm @[fun_prop] -theorem computableTidilyInPolyTime_binaryValue_comp {encIn : α ↪ List Bool} {w : α → List Bool} - (hw : ComputableTidilyInPolyTime w encIn encBits) : - ComputableTidilyInPolyTime (fun a => binaryValue (w a)) encIn encNat := - computableTidilyInPolyTime_binaryValue.comp hw +theorem computableInPolyTime_binaryValue_comp {encIn : α ↪ List Bool} {w : α → List Bool} + (hw : ComputableInPolyTime w encIn encBits) : + ComputableInPolyTime (fun a => binaryValue (w a)) encIn encNat := by + have hw := hw.tidy + exact .of_tidy (computableTidilyInPolyTime_binaryValue.comp hw) /-- Comparing the binary values of two bit strings is polynomial-time. -/ -theorem computableTidilyInPolyTime_binaryValue_le : - ComputableTidilyInPolyTime +theorem computableInPolyTime_binaryValue_le : + ComputableInPolyTime (fun p : List Bool × List Bool => decide (binaryValue p.1 ≤ binaryValue p.2)) (encPair encBits encBits) encBool := - binary_le.comp + .of_tidy (binary_le.comp ((computableTidilyInPolyTime_binaryValue.comp (fst encBits encBits)).prod - (computableTidilyInPolyTime_binaryValue.comp (snd encBits encBits))) + (computableTidilyInPolyTime_binaryValue.comp (snd encBits encBits)))) /-- Comparing two binary natural numbers (`encNat`) is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_nat_le : - ComputableTidilyInPolyTime (fun p : ℕ × ℕ => decide (p.1 ≤ p.2)) +theorem computableInPolyTime_nat_le : + ComputableInPolyTime (fun p : ℕ × ℕ => decide (p.1 ≤ p.2)) (encPair encNat encNat) encBool := - binary_le + .of_tidy (binary_le) @[fun_prop] -theorem computableTidilyInPolyTime_nat_le' {encIn : α ↪ List Bool} {left right : α → ℕ} - (hleft : ComputableTidilyInPolyTime left encIn encNat) - (hright : ComputableTidilyInPolyTime right encIn encNat) : - ComputableTidilyInPolyTime (fun a => decide (left a ≤ right a)) encIn encBool := - computableTidilyInPolyTime_nat_le.comp (hleft.prod hright) +theorem computableInPolyTime_nat_le' {encIn : α ↪ List Bool} {left right : α → ℕ} + (hleft : ComputableInPolyTime left encIn encNat) + (hright : ComputableInPolyTime right encIn encNat) : + ComputableInPolyTime (fun a => decide (left a ≤ right a)) encIn encBool := + computableInPolyTime_nat_le.comp (hleft.prod hright) /-! ### `FNP` and `TFNP` membership of the family relations -/ @[fun_prop] -theorem computableTidilyInPolyTime_hasOut {enc : α ↪ List Bool} {n : α → ℕ} - {P S : α × List Bool → List Bool} (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) : - ComputableTidilyInPolyTime (fun x : α × List Bool => hasOut n P S x.1 x.2) +theorem computableInPolyTime_hasOut {enc : α ↪ List Bool} {n : α → ℕ} + {P S : α × List Bool → List Bool} (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) : + ComputableInPolyTime (fun x : α × List Bool => hasOut n P S x.1 x.2) (encPair enc encBits) encBool := by unfold hasOut fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_hasIn {enc : α ↪ List Bool} {n : α → ℕ} - {P S : α × List Bool → List Bool} (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) : - ComputableTidilyInPolyTime (fun x : α × List Bool => hasIn n P S x.1 x.2) +theorem computableInPolyTime_hasIn {enc : α ↪ List Bool} {n : α → ℕ} + {P S : α × List Bool → List Bool} (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) : + ComputableInPolyTime (fun x : α × List Bool => hasIn n P S x.1 x.2) (encPair enc encBits) encBool := by unfold hasIn fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_undirectedEdge {enc : α ↪ List Bool} +theorem computableInPolyTime_undirectedEdge {enc : α ↪ List Bool} {N₁ N₂ : α × List Bool → List Bool} - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) {u v : α × List Bool → List Bool} - (hu : ComputableTidilyInPolyTime u (encPair enc encBits) encBits) - (hv : ComputableTidilyInPolyTime v (encPair enc encBits) encBits) : - ComputableTidilyInPolyTime (fun x : α × List Bool => undirectedEdge N₁ N₂ x.1 (u x) (v x)) + (hu : ComputableInPolyTime u (encPair enc encBits) encBits) + (hv : ComputableInPolyTime v (encPair enc encBits) encBits) : + ComputableInPolyTime (fun x : α × List Bool => undirectedEdge N₁ N₂ x.1 (u x) (v x)) (encPair enc encBits) encBool := by unfold undirectedEdge fun_prop @@ -241,11 +243,11 @@ private theorem computableTidilyInPolyTime_bool_bne {encIn : α ↪ List Bool} { (of_finite (fun p : Bool × Bool => p.1 != p.2)).comp (hf.prod hg) @[fun_prop] -theorem computableTidilyInPolyTime_hasOddDegree {enc : α ↪ List Bool} +theorem computableInPolyTime_hasOddDegree {enc : α ↪ List Bool} {N₁ N₂ : α × List Bool → List Bool} - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) : - ComputableTidilyInPolyTime (fun x : α × List Bool => hasOddDegree N₁ N₂ x.1 x.2) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) : + ComputableInPolyTime (fun x : α × List Bool => hasOddDegree N₁ N₂ x.1 x.2) (encPair enc encBits) encBool := by unfold hasOddDegree fun_prop @@ -253,10 +255,13 @@ theorem computableTidilyInPolyTime_hasOddDegree {enc : α ↪ List Bool} /-- A polynomial-time local-search family defines an `FNP` relation. -/ theorem localOptRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {N : α × List Bool → List Bool} {C : α × List Bool → ℕ} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN : ComputableTidilyInPolyTime N (encPair enc encBits) encBits) - (hC : ComputableTidilyInPolyTime C (encPair enc encBits) encNat) : + (hn : ComputableInPolyTime n enc encUnary) + (hN : ComputableInPolyTime N (encPair enc encBits) encBits) + (hC : ComputableInPolyTime C (encPair enc encBits) encNat) : localOptRel n N C ∈ FNP enc := by + have hn := hn.tidy + have hN := hN.tidy + have hC := hC.tidy obtain ⟨p, hp⟩ := hn.polyBounded.exists_polynomial refine ⟨⟨p, fun a u h => h.1 ▸ hp a⟩, fun x => decide (x.2.length = n x.1) && decide (C x ≤ C (x.1, N x)), ?_, fun a u => ?_⟩ @@ -266,18 +271,20 @@ theorem localOptRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} /-- A polynomial-time length-preserving local-search family defines a `TFNP` relation. -/ theorem localOptRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {N : α × List Bool → List Bool} {C : α × List Bool → ℕ} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN : ComputableTidilyInPolyTime N (encPair enc encBits) encBits) - (hC : ComputableTidilyInPolyTime C (encPair enc encBits) encNat) + (hn : ComputableInPolyTime n enc encUnary) + (hN : ComputableInPolyTime N (encPair enc encBits) encBits) + (hC : ComputableInPolyTime C (encPair enc encBits) encNat) (hlen : ∀ a u, u.length = n a → (N (a, u)).length = n a) : localOptRel n N C ∈ TFNP enc := ⟨localOptRel_mem_FNP hn hN hC, isTotalSearch_localOptRel hlen⟩ /-- A polynomial-time pigeonhole family defines an `FNP` relation. -/ theorem pigeonRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) : + (hn : ComputableInPolyTime n enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) : pigeonRel n F ∈ FNP enc := by + have hn := hn.tidy + have hF := hF.tidy obtain ⟨p, hp⟩ := hn.polyBounded.exists_polynomial refine mem_FNP_iff_tidy.mpr ⟨⟨2 * p, fun a w h => by simp only [Polynomial.eval_mul, Polynomial.eval_ofNat] @@ -296,8 +303,8 @@ theorem pigeonRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × L /-- A polynomial-time length-preserving pigeonhole family defines a `TFNP` relation. -/ theorem pigeonRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) (hlen : ∀ a u, u.length = n a → (F (a, u)).length = n a) : pigeonRel n F ∈ TFNP enc := ⟨pigeonRel_mem_FNP hn hF, isTotalSearch_pigeonRel hlen⟩ @@ -305,10 +312,13 @@ theorem pigeonRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × /-- A polynomial-time directed end-of-line family defines an `FNP` relation. -/ theorem endOfLineRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {P S : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) : + (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) : endOfLineRel n P S ∈ FNP enc := by + have hn := hn.tidy + have hP := hP.tidy + have hS := hS.tidy obtain ⟨p, hp⟩ := hn.polyBounded.exists_polynomial refine ⟨⟨p, fun a u h => h.1 ▸ hp a⟩, fun x => decide (x.2.length = n x.1) && @@ -320,9 +330,9 @@ theorem endOfLineRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} /-- A polynomial-time length-preserving directed end-of-line family defines a `TFNP` relation. -/ theorem endOfLineRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {P S : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) (hS_len : ∀ a u, u.length = n a → (S (a, u)).length = n a) : endOfLineRel n P S ∈ TFNP enc := ⟨endOfLineRel_mem_FNP hn hP hS, isTotalSearch_endOfLineRel hS_len⟩ @@ -330,10 +340,13 @@ theorem endOfLineRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} /-- A polynomial-time undirected parity family defines an `FNP` relation. -/ theorem leafRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) : + (hn : ComputableInPolyTime n enc encUnary) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) : leafRel n N₁ N₂ ∈ FNP enc := by + have hn := hn.tidy + have hN₁ := hN₁.tidy + have hN₂ := hN₂.tidy obtain ⟨p, hp⟩ := hn.polyBounded.exists_polynomial refine ⟨⟨p, fun a u h => h.1 ▸ hp a⟩, fun x => decide (x.2.length = n x.1) && @@ -345,9 +358,9 @@ theorem leafRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} /-- A polynomial-time length-preserving undirected parity family defines a `TFNP` relation. -/ theorem leafRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) (hN₁_len : ∀ a u, u.length = n a → (N₁ (a, u)).length = n a) (hN₂_len : ∀ a u, u.length = n a → (N₂ (a, u)).length = n a) : leafRel n N₁ N₂ ∈ TFNP enc := @@ -483,42 +496,53 @@ theorem mem_PPA_iff_tidy : R ∈ PPA enc ↔ R ∈ FNP enc ∧ /-- Every uniform polynomial-time local-search family is in `PLS`. -/ theorem localOptRel_mem_PLS {n : α → ℕ} {N : α × List Bool → List Bool} {C : α × List Bool → ℕ} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN : ComputableTidilyInPolyTime N (encPair enc encBits) encBits) - (hC : ComputableTidilyInPolyTime C (encPair enc encBits) encNat) + (hn : ComputableInPolyTime n enc encUnary) + (hN : ComputableInPolyTime N (encPair enc encBits) encBits) + (hC : ComputableInPolyTime C (encPair enc encBits) encNat) (hlen : ∀ a u, u.length = n a → (N (a, u)).length = n a) : - localOptRel n N C ∈ PLS enc := - mem_PLS_iff_tidy.mpr ⟨localOptRel_mem_FNP hn hN hC, n, N, C, hn, hN, hC, hlen, .refl _ _⟩ + localOptRel n N C ∈ PLS enc := by + have hn := hn.tidy + have hN := hN.tidy + have hC := hC.tidy + exact mem_PLS_iff_tidy.mpr ⟨localOptRel_mem_FNP (.of_tidy hn) (.of_tidy hN) (.of_tidy hC), n, N, C, hn, hN, hC, hlen, .refl _ _⟩ /-- Every uniform polynomial-time pigeonhole family is in `PPP`. -/ theorem pigeonRel_mem_PPP {n : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) (hlen : ∀ a u, u.length = n a → (F (a, u)).length = n a) : - pigeonRel n F ∈ PPP enc := - mem_PPP_iff_tidy.mpr ⟨pigeonRel_mem_FNP hn hF, n, F, hn, hF, hlen, .refl _ _⟩ + pigeonRel n F ∈ PPP enc := by + have hn := hn.tidy + have hF := hF.tidy + exact mem_PPP_iff_tidy.mpr ⟨pigeonRel_mem_FNP (.of_tidy hn) (.of_tidy hF), n, F, hn, hF, hlen, .refl _ _⟩ /-- Every uniform polynomial-time directed end-of-line family is in `PPAD`. -/ theorem endOfLineRel_mem_PPAD {n : α → ℕ} {P S : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) (hP_len : ∀ a u, u.length = n a → (P (a, u)).length = n a) (hS_len : ∀ a u, u.length = n a → (S (a, u)).length = n a) : - endOfLineRel n P S ∈ PPAD enc := - mem_PPAD_iff_tidy.mpr - ⟨endOfLineRel_mem_FNP hn hP hS, n, P, S, hn, hP, hS, hP_len, hS_len, .refl _ _⟩ + endOfLineRel n P S ∈ PPAD enc := by + have hn := hn.tidy + have hP := hP.tidy + have hS := hS.tidy + exact mem_PPAD_iff_tidy.mpr + ⟨endOfLineRel_mem_FNP (.of_tidy hn) (.of_tidy hP) (.of_tidy hS), n, P, S, hn, hP, hS, hP_len, hS_len, .refl _ _⟩ /-- Every uniform polynomial-time undirected parity family is in `PPA`. -/ theorem leafRel_mem_PPA {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) (hN₁_len : ∀ a u, u.length = n a → (N₁ (a, u)).length = n a) (hN₂_len : ∀ a u, u.length = n a → (N₂ (a, u)).length = n a) : - leafRel n N₁ N₂ ∈ PPA enc := - mem_PPA_iff_tidy.mpr - ⟨leafRel_mem_FNP hn hN₁ hN₂, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, .refl _ _⟩ + leafRel n N₁ N₂ ∈ PPA enc := by + have hn := hn.tidy + have hN₁ := hN₁.tidy + have hN₂ := hN₂.tidy + exact mem_PPA_iff_tidy.mpr + ⟨leafRel_mem_FNP (.of_tidy hn) (.of_tidy hN₁) (.of_tidy hN₂), n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, .refl _ _⟩ /-! ### Closure under search reductions -/ @@ -663,10 +687,10 @@ theorem padBits_of_length_eq {n : ℕ} {w : List Bool} (h : w.length = n) : padB simp [padBits, h, zeroVertex] @[fun_prop] -theorem computableTidilyInPolyTime_padBits {encIn : α ↪ List Bool} {n : α → ℕ} - {w : α → List Bool} (hn : ComputableTidilyInPolyTime n encIn encUnary) - (hw : ComputableTidilyInPolyTime w encIn encBits) : - ComputableTidilyInPolyTime (fun a => padBits (n a) (w a)) encIn encBits := by +theorem computableInPolyTime_padBits {encIn : α ↪ List Bool} {n : α → ℕ} + {w : α → List Bool} (hn : ComputableInPolyTime n encIn encUnary) + (hw : ComputableInPolyTime w encIn encBits) : + ComputableInPolyTime (fun a => padBits (n a) (w a)) encIn encBits := by unfold padBits fun_prop @@ -692,11 +716,14 @@ theorem evalCircuitOutputs_code {n m : ℕ} (c : Circuit signature n m) (x : Fin exact (c.eval_eq_getD interpretation false x ⟨j, by simpa using hj₂⟩).symm @[fun_prop] -theorem computableTidilyInPolyTime_evalCircuitOutputs {encIn : α ↪ List Bool} +theorem computableInPolyTime_evalCircuitOutputs {encIn : α ↪ List Bool} {code : α → CircuitCode} {u : α → List Bool} - (hcode : ComputableTidilyInPolyTime code encIn encCode) - (hu : ComputableTidilyInPolyTime u encIn encBits) : - ComputableTidilyInPolyTime (fun a => evalCircuitOutputs (code a) (u a)) encIn encBits := by + (hcode : ComputableInPolyTime code encIn encCode) + (hu : ComputableInPolyTime u encIn encBits) : + ComputableInPolyTime (fun a => evalCircuitOutputs (code a) (u a)) encIn encBits := by + have hcode := hcode.tidy + have hu := hu.tidy + refine .of_tidy ?_ have hvals : ComputableTidilyInPolyTime (fun a => evalCode interpretation false (u a) (code a).1) encIn encBits := (computableInPolyTime_evalCode (.of_tidy hu) (.of_tidy hcode.fst')).tidy @@ -719,12 +746,12 @@ theorem evalCircuitCode_code {n : ℕ} (c : Circuit signature n n) (x : Fin n rw [evalCircuitCode, evalCircuitOutputs_code, padBits_of_length_eq (List.length_ofFn)] @[fun_prop] -theorem computableTidilyInPolyTime_evalCircuitCode {encIn : α ↪ List Bool} +theorem computableInPolyTime_evalCircuitCode {encIn : α ↪ List Bool} {n : α → ℕ} {code : α → CircuitCode} {u : α → List Bool} - (hn : ComputableTidilyInPolyTime n encIn encUnary) - (hcode : ComputableTidilyInPolyTime code encIn encCode) - (hu : ComputableTidilyInPolyTime u encIn encBits) : - ComputableTidilyInPolyTime (fun a => evalCircuitCode (n a) (code a) (u a)) encIn encBits := by + (hn : ComputableInPolyTime n encIn encUnary) + (hcode : ComputableInPolyTime code encIn encCode) + (hu : ComputableInPolyTime u encIn encBits) : + ComputableInPolyTime (fun a => evalCircuitCode (n a) (code a) (u a)) encIn encBits := by unfold evalCircuitCode fun_prop @@ -798,12 +825,12 @@ theorem Pigeon_mem_PPP : Pigeon ∈ PPP encPigeon := /-- `EndOfLine` is in `PPAD`. -/ theorem EndOfLine_mem_PPAD : EndOfLine ∈ PPAD encEndOfLine := - endOfLineRel_mem_PPAD (by fun_prop) (by fun_prop) (by fun_prop) + endOfLineRel_mem_PPAD (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (fun _ _ _ => length_evalCircuitCode _ _ _) (fun _ _ _ => length_evalCircuitCode _ _ _) /-- `Leaf` is in `PPA`. -/ theorem Leaf_mem_PPA : Leaf ∈ PPA encLeaf := - leafRel_mem_PPA (by fun_prop) (by fun_prop) (by fun_prop) + leafRel_mem_PPA (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (fun _ _ _ => length_evalCircuitCode _ _ _) (fun _ _ _ => length_evalCircuitCode _ _ _) /-- `LocalOpt` is in `TFNP`. -/ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean index 830c559a5..c5532ec61 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean @@ -50,11 +50,11 @@ variable {α : Type} {enc : α ↪ List Bool} /-- Compile fixed-width function families exactly on their prescribed input cubes. -/ theorem exists_uniformCircuitCodes {n m : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hm : ComputableTidilyInPolyTime m enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hm : ComputableInPolyTime m enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) (hlen : ∀ a u, u.length = n a → (F (a, u)).length = m a) : - ∃ code : α → CircuitCode, ComputableTidilyInPolyTime code enc encCode ∧ + ∃ code : α → CircuitCode, ComputableInPolyTime code enc encCode ∧ ∀ a u, u.length = n a → evalCircuitOutputs (code a) u = F (a, u) := by obtain ⟨circuits, hcode, hsem⟩ := CircuitValue.exists_uniformCircuitFamily hn hm hF refine ⟨fun a => (circuits a).code, hcode, fun a u hu => ?_⟩ @@ -83,10 +83,12 @@ private theorem exists_endomorphismCodes {n : α → ℕ} {F : α × List Bool /-- A uniform polynomial-time pigeonhole family reduces to the canonical circuit problem. -/ theorem pigeonRel_searchReducible_Pigeon {n : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) (hlen : ∀ a u, u.length = n a → (F (a, u)).length = n a) : SearchReducible enc encPigeon (pigeonRel n F) Pigeon := by + have hn := hn.tidy + have hF := hF.tidy obtain ⟨code, hcode, hsem⟩ := exists_endomorphismCodes hn hF hlen apply SearchReducible.of_isTotalSearch isTotalSearch_Pigeon (hn.prod hcode) (snd enc encBits) intro a w hw @@ -104,12 +106,15 @@ theorem pigeonRel_searchReducible_Pigeon {n : α → ℕ} {F : α × List Bool /-- A uniform polynomial-time end-of-line family reduces to its circuit presentation. -/ theorem endOfLineRel_searchReducible_EndOfLine {n : α → ℕ} {P S : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) - (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hP : ComputableInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableInPolyTime S (encPair enc encBits) encBits) (hP_len : ∀ a u, u.length = n a → (P (a, u)).length = n a) (hS_len : ∀ a u, u.length = n a → (S (a, u)).length = n a) : SearchReducible enc encEndOfLine (endOfLineRel n P S) EndOfLine := by + have hn := hn.tidy + have hP := hP.tidy + have hS := hS.tidy obtain ⟨cP, hcP, hPs⟩ := exists_endomorphismCodes hn hP hP_len obtain ⟨cS, hcS, hSs⟩ := exists_endomorphismCodes hn hS hS_len apply SearchReducible.of_isTotalSearch isTotalSearch_EndOfLine @@ -127,12 +132,15 @@ theorem endOfLineRel_searchReducible_EndOfLine {n : α → ℕ} /-- A uniform polynomial-time undirected parity family reduces to its circuit presentation. -/ theorem leafRel_searchReducible_Leaf {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) - (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) + (hn : ComputableInPolyTime n enc encUnary) + (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) (hN₁_len : ∀ a u, u.length = n a → (N₁ (a, u)).length = n a) (hN₂_len : ∀ a u, u.length = n a → (N₂ (a, u)).length = n a) : SearchReducible enc encLeaf (leafRel n N₁ N₂) Leaf := by + have hn := hn.tidy + have hN₁ := hN₁.tidy + have hN₂ := hN₂.tidy obtain ⟨c₁, hc₁, h₁⟩ := exists_endomorphismCodes hn hN₁ hN₁_len obtain ⟨c₂, hc₂, h₂⟩ := exists_endomorphismCodes hn hN₂ hN₂_len apply SearchReducible.of_isTotalSearch isTotalSearch_Leaf @@ -184,11 +192,14 @@ private theorem exists_costCodes {n : α → ℕ} {C : α × List Bool → ℕ} Costs are encoded with leading zeros, so the comparison is unchanged. -/ theorem localOptRel_searchReducible_LocalOpt {n : α → ℕ} {N : α × List Bool → List Bool} {C : α × List Bool → ℕ} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hN : ComputableTidilyInPolyTime N (encPair enc encBits) encBits) - (hC : ComputableTidilyInPolyTime C (encPair enc encBits) encNat) + (hn : ComputableInPolyTime n enc encUnary) + (hN : ComputableInPolyTime N (encPair enc encBits) encBits) + (hC : ComputableInPolyTime C (encPair enc encBits) encNat) (hlen : ∀ a u, u.length = n a → (N (a, u)).length = n a) : SearchReducible enc encLocalOpt (localOptRel n N C) LocalOpt := by + have hn := hn.tidy + have hN := hN.tidy + have hC := hC.tidy obtain ⟨cN, hcN, hNs⟩ := exists_endomorphismCodes hn hN hlen obtain ⟨cC, hcC, hCs⟩ := exists_costCodes hn hC apply SearchReducible.of_isTotalSearch isTotalSearch_LocalOpt @@ -204,24 +215,24 @@ theorem localOptRel_searchReducible_LocalOpt {n : α → ℕ} theorem Pigeon_searchComplete : SearchComplete @PPP encPigeon Pigeon := by refine ⟨Pigeon_mem_PPP, fun _ enc R hR => ?_⟩ obtain ⟨-, n, F, hn, hF, hlen, hred⟩ := mem_PPP_iff_tidy.mp hR - exact hred.trans (pigeonRel_searchReducible_Pigeon hn hF hlen) + exact hred.trans (pigeonRel_searchReducible_Pigeon (.of_tidy hn) (.of_tidy hF) hlen) /-- Circuit `EndOfLine` is complete for `PPAD` under polynomial-time search reductions. -/ theorem EndOfLine_searchComplete : SearchComplete @PPAD encEndOfLine EndOfLine := by refine ⟨EndOfLine_mem_PPAD, fun _ enc R hR => ?_⟩ obtain ⟨-, n, P, S, hn, hP, hS, hP_len, hS_len, hred⟩ := mem_PPAD_iff_tidy.mp hR - exact hred.trans (endOfLineRel_searchReducible_EndOfLine hn hP hS hP_len hS_len) + exact hred.trans (endOfLineRel_searchReducible_EndOfLine (.of_tidy hn) (.of_tidy hP) (.of_tidy hS) hP_len hS_len) /-- Circuit `Leaf` is complete for `PPA` under polynomial-time search reductions. -/ theorem Leaf_searchComplete : SearchComplete @PPA encLeaf Leaf := by refine ⟨Leaf_mem_PPA, fun _ enc R hR => ?_⟩ obtain ⟨-, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, hred⟩ := mem_PPA_iff_tidy.mp hR - exact hred.trans (leafRel_searchReducible_Leaf hn hN₁ hN₂ hN₁_len hN₂_len) + exact hred.trans (leafRel_searchReducible_Leaf (.of_tidy hn) (.of_tidy hN₁) (.of_tidy hN₂) hN₁_len hN₂_len) /-- Circuit `LocalOpt` is complete for `PLS` under polynomial-time search reductions. -/ theorem LocalOpt_searchComplete : SearchComplete @PLS encLocalOpt LocalOpt := by refine ⟨LocalOpt_mem_PLS, fun _ enc R hR => ?_⟩ obtain ⟨-, n, N, C, hn, hN, hC, hlen, hred⟩ := mem_PLS_iff_tidy.mp hR - exact hred.trans (localOptRel_searchReducible_LocalOpt hn hN hC hlen) + exact hred.trans (localOptRel_searchReducible_LocalOpt (.of_tidy hn) (.of_tidy hN) (.of_tidy hC) hlen) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Time.lean b/Complexity/Computability/Complexity/Classes/Time.lean index 1788883e9..bb9731e4b 100644 --- a/Complexity/Computability/Complexity/Classes/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Time.lean @@ -22,6 +22,7 @@ import Complexity.Computability.Probabilistic.PPT.Clock import Complexity.Computability.Probabilistic.Sampling import Complexity.Probability.PMF.Map import Mathlib.Data.Set.Finite.List +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Time classes @@ -65,7 +66,7 @@ function `g` computable within time `O(T a)` to a problem decidable within time `O(T a + t' |encB (g a)|)` (`Cslib.Complexity.preimage_mem_DTIME`): compute `g a`, then decide whether it is in `B`. A decider of `B` within time `O(t' m)` is first brought to the tidy form, within time and space `O(t' m)` -(`Cslib.Complexity.computableTidilyInO_indicator_of_mem_DTIME`), in which computations compose. +(`Cslib.Complexity.computableInO_indicator_of_mem_DTIME`), in which computations compose. ## Main definitions @@ -75,7 +76,7 @@ within time and space `O(t' m)` ## Main results * `Cslib.Complexity.DTIME_mono_of_le_mul_add`: `DTIME` absorbs constant factors. -* `Cslib.Complexity.computableTidilyInO_indicator_of_mem_DTIME`: a tidy decider within the +* `Cslib.Complexity.computableInO_indicator_of_mem_DTIME`: a tidy decider within the same time and space bounds up to constants. * `Cslib.Complexity.preimage_mem_DTIME`: `DTIME` under timed reductions. * `Cslib.Complexity.DTIME_mono_of_eventually_le`, `Cslib.Complexity.NTIME_mono_of_eventually_le`, @@ -184,9 +185,10 @@ private theorem exists_le_length (enc : α ↪ List Bool) (S : α → ℕ) : /-- A Boolean function, tidily computable within a time bound of the length of the encoded instance, decides a problem within that time. -/ -theorem setOf_mem_DTIME_of_computableTidilyInO {enc : α ↪ List Bool} {f : α → Bool} - {T S : α → ℕ} {t : ℕ → ℕ} (h : ComputableTidilyInO f enc encBool T S) +theorem setOf_mem_DTIME_of_computableInO {enc : α ↪ List Bool} {f : α → Bool} + {T S : α → ℕ} {t : ℕ → ℕ} (h : Turing.MultiTapeTM.ComputableInO f enc encBool T S) (hT : ∀ a, T a ≤ t (enc a).length) : {a | f a = true} ∈ DTIME enc t := by + have h := h.tidy obtain ⟨c, hc, -⟩ := h obtain ⟨s, hs⟩ := exists_le_length enc S refine ⟨c, c, fun n => c * (s n + 1), decidableInTimeAndSpace_iff.mpr ⟨f, ?_, fun a => Iff.rfl⟩⟩ @@ -211,53 +213,56 @@ theorem DTIME_mono_of_le_mul_add {t₁ t₂ : ℕ → ℕ} {C : ℕ} (h : ∀ n, /-- A problem in `DTIME enc t` is decided by a machine tidily computing its indicator within time and space `O(t n)`, on instances whose encoding has length `n`. -/ -theorem computableTidilyInO_indicator_of_mem_DTIME {A : Set α} {t : ℕ → ℕ} +theorem computableInO_indicator_of_mem_DTIME {A : Set α} {t : ℕ → ℕ} (h : A ∈ DTIME enc t) : - ComputableTidilyInO (indicator A) enc encBool (fun a => t (enc a).length) + Turing.MultiTapeTM.ComputableInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t (enc a).length := by - obtain ⟨c₁, c₂, s, hA⟩ := h - obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA - obtain ⟨c, hg⟩ := hg.exists_space_linear - obtain ⟨d, hg⟩ := hg.exists_computableTidilyInTimeAndSpace - rw [indicator_eq_iff.mpr hgA] - refine .of_bounds hg ((2 + 3 * c) * (c₁ + c₂) + 3 * c + d + d * (c * (c₁ + c₂) + c + 1) + 1) - (fun a => ?_) (fun a => ?_) fun a => ?_ - · set T := t (enc a).length - have hu : c₁ * T + c₂ ≤ (c₁ + c₂) * (T + 1) := by nlinarith - calc 2 * (c₁ * T + c₂) + 3 * (c * (c₁ * T + c₂) + c) + d - = (2 + 3 * c) * (c₁ * T + c₂) + (3 * c + d) := by ring - _ ≤ (2 + 3 * c) * ((c₁ + c₂) * (T + 1)) + (3 * c + d) * (T + 1) := - Nat.add_le_add (Nat.mul_le_mul_left _ hu) (Nat.le_mul_of_pos_right _ (by omega)) - _ = ((2 + 3 * c) * (c₁ + c₂) + 3 * c + d) * (T + 1) := by ring - _ ≤ _ := Nat.mul_le_mul_right _ (by omega) - · set T := t (enc a).length - have hu : c₁ * T + c₂ ≤ (c₁ + c₂) * (T + 1) := by nlinarith - calc d * (c * (c₁ * T + c₂) + c + 1) - ≤ d * (c * ((c₁ + c₂) * (T + 1)) + (c + 1) * (T + 1)) := - Nat.mul_le_mul_left _ (by - have := Nat.mul_le_mul_left c hu - have : c + 1 ≤ (c + 1) * (T + 1) := Nat.le_mul_of_pos_right _ (by omega) - omega) - _ = d * (c * (c₁ + c₂) + c + 1) * (T + 1) := by ring - _ ≤ _ := Nat.mul_le_mul_right _ (by omega) - · simp only [encBool_apply, List.length_singleton] - exact Nat.one_le_iff_ne_zero.mpr (Nat.mul_ne_zero (by omega) (by omega)) + have this : ComputableTidilyInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t (enc a).length := by + obtain ⟨c₁, c₂, s, hA⟩ := h + obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA + obtain ⟨c, hg⟩ := hg.exists_space_linear + obtain ⟨d, hg⟩ := hg.exists_computableTidilyInTimeAndSpace + rw [indicator_eq_iff.mpr hgA] + refine .of_bounds hg ((2 + 3 * c) * (c₁ + c₂) + 3 * c + d + d * (c * (c₁ + c₂) + c + 1) + 1) + (fun a => ?_) (fun a => ?_) fun a => ?_ + · set T := t (enc a).length + have hu : c₁ * T + c₂ ≤ (c₁ + c₂) * (T + 1) := by nlinarith + calc 2 * (c₁ * T + c₂) + 3 * (c * (c₁ * T + c₂) + c) + d + = (2 + 3 * c) * (c₁ * T + c₂) + (3 * c + d) := by ring + _ ≤ (2 + 3 * c) * ((c₁ + c₂) * (T + 1)) + (3 * c + d) * (T + 1) := + Nat.add_le_add (Nat.mul_le_mul_left _ hu) (Nat.le_mul_of_pos_right _ (by omega)) + _ = ((2 + 3 * c) * (c₁ + c₂) + 3 * c + d) * (T + 1) := by ring + _ ≤ _ := Nat.mul_le_mul_right _ (by omega) + · set T := t (enc a).length + have hu : c₁ * T + c₂ ≤ (c₁ + c₂) * (T + 1) := by nlinarith + calc d * (c * (c₁ * T + c₂) + c + 1) + ≤ d * (c * ((c₁ + c₂) * (T + 1)) + (c + 1) * (T + 1)) := + Nat.mul_le_mul_left _ (by + have := Nat.mul_le_mul_left c hu + have : c + 1 ≤ (c + 1) * (T + 1) := Nat.le_mul_of_pos_right _ (by omega) + omega) + _ = d * (c * (c₁ + c₂) + c + 1) * (T + 1) := by ring + _ ≤ _ := Nat.mul_le_mul_right _ (by omega) + · simp only [encBool_apply, List.length_singleton] + exact Nat.one_le_iff_ne_zero.mpr (Nat.mul_ne_zero (by omega) (by omega)) + simpa only [Turing.MultiTapeTM.computableInO_iff_computableTidilyInO] using this /-- **`DTIME` under timed reductions.** If `B` is decidable within time `O(t' m)` on instances whose encoding has length `m`, and `g` is computable within time `O(T a)`, then `g ⁻¹' B` is decidable within time `O(t n)` on instances whose encoding has length `n`, as soon as `T a + t' |encB (g a)|` is within `O(t |enc a|)`: compute `g a`, then decide whether it is in `B`. -/ theorem preimage_mem_DTIME {B : Set β} {t' t : ℕ → ℕ} {g : α → β} {T S : α → ℕ} {C : ℕ} - (hB : B ∈ DTIME encB t') (hg : ComputableTidilyInO g enc encB T S) + (hB : B ∈ DTIME encB t') (hg : Turing.MultiTapeTM.ComputableInO g enc encB T S) (ht : ∀ a, T a + t' (encB (g a)).length ≤ C * t (enc a).length + C) : g ⁻¹' B ∈ DTIME enc t := by - have h := (computableTidilyInO_indicator_of_mem_DTIME hB).comp hg + have hg := hg.tidy + have h := (computableInO_indicator_of_mem_DTIME hB).tidy.comp hg have hset : g ⁻¹' B = {a | (indicator B ∘ g) a = true} := by ext a simp [indicator] rw [hset] exact DTIME_mono_of_le_mul_add (C := C) (fun _ => le_rfl) - (setOf_mem_DTIME_of_computableTidilyInO (t := fun n => C * t n + C) h ht) + (setOf_mem_DTIME_of_computableInO (t := fun n => C * t n + C) (.of_tidy h) ht) end TimedReductions diff --git a/Complexity/Computability/Complexity/Classes/Toda/Counting.lean b/Complexity/Computability/Complexity/Classes/Toda/Counting.lean index d0a9621e0..c4b41e822 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Counting.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Counting.lean @@ -145,16 +145,16 @@ def subsetTest (acc : List Bool → Bool) (K Z k : ℕ) (zs : List Bool) : Bool BitString.wordLt (BitString.listRow Z i zs) (BitString.listRow Z (i + 1) zs) @[fun_prop] -theorem computableTidilyInPolyTime_subsetTest {γ : Type} {input : γ ↪ List Bool} +theorem computableInPolyTime_subsetTest {γ : Type} {input : γ ↪ List Bool} {acc : γ → List Bool → Bool} - (hacc : ComputableTidilyInPolyTime (fun p : γ × List Bool => acc p.1 p.2) + (hacc : ComputableInPolyTime (fun p : γ × List Bool => acc p.1 p.2) (encPair input encBits) encBool) {K Z k : γ → ℕ} {zs : γ → List Bool} - (hK : ComputableTidilyInPolyTime K input encUnary) - (hZ : ComputableTidilyInPolyTime Z input encUnary) - (hk : ComputableTidilyInPolyTime k input encUnary) - (hzs : ComputableTidilyInPolyTime zs input encBits) : - ComputableTidilyInPolyTime (fun c => subsetTest (acc c) (K c) (Z c) (k c) (zs c)) input + (hK : ComputableInPolyTime K input encUnary) + (hZ : ComputableInPolyTime Z input encUnary) + (hk : ComputableInPolyTime k input encUnary) + (hzs : ComputableInPolyTime zs input encBits) : + ComputableInPolyTime (fun c => subsetTest (acc c) (K c) (Z c) (k c) (zs c)) input encBool := by unfold subsetTest fun_prop @@ -260,11 +260,11 @@ def unaryTest (K : ℕ) (kb : List Bool) : Bool := kb == List.replicate (kb.count true) true ++ List.replicate (K - kb.count true) false @[fun_prop] -theorem computableTidilyInPolyTime_unaryTest {γ : Type} {input : γ ↪ List Bool} +theorem computableInPolyTime_unaryTest {γ : Type} {input : γ ↪ List Bool} {K : γ → ℕ} {kb : γ → List Bool} - (hK : ComputableTidilyInPolyTime K input encUnary) - (hkb : ComputableTidilyInPolyTime kb input encBits) : - ComputableTidilyInPolyTime (fun c => unaryTest (K c) (kb c)) input encBool := by + (hK : ComputableInPolyTime K input encUnary) + (hkb : ComputableInPolyTime kb input encBits) : + ComputableInPolyTime (fun c => unaryTest (K c) (kb c)) input encBool := by unfold unaryTest fun_prop @@ -310,12 +310,12 @@ def coeffTest (K k : ℕ) (cb : List Bool) : Bool := else (cb.take (K + 1 - k)).any fun b => b @[fun_prop] -theorem computableTidilyInPolyTime_coeffTest {γ : Type} {input : γ ↪ List Bool} +theorem computableInPolyTime_coeffTest {γ : Type} {input : γ ↪ List Bool} {K k : γ → ℕ} {cb : γ → List Bool} - (hK : ComputableTidilyInPolyTime K input encUnary) - (hk : ComputableTidilyInPolyTime k input encUnary) - (hcb : ComputableTidilyInPolyTime cb input encBits) : - ComputableTidilyInPolyTime (fun c => coeffTest (K c) (k c) (cb c)) input encBool := by + (hK : ComputableInPolyTime K input encUnary) + (hk : ComputableInPolyTime k input encUnary) + (hcb : ComputableInPolyTime cb input encBits) : + ComputableInPolyTime (fun c => coeffTest (K c) (k c) (cb c)) input encBool := by unfold coeffTest fun_prop @@ -522,15 +522,15 @@ theorem testBit_card_filter_sharpTest (accept : List Bool → List Bool → Bool variable {α : Type} {enc : α ↪ List Bool} {γ : Type} {input : γ ↪ List Bool} @[fun_prop] -theorem computableTidilyInPolyTime_countingTest {V : (α × List Bool) × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair (encPair enc encBits) encBits) encBool) +theorem computableInPolyTime_countingTest {V : (α × List Bool) × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair (encPair enc encBits) encBits) encBool) {a : γ → α} {K R Z : γ → ℕ} {w : γ → List Bool} - (ha : ComputableTidilyInPolyTime a input enc) - (hK : ComputableTidilyInPolyTime K input encUnary) - (hR : ComputableTidilyInPolyTime R input encUnary) - (hZ : ComputableTidilyInPolyTime Z input encUnary) - (hw : ComputableTidilyInPolyTime w input encBits) : - ComputableTidilyInPolyTime (fun c => countingTest (fun r z => V ((a c, r), z)) (K c) (R c) + (ha : ComputableInPolyTime a input enc) + (hK : ComputableInPolyTime K input encUnary) + (hR : ComputableInPolyTime R input encUnary) + (hZ : ComputableInPolyTime Z input encUnary) + (hw : ComputableInPolyTime w input encBits) : + ComputableInPolyTime (fun c => countingTest (fun r z => V ((a c, r), z)) (K c) (R c) (Z c) (w c)) input encBool := by unfold countingTest fun_prop diff --git a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean index ebb3f1367..9641a2471 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean @@ -206,37 +206,37 @@ def existsVerifier (enc : α ↪ List Bool) (ℓ m ρ ζ e : Polynomial ℕ) (W ((m.eval (enc x.1).length + 2) * (m.eval (enc x.1).length + 1)))) @[fun_prop] -theorem computableTidilyInPolyTime_trialVerifier {W : α × List Bool → Bool} - (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) +theorem computableInPolyTime_trialVerifier {W : α × List Bool → Bool} + (hW : ComputableInPolyTime W (encPair enc encBits) encBool) {γ : Type} {input : γ ↪ List Bool} {a : γ → α} {u r seed block : γ → List Bool} {M level : γ → ℕ} - (ha : ComputableTidilyInPolyTime a input enc) - (hu : ComputableTidilyInPolyTime u input encBits) - (hr : ComputableTidilyInPolyTime r input encBits) - (hM : ComputableTidilyInPolyTime M input encUnary) - (hlevel : ComputableTidilyInPolyTime level input encUnary) - (hseed : ComputableTidilyInPolyTime seed input encBits) - (hblock : ComputableTidilyInPolyTime block input encBits) : - ComputableTidilyInPolyTime (fun x => trialVerifier W (a x) (u x) (r x) (M x) (level x) + (ha : ComputableInPolyTime a input enc) + (hu : ComputableInPolyTime u input encBits) + (hr : ComputableInPolyTime r input encBits) + (hM : ComputableInPolyTime M input encUnary) + (hlevel : ComputableInPolyTime level input encUnary) + (hseed : ComputableInPolyTime seed input encBits) + (hblock : ComputableInPolyTime block input encBits) : + ComputableInPolyTime (fun x => trialVerifier W (a x) (u x) (r x) (M x) (level x) (seed x) (block x)) input encBool := by unfold trialVerifier fun_prop @[fun_prop] -theorem computableTidilyInPolyTime_trialsVerifier {W : α × List Bool → Bool} - (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) +theorem computableInPolyTime_trialsVerifier {W : α × List Bool → Bool} + (hW : ComputableInPolyTime W (encPair enc encBits) encBool) {γ : Type} {input : γ ↪ List Bool} {a : γ → α} {u r seeds y : γ → List Bool} {M Z T B : γ → ℕ} - (ha : ComputableTidilyInPolyTime a input enc) - (hu : ComputableTidilyInPolyTime u input encBits) - (hr : ComputableTidilyInPolyTime r input encBits) - (hseeds : ComputableTidilyInPolyTime seeds input encBits) - (hM : ComputableTidilyInPolyTime M input encUnary) - (hZ : ComputableTidilyInPolyTime Z input encUnary) - (hT : ComputableTidilyInPolyTime T input encUnary) - (hB : ComputableTidilyInPolyTime B input encUnary) - (hy : ComputableTidilyInPolyTime y input encBits) : - ComputableTidilyInPolyTime (fun x => trialsVerifier W (a x) (u x) (r x) (seeds x) (M x) (Z x) + (ha : ComputableInPolyTime a input enc) + (hu : ComputableInPolyTime u input encBits) + (hr : ComputableInPolyTime r input encBits) + (hseeds : ComputableInPolyTime seeds input encBits) + (hM : ComputableInPolyTime M input encUnary) + (hZ : ComputableInPolyTime Z input encUnary) + (hT : ComputableInPolyTime T input encUnary) + (hB : ComputableInPolyTime B input encUnary) + (hy : ComputableInPolyTime y input encBits) : + ComputableInPolyTime (fun x => trialsVerifier W (a x) (u x) (r x) (seeds x) (M x) (Z x) (T x) (B x) (y x)) input encBool := by unfold trialsVerifier fun_prop @@ -384,31 +384,34 @@ theorem IsRandomParityRep.exists {ℓ m ρ ζ e : Polynomial ℕ} {W : α × Lis have a polynomial-time random parity representation at every prefix length `ℓ` with every error `2 ^ (-e)`. -/ theorem exists_isRandomParityRep_alternation {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) (ps : List (Polynomial ℕ)) : + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (ps : List (Polynomial ℕ)) : ∀ (q : Bool) (ℓ e : Polynomial ℕ), ∃ (ρ ζ : Polynomial ℕ) (W : α × List Bool → Bool), - ComputableTidilyInPolyTime W (encPair enc encBits) encBool ∧ + ComputableInPolyTime W (encPair enc encBits) encBool ∧ IsRandomParityRep enc ℓ e ρ ζ W fun a u => Alternation q (ps.map fun p => p.eval (enc a).length) fun w => V (a, u ++ w) = true := by - induction ps with - | nil => - intro q ℓ e - refine ⟨0, 0, _, by fun_prop, (isRandomParityRep_base ℓ e V).congr fun a u _ => ?_⟩ - simp - | cons p ps ih => - intro q ℓ e - cases q - · -- `∀ w, P (u ++ w)` is `¬∃ w, ¬P (u ++ w)` - obtain ⟨ρ, ζ, W, hW, h⟩ := ih true (ℓ + p) (e + p + 1) - refine ⟨_, _, _, computableTidilyInPolyTime_notVerifier _ _ - (computableTidilyInPolyTime_existsVerifier ℓ p ρ (ζ + 1) e - (computableTidilyInPolyTime_notVerifier _ _ hW)), (h.not.exists.not).congr + have hV := hV.tidy + have this : ∀ (q : Bool) (ℓ e : Polynomial ℕ), ∃ (ρ ζ : Polynomial ℕ) (W : α × List Bool → Bool), ComputableTidilyInPolyTime W (encPair enc encBits) encBool ∧ IsRandomParityRep enc ℓ e ρ ζ W fun a u => Alternation q (ps.map fun p => p.eval (enc a).length) fun w => V (a, u ++ w) = true := by + induction ps with + | nil => + intro q ℓ e + refine ⟨0, 0, _, by fun_prop, (isRandomParityRep_base ℓ e V).congr fun a u _ => ?_⟩ + simp + | cons p ps ih => + intro q ℓ e + cases q + · -- `∀ w, P (u ++ w)` is `¬∃ w, ¬P (u ++ w)` + obtain ⟨ρ, ζ, W, hW, h⟩ := ih true (ℓ + p) (e + p + 1) + refine ⟨_, _, _, computableTidilyInPolyTime_notVerifier _ _ + (computableTidilyInPolyTime_existsVerifier ℓ p ρ (ζ + 1) e + (computableTidilyInPolyTime_notVerifier _ _ hW)), (h.not.exists.not).congr + fun a u _ => ?_⟩ + simp only [List.map_cons, alternation_false_cons, List.append_assoc, not_exists, not_and, + not_not] + · obtain ⟨ρ, ζ, W, hW, h⟩ := ih false (ℓ + p) (e + p + 1) + refine ⟨_, _, _, computableTidilyInPolyTime_existsVerifier ℓ p ρ ζ e hW, h.exists.congr fun a u _ => ?_⟩ - simp only [List.map_cons, alternation_false_cons, List.append_assoc, not_exists, not_and, - not_not] - · obtain ⟨ρ, ζ, W, hW, h⟩ := ih false (ℓ + p) (e + p + 1) - refine ⟨_, _, _, computableTidilyInPolyTime_existsVerifier ℓ p ρ ζ e hW, h.exists.congr - fun a u _ => ?_⟩ - simp only [List.map_cons, alternation_true_cons, List.append_assoc] + simp only [List.map_cons, alternation_true_cons, List.append_assoc] + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- Padding the witnesses of length `Z` to length `N ≥ Z` with `false`s keeps their number. -/ private theorem acceptCount_padWitness (W : α × List Bool → Bool) (a : α) (r : List Bool) {Z N : ℕ} diff --git a/Complexity/Computability/Complexity/Classes/Toda/Isolation.lean b/Complexity/Computability/Complexity/Classes/Toda/Isolation.lean index d26eb7747..b607cebc9 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Isolation.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Isolation.lean @@ -84,12 +84,12 @@ def hashesToZero (k : ℕ) (seed w : List Bool) : Bool := /-- The test is polynomial-time, with all its arguments computed. -/ @[fun_prop] -theorem computableTidilyInPolyTime_hashesToZero {γ : Type} {input : γ ↪ List Bool} {k : γ → ℕ} +theorem computableInPolyTime_hashesToZero {γ : Type} {input : γ ↪ List Bool} {k : γ → ℕ} {seed w : γ → List Bool} - (hk : ComputableTidilyInPolyTime k input encUnary) - (hseed : ComputableTidilyInPolyTime seed input encBits) - (hw : ComputableTidilyInPolyTime w input encBits) : - ComputableTidilyInPolyTime (fun x => hashesToZero (k x) (seed x) (w x)) input encBool := by + (hk : ComputableInPolyTime k input encUnary) + (hseed : ComputableInPolyTime seed input encBits) + (hw : ComputableInPolyTime w input encBits) : + ComputableInPolyTime (fun x => hashesToZero (k x) (seed x) (w x)) input encBool := by unfold hashesToZero fun_prop diff --git a/Complexity/Computability/Complexity/Classes/UP.lean b/Complexity/Computability/Complexity/Classes/UP.lean index 509e6e291..5f4471df9 100644 --- a/Complexity/Computability/Complexity/Classes/UP.lean +++ b/Complexity/Computability/Complexity/Classes/UP.lean @@ -54,14 +54,16 @@ def UP (enc : α ↪ List Bool) : Set (Set α) := /-- `UP` through verifiers: at most one certificate of the specified length accepts on each input, and exactly one accepts on members. -/ theorem mem_UP : A ∈ UP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ 1) ∧ ∀ a, a ∈ A ↔ acceptCount V a (p.eval (enc a).length) = 1 := by - constructor - · rintro ⟨f, ⟨p, V, hV, hf⟩, hle, hA⟩ - exact ⟨p, V, hV.tidy, fun a => hf a ▸ hle a, fun a => (hA a).trans (by rw [hf a])⟩ - · rintro ⟨p, V, hV, hle, hA⟩ - exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, hle, hA⟩ + have this : A ∈ UP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ 1) ∧ ∀ a, a ∈ A ↔ acceptCount V a (p.eval (enc a).length) = 1 := by + constructor + · rintro ⟨f, ⟨p, V, hV, hf⟩, hle, hA⟩ + exact ⟨p, V, hV.tidy, fun a => hf a ▸ hle a, fun a => (hA a).trans (by rw [hf a])⟩ + · rintro ⟨p, V, hV, hle, hA⟩ + exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, hle, hA⟩ + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- A deterministic decider uses only the empty certificate. -/ theorem P_subset_UP : P enc ⊆ UP enc := by @@ -94,7 +96,7 @@ theorem PolyTimeReducible.mem_UP {β : Type} {encB : β ↪ List Bool} {B : Set (h : PolyTimeReducible enc encB A B) (hB : B ∈ UP encB) : A ∈ UP enc := by obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, hf, hle, hB⟩ := hB - exact ⟨f ∘ g, SharpP.comp_mem hf hg.tidy, fun a => hle (g a), + exact ⟨f ∘ g, SharpP.comp_mem hf hg, fun a => hle (g a), fun a => (hAB a).trans (hB (g a))⟩ /-- Complements of unambiguous polynomial-time languages, using the usual `co` convention. -/ diff --git a/Complexity/Computability/Complexity/Classes/US.lean b/Complexity/Computability/Complexity/Classes/US.lean index 8f6612b79..27c863618 100644 --- a/Complexity/Computability/Complexity/Classes/US.lean +++ b/Complexity/Computability/Complexity/Classes/US.lean @@ -74,6 +74,6 @@ theorem PolyTimeReducible.mem_US {β : Type} {encB : β ↪ List Bool} {B : Set (h : PolyTimeReducible enc encB A B) (hB : B ∈ US encB) : A ∈ US enc := by obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, hf, hB⟩ := hB - exact ⟨f ∘ g, SharpP.comp_mem hf hg.tidy, fun a => (hAB a).trans (hB (g a))⟩ + exact ⟨f ∘ g, SharpP.comp_mem hf hg, fun a => (hAB a).trans (hB (g a))⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean index 463dcb762..f300ec7c6 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean @@ -45,7 +45,7 @@ injective `Cslib.Complexity.splitVarToNat`. ## Main results -* `Cslib.Complexity.ValiantVazirani.computableTidilyInPolyTime_reduce`: polynomial time. +* `Cslib.Complexity.ValiantVazirani.computableInPolyTime_reduce`: polynomial time. * `Cslib.Complexity.ValiantVazirani.reduce_mem_UNSAT`: soundness. * `Cslib.Complexity.ValiantVazirani.three_mul_two_pow_le_card_reduce_mem_USAT`, `Cslib.Complexity.ValiantVazirani.three_div_le_dens_reduce_mem_USAT`: success probability @@ -114,8 +114,8 @@ def reduce (x : CNF ℕ × List Bool) : CNF ℕ := /-- Building the clauses of one step is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_stepClauses : - ComputableTidilyInPolyTime (fun p : Bool × Var × Var × Var => +theorem computableInPolyTime_stepClauses : + ComputableInPolyTime (fun p : Bool × Var × Var × Var => stepClauses p.1 p.2.1 p.2.2.1 p.2.2.2) (encPair encBool (encPair encVar (encPair encVar encVar))) (encList (encList (encPair encVar encBool))) := by @@ -124,8 +124,8 @@ theorem computableTidilyInPolyTime_stepClauses : /-- Building the clauses of one equation is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_rowClauses : - ComputableTidilyInPolyTime (fun p : List ℕ × ℕ × List Bool × Bool => +theorem computableInPolyTime_rowClauses : + ComputableInPolyTime (fun p : List ℕ × ℕ × List Bool × Bool => rowClauses p.1 p.2.1 p.2.2.1 p.2.2.2) (encPair (encList encNat) (encPair encUnary (encPair encBits encBool))) (encList (encList (encPair encVar encBool))) := by @@ -134,8 +134,8 @@ theorem computableTidilyInPolyTime_rowClauses : /-- Building all equations is polynomial-time, with the number of equations in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_hashCNF : - ComputableTidilyInPolyTime (fun p : List ℕ × ℕ × List Bool => hashCNF p.1 p.2.1 p.2.2) +theorem computableInPolyTime_hashCNF : + ComputableInPolyTime (fun p : List ℕ × ℕ × List Bool => hashCNF p.1 p.2.1 p.2.2) (encPair (encList encNat) (encPair encUnary encBits)) (encList (encList (encPair encVar encBool))) := by unfold hashCNF @@ -168,8 +168,9 @@ private theorem binaryValue_take_hashBits (φ : CNF ℕ) (r : List Bool) : /-- **The Valiant–Vazirani reduction is polynomial-time**, on the framed encoding of the formula followed by the raw random bits. -/ @[fun_prop] -theorem computableTidilyInPolyTime_reduce : - ComputableTidilyInPolyTime reduce (encPair encCNF encBits) encCNF := by +theorem computableInPolyTime_reduce : + ComputableInPolyTime reduce (encPair encCNF encBits) encCNF := by + refine .of_tidy ?_ have h : reduce = fun x : CNF ℕ × List Bool => reduceWith x.1 (BitString.boundedBinaryValue (2 * x.1.vars.length + 5) (x.2.take (Nat.log 2 (x.1.vars.length + 2) + 1))) @@ -188,7 +189,7 @@ theorem computableTidilyInPolyTime_reduce : have hsplit : ComputableTidilyInPolyTime (CNF.relabel splitVarToNat) (encList (encList (encPair (encSum encNat (encPair encUnary encUnary)) encBool))) (encList (encList (encPair encNat encBool))) := - (CNF.computableInPolyTime_relabel (.of_tidy computableTidilyInPolyTime_splitVarToNat)).tidy + (CNF.computableInPolyTime_relabel computableInPolyTime_splitVarToNat).tidy rw [h] unfold reduceWith encCNF fun_prop diff --git a/Complexity/Computability/Complexity/Classes/WPP.lean b/Complexity/Computability/Complexity/Classes/WPP.lean index e55993139..a99ed5f1f 100644 --- a/Complexity/Computability/Complexity/Classes/WPP.lean +++ b/Complexity/Computability/Complexity/Classes/WPP.lean @@ -158,7 +158,7 @@ theorem FewP_subset_WPP : FewP enc ⊆ WPP enc := /-- Subtraction of the target gives a zero test for WPP membership. -/ theorem WPP_subset_CeqP : WPP enc ⊆ CeqP enc := by rintro A ⟨g, hg, f, hf, -, -, hA⟩ - exact ⟨g - f, GapP.sub_mem' hg (mem_GapP_of_polyTime hf.tidy), fun a => by + exact ⟨g - f, GapP.sub_mem' hg (mem_GapP_of_polyTime hf), fun a => by simpa [sub_eq_zero] using hA a⟩ /-- A WPP gap is nonzero exactly on members. -/ @@ -172,7 +172,7 @@ theorem WPP_subset_coCeqP : WPP enc ⊆ coCeqP enc := by theorem compl_mem_WPP (hA : A ∈ WPP enc) : Aᶜ ∈ WPP enc := by rw [mem_WPP_iff_tidy] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA - refine ⟨f - g, GapP.sub_mem' (mem_GapP_of_polyTime hf) hg, f, hf, hn, + refine ⟨f - g, GapP.sub_mem' (mem_GapP_of_polyTime (.of_tidy hf)) hg, f, hf, hn, fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> simp [h] · rcases hr a with h | h <;> simp [hA a, h, (hn a).symm] @@ -216,14 +216,14 @@ theorem PolyTimeReducible.mem_WPP {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ WPP encB) : A ∈ WPP enc := by obtain ⟨r, hr, hAB⟩ := h obtain ⟨g, hg, f, hf, hn, hgr, hB⟩ := hB - exact ⟨g ∘ r, GapP.comp_mem hg hr.tidy, f ∘ r, hf.comp hr, fun a => hn _, + exact ⟨g ∘ r, GapP.comp_mem hg hr, f ∘ r, hf.comp hr, fun a => hn _, fun a => hgr _, fun a => (hAB a).trans (hB _)⟩ /-- The complementary gap uses the same length-dependent target. -/ theorem compl_mem_LWPP (hA : A ∈ LWPP enc) : Aᶜ ∈ LWPP enc := by rw [mem_LWPP_iff_tidy] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA - have htarget := mem_GapP_of_polyTime (hf.comp (.encoding_length enc)) + have htarget := mem_GapP_of_polyTime (.of_tidy (hf.comp (.encoding_length enc))) refine ⟨(fun a => f (enc a).length) - g, GapP.sub_mem' htarget hg, f, hf, hn, fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> simp [h] @@ -303,13 +303,13 @@ private theorem finsetTargetWitness {ι : Type*} (s : Finset ι) {g : α → ℤ have hF : ComputableTidilyInPolyTime F enc encIntBin := finset_prod_intBin s hf have hFn (a : α) : F a ≠ 0 := Finset.prod_ne_zero_iff.mpr fun i hi => hn i hi a have hP : P ∈ GapP enc := - finset_prod_mem_GapP s fun i hi => GapP.sub_mem' (mem_GapP_of_polyTime (hf i hi)) hg + finset_prod_mem_GapP s fun i hi => GapP.sub_mem' (mem_GapP_of_polyTime (.of_tidy (hf i hi))) hg have hP_zero {a : α} (hz : g a = 0) : P a = F a := by simp [P, F, hz] have hP_mem {a : α} (hmem : ∃ i ∈ s, g a = f i a) : P a = 0 := by obtain ⟨i, hi, hgi⟩ := hmem exact Finset.prod_eq_zero hi (by lia) - refine ⟨F - P, GapP.sub_mem' (mem_GapP_of_polyTime hF) hP, fun a => ?_, fun a => ?_⟩ + refine ⟨F - P, GapP.sub_mem' (mem_GapP_of_polyTime (.of_tidy hF)) hP, fun a => ?_, fun a => ?_⟩ · rcases hr a with hz | hmem · exact Or.inl (by simp [F, hP_zero hz]) · exact Or.inr (by simp [F, hP_mem hmem]) @@ -332,10 +332,11 @@ and one of a fixed finite family of nonzero polynomial-time targets on `A` witne [Hemaspaandra et al., Theorem 3.1][HemaspaandraEtAl2018]). -/ theorem mem_WPP_of_finset_targets {ι : Type*} (s : Finset ι) {g : α → ℤ} {f : ι → α → ℤ} (hg : g ∈ GapP enc) - (hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) enc encIntBin) + (hf : ∀ i ∈ s, ComputableInPolyTime (f i) enc encIntBin) (hn : ∀ i ∈ s, ∀ a, f i a ≠ 0) (hr : ∀ a, g a = 0 ∨ ∃ i ∈ s, g a = f i a) (hA : ∀ a, a ∈ A ↔ ∃ i ∈ s, g a = f i a) : A ∈ WPP enc := by + have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) enc encIntBin := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using hf obtain ⟨G, hG, hR, hGA⟩ := finsetTargetWitness s hg hf hn hr hA exact ⟨G, hG, _, .of_tidy (finset_prod_intBin s hf), fun a => Finset.prod_ne_zero_iff.mpr fun i hi => hn i hi a, hR, hGA⟩ @@ -346,10 +347,11 @@ witnesses `A ∈ LWPP` (the fixed-`Finset` case of the product interpolation in [Hemaspaandra et al., Theorem 3.1][HemaspaandraEtAl2018]). -/ theorem mem_LWPP_of_finset_targets {ι : Type*} (s : Finset ι) {g : α → ℤ} {f : ι → ℕ → ℤ} (hg : g ∈ GapP enc) - (hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) encUnary encIntBin) + (hf : ∀ i ∈ s, ComputableInPolyTime (f i) encUnary encIntBin) (hn : ∀ i ∈ s, ∀ n, f i n ≠ 0) (hr : ∀ a, g a = 0 ∨ ∃ i ∈ s, g a = f i (enc a).length) (hA : ∀ a, a ∈ A ↔ ∃ i ∈ s, g a = f i (enc a).length) : A ∈ LWPP enc := by + have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) encUnary encIntBin := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using hf obtain ⟨G, hG, hR, hGA⟩ := finsetTargetWitness s hg (fun i hi => (hf i hi).comp (.encoding_length enc)) (fun i hi a => hn i hi (enc a).length) hr hA @@ -367,11 +369,13 @@ only on [Hemaspaandra et al., Section 3][HemaspaandraEtAl2018]. -/ theorem mem_LWPP_of_polyTime_index {g : α → ℤ} {f : ℕ → ℤ} {k : α → ℕ} (hg : g ∈ GapP enc) - (hf : ComputableTidilyInPolyTime f encUnary encIntBin) + (hf : ComputableInPolyTime f encUnary encIntBin) (hn : ∀ n, f n ≠ 0) - (hk : ComputableTidilyInPolyTime k enc encUnary) + (hk : ComputableInPolyTime k enc encUnary) (hr : ∀ a, g a = 0 ∨ g a = f (k a)) (hA : ∀ a, a ∈ A ↔ g a = f (k a)) : A ∈ LWPP enc := by + have hf := hf.tidy + have hk := hk.tidy obtain ⟨p, hp⟩ := hk.polyBounded.exists_polynomial have hlt (a : α) : k a < p.eval (enc a).length + 1 := Nat.lt_succ_of_le (hp a) let bound (n : ℕ) : ℕ := p.eval n + 1 @@ -407,7 +411,7 @@ theorem mem_LWPP_of_polyTime_index {g : α → ℤ} {f : ℕ → ℤ} {k : α rw [List.nodup_range.erase_eq_filter] exact List.filter_congr fun i _ => by simp [bne, beq_eq_decide] simpa only [h, F, herase] using List.prod_map_erase f (List.mem_range.mpr (hlt a)) - refine ⟨g * h, GapP.mul_mem hg (mem_GapP_of_polyTime hh), F, .of_tidy hF, hFn, fun a => ?_, + refine ⟨g * h, GapP.mul_mem hg (mem_GapP_of_polyTime (.of_tidy hh)), F, .of_tidy hF, hFn, fun a => ?_, fun a => ?_⟩ · rcases hr a with hz | hfk · exact Or.inl (by simp [hz]) @@ -425,8 +429,8 @@ theorem PolyTimeReducible.mem_LWPP {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ LWPP encB) : A ∈ LWPP enc := by obtain ⟨r, hr, hAB⟩ := polyTimeReducible_iff_tidy.mp h obtain ⟨g, hg, f, hf, hn, hgr, hB⟩ := hB - exact mem_LWPP_of_polyTime_index (GapP.comp_mem hg hr) hf.tidy hn - ((ComputableTidilyInPolyTime.encoding_length encB).comp hr) + exact mem_LWPP_of_polyTime_index (GapP.comp_mem hg (.of_tidy hr)) hf hn + (.of_tidy ((ComputableTidilyInPolyTime.encoding_length encB).comp hr)) (fun a => hgr (r a)) (fun a => (hAB a).trans (hB (r a))) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean b/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean index 9572ef668..eb8ce8e31 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean @@ -54,8 +54,9 @@ private theorem prod_eq_zero_of_not_forall {g f : α × ℕ → ℤ} /-- A jointly WPP family is closed under conjunction over a polynomial-time unary bound. -/ theorem forall_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∀ i < r a, (a, i) ∈ A} ∈ WPP enc := by + have hr := hr.tidy rw [mem_WPP_iff_tidy] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := hA let G a := ∏ i ∈ range (r a), g (a, i) @@ -65,7 +66,7 @@ theorem forall_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) prod_congr rfl fun i hi => (hA (a, i)).mp (ha i (mem_range.mp hi)) have hno (a) (ha : ¬ ∀ i < r a, (a, i) ∈ A) : G a = 0 := prod_eq_zero_of_not_forall hR hA ha - refine ⟨G, GapP.prod_range_mem hg hr, F, + refine ⟨G, GapP.prod_range_mem hg (.of_tidy hr), F, ComputableTidilyInPolyTime.intBin_prod_range hf hr, hF, ?_, ?_⟩ · intro a by_cases ha : ∀ i < r a, (a, i) ∈ A @@ -81,7 +82,7 @@ theorem forall_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) /-- A jointly WPP family is closed under disjunction over a polynomial-time unary bound. -/ theorem exists_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∃ i < r a, (a, i) ∈ A} ∈ WPP enc := by convert compl_mem_WPP (forall_lt_mem_WPP (compl_mem_WPP hA) hr) using 1 ext a @@ -91,8 +92,9 @@ theorem exists_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) The count `r a` may vary at fixed input length. If `p` bounds it, polynomial-family robustness normalizes the nonzero targets `∏ i < k, f (2 * n + 1 + i)` for every `k ≤ p n`. -/ theorem forall_lt_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∀ i < r a, (a, i) ∈ A} ∈ LWPP enc := by + have hr := hr.tidy obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP_iff_tidy.mp hA obtain ⟨p, hb⟩ := hr.polyBounded.exists_polynomial let T (x : ℕ × ℕ) := ∏ i ∈ range x.2, f (2 * x.1 + 1 + i) @@ -100,7 +102,7 @@ theorem forall_lt_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) apply ComputableTidilyInPolyTime.intBin_prod_range (f := fun x : (ℕ × ℕ) × ℕ => f (2 * x.1.1 + 1 + x.2)) <;> fun_prop have hp : ComputableTidilyInPolyTime (fun n => p.eval n + 1) encUnary encUnary := by fun_prop - apply mem_LWPP_of_indexed_targets (GapP.prod_range_mem hg hr) + apply mem_LWPP_of_indexed_targets (GapP.prod_range_mem hg (.of_tidy hr)) hT.computableInPolyTime hp.computableInPolyTime · intro n k _ exact prod_ne_zero_iff.mpr fun i _ => hn _ @@ -117,7 +119,7 @@ theorem forall_lt_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) /-- A jointly LWPP family is closed under disjunction over an input-dependent polynomial-time unary bound. The empty range gives the empty language. -/ theorem exists_lt_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) : + (hr : ComputableInPolyTime r enc encUnary) : {a | ∃ i < r a, (a, i) ∈ A} ∈ LWPP enc := by convert compl_mem_LWPP (forall_lt_mem_LWPP (compl_mem_LWPP hA) hr) using 1 ext a diff --git a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean index 55f4aaa76..6be7bbc97 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean @@ -280,16 +280,16 @@ theorem GapP.generalWeightedReplay_mem {k : ℕ} {Control Operation : Type} let p : (α × List Bool) × ℕ → ℤ := fun x => if (machine.pendingQuery (cfg x)).isSome then H (x.1.1, machine.pendingRequest (cfg x)) else 0 have hp : p ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.ite_mem hquery (GapP.comp_mem hH hrequest) GapP.zero_mem + GapP.ite_mem (.of_tidy hquery) (GapP.comp_mem hH (.of_tidy hrequest)) GapP.zero_mem have hdenom : (fun x : (α × List Bool) × ℕ => D x.1.1) ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.comp_mem hD (by fun_prop) + GapP.comp_mem hD (.of_tidy (by fun_prop)) have hbit : ComputableTidilyInPolyTime (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop - have hfactor := GapP.ite_mem hbit hp (GapP.sub_mem' hdenom hp) + have hfactor := GapP.ite_mem (.of_tidy hbit) hp (GapP.sub_mem' hdenom hp) have hprod := GapP.prod_range_mem hfactor - (r := fun x : α × List Bool => x.2.length) (by fun_prop) + (r := fun x : α × List Bool => x.2.length) (.of_tidy (by fun_prop)) have hout : ComputableTidilyInPolyTime (fun x : α × List Bool => (machine.replayOutput (input x.1) x.2).headD false) (encPair enc encBits) encBool := by @@ -300,8 +300,8 @@ theorem GapP.generalWeightedReplay_mem {k : ℕ} {Control Operation : Type} (machine.replayOutput_pt.comp hreindex) have hmask : (fun x : α × List Bool => if (machine.replayOutput (input x.1) x.2).headD false then (1 : ℤ) else 0) ∈ - GapP (encPair enc encBits) := GapP.ite_mem hout GapP.one_mem GapP.zero_mem - have hsum := GapP.sum_bits_mem (GapP.mul_mem hprod hmask) hT + GapP (encPair enc encBits) := GapP.ite_mem (.of_tidy hout) GapP.one_mem GapP.zero_mem + have hsum := GapP.sum_bits_mem (GapP.mul_mem hprod hmask) (.of_tidy hT) convert hsum using 1 funext a rw [generalWeightedReplay, acceptWeight_eq_sum] @@ -395,9 +395,9 @@ private theorem sharpPWithOracle_mem_GapP_of_mem_SPP (hA : A ∈ SPP encBits) dsimp [T']; fun_prop have hF : F ∈ GapP (encPair enc encBits) := GapP.generalWeightedReplay_mem machine hinput_pt.computableInPolyTime - hT'_pt.computableInPolyTime GapP.one_mem (GapP.comp_mem hg (by fun_prop)) + hT'_pt.computableInPolyTime GapP.one_mem (GapP.comp_mem hg (.of_tidy (by fun_prop))) have hsum : (fun a => ∑ w : Fin (r a) → Bool, F (a, List.ofFn w)) ∈ GapP enc := - GapP.sum_bits_mem hF hr + GapP.sum_bits_mem hF (.of_tidy hr) convert hsum using 1 funext a have hF_eval (w : Fin (r a) → Bool) : @@ -507,7 +507,7 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ (ComputableTidilyInPolyTime.filterWithInput hlist htest)) let H : α × List Bool → ℤ := fun x => g x.2 * K x have hH : H ∈ GapP (encPair enc encBits) := - GapP.mul_mem (GapP.comp_mem hg (by fun_prop)) (mem_GapP_of_polyTime hK) + GapP.mul_mem (GapP.comp_mem hg (.of_tidy (by fun_prop))) (mem_GapP_of_polyTime (.of_tidy hK)) let input : α × List Bool → List Bool := encPair enc encBits let T' : α × List Bool → ℕ := fun x => T x.1 let D' : α × List Bool → ℤ := fun x => D (enc x.1).length @@ -521,9 +521,9 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ (hD.comp (.encoding_length enc)).comp (.fst enc encBits) have hF : F ∈ GapP (encPair enc encBits) := GapP.generalWeightedReplay_mem machine hinput_pt.computableInPolyTime - hT'_pt.computableInPolyTime (mem_GapP_of_polyTime hD'_pt) (GapP.comp_mem hH (by fun_prop)) + hT'_pt.computableInPolyTime (mem_GapP_of_polyTime (.of_tidy hD'_pt)) (GapP.comp_mem hH (.of_tidy (by fun_prop))) have hsum : (fun a => ∑ w : Fin (r a) → Bool, F (a, List.ofFn w)) ∈ GapP enc := - GapP.sum_bits_mem hF hr + GapP.sum_bits_mem hF (.of_tidy hr) refine ⟨S, hS, hSn, ?_⟩ convert hsum using 1 funext a @@ -568,9 +568,9 @@ theorem exists_mul_mem_GapP_of_mem_LWPP (hA : A ∈ LWPP encBits) {h : α → let S : ℕ → ℤ := fun n => S₁ n * S₂ n have hS : ComputableTidilyInPolyTime S encUnary encIntBin := hS₁.intBin_mul' hS₂ have hS₁_gap : (fun a : α => S₁ (enc a).length) ∈ GapP enc := - mem_GapP_of_polyTime (hS₁.comp (.encoding_length enc)) + mem_GapP_of_polyTime (.of_tidy (hS₁.comp (.encoding_length enc))) have hS₂_gap : (fun a : α => S₂ (enc a).length) ∈ GapP enc := - mem_GapP_of_polyTime (hS₂.comp (.encoding_length enc)) + mem_GapP_of_polyTime (.of_tidy (hS₂.comp (.encoding_length enc))) refine ⟨S, hS.computableInPolyTime, fun n => mul_ne_zero (hS₁n n) (hS₂n n), ?_⟩ have hcomb := GapP.sub_mem' (GapP.mul_mem hS₂_gap hG₁) (GapP.mul_mem hS₁_gap hG₂) convert hcomb using 1 diff --git a/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean b/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean index 498b6b7c7..8a5818df4 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean @@ -104,13 +104,13 @@ theorem GapP.prod_sub_mem {α : Type} {enc : α ↪ List Bool} (hf : ComputableInPolyTime f enc (encList encIntBin)) (hg : g ∈ GapP enc) : (fun a => ((f a).map (fun z => z - g a)).prod) ∈ GapP enc := by have hf := hf.tidy - have hc := mem_GapP_of_polyTime (polyTime_selectedProduct hf) + have hc := mem_GapP_of_polyTime (.of_tidy (polyTime_selectedProduct hf)) have hp := GapP.pow_mem_polyTime - (GapP.comp_mem (GapP.neg_mem hg) (ComputableTidilyInPolyTime.fst enc encBits)) - (show ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.countP id) - (encPair enc encBits) encUnary by fun_prop) + (GapP.comp_mem (GapP.neg_mem hg) (.of_tidy (ComputableTidilyInPolyTime.fst enc encBits))) + (.of_tidy (show ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.countP id) + (encPair enc encBits) encUnary by fun_prop)) have hs := GapP.sum_bits_mem (GapP.mul_mem hc hp) - (show ComputableTidilyInPolyTime (fun a => (f a).length) enc encUnary by fun_prop) + (.of_tidy (show ComputableTidilyInPolyTime (fun a => (f a).length) enc encUnary by fun_prop)) convert hs using 1 ext a rw [expansion_list] @@ -133,7 +133,7 @@ private theorem targetWitness {α : Type} {enc : α ↪ List Bool} {A : Set α} exact List.mem_map.mpr ⟨g a, hy a ha, sub_self _⟩ have hnon (a : α) (ha : a ∉ A) : P a = F a := by simp [P, F, hno a ha] - refine ⟨F - P, GapP.sub_mem' (mem_GapP_of_polyTime hF) hP, + refine ⟨F - P, GapP.sub_mem' (mem_GapP_of_polyTime (.of_tidy hF)) hP, fun a => ?_, fun a => ?_⟩ · change (F - P) a = 0 ∨ (F - P) a = F a by_cases ha : a ∈ A diff --git a/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean b/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean index 9e8d4b371..a168f6b63 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean @@ -69,12 +69,12 @@ private theorem answerGap_mem {α : Type} {enc : α ↪ List Bool} if x.1.2.getD x.2 false then g (x.1.1, x.2) else f (x.1.1, x.2) - g (x.1.1, x.2)) ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.ite_mem (by fun_prop) (GapP.comp_mem hg hq) - (GapP.comp_mem (GapP.sub_mem' hf hg) hq) - have hp := GapP.prod_range_mem hs (hr.comp (.fst enc encBits)) + GapP.ite_mem (.of_tidy (by fun_prop)) (GapP.comp_mem hg (.of_tidy hq)) + (GapP.comp_mem (GapP.sub_mem' hf hg) (.of_tidy hq)) + have hp := GapP.prod_range_mem hs (.of_tidy (hr.comp (.fst enc encBits))) have hw : ComputableTidilyInPolyTime (fun x => if d x then (1 : ℤ) else 0) (encPair enc encBits) encIntBin := by fun_prop - exact GapP.sum_bits_mem (GapP.mul_mem (mem_GapP_of_polyTime hw) hp) hr + exact GapP.sum_bits_mem (GapP.mul_mem (mem_GapP_of_polyTime (.of_tidy hw)) hp) (.of_tidy hr) private theorem answerGap_eq {α : Type} {A : Set (α × ℕ)} {g f : α × ℕ → ℤ} {r : α → ℕ} {d : α × List Bool → Bool} @@ -121,14 +121,16 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set (α × ℕ)} /-- A jointly WPP family supports any polynomial-time Boolean combination of a computed batch. -/ theorem truthTable_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) - (hd : ComputableTidilyInPolyTime d (encPair enc encBits) encBool) : + (hr : ComputableInPolyTime r enc encUnary) + (hd : ComputableInPolyTime d (encPair enc encBits) encBool) : {a | d (a, truthTableAnswers A r a) = true} ∈ WPP enc := by + have hr := hr.tidy + have hd := hd.tidy rw [mem_WPP_iff_tidy] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := hA have hF (a) : (∏ i ∈ range (r a), f (a, i)) ≠ 0 := prod_ne_zero_iff.mpr fun i _ => hn (a, i) - refine ⟨answerGap g f r d, answerGap_mem hg (mem_GapP_of_polyTime hf) hr hd, + refine ⟨answerGap g f r d, answerGap_mem hg (mem_GapP_of_polyTime (.of_tidy hf)) hr hd, _, ComputableTidilyInPolyTime.intBin_prod_range hf hr, hF, ?_, ?_⟩ · intro a rw [answerGap_eq hR hA] @@ -141,9 +143,11 @@ theorem truthTable_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) /-- A jointly LWPP family supports any polynomial-time Boolean combination of a computed batch. Polynomial-family robustness normalizes the prefix target for the input-dependent batch size. -/ theorem truthTable_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) - (hr : ComputableTidilyInPolyTime r enc encUnary) - (hd : ComputableTidilyInPolyTime d (encPair enc encBits) encBool) : + (hr : ComputableInPolyTime r enc encUnary) + (hd : ComputableInPolyTime d (encPair enc encBits) encBool) : {a | d (a, truthTableAnswers A r a) = true} ∈ LWPP enc := by + have hr := hr.tidy + have hd := hd.tidy obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP_iff_tidy.mp hA let F (x : α × ℕ) := f ((encPair enc encUnary x).length) have hF : ComputableTidilyInPolyTime F (encPair enc encUnary) encIntBin := @@ -155,7 +159,7 @@ theorem truthTable_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) apply ComputableTidilyInPolyTime.intBin_prod_range (f := fun x : (ℕ × ℕ) × ℕ => f (2 * x.1.1 + 1 + x.2)) <;> fun_prop have hp : ComputableTidilyInPolyTime (fun n => p.eval n + 1) encUnary encUnary := by fun_prop - apply mem_LWPP_of_indexed_targets (answerGap_mem hg (mem_GapP_of_polyTime hF) hr hd) + apply mem_LWPP_of_indexed_targets (answerGap_mem hg (mem_GapP_of_polyTime (.of_tidy hF)) hr hd) hT.computableInPolyTime hp.computableInPolyTime · intro n k _ exact prod_ne_zero_iff.mpr fun i _ => hn _ @@ -177,7 +181,7 @@ theorem PolyTimeTruthTableReducible.mem_WPP {β : Type} {encB : β ↪ List Bool obtain ⟨r, q, d, hr, hq, hd, hL⟩ := h have hqB : q ⁻¹' B ∈ WPP (encPair enc encUnary) := PolyTimeReducible.mem_WPP ⟨q, hq, fun _ => Iff.rfl⟩ hB - convert truthTable_mem_WPP hqB hr.tidy hd.tidy using 1 + convert truthTable_mem_WPP hqB hr hd using 1 ext a exact hL a @@ -190,7 +194,7 @@ theorem PolyTimeTruthTableReducible.mem_LWPP {β : Type} {encB : β ↪ List Boo obtain ⟨r, q, d, hr, hq, hd, hL⟩ := h have hqB : q ⁻¹' B ∈ LWPP (encPair enc encUnary) := PolyTimeReducible.mem_LWPP ⟨q, hq, fun _ => Iff.rfl⟩ hB - convert truthTable_mem_LWPP hqB hr.tidy hd.tidy using 1 + convert truthTable_mem_LWPP hqB hr hd using 1 ext a exact hL a diff --git a/Complexity/Computability/Complexity/CookLevin/Clauses.lean b/Complexity/Computability/Complexity/CookLevin/Clauses.lean index 469025551..69d34348d 100644 --- a/Complexity/Computability/Complexity/CookLevin/Clauses.lean +++ b/Complexity/Computability/Complexity/CookLevin/Clauses.lean @@ -12,6 +12,7 @@ public import Complexity.Computability.Complexity.CookLevin.Encoding import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Window import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Logics.Propositional.CNF.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Polynomial-time construction of tableau clauses @@ -29,14 +30,14 @@ multiplicity. These certificates assemble into the complete reduction in ## Main results -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_initClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_acceptClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_sitClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_uniqueClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_oneHotClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inputClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_readClauses`. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_stepClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_initClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_uniqueClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_readClauses`. +* `Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses`. ## References @@ -51,12 +52,14 @@ open Turing Turing.MultiTapeTM ComputableTidilyInPolyTime Cslib.Logic.PL variable {k : ℕ} {State : Type} [Fintype State] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Enumerate the feature groups in polynomial time in the unary input and window bounds. -/ @[fun_prop] -theorem computableTidilyInPolyTime_groups : - ComputableTidilyInPolyTime +theorem computableInPolyTime_groups : + ComputableInPolyTime (fun p : ℕ × ℕ => Feature.groups (k := k) (State := State) p.1 p.2) (encPair encUnary encUnary) (encList (encList encFeature)) := by + refine .of_tidy ?_ unfold Feature.groups simp only [SProd.sprod, List.product, List.map_flatMap, List.map_map, Function.comp_def] fun_prop @@ -64,73 +67,87 @@ theorem computableTidilyInPolyTime_groups : attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build all exactly-one clauses for one tableau row, including the input-dependent windows. -/ @[fun_prop] -theorem computableTidilyInPolyTime_oneHotClauses [DecidableEq State] +theorem computableInPolyTime_oneHotClauses [DecidableEq State] {α : Type} {enc : α ↪ List Bool} {u : α → List Bool} {L T t : α → ℕ} - (hu : ComputableTidilyInPolyTime u enc encBits) - (hL : ComputableTidilyInPolyTime L enc encUnary) - (hT : ComputableTidilyInPolyTime T enc encUnary) - (ht : ComputableTidilyInPolyTime t enc encUnary) : - ComputableTidilyInPolyTime + (hu : ComputableInPolyTime u enc encBits) + (hL : ComputableInPolyTime L enc encUnary) + (hT : ComputableInPolyTime T enc encUnary) + (ht : ComputableInPolyTime t enc encUnary) : + ComputableInPolyTime (fun a => oneHotClauses (k := k) (State := State) (u a) (L a) (T a) (t a)) enc (encList (encList (encPair encVar encBool))) := by fun_prop [oneHotClauses] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build the existing initial-configuration clauses from a unary window bound. -/ @[fun_prop] -theorem computableTidilyInPolyTime_initClauses (tm : MultiTapeTM k Bool State) : - ComputableTidilyInPolyTime (initClauses tm) encUnary +theorem computableInPolyTime_initClauses (tm : MultiTapeTM k Bool State) : + ComputableInPolyTime (initClauses tm) encUnary (encList (encList (encPair encVar encBool))) := by + refine .of_tidy ?_ fun_prop [initClauses] /-- Build the two accepting-configuration clauses from a unary time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_acceptClauses : - ComputableTidilyInPolyTime (acceptClauses (k := k) (State := State)) encUnary +theorem computableInPolyTime_acceptClauses : + ComputableInPolyTime (acceptClauses (k := k) (State := State)) encUnary (encList (encList (encPair encVar encBool))) := by fun_prop [acceptClauses] attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build the situation clauses at a unary time, with the finite machine data fixed. -/ @[fun_prop] -theorem computableTidilyInPolyTime_sitClauses : - ComputableTidilyInPolyTime (sitClauses (k := k) (State := State)) encUnary +theorem computableInPolyTime_sitClauses : + ComputableInPolyTime (sitClauses (k := k) (State := State)) encUnary (encList (encList (encPair encVar encBool))) := by + refine .of_tidy ?_ fun_prop [sitClauses] attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build the uniqueness clauses at a unary time, with the finite machine data fixed. -/ @[fun_prop] -theorem computableTidilyInPolyTime_uniqueClauses [DecidableEq State] : - ComputableTidilyInPolyTime (uniqueClauses (k := k) (State := State)) encUnary +theorem computableInPolyTime_uniqueClauses [DecidableEq State] : + ComputableInPolyTime (uniqueClauses (k := k) (State := State)) encUnary (encList (encList (encPair encVar encBool))) := by + refine .of_tidy ?_ fun_prop [uniqueClauses] attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build input-symbol clauses from computed input, certificate length, time and position. -/ @[fun_prop] -theorem computableTidilyInPolyTime_inputClauses {α : Type} {enc : α ↪ List Bool} +theorem computableInPolyTime_inputClauses {α : Type} {enc : α ↪ List Bool} {u : α → List Bool} {L t j : α → ℕ} - (hu : ComputableTidilyInPolyTime u enc encBits) - (hL : ComputableTidilyInPolyTime L enc encUnary) - (ht : ComputableTidilyInPolyTime t enc encUnary) - (hj : ComputableTidilyInPolyTime j enc encUnary) : - ComputableTidilyInPolyTime + (hu : ComputableInPolyTime u enc encBits) + (hL : ComputableInPolyTime L enc encUnary) + (ht : ComputableInPolyTime t enc encUnary) + (hj : ComputableInPolyTime j enc encUnary) : + ComputableInPolyTime (fun a => inputClauses (k := k) (State := State) (u a) (L a) (t a) (j a)) enc (encList (encList (encPair encVar encBool))) := by + have hu := hu.tidy + have hL := hL.tidy + have ht := ht.tidy + have hj := hj.tidy + refine .of_tidy ?_ fun_prop [inputClauses] attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Enumerate work-tape and input-symbol clauses, charging the complete input-dependent lists. -/ @[fun_prop] -theorem computableTidilyInPolyTime_readClauses +theorem computableInPolyTime_readClauses {α : Type} {enc : α ↪ List Bool} {u : α → List Bool} {L T t : α → ℕ} - (hu : ComputableTidilyInPolyTime u enc encBits) - (hL : ComputableTidilyInPolyTime L enc encUnary) - (hT : ComputableTidilyInPolyTime T enc encUnary) - (ht : ComputableTidilyInPolyTime t enc encUnary) : - ComputableTidilyInPolyTime + (hu : ComputableInPolyTime u enc encBits) + (hL : ComputableInPolyTime L enc encUnary) + (hT : ComputableInPolyTime T enc encUnary) + (ht : ComputableInPolyTime t enc encUnary) : + ComputableInPolyTime (fun a => readClauses (k := k) (State := State) (u a) (L a) (T a) (t a)) enc (encList (encList (encPair encVar encBool))) := by + have hu := hu.tidy + have hL := hL.tidy + have hT := hT.tidy + have ht := ht.tidy + refine .of_tidy ?_ unfold readClauses apply listAppend' <;> fun_prop @@ -147,12 +164,16 @@ private theorem stepTerms_out (o : OutView) : ComputableTidilyInPolyTime (fun a => Feature.stepTerms tm (n a) (T a) (.out o)) enc (encList (encList (encPair encFeature encBool))) := const _ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem stepTerms_cell (i : Fin k) (s : Option Bool) {z : α → ℤ} (hz : ComputableTidilyInPolyTime z enc encInt) : ComputableTidilyInPolyTime (fun a => Feature.stepTerms tm (n a) (T a) (.cell i (z a) s)) enc (encList (encList (encPair encFeature encBool))) := by fun_prop [Feature.stepTerms] +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem stepTerms_head (i : Fin k) {z : α → ℤ} (hT : ComputableTidilyInPolyTime T enc encUnary) (hz : ComputableTidilyInPolyTime z enc encInt) : @@ -167,6 +188,8 @@ private theorem stepTerms_head (i : Fin k) {z : α → ℤ} · intro y _ fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem stepTerms_inPos {j : α → ℕ} (hn : ComputableTidilyInPolyTime n enc encUnary) (hj : ComputableTidilyInPolyTime j enc encUnary) : @@ -200,19 +223,25 @@ private theorem stepImpClauses {t : α → ℕ} {feature : α → Feature k Stat end Step +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Build the step constraints by enumerating the fixed constructor templates in their original order. Positions and bounds are unary; the machine's finite transition table is fixed. -/ @[fun_prop] -theorem computableTidilyInPolyTime_stepClauses [DecidableEq State] +theorem computableInPolyTime_stepClauses [DecidableEq State] (tm : MultiTapeTM k Bool State) {α : Type} {enc : α ↪ List Bool} {u : α → List Bool} {L T t : α → ℕ} - (hu : ComputableTidilyInPolyTime u enc encBits) - (hL : ComputableTidilyInPolyTime L enc encUnary) - (hT : ComputableTidilyInPolyTime T enc encUnary) - (ht : ComputableTidilyInPolyTime t enc encUnary) : - ComputableTidilyInPolyTime + (hu : ComputableInPolyTime u enc encBits) + (hL : ComputableInPolyTime L enc encUnary) + (hT : ComputableInPolyTime T enc encUnary) + (ht : ComputableInPolyTime t enc encUnary) : + ComputableInPolyTime (fun a => stepClauses tm (u a) (L a) (T a) (t a)) enc (encList (encList (encPair encVar encBool))) := by + have hu := hu.tidy + have hL := hL.tidy + have hT := hT.tidy + have ht := ht.tidy + refine .of_tidy ?_ unfold stepClauses simp only [Feature.basic, Feature.groups, List.flatten_eq_flatMap, List.flatMap_assoc, List.flatMap_cons, List.flatMap_nil, List.flatMap_map, List.flatMap_append, diff --git a/Complexity/Computability/Complexity/CookLevin/Completeness.lean b/Complexity/Computability/Complexity/CookLevin/Completeness.lean index 2135eeeaa..23404c4ee 100644 --- a/Complexity/Computability/Complexity/CookLevin/Completeness.lean +++ b/Complexity/Computability/Complexity/CookLevin/Completeness.lean @@ -45,7 +45,7 @@ theorem SAT_npHard : NPHard encCNF SAT := by obtain ⟨c, d, ht⟩ := ht.exists_le have := Fintype.ofFinite State classical - refine ⟨reduce tm p c d enc, .of_tidy (computableTidilyInPolyTime_reduce tm p c d enc), fun a => + refine ⟨reduce tm p c d enc, (computableInPolyTime_reduce tm p c d enc), fun a => (reduce_mem_SAT_iff_of_computesTidily (s := s) hV ?_ a).symm⟩ exact htm.mono (fun x => ht x) (fun _ => le_rfl) diff --git a/Complexity/Computability/Complexity/CookLevin/Counting.lean b/Complexity/Computability/Complexity/CookLevin/Counting.lean index 80965b34c..423fb5de8 100644 --- a/Complexity/Computability/Complexity/CookLevin/Counting.lean +++ b/Complexity/Computability/Complexity/CookLevin/Counting.lean @@ -52,7 +52,7 @@ theorem SharpSAT_sharpPHard : SharpPHard encCNF SharpSAT := by have := Fintype.ofFinite State classical have htm' := htm.mono (fun x => ht x) (fun _ => le_rfl) - exact ⟨reduce tm p c d enc, .of_tidy (computableTidilyInPolyTime_reduce tm p c d enc), fun a => by + exact ⟨reduce tm p c d enc, (computableInPolyTime_reduce tm p c d enc), fun a => by rw [hf a, SharpSAT, modelCount_reduce a fun w _ => (htm' (a, w)).runFrom_initCfg]⟩ /-- **`#SAT` is `#P`-complete** under parsimonious polynomial-time reductions. -/ diff --git a/Complexity/Computability/Complexity/CookLevin/Encoding.lean b/Complexity/Computability/Complexity/CookLevin/Encoding.lean index 63e1cbd7e..8d9673185 100644 --- a/Complexity/Computability/Complexity/CookLevin/Encoding.lean +++ b/Complexity/Computability/Complexity/CookLevin/Encoding.lean @@ -30,13 +30,13 @@ decoder or certify pattern matching on an arbitrary encoded feature. ## Main results -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inPos`, - `.computableTidilyInPolyTime_head`, `.computableTidilyInPolyTime_cell`: varying positions. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_holds`, - `.computableTidilyInPolyTime_cert`: tableau variable constructors. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_index`: the existing variable numbering +* `Cslib.Complexity.CookLevin.computableInPolyTime_inPos`, + `.computableInPolyTime_head`, `.computableInPolyTime_cell`: varying positions. +* `Cslib.Complexity.CookLevin.computableInPolyTime_holds`, + `.computableInPolyTime_cert`: tableau variable constructors. +* `Cslib.Complexity.CookLevin.computableInPolyTime_index`: the existing variable numbering with binary output. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_relabel`: number all variables in a +* `Cslib.Complexity.CookLevin.computableInPolyTime_relabel`: number all variables in a constructed tableau, producing the SAT encoding. ## References @@ -62,45 +62,49 @@ noncomputable def encVar : Var k State ↪ List Bool := /-- The unary feature index is already the encoded word. -/ @[fun_prop] -theorem computableTidilyInPolyTime_featureIndex : - ComputableTidilyInPolyTime (featureIndex (k := k) (State := State)) encFeature encUnary := - of_eq fun _ => rfl +theorem computableInPolyTime_featureIndex : + ComputableInPolyTime (featureIndex (k := k) (State := State)) encFeature encUnary := + ComputableInPolyTime.of_eq fun _ => rfl /-- Construct the input-symbol feature from an optional Boolean symbol. -/ @[fun_prop] -theorem computableTidilyInPolyTime_inRead : - ComputableTidilyInPolyTime (Feature.inRead (k := k) (State := State)) - (encOption encBool) encFeature := of_finite _ +theorem computableInPolyTime_inRead : + ComputableInPolyTime (Feature.inRead (k := k) (State := State)) + (encOption encBool) encFeature := ComputableInPolyTime.of_finite _ /-- Construct an input-head feature from a unary position. -/ @[fun_prop] -theorem computableTidilyInPolyTime_inPos : - ComputableTidilyInPolyTime (Feature.inPos (k := k) (State := State)) encUnary encFeature := - (unary_pair.comp ((const 1).prod id')).of_enc_eq fun _ => rfl +theorem computableInPolyTime_inPos : + ComputableInPolyTime (Feature.inPos (k := k) (State := State)) encUnary encFeature := + .of_tidy ((unary_pair.comp ((const 1).prod id')).of_enc_eq fun _ => rfl) /-- Construct a work-head feature on a fixed tape from a signed unary position. -/ @[fun_prop] -theorem computableTidilyInPolyTime_head (i : Fin k) : - ComputableTidilyInPolyTime (Feature.head (State := State) i) encInt encFeature := by +theorem computableInPolyTime_head (i : Fin k) : + ComputableInPolyTime (Feature.head (State := State) i) encInt encFeature := by + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun z => Nat.pair 2 (Nat.pair i (Equiv.intEquivNat z))) encInt encUnary := by fun_prop exact h.of_enc_eq fun _ => rfl /-- Construct a cell feature for a fixed tape and symbol from a signed unary position. -/ @[fun_prop] -theorem computableTidilyInPolyTime_cell (i : Fin k) (s : Option Bool) : - ComputableTidilyInPolyTime (fun z => Feature.cell (State := State) i z s) +theorem computableInPolyTime_cell (i : Fin k) (s : Option Bool) : + ComputableInPolyTime (fun z => Feature.cell (State := State) i z s) encInt encFeature := by + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun z => Nat.pair 3 (Nat.pair i (Nat.pair (Equiv.intEquivNat z) (Encodable.encode s)))) encInt encUnary := by fun_prop exact h.of_enc_eq fun _ => rfl +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Attach a unary time to an encoded feature. -/ @[fun_prop] -theorem computableTidilyInPolyTime_holds : - ComputableTidilyInPolyTime (fun p : ℕ × Feature k State => Var.holds p.1 p.2) +theorem computableInPolyTime_holds : + ComputableInPolyTime (fun p : ℕ × Feature k State => Var.holds p.1 p.2) (encPair encUnary encFeature) encVar := by + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun p : ℕ × Feature k State => Nat.pair 0 (Nat.pair p.1 (featureIndex p.2))) (encPair encUnary encFeature) encUnary := by fun_prop @@ -108,21 +112,21 @@ theorem computableTidilyInPolyTime_holds : /-- Construct a certificate variable from its unary index. -/ @[fun_prop] -theorem computableTidilyInPolyTime_cert : - ComputableTidilyInPolyTime (Var.cert (k := k) (State := State)) encUnary encVar := - (unary_pair.comp ((const 1).prod id')).of_enc_eq fun _ => rfl +theorem computableInPolyTime_cert : + ComputableInPolyTime (Var.cert (k := k) (State := State)) encUnary encVar := + .of_tidy ((unary_pair.comp ((const 1).prod id')).of_enc_eq fun _ => rfl) /-- Emit the existing variable index in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_index : - ComputableTidilyInPolyTime (Var.index (k := k) (State := State)) encVar encNat := - unary_to_binary.comp (of_eq (encMid := encUnary) fun _ => rfl) +theorem computableInPolyTime_index : + ComputableInPolyTime (Var.index (k := k) (State := State)) encVar encNat := + .of_tidy (unary_to_binary.comp (of_eq (encMid := encUnary) fun _ => rfl)) /-- Convert a constructed tableau to the SAT encoding using its existing variable numbering. -/ @[fun_prop] -theorem computableTidilyInPolyTime_relabel : - ComputableTidilyInPolyTime (Cslib.Logic.PL.CNF.relabel (Var.index (k := k) (State := State))) +theorem computableInPolyTime_relabel : + ComputableInPolyTime (Cslib.Logic.PL.CNF.relabel (Var.index (k := k) (State := State))) (encList (encList (encPair encVar encBool))) encCNF := - (Cslib.Logic.PL.CNF.computableInPolyTime_relabel (.of_tidy computableTidilyInPolyTime_index)).tidy + (Cslib.Logic.PL.CNF.computableInPolyTime_relabel computableInPolyTime_index) end Cslib.Complexity.CookLevin diff --git a/Complexity/Computability/Complexity/CookLevin/Parameters.lean b/Complexity/Computability/Complexity/CookLevin/Parameters.lean index 82a3c9ad8..0bf9c3539 100644 --- a/Complexity/Computability/Complexity/CookLevin/Parameters.lean +++ b/Complexity/Computability/Complexity/CookLevin/Parameters.lean @@ -29,7 +29,7 @@ The clause and variable-numbering certificates in ## Main results -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_parameters`: +* `Cslib.Complexity.CookLevin.computableInPolyTime_parameters`: computing the exact prefix and bounds used by the reduction. ## References @@ -46,9 +46,9 @@ open Turing.MultiTapeTM /-- The input prefix, certificate length and verifier time bound used by the Cook–Levin reduction are jointly computable in polynomial time, with the bounds in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_parameters {α : Type} (p : Polynomial ℕ) (c d : ℕ) +theorem computableInPolyTime_parameters {α : Type} (p : Polynomial ℕ) (c d : ℕ) (enc : α ↪ List Bool) : - ComputableTidilyInPolyTime (parameters p c d enc) + ComputableInPolyTime (parameters p c d enc) enc (encPair encBits (encPair encUnary encUnary)) := by unfold parameters fun_prop diff --git a/Complexity/Computability/Complexity/CookLevin/PolyTime.lean b/Complexity/Computability/Complexity/CookLevin/PolyTime.lean index 70e5611df..ead2e9f4d 100644 --- a/Complexity/Computability/Complexity/CookLevin/PolyTime.lean +++ b/Complexity/Computability/Complexity/CookLevin/PolyTime.lean @@ -24,8 +24,8 @@ and polynomial work for every encoded instance. ## Main results -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_tableau`: the entire original tableau. -* `Cslib.Complexity.CookLevin.computableTidilyInPolyTime_reduce`: the complete SAT reduction. +* `Cslib.Complexity.CookLevin.computableInPolyTime_tableau`: the entire original tableau. +* `Cslib.Complexity.CookLevin.computableInPolyTime_reduce`: the complete SAT reduction. ## References @@ -40,21 +40,23 @@ open Turing Turing.MultiTapeTM variable {k : ℕ} {State : Type} [Fintype State] [DecidableEq State] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Construct the whole tableau from its prefix and unary certificate/time bounds. -/ @[fun_prop] -theorem computableTidilyInPolyTime_tableau (tm : MultiTapeTM k Bool State) : - ComputableTidilyInPolyTime (fun q : List Bool × ℕ × ℕ => tableau tm q.1 q.2.1 q.2.2) +theorem computableInPolyTime_tableau (tm : MultiTapeTM k Bool State) : + ComputableInPolyTime (fun q : List Bool × ℕ × ℕ => tableau tm q.1 q.2.1 q.2.2) (encPair encBits (encPair encUnary encUnary)) (encList (encList (encPair encVar encBool))) := by + refine .of_tidy ?_ unfold tableau polytime /-- The existing Cook–Levin reduction is polynomial-time for every fixed verifier and bounds. -/ @[fun_prop] -theorem computableTidilyInPolyTime_reduce (tm : MultiTapeTM k Bool State) (p : Polynomial ℕ) +theorem computableInPolyTime_reduce (tm : MultiTapeTM k Bool State) (p : Polynomial ℕ) (c d : ℕ) {α : Type} (enc : α ↪ List Bool) : - ComputableTidilyInPolyTime (reduce tm p c d enc) enc encCNF := - computableTidilyInPolyTime_relabel.comp - ((computableTidilyInPolyTime_tableau tm).comp (computableTidilyInPolyTime_parameters p c d enc)) + ComputableInPolyTime (reduce tm p c d enc) enc encCNF := + computableInPolyTime_relabel.comp + ((computableInPolyTime_tableau tm).comp (computableInPolyTime_parameters p c d enc)) end Cslib.Complexity.CookLevin diff --git a/Complexity/Computability/Complexity/CookLevin/Reduction.lean b/Complexity/Computability/Complexity/CookLevin/Reduction.lean index b2f94d1a5..77a3af708 100644 --- a/Complexity/Computability/Complexity/CookLevin/Reduction.lean +++ b/Complexity/Computability/Complexity/CookLevin/Reduction.lean @@ -28,7 +28,7 @@ allowed number of steps with output `[V (a, w)]`, so it applies to any machine c that time, tidily (`reduce_mem_SAT_iff_of_computesTidily`) or not. The input prefix and unary bounds are jointly computable in polynomial time -(`computableTidilyInPolyTime_parameters` in +(`computableInPolyTime_parameters` in `Complexity/Computability/Complexity/CookLevin/Parameters.lean`). Variable construction and numbering are certified in `Complexity/Computability/Complexity/CookLevin/Encoding.lean`, and all clause diff --git a/Complexity/Computability/Complexity/Fagin/Converse.lean b/Complexity/Computability/Complexity/Fagin/Converse.lean index 2ec95f2da..53655043d 100644 --- a/Complexity/Computability/Complexity/Fagin/Converse.lean +++ b/Complexity/Computability/Complexity/Fagin/Converse.lean @@ -254,7 +254,7 @@ theorem exists_powerSentence_of_mem_NP {K : Set EncodedStructure} (hNP : K ∈ N (a ∈ K ↔ letI := v.powerStructure a (a.1 ^ k); Ψ.Realize (Fin (a.1 ^ k))) := by rcases hNP with ⟨p, V, hVpoly, hV⟩ obtain ⟨t, s, ht, -, m, State, hfin, tm, htm⟩ := - computableTidilyInPolyTime_strictVerifier encStructure p hVpoly.tidy + (computableInPolyTime_strictVerifier encStructure p hVpoly).tidy obtain ⟨c, d, ht⟩ := ht.exists_le let _ := Fintype.ofFinite State classical diff --git a/Complexity/Computability/Complexity/Fagin/StrictVerifier.lean b/Complexity/Computability/Complexity/Fagin/StrictVerifier.lean index ace11d4fc..5ad17f272 100644 --- a/Complexity/Computability/Complexity/Fagin/StrictVerifier.lean +++ b/Complexity/Computability/Complexity/Fagin/StrictVerifier.lean @@ -38,7 +38,7 @@ polynomial `p` in first-order logic. * `Cslib.Complexity.IsVerifier.strictVerifier`: `strictVerifier` verifies the same problem with the same certificate polynomial. -* `Cslib.Complexity.computableTidilyInPolyTime_strictVerifier`: `strictVerifier` is computable in +* `Cslib.Complexity.computableInPolyTime_strictVerifier`: `strictVerifier` is computable in polynomial time when `V` is. * `Cslib.Complexity.CookLevin.strictVerifier_eq_true_of_tableau_satisfiable`, `Cslib.Complexity.CookLevin.exists_tableau_satisfiable_iff_of_strictVerifier`: when `tm` computes @@ -99,10 +99,10 @@ theorem IsVerifier.exists_strictVerifier_eq_true_iff {enc : α ↪ List Bool} {p /-- Guarding a polynomial-time verifier by its certificate-length check preserves polynomial-time computability. -/ @[fun_prop] -theorem computableTidilyInPolyTime_strictVerifier (enc : α ↪ List Bool) (p : Polynomial ℕ) +theorem computableInPolyTime_strictVerifier (enc : α ↪ List Bool) (p : Polynomial ℕ) {V : α × List Bool → Bool} - (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : - ComputableTidilyInPolyTime (strictVerifier enc p V) (encPair enc encBits) encBool := by + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : + ComputableInPolyTime (strictVerifier enc p V) (encPair enc encBits) encBool := by unfold strictVerifier fun_prop diff --git a/Complexity/Computability/Complexity/Fagin/Verifier.lean b/Complexity/Computability/Complexity/Fagin/Verifier.lean index 31e59c4ca..fc7f2c568 100644 --- a/Complexity/Computability/Complexity/Fagin/Verifier.lean +++ b/Complexity/Computability/Complexity/Fagin/Verifier.lean @@ -371,11 +371,12 @@ variable {v} {γ : Type} {encIn : γ ↪ List Bool} omit [L.IsRelational] in /-- Reading a table of the input is polynomial-time. -/ @[fun_prop] -theorem _root_.Cslib.Logic.Vocabulary.computableTidilyInPolyTime_table (r : Σ n, L.Relations n) - {a : γ → EncodedStructure} (ha : ComputableTidilyInPolyTime a encIn encStructure) : - ComputableTidilyInPolyTime (fun x => v.table (a x) r) encIn encBits := - (listGetD (encA := encBits) []).comp (((snd encUnary (encList encBits)).comp ha).prod - (const (encMid := encUnary) (v.index r))) +theorem _root_.Cslib.Logic.Vocabulary.computableInPolyTime_table (r : Σ n, L.Relations n) + {a : γ → EncodedStructure} (ha : ComputableInPolyTime a encIn encStructure) : + ComputableInPolyTime (fun x => v.table (a x) r) encIn encBits := by + have ha := ha.tidy + exact .of_tidy ((listGetD (encA := encBits) []).comp (((snd encUnary (encList encBits)).comp ha).prod + (const (encMid := encUnary) (v.index r)))) /-- The cardinality of the input, in unary. -/ private theorem computableTidilyInPolyTime_card {a : γ → EncodedStructure} @@ -386,8 +387,9 @@ private theorem computableTidilyInPolyTime_card {a : γ → EncodedStructure} omit [L.IsRelational] in /-- Checking well-formedness is polynomial-time. -/ @[fun_prop] -theorem _root_.Cslib.Logic.Vocabulary.computableTidilyInPolyTime_checkShape : - ComputableTidilyInPolyTime v.checkShape encStructure encBool := by +theorem _root_.Cslib.Logic.Vocabulary.computableInPolyTime_checkShape : + ComputableInPolyTime v.checkShape encStructure encBool := by + refine .of_tidy ?_ unfold Vocabulary.checkShape refine bool_and' (unary_beq ((length_list encBits).comp (snd encUnary (encList encBits))) (const v.count)) (allConst _ fun i _ => unary_beq ?_ ?_) @@ -396,12 +398,13 @@ theorem _root_.Cslib.Logic.Vocabulary.computableTidilyInPolyTime_checkShape : · exact (unary_pow _).comp (computableTidilyInPolyTime_card id') @[fun_prop] -theorem computableTidilyInPolyTime_termValue {k : ℕ} {σ : γ → List ℕ} - (hσ : ComputableTidilyInPolyTime σ encIn (encList encUnary)) +theorem computableInPolyTime_termValue {k : ℕ} {σ : γ → List ℕ} + (hσ : ComputableInPolyTime σ encIn (encList encUnary)) (t : (L.sum (varLanguage Φ.arity)).Term (Empty ⊕ Fin k)) : - ComputableTidilyInPolyTime (fun x => termValue (Φ := Φ) (σ x) t) encIn encUnary := - (listGetD (encA := encUnary) 0).comp - (hσ.prod (const (encMid := encUnary) (varPos (FO.termVar t)))) + ComputableInPolyTime (fun x => termValue (Φ := Φ) (σ x) t) encIn encUnary := by + have hσ := hσ.tidy + exact .of_tidy ((listGetD (encA := encUnary) 0).comp + (hσ.prod (const (encMid := encUnary) (varPos (FO.termVar t))))) @[fun_prop] theorem computableTidilyInPolyTime_termsIndex {k : ℕ} {n : γ → ℕ} {σ : γ → List ℕ} @@ -411,22 +414,27 @@ theorem computableTidilyInPolyTime_termsIndex {k : ℕ} {n : γ → ℕ} {σ : ComputableTidilyInPolyTime (fun x => termsIndex (Φ := Φ) (n x) (σ x) ts) encIn encUnary | 0, _ => const 0 | _ + 1, ts => - unary_add.comp ((computableTidilyInPolyTime_termValue hσ (ts 0)).prod + unary_add.comp ((computableInPolyTime_termValue (.of_tidy hσ) (ts 0)).tidy.prod (unary_mul.comp (hn.prod (computableTidilyInPolyTime_termsIndex hn hσ fun j => ts j.succ)))) omit [L.IsRelational] in +attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] -theorem computableTidilyInPolyTime_relBit {l : ℕ} +theorem computableInPolyTime_relBit {l : ℕ} (R : (L.sum (varLanguage Φ.arity)).Relations l) {a : γ → EncodedStructure} {N : γ → ℕ} - {w : γ → List Bool} {idx : γ → ℕ} (ha : ComputableTidilyInPolyTime a encIn encStructure) - (hN : ComputableTidilyInPolyTime N encIn encUnary) - (hw : ComputableTidilyInPolyTime w encIn encBits) - (hidx : ComputableTidilyInPolyTime idx encIn encUnary) : - ComputableTidilyInPolyTime (fun x => ℓ.relBit v (a x) (N x) (w x) R (idx x)) encIn encBool := - match R with - | .inl r => (bitsGetD false).comp ((v.computableTidilyInPolyTime_table ⟨_, r⟩ ha).prod hidx) - | .inr r => (bitsGetD false).comp (hw.prod (unary_add.comp ((unary_mul.comp - ((const (encMid := encUnary) (ℓ.block r.1 : ℕ)).prod ((unary_pow _).comp hN))).prod hidx))) + {w : γ → List Bool} {idx : γ → ℕ} (ha : ComputableInPolyTime a encIn encStructure) + (hN : ComputableInPolyTime N encIn encUnary) + (hw : ComputableInPolyTime w encIn encBits) + (hidx : ComputableInPolyTime idx encIn encUnary) : + ComputableInPolyTime (fun x => ℓ.relBit v (a x) (N x) (w x) R (idx x)) encIn encBool := by + have ha := ha.tidy + have hN := hN.tidy + have hw := hw.tidy + have hidx := hidx.tidy + exact .of_tidy (match R with + | .inl r => (bitsGetD false).comp (((v.computableInPolyTime_table (.of_tidy ⟨_, r⟩)).tidy ha).prod hidx) + | .inr r => (bitsGetD false).comp (hw.prod (unary_add.comp ((unary_mul.comp + ((const (encMid := encUnary) (ℓ.block r.1 : ℕ)).prod ((unary_pow _).comp hN))).prod hidx)))) /-- **The evaluator is polynomial-time** for each fixed formula, by induction on the formula. The input type is generalized, as the body of a quantifier takes the current element as well. -/ @@ -442,11 +450,11 @@ theorem computableTidilyInPolyTime_eval {k : ℕ} induction φ generalizing γ with | falsum => exact const false | equal t₁ t₂ => - exact unary_beq (computableTidilyInPolyTime_termValue hσ t₁) - (computableTidilyInPolyTime_termValue hσ t₂) + exact unary_beq (computableInPolyTime_termValue (.of_tidy hσ) t₁).tidy + (computableInPolyTime_termValue (.of_tidy hσ) t₂).tidy | rel R ts => - exact ℓ.computableTidilyInPolyTime_relBit R ha hN hw - (computableTidilyInPolyTime_termsIndex (computableTidilyInPolyTime_card ha) hσ ts) + exact (ℓ.computableInPolyTime_relBit R (.of_tidy ha) (.of_tidy hN) (.of_tidy hw) + (.of_tidy (computableTidilyInPolyTime_termsIndex (computableTidilyInPolyTime_card ha) hσ ts))).tidy | imp φ ψ ih₁ ih₂ => exact bool_or.comp ((bool_not.comp (ih₁ ha hN hw hσ)).prod (ih₂ ha hN hw hσ)) | all φ ih => @@ -459,7 +467,7 @@ theorem computableTidilyInPolyTime_eval {k : ℕ} @[fun_prop] theorem computableTidilyInPolyTime_verifier : ComputableTidilyInPolyTime (ℓ.verifier v) (encPair encStructure encBits) encBool := - bool_and' (v.computableTidilyInPolyTime_checkShape.comp (fst encStructure encBits)) + bool_and' (v.computableInPolyTime_checkShape.comp (fst encStructure encBits)) (ℓ.computableTidilyInPolyTime_eval Φ.matrix (fst encStructure encBits) ((encoding_length encStructure).comp (fst encStructure encBits)) (snd encStructure encBits) (const [])) diff --git a/Complexity/Computability/Complexity/FineGrained.lean b/Complexity/Computability/Complexity/FineGrained.lean index a91682a2f..635353345 100644 --- a/Complexity/Computability/Complexity/FineGrained.lean +++ b/Complexity/Computability/Complexity/FineGrained.lean @@ -15,6 +15,7 @@ public import Mathlib.Analysis.SpecialFunctions.Pow.Real import Complexity.Computability.Machines.Turing.MultiTape.Combinators.TidyNormalForm import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Basic import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The exponential time hypotheses @@ -61,7 +62,7 @@ The negation of `ETH` is `Cslib.Complexity.DecidableInSubexpTime`: decidability * `Cslib.Complexity.mem_DTIME_iff_decidableInTimeO`: `DTIME` is `DecidableInTimeO` for bounds in the length of the encoded instance. * `Cslib.Complexity.DecidableInTimeO.exists_computableTidilyInO`, - `Cslib.Complexity.DecidableInTimeO.of_computableTidilyInO`: deciders within time `O(T)` are tidy + `Cslib.Complexity.DecidableInTimeO.of_computableInO`: deciders within time `O(T)` are tidy deciders within time `O(T)`, which compose. * `Cslib.Complexity.DecidableInTimeO.inter`: restricting to a set decided in polynomial time. * `Cslib.Complexity.DecidableInExpTime.mono`: larger exponents allow more problems. @@ -148,9 +149,10 @@ theorem DecidableInTimeO.exists_computableTidilyInO (h : DecidableInTimeO A enc omega /-- A tidy decider within time `O(t)`, for `t ≤ T`, decides within time `O(T)`. -/ -theorem DecidableInTimeO.of_computableTidilyInO {g : α → Bool} {t S : α → ℕ} - (hg : ComputableTidilyInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) +theorem DecidableInTimeO.of_computableInO {g : α → Bool} {t S : α → ℕ} + (hg : ComputableInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) (hT : ∀ a, (t a : ℝ) ≤ T a) : DecidableInTimeO A enc T := by + have hg := hg.tidy obtain ⟨c, hg, -⟩ := hg refine ⟨c, _, _, fun a => ?_, decidableInTimeAndSpace_iff.mpr ⟨g, hg.computableInTimeAndSpace, hA⟩⟩ @@ -161,16 +163,17 @@ theorem DecidableInTimeO.of_computableTidilyInO {g : α → Bool} {t S : α → and `B` is decidable within time `O(T)`, then the instances of `B` satisfying `p` are decidable within time `O(T)` on instances satisfying `p`, plus a polynomial in the length of the encoded instance: the decider tests `p` first, and rejects at once when it fails. -/ -theorem DecidableInTimeO.inter {p : α → Bool} (hp : ComputableTidilyInPolyTime p enc encBool) +theorem DecidableInTimeO.inter {p : α → Bool} (hp : ComputableInPolyTime p enc encBool) (hB : DecidableInTimeO B enc T) (hT : ∀ a, 0 ≤ T a) : ∃ e : ℕ, DecidableInTimeO ({a | p a = true} ∩ B) enc fun a => (if p a = true then T a else 0) + ((enc a).length + 1) ^ e := by + have hp := hp.tidy obtain ⟨g, t, c, hg, hgB, ht⟩ := hB.exists_computableTidilyInO obtain ⟨d, _, hp⟩ := hp.exists_degree have h := hp.inO.ite hg (ComputableTidilyInO.const false) refine ⟨d + 1, DecidableInTimeO.mono (T := fun a => ((((enc a).length + 1) ^ d + if p a then t a else (enc a).length : ℕ) : ℝ)) - (DecidableInTimeO.of_computableTidilyInO h (fun a => ?_) fun a => le_rfl) (c + 2) + (Complexity.DecidableInTimeO.of_computableInO h (fun a => ?_) fun a => le_rfl) (c + 2) (fun a => ?_) fun a => ?_⟩ · simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, hgB] cases p a <;> simp @@ -228,16 +231,16 @@ variable {α : Type} {enc : α ↪ List Bool} {A B : Set α} /-- A tidy decider within time `O(t)`, for `t` within a constant times `2 ^ (δ μ a)` times a polynomial, decides within time `2 ^ (δ μ a)` times a polynomial. -/ -theorem DecidableInExpTime.of_computableTidilyInO {μ : α → ℕ} {δ : ℝ} {g : α → Bool} - {t S : α → ℕ} (hg : ComputableTidilyInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) +theorem DecidableInExpTime.of_computableInO {μ : α → ℕ} {δ : ℝ} {g : α → Bool} + {t S : α → ℕ} (hg : ComputableInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) (c e : ℕ) (ht : ∀ a, (t a : ℝ) ≤ c * (2 ^ (δ * μ a) * ((enc a).length + 1) ^ e)) : DecidableInExpTime A enc μ δ := - ⟨e, (DecidableInTimeO.of_computableTidilyInO hg hA ht).mono c + ⟨e, (DecidableInTimeO.of_computableInO hg hA ht).mono c (fun a => le_add_of_nonneg_right (Nat.cast_nonneg c)) fun a => by positivity⟩ /-- **Restriction to a set decided in polynomial time**, for exponential bounds with `δ ≥ 0`. -/ theorem DecidableInExpTime.inter {μ : α → ℕ} {δ : ℝ} {p : α → Bool} - (hp : ComputableTidilyInPolyTime p enc encBool) (h : DecidableInExpTime B enc μ δ) + (hp : ComputableInPolyTime p enc encBool) (h : DecidableInExpTime B enc μ δ) (hδ : 0 ≤ δ) : DecidableInExpTime ({a | p a = true} ∩ B) enc μ δ := by obtain ⟨e, h⟩ := h obtain ⟨e', h⟩ := h.inter hp fun a => by positivity diff --git a/Complexity/Computability/Complexity/FineGrained/Assignment.lean b/Complexity/Computability/Complexity/FineGrained/Assignment.lean index 48d817576..04b169733 100644 --- a/Complexity/Computability/Complexity/FineGrained/Assignment.lean +++ b/Complexity/Computability/Complexity/FineGrained/Assignment.lean @@ -22,11 +22,11 @@ assignments satisfies it (`Cslib.Logic.PL.CNF.satisfiable_iff_exists_bitsAssignm distinct variables of a formula are listed by `Cslib.Logic.PL.CNF.distinctVars`, of length `Cslib.Logic.PL.CNF.numVars` (`Cslib.Logic.PL.CNF.length_distinctVars`). Evaluating a formula under a numbered assignment is polynomial-time -(`Cslib.Complexity.computableTidilyInPolyTime_eval_bitsAssignment`). +(`Cslib.Complexity.computableInPolyTime_eval_bitsAssignment`). ## Main results -* `Cslib.Complexity.computableTidilyInPolyTime_eval_bitsAssignment`: evaluation under a numbered +* `Cslib.Complexity.computableInPolyTime_eval_bitsAssignment`: evaluation under a numbered assignment is polynomial-time. ## References @@ -43,10 +43,10 @@ open Cslib.Logic.PL Turing.MultiTapeTM /-- Evaluating a formula under the assignment numbered by `i` on a list of variables is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_eval_bitsAssignment : - ComputableTidilyInPolyTime +theorem computableInPolyTime_eval_bitsAssignment : + ComputableInPolyTime (fun p : (CNF ℕ × List ℕ) × ℕ => p.1.1.eval (bitsAssignment p.1.2 p.2)) (encPair (encPair encCNF (encList encNat)) encNat) encBool := - (CNF.computableInPolyTime_eval_bitsAssignment encNat).tidy + (CNF.computableInPolyTime_eval_bitsAssignment encNat) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean index 3874c4979..fac2cd5a5 100644 --- a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean +++ b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean @@ -15,6 +15,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Ba import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Exhaustive search for satisfiability @@ -24,7 +25,7 @@ variables of a formula (`Cslib.Logic.PL.CNF.satisfiable_iff_exists_bitsAssignmen polynomial-time step `2 ^ n` times with a binary counter (`Turing.MultiTapeTM.ComputableTidilyInO.iterate`), so it runs within time `2 ^ n` times a polynomial in the length of the encoded formula -(`Cslib.Complexity.BruteForce.exists_computableTidilyInO_search`). Hence `SAT`, and every +(`Cslib.Complexity.BruteForce.exists_computableInO_search`). Hence `SAT`, and every `k`-SAT, is decidable within time `2 ^ n` times a polynomial (`Cslib.Complexity.SAT_decidableInExpTime_one`, `Cslib.Complexity.KSAT_decidableInExpTime_one`). @@ -35,7 +36,7 @@ polynomial in the length of the encoded formula ## Main results * `Cslib.Complexity.BruteForce.search_eq_true_iff`: exhaustive search decides `SAT`. -* `Cslib.Complexity.BruteForce.exists_computableTidilyInO_search`: its running time. +* `Cslib.Complexity.BruteForce.exists_computableInO_search`: its running time. * `Cslib.Complexity.SAT_decidableInExpTime_one`, `Cslib.Complexity.KSAT_decidableInExpTime_one`: `SAT` and `k`-SAT are decidable within time `2 ^ n` times a polynomial. @@ -122,7 +123,7 @@ private theorem computableTidilyInPolyTime_step : ComputableTidilyInPolyTime step encState encState := by have h : ComputableTidilyInPolyTime (fun s : State => s.1.1.eval (bitsAssignment s.1.2 s.2.1)) encState encBool := - computableTidilyInPolyTime_eval_bitsAssignment.comp + computableInPolyTime_eval_bitsAssignment.tidy.comp (show ComputableTidilyInPolyTime (fun s : State => (s.1, s.2.1)) encState (encPair (encPair encCNF (encList encNat)) encNat) by fun_prop) unfold step @@ -145,89 +146,91 @@ private theorem computableTidilyInPolyTime_count : /-- **The running time of exhaustive search**: within time `2 ^ n` times a polynomial in the length of the encoded formula, on formulas with `n` variables. -/ -theorem exists_computableTidilyInO_search : ∃ e, ComputableTidilyInO search encCNF encBool +theorem exists_computableInO_search : ∃ e, ComputableInO search encCNF encBool (fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e := by - obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree - obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree - obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree - obtain ⟨d₂, _, hans⟩ := (show ComputableTidilyInPolyTime (fun s : State => s.2.2) encState encBool - by fun_prop).exists_degree - obtain ⟨cv, dv, hvs⟩ := - SAT.computableInPolyTime_distinctVars.tidy.polyBounded_length.exists_le - set size : CNF ℕ → ℕ := fun φ => (encCNF φ).length - set B : CNF ℕ → ℕ := fun φ => (2 * cv + 13) * (size φ + 1) ^ (dv + 1) - have hn (φ : CNF ℕ) : φ.distinctVars.length ≤ size φ := by - rw [CNF.length_distinctVars] - exact φ.numVars_le_length_vars.trans (SAT.length_vars_le φ) - have hstate : ∀ φ, ∀ k ≤ 2 ^ φ.distinctVars.length, - (encState (step^[k] (init φ))).length ≤ B φ := by - intro φ k hk - have hK := ComputableTidilyInO.length_encNat_mono hk - rw [encNat_two_pow] at hK - have hV := hvs φ - have h₁ : size φ + 1 ≤ (size φ + 1) ^ (dv + 1) := by - simpa using Nat.pow_le_pow_right (Nat.succ_pos (size φ)) (Nat.le_add_left 1 dv) - have h₂ : (size φ + 1) ^ dv ≤ (size φ + 1) ^ (dv + 1) := - Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_succ dv) - have h₃ := Nat.mul_le_mul_left cv h₂ - have h₄ := hn φ - rw [iterate_step_init] - simp only [List.length_append, List.length_replicate, List.length_singleton] at hK - simp only [encState, length_encPair, encBool_apply, List.length_singleton, B, size] - at hV h₁ h₃ h₄ ⊢ - nlinarith - have hiter := ComputableTidilyInO.iterate hcount.inO hinit.inO hstep.inO - (R := fun φ => (B φ + 1) ^ d) (Q := fun φ => (B φ + 1) ^ d) (B := B) - (fun φ k hk => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ k hk) 1) d) - (fun φ k hk => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ k hk) 1) d) hstate - have h := hans.inO.comp hiter - have hB : PolyBounded size B := .of_forall_le (2 * cv + 13) (dv + 1) fun φ => le_rfl - have hpow (j : ℕ) : PolyBounded size fun φ => (B φ + 1) ^ j := - ((PolyBounded.of_polynomiallyBounded id (bound := fun x => (x + 1) ^ j) (by fun_prop)).comp - hB).mono fun φ => le_rfl - have hL (j : ℕ) : PolyBounded size fun φ => (size φ + 1) ^ j := - .of_forall_le 1 j fun φ => by simp - obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (size := size) (μ := CNF.numVars) - ((hpow d).add (hB.add (.of_forall_le 4 2 fun φ => le_rfl))) - ((hL d₁).add ((hL d₀).add (hpow d₂))) - (T := fun φ => ((encCNF φ).length + 1) ^ d₁ + ((encCNF φ).length + 1) ^ d₀ + - (2 ^ φ.distinctVars.length + 1) * ((B φ + 1) ^ d + B φ + - ((encNat (2 ^ φ.distinctVars.length)).length + 1) ^ 2) + - ((encState (step^[2 ^ φ.distinctVars.length] (init φ))).length + 1) ^ d₂) - (fun φ => by - have hK : ((encNat (2 ^ φ.distinctVars.length)).length + 1) ^ 2 ≤ - 4 * (size φ + 1) ^ 2 := by - rw [encNat_two_pow] - simp only [List.length_append, List.length_replicate, List.length_singleton] - calc (φ.distinctVars.length + 1 + 1) ^ 2 ≤ (2 * (size φ + 1)) ^ 2 := - Nat.pow_le_pow_left (by have := hn φ; omega) 2 - _ = 4 * (size φ + 1) ^ 2 := by ring - have hS := Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ _ le_rfl) 1) d₂ - rw [CNF.length_distinctVars] at hK hS ⊢ - have := Nat.mul_le_mul_left (2 ^ φ.numVars + 1) - (Nat.add_le_add_left hK ((B φ + 1) ^ d + B φ)) - simp only [size] at this hS ⊢ - nlinarith) - refine ⟨e, (h.mono c (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => rfl⟩ - all_goals - have h₁ := hT φ - simp only [size] at h₁ - generalize 2 ^ φ.distinctVars.length = N at h₁ ⊢ - generalize (encNat N).length = K at h₁ ⊢ - obtain ⟨X, hX⟩ : ∃ X, (B φ + 1) ^ d + B φ = X := ⟨_, rfl⟩ - rw [hX] at h₁ - have h₂ : K ≤ (K + 1) ^ 2 := by nlinarith - have h₃ : X + (K + 1) ^ 2 ≤ (N + 1) * (X + (K + 1) ^ 2) := Nat.le_mul_of_pos_left _ (by omega) - nlinarith + have this : ∃ e, ComputableTidilyInO search encCNF encBool (fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e := by + obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree + obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree + obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree + obtain ⟨d₂, _, hans⟩ := (show ComputableTidilyInPolyTime (fun s : State => s.2.2) encState encBool + by fun_prop).exists_degree + obtain ⟨cv, dv, hvs⟩ := + SAT.computableInPolyTime_distinctVars.tidy.polyBounded_length.exists_le + set size : CNF ℕ → ℕ := fun φ => (encCNF φ).length + set B : CNF ℕ → ℕ := fun φ => (2 * cv + 13) * (size φ + 1) ^ (dv + 1) + have hn (φ : CNF ℕ) : φ.distinctVars.length ≤ size φ := by + rw [CNF.length_distinctVars] + exact φ.numVars_le_length_vars.trans (SAT.length_vars_le φ) + have hstate : ∀ φ, ∀ k ≤ 2 ^ φ.distinctVars.length, + (encState (step^[k] (init φ))).length ≤ B φ := by + intro φ k hk + have hK := ComputableTidilyInO.length_encNat_mono hk + rw [encNat_two_pow] at hK + have hV := hvs φ + have h₁ : size φ + 1 ≤ (size φ + 1) ^ (dv + 1) := by + simpa using Nat.pow_le_pow_right (Nat.succ_pos (size φ)) (Nat.le_add_left 1 dv) + have h₂ : (size φ + 1) ^ dv ≤ (size φ + 1) ^ (dv + 1) := + Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_succ dv) + have h₃ := Nat.mul_le_mul_left cv h₂ + have h₄ := hn φ + rw [iterate_step_init] + simp only [List.length_append, List.length_replicate, List.length_singleton] at hK + simp only [encState, length_encPair, encBool_apply, List.length_singleton, B, size] + at hV h₁ h₃ h₄ ⊢ + nlinarith + have hiter := ComputableTidilyInO.iterate hcount.inO hinit.inO hstep.inO + (R := fun φ => (B φ + 1) ^ d) (Q := fun φ => (B φ + 1) ^ d) (B := B) + (fun φ k hk => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ k hk) 1) d) + (fun φ k hk => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ k hk) 1) d) hstate + have h := hans.inO.comp hiter + have hB : PolyBounded size B := .of_forall_le (2 * cv + 13) (dv + 1) fun φ => le_rfl + have hpow (j : ℕ) : PolyBounded size fun φ => (B φ + 1) ^ j := + ((PolyBounded.of_polynomiallyBounded id (bound := fun x => (x + 1) ^ j) (by fun_prop)).comp + hB).mono fun φ => le_rfl + have hL (j : ℕ) : PolyBounded size fun φ => (size φ + 1) ^ j := + .of_forall_le 1 j fun φ => by simp + obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (size := size) (μ := CNF.numVars) + ((hpow d).add (hB.add (.of_forall_le 4 2 fun φ => le_rfl))) + ((hL d₁).add ((hL d₀).add (hpow d₂))) + (T := fun φ => ((encCNF φ).length + 1) ^ d₁ + ((encCNF φ).length + 1) ^ d₀ + + (2 ^ φ.distinctVars.length + 1) * ((B φ + 1) ^ d + B φ + + ((encNat (2 ^ φ.distinctVars.length)).length + 1) ^ 2) + + ((encState (step^[2 ^ φ.distinctVars.length] (init φ))).length + 1) ^ d₂) + (fun φ => by + have hK : ((encNat (2 ^ φ.distinctVars.length)).length + 1) ^ 2 ≤ + 4 * (size φ + 1) ^ 2 := by + rw [encNat_two_pow] + simp only [List.length_append, List.length_replicate, List.length_singleton] + calc (φ.distinctVars.length + 1 + 1) ^ 2 ≤ (2 * (size φ + 1)) ^ 2 := + Nat.pow_le_pow_left (by have := hn φ; omega) 2 + _ = 4 * (size φ + 1) ^ 2 := by ring + have hS := Nat.pow_le_pow_left (Nat.add_le_add_right (hstate φ _ le_rfl) 1) d₂ + rw [CNF.length_distinctVars] at hK hS ⊢ + have := Nat.mul_le_mul_left (2 ^ φ.numVars + 1) + (Nat.add_le_add_left hK ((B φ + 1) ^ d + B φ)) + simp only [size] at this hS ⊢ + nlinarith) + refine ⟨e, (h.mono c (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => rfl⟩ + all_goals + have h₁ := hT φ + simp only [size] at h₁ + generalize 2 ^ φ.distinctVars.length = N at h₁ ⊢ + generalize (encNat N).length = K at h₁ ⊢ + obtain ⟨X, hX⟩ : ∃ X, (B φ + 1) ^ d + B φ = X := ⟨_, rfl⟩ + rw [hX] at h₁ + have h₂ : K ≤ (K + 1) ^ 2 := by nlinarith + have h₃ : X + (K + 1) ^ 2 ≤ (N + 1) * (X + (K + 1) ^ 2) := Nat.le_mul_of_pos_left _ (by omega) + nlinarith + simpa only [computableInO_iff_computableTidilyInO] using this end BruteForce /-- **`SAT` by exhaustive search**: `SAT` is decidable within time `2 ^ n` times a polynomial in the length of the encoded formula, on formulas with `n` variables. -/ theorem SAT_decidableInExpTime_one : DecidableInExpTime SAT encCNF CNF.numVars 1 := by - obtain ⟨e, h⟩ := BruteForce.exists_computableTidilyInO_search - refine .of_computableTidilyInO h (fun φ => (BruteForce.search_eq_true_iff φ).symm) 1 e + obtain ⟨e, h⟩ := BruteForce.exists_computableInO_search + refine DecidableInExpTime.of_computableInO h (fun φ => (BruteForce.search_eq_true_iff φ).symm) 1 e fun φ => ?_ rw [one_mul, Real.rpow_natCast] push_cast @@ -236,8 +239,8 @@ theorem SAT_decidableInExpTime_one : DecidableInExpTime SAT encCNF CNF.numVars 1 open ComputableTidilyInPolyTime in /-- Checking that every clause has at most `k` literals is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_all_length_le (k : ℕ) : - ComputableTidilyInPolyTime (fun φ : CNF ℕ => φ.all fun c => decide (c.length ≤ k)) encCNF +theorem computableInPolyTime_all_length_le (k : ℕ) : + ComputableInPolyTime (fun φ : CNF ℕ => φ.all fun c => decide (c.length ≤ k)) encCNF encBool := by unfold encCNF fun_prop @@ -253,6 +256,6 @@ theorem KSAT_eq_inter (k : ℕ) {B : Set (CNF ℕ)} (hB : KSAT k ⊆ B) (hBSAT : in the length of the encoded formula, on formulas with `n` variables. -/ theorem KSAT_decidableInExpTime_one (k : ℕ) : DecidableInExpTime (KSAT k) encCNF CNF.numVars 1 := by rw [KSAT_eq_inter k (KSAT_subset_SAT k) le_rfl] - exact SAT_decidableInExpTime_one.inter (computableTidilyInPolyTime_all_length_le k) zero_le_one + exact SAT_decidableInExpTime_one.inter (computableInPolyTime_all_length_le k).tidy zero_le_one end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/FineGrained/Exponents.lean b/Complexity/Computability/Complexity/FineGrained/Exponents.lean index 7ba6ce6b4..efc031135 100644 --- a/Complexity/Computability/Complexity/FineGrained/Exponents.lean +++ b/Complexity/Computability/Complexity/FineGrained/Exponents.lean @@ -67,7 +67,7 @@ theorem DecidableInExpTime.KSAT_of_le {k k' : ℕ} (hk : k ≤ k') {δ : ℝ} (h DecidableInExpTime (KSAT k) encCNF CNF.numVars δ := by rw [KSAT_eq_inter k (B := KSAT k') (fun φ hφ => ⟨fun c hc => (hφ.1 c hc).trans hk, hφ.2⟩) (KSAT_subset_SAT k')] - exact h.inter (computableTidilyInPolyTime_all_length_le k) hδ + exact h.inter (computableInPolyTime_all_length_le k).tidy hδ /-- The exponents of `k`-SAT. -/ private abbrev exponents (k : ℕ) : Set ℝ := @@ -159,7 +159,7 @@ theorem DecidableInExpTime.length_of_numVars {k : ℕ} {δ : ℝ} (hδ : 0 ≤ (h : DecidableInExpTime (KSAT k) encCNF CNF.numVars δ) : DecidableInExpTime (KSAT k) encCNF List.length (k * δ) := by obtain ⟨e, h⟩ := h - obtain ⟨e', h⟩ := h.inter (computableTidilyInPolyTime_all_length_le k) fun φ => by positivity + obtain ⟨e', h⟩ := h.inter (computableInPolyTime_all_length_le k).tidy fun φ => by positivity rw [← KSAT_eq_inter k le_rfl (KSAT_subset_SAT k)] at h refine ⟨e + e', h.mono 2 (fun φ => ?_) fun φ => by positivity⟩ have hL : (1 : ℝ) ≤ (encCNF φ).length + 1 := by diff --git a/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean b/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean index 461487af6..8001b77cb 100644 --- a/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean +++ b/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean @@ -94,7 +94,7 @@ polynomial in the length of the encoded graph, for graphs with `|V|` declared ve edges. -/ theorem ETH.not_decidableInSubexpTime_ThreeColoring (h : ETH) : ¬DecidableInSubexpTime ThreeColoring encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toThreeColoring + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring.tidy -- `(24 * 3 + 12) m + 9 ≤ 93 m + 93` (fun φ _ => SAT.toThreeColoring_mem_iff φ) (k := 93) fun φ hφ => by have := SAT.length_toThreeColoring_le hφ @@ -107,7 +107,7 @@ edges. -/ theorem ETH.not_decidableInSubexpTime_IndependentSet (h : ETH) : ¬DecidableInSubexpTime IndependentSet (encPair encGraph encNat) fun x => x.1.1.length + x.1.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toSparseIndependentSet + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet.tidy (fun φ _ => SAT.toSparseIndependentSet_mem_iff φ) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ omega @@ -117,7 +117,7 @@ some `δ > 0`, `IndependentSet` is not decidable within time `2 ^ (δ |V|)` time the length of the encoded instance, for graphs with `|V|` declared vertices. -/ theorem ETH.not_decidableInSubexpTime_IndependentSet_vertices (h : ETH) : ¬DecidableInSubexpTime IndependentSet (encPair encGraph encNat) fun x => x.1.1.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toSparseIndependentSet + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet.tidy (fun φ _ => SAT.toSparseIndependentSet_mem_iff φ) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ omega @@ -130,8 +130,8 @@ theorem ETH.not_decidableInSubexpTime_VertexCover (h : ETH) : ¬DecidableInSubexpTime VertexCover (encPair encGraph encNat) fun x => x.1.1.length + x.1.2.length := h.not_decidableInSubexpTime_of_reduction - (IndependentSet.computableTidilyInPolyTime_toVertexCover.comp - SAT.computableTidilyInPolyTime_toSparseIndependentSet) + (IndependentSet.computableInPolyTime_toVertexCover.tidy.comp + SAT.computableInPolyTime_toSparseIndependentSet.tidy) (fun φ _ => (IndependentSet.toVertexCover_mem_iff _).trans (SAT.toSparseIndependentSet_mem_iff φ)) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ @@ -147,7 +147,7 @@ theorem ETH.not_decidableInSubexpTime_Clique (h : ETH) : ((SAT.toSparseIndependentSet φ).1.compl, (SAT.toSparseIndependentSet φ).2)) ((show ComputableTidilyInPolyTime (fun x : Graph × ℕ => (x.1.compl, x.2)) (encPair encGraph encNat) (encPair encGraph encNat) by fun_prop).comp - SAT.computableTidilyInPolyTime_toSparseIndependentSet) + SAT.computableInPolyTime_toSparseIndependentSet.tidy) (fun φ _ => (Graph.compl_mem_Clique_iff _ _).trans (SAT.toSparseIndependentSet_mem_iff φ)) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ @@ -160,7 +160,7 @@ any polynomial in the length of the encoded graph, for graphs with `|V|` declare `|E|` edges. -/ theorem ETH.not_decidableInSubexpTime_HamCycle (h : ETH) : ¬DecidableInSubexpTime HamCycle encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toSparseHamCycle + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseHamCycle.tidy (fun φ _ => SAT.toSparseHamCycle_mem_iff φ) (k := 350) fun φ hφ => by have := SAT.length_toSparseHamCycle_le hφ omega @@ -171,7 +171,7 @@ theorem ETH.not_decidableInSubexpTime_HamCycle (h : ETH) : `|V|` declared vertices and `|E|` arcs. -/ theorem ETH.not_decidableInSubexpTime_DirHamCycle (h : ETH) : ¬DecidableInSubexpTime DirHamCycle encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toSparseDirHamCycle + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamCycle.tidy (fun φ _ => SAT.toSparseDirHamCycle_mem_iff φ) (k := 70) fun φ hφ => by have := SAT.length_toSparseDirHamCycle_le hφ omega @@ -183,7 +183,7 @@ theorem ETH.not_decidableInSubexpTime_DirHamCycle (h : ETH) : theorem ETH.not_decidableInSubexpTime_DirHamPath (h : ETH) : ¬DecidableInSubexpTime DirHamPath (encPair encGraph (encPair encNat encNat)) fun x => x.1.1.length + x.1.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toSparseDirHamPath + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamPath.tidy (fun φ _ => SAT.toSparseDirHamPath_mem_iff φ) (k := 70) fun φ hφ => by have := SAT.length_sparseDiamondGraph_le hφ simp only [SAT.toSparseDirHamPath] @@ -197,8 +197,8 @@ theorem ETH.not_decidableInSubexpTime_HamPath (h : ETH) : ¬DecidableInSubexpTime HamPath (encPair encGraph (encPair encNat encNat)) fun x => x.1.1.length + x.1.2.length := h.not_decidableInSubexpTime_of_reduction - (DirHamPath.computableTidilyInPolyTime_toHamPath.comp - SAT.computableTidilyInPolyTime_toSparseDirHamPath) + (DirHamPath.computableInPolyTime_toHamPath.tidy.comp + SAT.computableInPolyTime_toSparseDirHamPath.tidy) (fun φ _ => (DirHamPath.toHamPath_mem_iff _).trans (SAT.toSparseDirHamPath_mem_iff φ)) (k := 350) fun φ hφ => by have := SAT.length_sparseDiamondGraph_le hφ diff --git a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean index 1a8e2d589..309e957e9 100644 --- a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean +++ b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean @@ -19,6 +19,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Li import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Div +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The strong exponential time hypothesis implies the orthogonal vectors hypothesis @@ -35,7 +36,7 @@ satisfy the formula. So the formula is satisfiable exactly when the instance `to The reduction writes its output of about `2 ^ ⌈n / 2⌉ m` bits within time `2 ^ ⌈n / 2⌉` times a polynomial in the length of the encoded formula -(`Cslib.Complexity.exists_computableTidilyInO_toOV`). The vectors are streamed to the output one +(`Cslib.Complexity.exists_computableInO_toOV`). The vectors are streamed to the output one at a time (`Turing.MultiTapeTM.ComputableTidilyInTimeAndSpace.iterate_unary_stream_sum`); accumulating them in a list would cost time quadratic in the number of vectors. Then a decider for `OV` within time `N ^ (2 - ε)` times a polynomial in the dimension, on `N` vectors, decides @@ -56,7 +57,7 @@ sparsification lemma, is not proved here. ## Main results * `Cslib.Complexity.toOV_mem_OV_iff`: `toOV φ ∈ OV ↔ φ ∈ SAT`. -* `Cslib.Complexity.exists_computableTidilyInO_toOV`: the reduction runs within time +* `Cslib.Complexity.exists_computableInO_toOV`: the reduction runs within time `2 ^ ⌈n / 2⌉` times a polynomial. * `Cslib.Complexity.DecidableInTimeO.decidableInExpTime_SAT`: a fast `OV` decider gives a fast `SAT` decider. @@ -257,8 +258,8 @@ abbrev encStreamState : StreamState ↪ List Bool := encPair (encPair encCNF (en open ComputableTidilyInPolyTime in /-- Computing the vector of a numbered assignment is polynomial-time. -/ -theorem computableTidilyInPolyTime_clauseVector : - ComputableTidilyInPolyTime (fun s : StreamState => clauseVector s.1.1 s.1.2 s.2) +theorem computableInPolyTime_clauseVector : + ComputableInPolyTime (fun s : StreamState => clauseVector s.1.1 s.1.2 s.2) encStreamState encBits := by have e : (fun s : StreamState => clauseVector s.1.1 s.1.2 s.2) = fun s => s.1.1.map fun c => !(c.any fun l => decide (s.1.2.idxOf l.1 < s.1.2.length) && @@ -296,167 +297,172 @@ private theorem iterate_next (s : StreamState) (i : ℕ) : /-- **Streaming the vectors of a half of the variables**: the vectors of the `2 ^ |half φ|` assignments numbered on `half φ`, each wrapped by `wrap`, followed by `fin`, are written within time `2 ^ |half φ|` times a polynomial in the length of the encoded formula. -/ -theorem exists_computableTidilyInO_stream {half : CNF ℕ → List ℕ} - (hhalf : ComputableTidilyInPolyTime half encCNF (encList encNat)) +theorem exists_computableInO_stream {half : CNF ℕ → List ℕ} + (hhalf : ComputableInPolyTime half encCNF (encList encNat)) (hlen : ∀ φ, (half φ).length ≤ (encCNF φ).length) - {wrap : List Bool → List Bool} (hwrap : ComputableTidilyInPolyTime wrap encBits encBits) + {wrap : List Bool → List Bool} (hwrap : ComputableInPolyTime wrap encBits encBits) (fin : List Bool) : - ∃ e, ComputableTidilyInO (fun φ => ((halfVectors φ (half φ)).map wrap).flatten ++ fin) encCNF + ∃ e, ComputableInO (fun φ => ((halfVectors φ (half φ)).map wrap).flatten ++ fin) encCNF encBits (fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e := by - -- the rounds - obtain ⟨dN, _, ⟨tN, sN, ⟨cN, htN⟩, ⟨cN', hsN⟩, hN⟩, _⟩ := - (show ComputableTidilyInPolyTime (fun s : StreamState => (s.1, s.2 + 1)) encStreamState - encStreamState by fun_prop).exists_degree - obtain ⟨dE, _, ⟨tE, sE, ⟨cE, htE⟩, ⟨cE', hsE⟩, hE⟩, _⟩ := - (hwrap.comp computableTidilyInPolyTime_clauseVector).exists_degree - obtain ⟨cF, hF⟩ := - ComputableTidilyInLinearTimeAndSpace.const (encIn := encStreamState) (encMid := encBits) fin - set D := dN + dE + 1 - set B : StreamState × ℕ → ℕ := fun x => - 2 * (encPair encCNF (encList encNat) x.1.1).length + 1 + (encNat (x.1.2 + x.2)).length - have hstate : ∀ x : StreamState × ℕ, ∀ i ≤ x.2, - (encStreamState ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).length ≤ B x := by - intro x i hi - rw [iterate_next] - have := ComputableTidilyInO.length_encNat_mono (show x.1.2 + i ≤ x.1.2 + x.2 by omega) - simp only [encStreamState, length_encPair, B] at this ⊢ - omega - have hpowN (x : StreamState × ℕ) (s : StreamState) (hs : (encStreamState s).length ≤ B x) : - (encStreamState s).length + 1 ≤ (B x + 1) := by omega - have hD (x : StreamState × ℕ) (d : ℕ) (hd : d ≤ D) : (B x + 1) ^ d ≤ (B x + 1) ^ D := - Nat.pow_le_pow_right (Nat.succ_pos _) hd - obtain ⟨c, h⟩ := hN.iterate_unary_stream_sum hE hF - (R := fun x _ => (cN + cE + 3) * (B x + 1) ^ D) (Q := fun x => (cN' + cE') * (B x + 1) ^ D) - (B := B) - (fun x i hi => by - have h₁ := hstate x i hi.le - have h₂ := hstate x (i + 1) hi - have h₃ := (htN ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans - (Nat.mul_le_mul_left cN ((Nat.pow_le_pow_left (hpowN x _ h₁) dN).trans - (hD x dN (by omega)))) - have h₄ := (htE ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans - (Nat.mul_le_mul_left cE ((Nat.pow_le_pow_left (hpowN x _ h₁) dE).trans - (hD x dE (by omega)))) - have h₅ : B x + 1 ≤ (B x + 1) ^ D := Nat.le_self_pow (by omega) _ - nlinarith) - (fun x i hi => by - have h₁ := hstate x i hi.le - have h₃ := (hsN ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans - (Nat.mul_le_mul_left cN' ((Nat.pow_le_pow_left (hpowN x _ h₁) dN).trans - (hD x dN (by omega)))) - have h₄ := (hsE ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans - (Nat.mul_le_mul_left cE' ((Nat.pow_le_pow_left (hpowN x _ h₁) dE).trans - (hD x dE (by omega)))) - nlinarith) - hstate - -- the stream, within `O((k + 1) (B x + 1) ^ D)` for `k` rounds - have hsum (x : StreamState × ℕ) : ∑ i ∈ Finset.range x.2, (cN + cE + 3) * (B x + 1) ^ D = - x.2 * ((cN + cE + 3) * (B x + 1) ^ D) := by simp - have hB1 (x : StreamState × ℕ) : B x + 1 ≤ (B x + 1) ^ D := Nat.le_self_pow (by omega) _ - have hstream : ComputableTidilyInO (fun x : StreamState × ℕ => - ((List.range x.2).map fun i => wrap (clauseVector x.1.1.1 x.1.1.2 (x.1.2 + i))).flatten ++ - fin) - (encPair encStreamState encUnary) encBits (fun x => (x.2 + 1) * (B x + 1) ^ D) - fun x => (x.2 + 1) * (B x + 1) ^ D := by - refine (ComputableTidilyInO.of_bounds h (c * (cF + cN + cE + cN' + cE' + 6)) (fun x => ?_) - (fun x => ?_) (fun x => ?_)).of_enc_eq fun x => ?_ - · have hs := hstate x x.2 le_rfl - rw [hsum, Nat.mul_assoc] - exact Nat.mul_le_mul_left c (stream_bound hs (hB1 x) (by omega)) - · have hs := hstate x x.2 le_rfl - rw [Nat.mul_assoc] - exact Nat.mul_le_mul_left c (stream_space_bound hs (hB1 x) (by omega)) - · refine (h.length_le x).trans ?_ - have hs := hstate x x.2 le_rfl - rw [hsum, Nat.mul_assoc] - exact Nat.mul_le_mul_left c (stream_bound hs (hB1 x) (by omega)) - · simp only [iterate_next, Function.comp_apply, encBits_apply] - -- the start of the stream: the state and the number of rounds in unary - obtain ⟨d₀, _, hp₀⟩ := (show ComputableTidilyInPolyTime (fun φ : CNF ℕ => ((φ, half φ), 0)) - encCNF encStreamState by fun_prop).exists_degree - obtain ⟨d₁, _, hp₁⟩ := - ((ComputableInPolyTime.length_list_binary encNat).tidy.comp hhalf).exists_degree - have h := hstream.comp (hp₀.inO.prod (unary_two_pow hp₁.inO)) - -- the bounds - obtain ⟨cv, dv, hV⟩ := hhalf.polyBounded_length.exists_le - set Bb : CNF ℕ → ℕ := fun φ => (2 * cv + 8) * ((encCNF φ).length + 1) ^ (dv + 1) - have hBb (φ : CNF ℕ) : B (((φ, half φ), 0), 2 ^ (half φ).length) ≤ Bb φ := by - have h₁ := hV φ - have h₂ := hlen φ - have h₃ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ (dv + 1) := - Nat.le_self_pow (by omega) _ - have h₄ : ((encCNF φ).length + 1) ^ dv ≤ ((encCNF φ).length + 1) ^ (dv + 1) := - Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_succ dv) - have h₅ := Nat.mul_le_mul_left cv h₄ - simp only [B, Bb, length_encPair, Nat.zero_add, encNat_two_pow, List.length_append, - List.length_replicate, List.length_singleton] at h₁ h₂ h₃ h₅ ⊢ - nlinarith - have hBbP : PolyBounded (fun φ => (encCNF φ).length) Bb := - .of_forall_le (2 * cv + 8) (dv + 1) fun φ => le_rfl - have hL (j : ℕ) : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) - fun φ => ((encCNF φ).length + 1) ^ j := .of_forall_le 1 j fun φ => by simp - have hL₁ : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) fun φ => (encCNF φ).length + 1 := - .of_forall_le 1 1 fun φ => by simp - have hP : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) - fun φ => 2 * ((Bb φ + 1) ^ D + 3 * ((encCNF φ).length + 1)) := - (PolyBounded.const 2).mul - ((((PolyBounded.of_polynomiallyBounded id (bound := fun x => (x + 1) ^ D) - (by fun_prop)).comp hBbP).mono fun φ => le_rfl).add ((PolyBounded.const 3).mul hL₁)) - have hQ : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) - fun φ => 2 * (((encCNF φ).length + 1) ^ d₀ + ((encCNF φ).length + 1) ^ d₁ + - ((encCNF φ).length + 1) + ((encCNF φ).length + 1) ^ 3) := - (PolyBounded.const 2).mul ((((hL d₀).add (hL d₁)).add hL₁).add (hL 3)) - obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (μ := fun φ => (half φ).length) - (T := fun φ => ((encCNF φ).length + 1) ^ d₀ + (((encCNF φ).length + 1) ^ d₁ + - (encCNF φ).length + ((half φ).length + 1) * (2 * 2 ^ (half φ).length + - 2 ^ (half φ).length + ((encNat (half φ).length).length + 1) ^ 2)) + - (2 ^ (half φ).length + 1) * (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D + - (((encCNF φ).length + 1) ^ d₀ + (((encCNF φ).length + 1) ^ d₁ + (encCNF φ).length + - 2 * 2 ^ (half φ).length + 2 ^ (half φ).length + (encNat (half φ).length).length) + - (2 ^ (half φ).length + 1) * (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D)) - hP hQ fun φ => by - have h₁ := Nat.mul_le_mul_left (2 ^ (half φ).length + 1) - (Nat.pow_le_pow_left (Nat.add_le_add_right (hBb φ) 1) D) + have hhalf := hhalf.tidy + have hwrap := hwrap.tidy + have this : ∃ e, ComputableTidilyInO (fun φ => ((halfVectors φ (half φ)).map wrap).flatten ++ fin) encCNF encBits (fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e := by + -- the rounds + obtain ⟨dN, _, ⟨tN, sN, ⟨cN, htN⟩, ⟨cN', hsN⟩, hN⟩, _⟩ := + (show ComputableTidilyInPolyTime (fun s : StreamState => (s.1, s.2 + 1)) encStreamState + encStreamState by fun_prop).exists_degree + obtain ⟨dE, _, ⟨tE, sE, ⟨cE, htE⟩, ⟨cE', hsE⟩, hE⟩, _⟩ := + (hwrap.comp computableInPolyTime_clauseVector.tidy).exists_degree + obtain ⟨cF, hF⟩ := + ComputableTidilyInLinearTimeAndSpace.const (encIn := encStreamState) (encMid := encBits) fin + set D := dN + dE + 1 + set B : StreamState × ℕ → ℕ := fun x => + 2 * (encPair encCNF (encList encNat) x.1.1).length + 1 + (encNat (x.1.2 + x.2)).length + have hstate : ∀ x : StreamState × ℕ, ∀ i ≤ x.2, + (encStreamState ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).length ≤ B x := by + intro x i hi + rw [iterate_next] + have := ComputableTidilyInO.length_encNat_mono (show x.1.2 + i ≤ x.1.2 + x.2 by omega) + simp only [encStreamState, length_encPair, B] at this ⊢ + omega + have hpowN (x : StreamState × ℕ) (s : StreamState) (hs : (encStreamState s).length ≤ B x) : + (encStreamState s).length + 1 ≤ (B x + 1) := by omega + have hD (x : StreamState × ℕ) (d : ℕ) (hd : d ≤ D) : (B x + 1) ^ d ≤ (B x + 1) ^ D := + Nat.pow_le_pow_right (Nat.succ_pos _) hd + obtain ⟨c, h⟩ := hN.iterate_unary_stream_sum hE hF + (R := fun x _ => (cN + cE + 3) * (B x + 1) ^ D) (Q := fun x => (cN' + cE') * (B x + 1) ^ D) + (B := B) + (fun x i hi => by + have h₁ := hstate x i hi.le + have h₂ := hstate x (i + 1) hi + have h₃ := (htN ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans + (Nat.mul_le_mul_left cN ((Nat.pow_le_pow_left (hpowN x _ h₁) dN).trans + (hD x dN (by omega)))) + have h₄ := (htE ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans + (Nat.mul_le_mul_left cE ((Nat.pow_le_pow_left (hpowN x _ h₁) dE).trans + (hD x dE (by omega)))) + have h₅ : B x + 1 ≤ (B x + 1) ^ D := Nat.le_self_pow (by omega) _ + nlinarith) + (fun x i hi => by + have h₁ := hstate x i hi.le + have h₃ := (hsN ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans + (Nat.mul_le_mul_left cN' ((Nat.pow_le_pow_left (hpowN x _ h₁) dN).trans + (hD x dN (by omega)))) + have h₄ := (hsE ((fun s : StreamState => (s.1, s.2 + 1))^[i] x.1)).trans + (Nat.mul_le_mul_left cE' ((Nat.pow_le_pow_left (hpowN x _ h₁) dE).trans + (hD x dE (by omega)))) + nlinarith) + hstate + -- the stream, within `O((k + 1) (B x + 1) ^ D)` for `k` rounds + have hsum (x : StreamState × ℕ) : ∑ i ∈ Finset.range x.2, (cN + cE + 3) * (B x + 1) ^ D = + x.2 * ((cN + cE + 3) * (B x + 1) ^ D) := by simp + have hB1 (x : StreamState × ℕ) : B x + 1 ≤ (B x + 1) ^ D := Nat.le_self_pow (by omega) _ + have hstream : ComputableTidilyInO (fun x : StreamState × ℕ => + ((List.range x.2).map fun i => wrap (clauseVector x.1.1.1 x.1.1.2 (x.1.2 + i))).flatten ++ + fin) + (encPair encStreamState encUnary) encBits (fun x => (x.2 + 1) * (B x + 1) ^ D) + fun x => (x.2 + 1) * (B x + 1) ^ D := by + refine (ComputableTidilyInO.of_bounds h (c * (cF + cN + cE + cN' + cE' + 6)) (fun x => ?_) + (fun x => ?_) (fun x => ?_)).of_enc_eq fun x => ?_ + · have hs := hstate x x.2 le_rfl + rw [hsum, Nat.mul_assoc] + exact Nat.mul_le_mul_left c (stream_bound hs (hB1 x) (by omega)) + · have hs := hstate x x.2 le_rfl + rw [Nat.mul_assoc] + exact Nat.mul_le_mul_left c (stream_space_bound hs (hB1 x) (by omega)) + · refine (h.length_le x).trans ?_ + have hs := hstate x x.2 le_rfl + rw [hsum, Nat.mul_assoc] + exact Nat.mul_le_mul_left c (stream_bound hs (hB1 x) (by omega)) + · simp only [iterate_next, Function.comp_apply, encBits_apply] + -- the start of the stream: the state and the number of rounds in unary + obtain ⟨d₀, _, hp₀⟩ := (show ComputableTidilyInPolyTime (fun φ : CNF ℕ => ((φ, half φ), 0)) + encCNF encStreamState by fun_prop).exists_degree + obtain ⟨d₁, _, hp₁⟩ := + ((ComputableInPolyTime.length_list_binary encNat).tidy.comp hhalf).exists_degree + have h := hstream.comp (hp₀.inO.prod (unary_two_pow hp₁.inO)) + -- the bounds + obtain ⟨cv, dv, hV⟩ := hhalf.polyBounded_length.exists_le + set Bb : CNF ℕ → ℕ := fun φ => (2 * cv + 8) * ((encCNF φ).length + 1) ^ (dv + 1) + have hBb (φ : CNF ℕ) : B (((φ, half φ), 0), 2 ^ (half φ).length) ≤ Bb φ := by + have h₁ := hV φ have h₂ := hlen φ - have h₃ := (Universal.length_encNat_le (half φ).length).trans h₂ - have h₄ : ((half φ).length + 1) * ((encNat (half φ).length).length + 1) ^ 2 ≤ - ((encCNF φ).length + 1) ^ 3 := by - rw [pow_succ' _ 2] - exact Nat.mul_le_mul (by omega) (Nat.pow_le_pow_left (by omega) 2) - have h₇ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ 3 := Nat.le_self_pow (by omega) _ - generalize (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D = X at h₁ ⊢ - generalize (Bb φ + 1) ^ D = Y at h₁ ⊢ - generalize ((encNat (half φ).length).length + 1) ^ 2 = K₂ at h₄ ⊢ - generalize (encNat (half φ).length).length = K at h₃ ⊢ - generalize ((encCNF φ).length + 1) ^ 3 = L₃ at h₄ h₇ ⊢ - generalize ((encCNF φ).length + 1) ^ d₀ = L₀ - generalize ((encCNF φ).length + 1) ^ d₁ = L₁ - generalize 2 ^ (half φ).length = N at h₁ ⊢ - generalize (encCNF φ).length = L at h₂ h₃ h₇ ⊢ - generalize (half φ).length = n at h₂ h₄ ⊢ - have h₆ : (n + 1) * (3 * N) ≤ (N + 1) * (3 * (L + 1)) := - calc (n + 1) * (3 * N) ≤ (L + 1) * (3 * (N + 1)) := - Nat.mul_le_mul (by omega) (by omega) - _ = (N + 1) * (3 * (L + 1)) := by ring - have h₈ : 3 * N ≤ (N + 1) * (3 * (L + 1)) := by nlinarith - have e₁ : (n + 1) * (2 * N + N + K₂) = (n + 1) * (3 * N) + (n + 1) * K₂ := by ring - have e₂ : (N + 1) * (2 * (Y + 3 * (L + 1))) = 2 * ((N + 1) * Y) + - 2 * ((N + 1) * (3 * (L + 1))) := by ring + have h₃ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ (dv + 1) := + Nat.le_self_pow (by omega) _ + have h₄ : ((encCNF φ).length + 1) ^ dv ≤ ((encCNF φ).length + 1) ^ (dv + 1) := + Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_succ dv) + have h₅ := Nat.mul_le_mul_left cv h₄ + simp only [B, Bb, length_encPair, Nat.zero_add, encNat_two_pow, List.length_append, + List.length_replicate, List.length_singleton] at h₁ h₂ h₃ h₅ ⊢ + nlinarith + have hBbP : PolyBounded (fun φ => (encCNF φ).length) Bb := + .of_forall_le (2 * cv + 8) (dv + 1) fun φ => le_rfl + have hL (j : ℕ) : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) + fun φ => ((encCNF φ).length + 1) ^ j := .of_forall_le 1 j fun φ => by simp + have hL₁ : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) fun φ => (encCNF φ).length + 1 := + .of_forall_le 1 1 fun φ => by simp + have hP : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) + fun φ => 2 * ((Bb φ + 1) ^ D + 3 * ((encCNF φ).length + 1)) := + (PolyBounded.const 2).mul + ((((PolyBounded.of_polynomiallyBounded id (bound := fun x => (x + 1) ^ D) + (by fun_prop)).comp hBbP).mono fun φ => le_rfl).add ((PolyBounded.const 3).mul hL₁)) + have hQ : PolyBounded (fun φ : CNF ℕ => (encCNF φ).length) + fun φ => 2 * (((encCNF φ).length + 1) ^ d₀ + ((encCNF φ).length + 1) ^ d₁ + + ((encCNF φ).length + 1) + ((encCNF φ).length + 1) ^ 3) := + (PolyBounded.const 2).mul ((((hL d₀).add (hL d₁)).add hL₁).add (hL 3)) + obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (μ := fun φ => (half φ).length) + (T := fun φ => ((encCNF φ).length + 1) ^ d₀ + (((encCNF φ).length + 1) ^ d₁ + + (encCNF φ).length + ((half φ).length + 1) * (2 * 2 ^ (half φ).length + + 2 ^ (half φ).length + ((encNat (half φ).length).length + 1) ^ 2)) + + (2 ^ (half φ).length + 1) * (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D + + (((encCNF φ).length + 1) ^ d₀ + (((encCNF φ).length + 1) ^ d₁ + (encCNF φ).length + + 2 * 2 ^ (half φ).length + 2 ^ (half φ).length + (encNat (half φ).length).length) + + (2 ^ (half φ).length + 1) * (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D)) + hP hQ fun φ => by + have h₁ := Nat.mul_le_mul_left (2 ^ (half φ).length + 1) + (Nat.pow_le_pow_left (Nat.add_le_add_right (hBb φ) 1) D) + have h₂ := hlen φ + have h₃ := (Universal.length_encNat_le (half φ).length).trans h₂ + have h₄ : ((half φ).length + 1) * ((encNat (half φ).length).length + 1) ^ 2 ≤ + ((encCNF φ).length + 1) ^ 3 := by + rw [pow_succ' _ 2] + exact Nat.mul_le_mul (by omega) (Nat.pow_le_pow_left (by omega) 2) + have h₇ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ 3 := Nat.le_self_pow (by omega) _ + generalize (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D = X at h₁ ⊢ + generalize (Bb φ + 1) ^ D = Y at h₁ ⊢ + generalize ((encNat (half φ).length).length + 1) ^ 2 = K₂ at h₄ ⊢ + generalize (encNat (half φ).length).length = K at h₃ ⊢ + generalize ((encCNF φ).length + 1) ^ 3 = L₃ at h₄ h₇ ⊢ + generalize ((encCNF φ).length + 1) ^ d₀ = L₀ + generalize ((encCNF φ).length + 1) ^ d₁ = L₁ + generalize 2 ^ (half φ).length = N at h₁ ⊢ + generalize (encCNF φ).length = L at h₂ h₃ h₇ ⊢ + generalize (half φ).length = n at h₂ h₄ ⊢ + have h₆ : (n + 1) * (3 * N) ≤ (N + 1) * (3 * (L + 1)) := + calc (n + 1) * (3 * N) ≤ (L + 1) * (3 * (N + 1)) := + Nat.mul_le_mul (by omega) (by omega) + _ = (N + 1) * (3 * (L + 1)) := by ring + have h₈ : 3 * N ≤ (N + 1) * (3 * (L + 1)) := by nlinarith + have e₁ : (n + 1) * (2 * N + N + K₂) = (n + 1) * (3 * N) + (n + 1) * K₂ := by ring + have e₂ : (N + 1) * (2 * (Y + 3 * (L + 1))) = 2 * ((N + 1) * Y) + + 2 * ((N + 1) * (3 * (L + 1))) := by ring + omega + refine ⟨e, (h.mono c (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => ?_⟩ + all_goals try + have := hT φ + have e : c * (2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e + 1) = + c * 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e + c := by ring + simp only [Function.comp_apply] at this ⊢ omega - refine ⟨e, (h.mono c (fun φ => ?_) fun φ => ?_).of_enc_eq fun φ => ?_⟩ - all_goals try - have := hT φ - have e : c * (2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e + 1) = - c * 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e + c := by ring - simp only [Function.comp_apply] at this ⊢ - omega - simp [halfVectors, Function.comp_def] + simp [halfVectors, Function.comp_def] + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] using this attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in -theorem computableTidilyInPolyTime_firstVars : - ComputableTidilyInPolyTime firstVars encCNF (encList encNat) := by +theorem computableInPolyTime_firstVars : + ComputableInPolyTime firstVars encCNF (encList encNat) := by + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun φ => (φ.distinctVars.reverse.drop (φ.distinctVars.length - φ.distinctVars.length / 2)).reverse) encCNF (encList encNat) := @@ -471,8 +477,9 @@ theorem computableTidilyInPolyTime_firstVars : attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in -theorem computableTidilyInPolyTime_secondVars : - ComputableTidilyInPolyTime secondVars encCNF (encList encNat) := by +theorem computableInPolyTime_secondVars : + ComputableInPolyTime secondVars encCNF (encList encNat) := by + refine .of_tidy ?_ exact (dropUnary (encA := encNat)).comp (SAT.computableInPolyTime_distinctVars.tidy.prod (show ComputableTidilyInPolyTime (fun φ => φ.distinctVars.length / 2) encCNF encUnary by fun_prop)) @@ -490,39 +497,41 @@ end OV open ComputableTidilyInPolyTime in /-- **The split-and-list reduction is fast**: it writes its output within time `2 ^ ⌈n / 2⌉` times a polynomial in the length of the encoded formula, on formulas with `n` variables. -/ -theorem exists_computableTidilyInO_toOV : ∃ e, ComputableTidilyInO toOV encCNF encOV +theorem exists_computableInO_toOV : ∃ e, ComputableInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by - obtain ⟨e₁, h₁⟩ := OV.exists_computableTidilyInO_stream OV.computableTidilyInPolyTime_firstVars - OV.length_firstVars_le (wrap := fun v => ((frame v).map fun b => [true, b]).flatten) - (by fun_prop) [false] - obtain ⟨e₂, h₂⟩ := OV.exists_computableTidilyInO_stream OV.computableTidilyInPolyTime_secondVars - OV.length_secondVars_le (wrap := frame) (bitsFrame encBits) [] - have hfm (l : List (List Bool)) (g : Bool → List Bool) : - l.flatten.flatMap g = (l.map (·.flatMap g)).flatten := by - induction l with - | nil => rfl - | cons a l ih => simp [List.flatMap_append, ih] - have hencList (L : List (List Bool)) : encList encBits L = (L.map frame).flatten := by - induction L with - | nil => rfl - | cons v L ih => rw [encList_cons, ih]; rfl - have h := h₁.append h₂ (g := toOV) (encOut := encOV) fun φ => by - rw [encOV, encPair_apply, hencList, hencList] - simp only [toOV, encBits_apply, List.append_nil] - rw [frame, hfm, List.map_map] - rfl - refine ⟨e₁ + e₂, h.mono 2 (fun φ => ?_) fun φ => ?_⟩ <;> - · simp only [OV.length_firstVars, OV.length_secondVars] - have h₁ : 2 ^ (φ.numVars / 2) ≤ 2 ^ (φ.numVars - φ.numVars / 2) := - Nat.pow_le_pow_right (by norm_num) (by omega) - have h₂ : ((encCNF φ).length + 1) ^ e₁ ≤ ((encCNF φ).length + 1) ^ (e₁ + e₂) := - Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_add_right _ _) - have h₃ : ((encCNF φ).length + 1) ^ e₂ ≤ ((encCNF φ).length + 1) ^ (e₁ + e₂) := - Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_add_left _ _) - have := Nat.mul_le_mul h₁ h₂ - have := Nat.mul_le_mul_left (2 ^ (φ.numVars - φ.numVars / 2)) h₃ - nlinarith + have this : ∃ e, ComputableTidilyInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by + obtain ⟨e₁, h₁⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_firstVars.tidy + OV.length_firstVars_le (wrap := fun v => ((frame v).map fun b => [true, b]).flatten) + (by fun_prop) [false] + obtain ⟨e₂, h₂⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_secondVars.tidy + OV.length_secondVars_le (wrap := frame) (bitsFrame encBits) [] + have hfm (l : List (List Bool)) (g : Bool → List Bool) : + l.flatten.flatMap g = (l.map (·.flatMap g)).flatten := by + induction l with + | nil => rfl + | cons a l ih => simp [List.flatMap_append, ih] + have hencList (L : List (List Bool)) : encList encBits L = (L.map frame).flatten := by + induction L with + | nil => rfl + | cons v L ih => rw [encList_cons, ih]; rfl + have h := h₁.append h₂ (g := toOV) (encOut := encOV) fun φ => by + rw [encOV, encPair_apply, hencList, hencList] + simp only [toOV, encBits_apply, List.append_nil] + rw [frame, hfm, List.map_map] + rfl + refine ⟨e₁ + e₂, h.mono 2 (fun φ => ?_) fun φ => ?_⟩ <;> + · simp only [OV.length_firstVars, OV.length_secondVars] + have h₁ : 2 ^ (φ.numVars / 2) ≤ 2 ^ (φ.numVars - φ.numVars / 2) := + Nat.pow_le_pow_right (by norm_num) (by omega) + have h₂ : ((encCNF φ).length + 1) ^ e₁ ≤ ((encCNF φ).length + 1) ^ (e₁ + e₂) := + Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_add_right _ _) + have h₃ : ((encCNF φ).length + 1) ^ e₂ ≤ ((encCNF φ).length + 1) ^ (e₁ + e₂) := + Nat.pow_le_pow_right (Nat.succ_pos _) (Nat.le_add_left _ _) + have := Nat.mul_le_mul h₁ h₂ + have := Nat.mul_le_mul_left (2 ^ (φ.numVars - φ.numVars / 2)) h₃ + nlinarith + simpa only [computableInO_iff_computableTidilyInO] using this /-! ### Williams' theorem -/ @@ -536,8 +545,8 @@ theorem DecidableInTimeO.decidableInExpTime_SAT {ε : ℝ} (hε : 0 < ε) {e : fun p => ((p.1.length + p.2.length : ℕ) : ℝ) ^ (2 - ε) * (OV.dim p + 1) ^ e) : DecidableInExpTime SAT encCNF CNF.numVars (1 - min ε 1 / 2) := by obtain ⟨g, t, c, hg, hgOV, ht⟩ := h.exists_computableTidilyInO - obtain ⟨E, hred⟩ := exists_computableTidilyInO_toOV - refine .of_computableTidilyInO (hg.comp hred) (fun φ => by + obtain ⟨E, hred⟩ := exists_computableInO_toOV + refine DecidableInExpTime.of_computableInO (hg.comp hred) (fun φ => by rw [← toOV_mem_OV_iff] exact hgOV _) (3 + 9 * c) (E + e) fun φ => ?_ set ε₀ := min ε 1 @@ -626,7 +635,7 @@ theorem OVH_of_SETH (h : SETH) : OVH := by obtain ⟨k, hk⟩ := h _ hδ refine hk ?_ rw [KSAT_eq_inter k (KSAT_subset_SAT k) le_rfl] - refine hSAT.inter (computableTidilyInPolyTime_all_length_le k) ?_ + refine hSAT.inter (computableInPolyTime_all_length_le k).tidy ?_ have : min ε 1 / 2 ≤ 1 / 2 := div_le_div_of_nonneg_right (min_le_right ε 1) zero_le_two linarith diff --git a/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean b/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean index 2b3ef9988..655e2b601 100644 --- a/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean +++ b/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean @@ -364,7 +364,7 @@ for some $\delta > 0$, `ThreeColoring` is not decidable within time $2^{\delta | polynomial in the length of the encoded graph, for graphs with $|V|$ declared vertices. -/ theorem ETH.not_decidableInSubexpTime_ThreeColoring_vertices (h : ETH) : ¬DecidableInSubexpTime ThreeColoring encGraph fun G => G.1.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableTidilyInPolyTime_toThreeColoring + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring.tidy (fun φ _ => SAT.toThreeColoring_mem_iff φ) (k := 93) fun φ hφ => by have := SAT.length_toThreeColoring_le hφ nlinarith @@ -859,7 +859,7 @@ private theorem computableTidilyInPolyTime_adjBoolWithInput (hu : ComputableTidilyInPolyTime u encIn encNat) (hv : ComputableTidilyInPolyTime v encIn encNat) : ComputableTidilyInPolyTime (fun x => (G x).adjBool (u x) (v x)) encIn encBool := - Graph.computableTidilyInPolyTime_adjBool.comp ((hG.prod hu).prod hv) + Graph.computableInPolyTime_adjBool.tidy.comp ((hG.prod hu).prod hv) @[fun_prop] private theorem computableTidilyInPolyTime_unary_div' @@ -1308,7 +1308,7 @@ theorem decidableInExpTime_ThreeColoring_of_bpis {M : ℕ} (hM : 0 < M) {δ : set E := dn + di + 2 * d + 2 * da + d_nd * e + 4 set C₂ : ℝ := c * 2 ^ (5 * δ) * ((c_nd : ℝ) + 1) ^ e + c + 1 set C₀ : ℝ := 3 + C₃ + (2 ^ K_M + 1 : ℝ) * (C₁ + C₂) - refine .of_computableTidilyInO hsearch + refine DecidableInExpTime.of_computableInO hsearch (fun H => (search_eq_true_iff (fun G => (hgB G).symm) H).symm) ⌈C₀⌉₊ E fun H => ?_ set L := (encGraph H).length set N := H.1.length diff --git a/Complexity/Computability/Complexity/FineGrained/Reduction.lean b/Complexity/Computability/Complexity/FineGrained/Reduction.lean index 154a025f8..57b3a8fdb 100644 --- a/Complexity/Computability/Complexity/FineGrained/Reduction.lean +++ b/Complexity/Computability/Complexity/FineGrained/Reduction.lean @@ -103,16 +103,17 @@ with `μB (f a) ≤ c μA a + c`, then a decider for `B` within time `2 ^ (δ μ in the length of the encoded instance gives a decider for `A` within time `2 ^ (c δ μA a)` times a polynomial. -/ theorem DecidableInExpTime.of_reduction {f : α → β} - (hf : ComputableTidilyInPolyTime f encA encB) (hfA : ∀ a, a ∈ A ↔ f a ∈ B) {c : ℕ} + (hf : ComputableInPolyTime f encA encB) (hfA : ∀ a, a ∈ A ↔ f a ∈ B) {c : ℕ} (hμ : ∀ a, μB (f a) ≤ c * μA a + c) {δ : ℝ} (hδ : 0 ≤ δ) (h : DecidableInExpTime B encB μB δ) : DecidableInExpTime A encA μA (c * δ) := by + have hf := hf.tidy obtain ⟨e, h⟩ := h obtain ⟨g, t, k, hg, hgB, ht⟩ := h.exists_computableTidilyInO obtain ⟨d, _, hf⟩ := hf.exists_degree have hfO := hf.inO obtain ⟨l, hl⟩ := hfO.length_le_time set K : ℝ := 1 + k * 2 ^ (δ * c) * (2 * l + 1) ^ e + k - refine .of_computableTidilyInO (hg.comp hfO) (fun a => (hfA a).trans (hgB (f a))) + refine Complexity.DecidableInExpTime.of_computableInO (hg.comp hfO) (fun a => (hfA a).trans (hgB (f a))) ⌈K⌉₊ (d * e + d) fun a => ?_ show _ ≤ _ set P : ℝ := ((encA a).length + 1) ^ d @@ -166,7 +167,7 @@ theorem DecidableInExpTime.of_reduction {f : α → β} with `μB (f a) ≤ c μA a + c`, and `B` is decidable in subexponential time in `μB`, then `A` is decidable in subexponential time in `μA`. -/ theorem DecidableInSubexpTime.of_reduction {f : α → β} - (hf : ComputableTidilyInPolyTime f encA encB) (hfA : ∀ a, a ∈ A ↔ f a ∈ B) {c : ℕ} + (hf : ComputableInPolyTime f encA encB) (hfA : ∀ a, a ∈ A ↔ f a ∈ B) {c : ℕ} (hμ : ∀ a, μB (f a) ≤ c * μA a + c) (h : DecidableInSubexpTime B encB μB) : DecidableInSubexpTime A encA μA := by intro δ hδ @@ -181,7 +182,7 @@ of `B` exactly when `φ` is satisfiable, with `μB (f φ) ≤ k m + k`, then `B` subexponential time in `μB`: for some `δ > 0`, no decider runs within time `2 ^ (δ μB b)` times a polynomial in the length of the encoded instance. -/ theorem ETH.not_decidableInSubexpTime_of_reduction (hETH : ETH) {f : CNF ℕ → β} - (hf : ComputableTidilyInPolyTime f encCNF encB) + (hf : ComputableInPolyTime f encCNF encB) (hfB : ∀ φ : CNF ℕ, (∀ c ∈ φ, c.length ≤ 3) → (f φ ∈ B ↔ φ ∈ SAT)) {k : ℕ} (hμ : ∀ φ : CNF ℕ, (∀ c ∈ φ, c.length ≤ 3) → μB (f φ) ≤ k * φ.length + k) : ¬DecidableInSubexpTime B encB μB := by @@ -189,8 +190,8 @@ theorem ETH.not_decidableInSubexpTime_of_reduction (hETH : ETH) {f : CNF ℕ → -- formulas with a clause of more than three literals go to the image of the empty clause refine ETH_iff_not_decidableInSubexpTime_length.mp hETH (h.of_reduction (f := fun φ => if φ.all (fun c => decide (c.length ≤ 3)) then f φ - else f [[]]) (ComputableTidilyInPolyTime.ite' (computableTidilyInPolyTime_all_length_le 3) - hf (ComputableTidilyInPolyTime.const _)) (fun φ => ?_) (c := 2 * k) fun φ => ?_) + else f [[]]) (ComputableInPolyTime.ite' (computableInPolyTime_all_length_le 3) + hf (ComputableInPolyTime.const _)) (fun φ => ?_) (c := 2 * k) fun φ => ?_) · by_cases hφ : ∀ c ∈ φ, c.length ≤ 3 · have hw : (φ.all fun c => decide (c.length ≤ 3)) = true := by simpa using hφ simp only [hw, ite_true, hfB φ hφ] diff --git a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean index af388bf34..a9c9e8734 100644 --- a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean +++ b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean @@ -19,6 +19,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Li import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Div +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Algorithmic sparsification @@ -538,11 +539,12 @@ formulas with `m` clauses, the formulas accepted by the search are decidable wit `2 ^ ((1 / M + c δ) n)` times a polynomial, on formulas with `n` variables, for `c = occBound K α`. -/ theorem decidableInExpTime_search {k M : ℕ} (hkK : k ≤ K) (hM : LeafBound K α M) - {g : CNF ℕ → Bool} {t : CNF ℕ → ℕ} (hg : ComputableTidilyInO g encCNF encBool t t) + {g : CNF ℕ → Bool} {t : CNF ℕ → ℕ} (hg : ComputableInO g encCNF encBool t t) {δ : ℝ} (hδ : 0 ≤ δ) {c e : ℕ} (ht : ∀ ψ : CNF ℕ, (t ψ : ℝ) ≤ c * (2 ^ (δ * ψ.length) * ((encCNF ψ).length + 1) ^ e) + c) : DecidableInExpTime {φ | search K α k M g φ = true} encCNF CNF.numVars (1 / M + occBound K α * δ) := by + have hg := hg.tidy obtain ⟨d, dn, di, h⟩ := exists_computableTidilyInO_search hK hα hkK hM hg hδ ht set Kx := K * base K α ^ (2 * K) set c₁ := (1 + Kx) * (6 * K + 1) @@ -551,7 +553,7 @@ theorem decidableInExpTime_search {k M : ℕ} (hkK : k ≤ K) (hM : LeafBound K set E := dn + di + 3 * d + 2 * e + 3 set C₂ : ℝ := c * 2 ^ δ * ((c₁ : ℝ) + 1) ^ e + c + 1 set C₀ : ℝ := 2 + 5 * (C₁ + C₂) - refine .of_computableTidilyInO h (fun φ => Iff.rfl) ⌈C₀⌉₊ E fun φ => ?_ + refine DecidableInExpTime.of_computableInO h (fun φ => Iff.rfl) ⌈C₀⌉₊ E fun φ => ?_ set L := (encCNF φ).length set N := φ.numVars set P := (L + 1) ^ E @@ -746,7 +748,7 @@ theorem exists_decidableInExpTime_numVars_of_length (k : ℕ) {ε : ℝ} (hε : fun ψ hψ => by rw [← hgA] exact ⟨fun h => h.2, fun h => ⟨hψ, h⟩⟩ - have hsearch := Sparsify.decidableInExpTime_search hK hα hkK hLB hg hδ ht + have hsearch := Sparsify.decidableInExpTime_search hK hα hkK hLB (.of_tidy hg) hδ ht have heq : KSAT k = {φ : CNF ℕ | (φ.all fun c => decide (c.length ≤ k)) = true} ∩ {φ | Sparsify.search K α k M g φ = true} := by ext φ @@ -757,7 +759,7 @@ theorem exists_decidableInExpTime_numVars_of_length (k : ℕ) {ε : ℝ} (hε : · rintro ⟨hw, hs⟩ exact ⟨hw, (Sparsify.search_eq_true_iff hK hα hkK hLB hgsat hw).mp hs⟩ rw [heq] - exact (hsearch.inter (computableTidilyInPolyTime_all_length_le k) (by positivity)).mono + exact (hsearch.inter (computableInPolyTime_all_length_le k).tidy (by positivity)).mono (by linarith) /-- **Subexponential time in the clauses gives subexponential time in the variables** diff --git a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean index 995ec10dd..170a97dc3 100644 --- a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean +++ b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean @@ -14,6 +14,7 @@ public import Complexity.Computability.Complexity.Classes.EXP import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Fold import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The worst-case-to-average-case encoding is computable in exponential time @@ -22,10 +23,10 @@ The program `Cslib.HardnessEncoding.encodedProgram` is certified in the polynomi tidy multi-tape machines, on padded inputs: with the length parameter `min |y| ⌊log₂ p⌋` for a unary padding `p`, every loop of the program runs over at most `p ^ O(1)` elements, and the decider of `L`, computable in time `2 ^ O(n)`, is called on words of length at most `⌊log₂ p⌋` -(`Cslib.HardnessEncoding.computableTidilyInPolyTime_paddedProgram`). With the padding +(`Cslib.HardnessEncoding.computableInPolyTime_paddedProgram`). With the padding `p = 2 ^ |y|` the program runs in time `2 ^ O(|y|)`, so the encoded language of a language in `E` is in `E` (`Cslib.HardnessEncoding.encodedLanguage_mem_E`, by -`Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad`). +`Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad`). ## Main definitions @@ -34,7 +35,7 @@ is in `E` (`Cslib.HardnessEncoding.encodedLanguage_mem_E`, by ## Main results -* `Cslib.HardnessEncoding.computableTidilyInPolyTime_paddedProgram`: the padded program is +* `Cslib.HardnessEncoding.computableInPolyTime_paddedProgram`: the padded program is polynomial-time. * `Cslib.HardnessEncoding.encodedLanguage_mem_E`: **the encoding of a language in `E` is in `E`**. @@ -58,17 +59,17 @@ open Turing.MultiTapeTM ComputableTidilyInPolyTime Cslib.AffineDisperser private theorem computableTidilyInPolyTime_powerMulTable : ComputableTidilyInPolyTime powerMulTable encBits encTable := by unfold powerMulTable - have := computableTidilyInPolyTime_powerTable + have := computableInPolyTime_powerTable.tidy fun_prop /-- Inverses in coordinates, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_fieldInv' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_fieldInv' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w : α → ℕ} {y : α → List Bool} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hy : ComputableTidilyInPolyTime y input encBits) : - ComputableTidilyInPolyTime (fun x => fieldInv (tab x) (w x) (y x)) input encBits := by + (htab : ComputableInPolyTime tab input encTable) + (hw : ComputableInPolyTime w input encUnary) + (hy : ComputableInPolyTime y input encBits) : + ComputableInPolyTime (fun x => fieldInv (tab x) (w x) (y x)) input encBits := by unfold fieldInv fun_prop @@ -118,30 +119,36 @@ private theorem computableTidilyInPolyTime_lagrangeNum : ComputableTidilyInPolyT /-- The Lagrange numerator, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_lagrangeNum' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_lagrangeNum' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w : α → ℕ} {E : α → List (List Bool)} {a t : α → List Bool} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hE : ComputableTidilyInPolyTime E input (encList encBits)) - (ha : ComputableTidilyInPolyTime a input encBits) - (ht : ComputableTidilyInPolyTime t input encBits) : - ComputableTidilyInPolyTime (fun x => lagrangeNum (tab x) (w x) (E x) (a x) (t x)) input + (htab : ComputableInPolyTime tab input encTable) + (hw : ComputableInPolyTime w input encUnary) + (hE : ComputableInPolyTime E input (encList encBits)) + (ha : ComputableInPolyTime a input encBits) + (ht : ComputableInPolyTime t input encBits) : + ComputableInPolyTime (fun x => lagrangeNum (tab x) (w x) (E x) (a x) (t x)) input encBits := by + have htab := htab.tidy + have hw := hw.tidy + have hE := hE.tidy + have ha := ha.tidy + have ht := ht.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_lagrangeNum.comp (((htab.prod hw).prod hE).prod (ha.prod ht)) /-- A Lagrange basis polynomial at a point, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_lagrangeVal' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_lagrangeVal' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w : α → ℕ} {E : α → List (List Bool)} {a t : α → List Bool} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hE : ComputableTidilyInPolyTime E input (encList encBits)) - (ha : ComputableTidilyInPolyTime a input encBits) - (ht : ComputableTidilyInPolyTime t input encBits) : - ComputableTidilyInPolyTime (fun x => lagrangeVal (tab x) (w x) (E x) (a x) (t x)) input + (htab : ComputableInPolyTime tab input encTable) + (hw : ComputableInPolyTime w input encUnary) + (hE : ComputableInPolyTime E input (encList encBits)) + (ha : ComputableInPolyTime a input encBits) + (ht : ComputableInPolyTime t input encBits) : + ComputableInPolyTime (fun x => lagrangeVal (tab x) (w x) (E x) (a x) (t x)) input encBits := by unfold lagrangeVal fun_prop @@ -185,33 +192,41 @@ private theorem computableTidilyInPolyTime_termVal : ComputableTidilyInPolyTime /-- A term of the extension, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w b M : α → ℕ} {E xs : α → List (List Bool)} {z : α → List Bool} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hb : ComputableTidilyInPolyTime b input encUnary) - (hM : ComputableTidilyInPolyTime M input encUnary) - (hE : ComputableTidilyInPolyTime E input (encList encBits)) - (hxs : ComputableTidilyInPolyTime xs input (encList encBits)) - (hz : ComputableTidilyInPolyTime z input encBits) : - ComputableTidilyInPolyTime (fun x => termVal (tab x) (w x) (b x) (M x) (E x) (xs x) (z x)) + (htab : ComputableInPolyTime tab input encTable) + (hw : ComputableInPolyTime w input encUnary) + (hb : ComputableInPolyTime b input encUnary) + (hM : ComputableInPolyTime M input encUnary) + (hE : ComputableInPolyTime E input (encList encBits)) + (hxs : ComputableInPolyTime xs input (encList encBits)) + (hz : ComputableInPolyTime z input encBits) : + ComputableInPolyTime (fun x => termVal (tab x) (w x) (b x) (M x) (E x) (xs x) (z x)) input encBits := by + have htab := htab.tidy + have hw := hw.tidy + have hb := hb.tidy + have hM := hM.tidy + have hE := hE.tidy + have hxs := hxs.tidy + have hz := hz.tidy + refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_termVal.comp ((((htab.prod hw).prod hb).prod hM).prod ((hE.prod hxs).prod hz)) /-- **The low-degree extension at a point is polynomial-time**, as a composition rule. -/ @[fun_prop] -theorem computableTidilyInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w b M : α → ℕ} {E pts xs : α → List (List Bool)} - (htab : ComputableTidilyInPolyTime tab input encTable) - (hw : ComputableTidilyInPolyTime w input encUnary) - (hb : ComputableTidilyInPolyTime b input encUnary) - (hM : ComputableTidilyInPolyTime M input encUnary) - (hE : ComputableTidilyInPolyTime E input (encList encBits)) - (hpts : ComputableTidilyInPolyTime pts input (encList encBits)) - (hxs : ComputableTidilyInPolyTime xs input (encList encBits)) : - ComputableTidilyInPolyTime (fun x => ldeVal (tab x) (w x) (b x) (M x) (E x) (pts x) (xs x)) + (htab : ComputableInPolyTime tab input encTable) + (hw : ComputableInPolyTime w input encUnary) + (hb : ComputableInPolyTime b input encUnary) + (hM : ComputableInPolyTime M input encUnary) + (hE : ComputableInPolyTime E input (encList encBits)) + (hpts : ComputableInPolyTime pts input (encList encBits)) + (hxs : ComputableInPolyTime xs input (encList encBits)) : + ComputableInPolyTime (fun x => ldeVal (tab x) (w x) (b x) (M x) (E x) (pts x) (xs x)) input encBits := by unfold ldeVal fun_prop @@ -248,8 +263,9 @@ private theorem polyBounded_two_pow_mul_padLength (c : ℕ) : /-- The length parameter is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_padLength : - ComputableTidilyInPolyTime padLength (encPair encBits encUnary) encUnary := by +theorem computableInPolyTime_padLength : + ComputableInPolyTime padLength (encPair encBits encUnary) encUnary := by + refine .of_tidy ?_ unfold padLength have := unary_log_two fun_prop @@ -258,11 +274,13 @@ theorem computableTidilyInPolyTime_padLength : time `2 ^ O(n)`: every loop runs over at most `p ^ O(1)` elements for the padding `p`, the modulus is found among `2 ^ (w + 1) ≤ 2 p + 2` codes, and `gL` is called on words of length at most `⌊log₂ p⌋`. -/ -theorem computableTidilyInPolyTime_paddedProgram (M : ℕ) {gL : List Bool → Bool} {k : ℕ} - (hgL : ComputableTidilyInO gL encBits encBool (fun y => 2 ^ (k * y.length)) +theorem computableInPolyTime_paddedProgram (M : ℕ) {gL : List Bool → Bool} {k : ℕ} + (hgL : ComputableInO gL encBits encBool (fun y => 2 ^ (k * y.length)) fun y => 2 ^ (k * y.length)) : - ComputableTidilyInPolyTime (paddedProgram M gL) (encPair encBits encUnary) encBool := by - have hℓ := computableTidilyInPolyTime_padLength + ComputableInPolyTime (paddedProgram M gL) (encPair encBits encUnary) encBool := by + have hgL : ComputableTidilyInO gL encBits encBool (fun y => 2 ^ (k * y.length)) fun y => 2 ^ (k * y.length) := by simpa only [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] using hgL + refine .of_tidy ?_ + have hℓ := computableInPolyTime_padLength.tidy have hb : ComputableTidilyInPolyTime (fun x => blockLength M (padLength x)) (encPair encBits encUnary) encUnary := by unfold blockLength @@ -314,8 +332,8 @@ theorem computableTidilyInPolyTime_paddedProgram (M : ℕ) {gL : List Bool → B have hmod : ComputableTidilyInPolyTime (fun x => modulusBits (4 * blockLength M (padLength x))) (encPair encBits encUnary) encBits := by unfold modulusBits - have := computableTidilyInPolyTime_bits_unary - have := computableTidilyInPolyTime_leastIrreducibleCode + have := computableInPolyTime_bits_unary.tidy + have := computableInPolyTime_leastIrreducibleCode.tidy fun_prop have htab : ComputableTidilyInPolyTime (fun x => fieldTable (4 * blockLength M (padLength x))) (encPair encBits encUnary) encTable := by @@ -336,9 +354,9 @@ is decided in time `2 ^ O(N)` by running the padded program with the padding `2 theorem encodedLanguage_mem_E {L : Language Bool} (hL : (L : Set (List Bool)) ∈ E encBits) (M : ℕ) : (encodedLanguage L M : Set (List Bool)) ∈ E encBits := by obtain ⟨k, hk⟩ := mem_E_iff.1 hL - obtain ⟨gL, hgL, hgLO⟩ := exists_computableTidilyInO_of_mem_DTIME hk - have h := setOf_mem_E_of_computableTidilyInPolyTime_pad - (computableTidilyInPolyTime_paddedProgram M hgLO) + obtain ⟨gL, hgL, hgLO⟩ := exists_computableInO_of_mem_DTIME hk + have h := setOf_mem_E_of_computableInPolyTime_pad + (computableInPolyTime_paddedProgram M (.of_tidy hgLO)) have hset : (encodedLanguage L M : Set (List Bool)) = {y | paddedProgram M gL (y, 2 ^ y.length) = true} := by ext y diff --git a/Complexity/Computability/Complexity/Parameterized.lean b/Complexity/Computability/Complexity/Parameterized.lean index c2d625067..9b94d2972 100644 --- a/Complexity/Computability/Complexity/Parameterized.lean +++ b/Complexity/Computability/Complexity/Parameterized.lean @@ -44,7 +44,7 @@ machine within time `F (κA a) * (L + 1) ^ c` (`Cslib.Complexity.ComputableInFPT (`Cslib.Complexity.computableInFPTTime_iff_computableTidilyInFPTTime`), and proofs that compose reductions use it through `Cslib.Complexity.fptReducible_iff_tidy`. Polynomial-time reductions with a parameter bound are fpt-reductions -(`Cslib.Complexity.FPTReducible.of_computableTidilyInPolyTime`). `FPT` and `XP` are closed under +(`Cslib.Complexity.FPTReducible.of_computableInPolyTime`). `FPT` and `XP` are closed under fpt-reductions. As for `FPT`, the functions `F` and `h` are arbitrary, where the cited definitions require them to be computable. @@ -412,53 +412,57 @@ private theorem decidableInTimeO_natCast_iff {A : Set α} {T : α → ℕ} : exact_mod_cast this exact ⟨g, hg.mono k ht' ht', hA⟩ · rintro ⟨g, hg, hA⟩ - exact DecidableInTimeO.of_computableTidilyInO hg hA fun _ => le_rfl + exact DecidableInTimeO.of_computableInO hg hA fun _ => le_rfl /-- **`FPT` in terms of fpt-time computability**: a problem is fixed-parameter tractable exactly when a Boolean function deciding it is tidily computable in fpt time. -/ -theorem mem_FPT_iff_computableTidilyInFPTTime {A : Set α} : +theorem mem_FPT_iff_computableInFPTTime {A : Set α} : A ∈ FPT encA κ ↔ - ∃ g : α → Bool, ComputableTidilyInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by - have e : ∀ (f : ℕ → ℕ) (c : ℕ), (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ c) = - fun a => ((f (κ a) * ((encA a).length + 1) ^ c : ℕ) : ℝ) := fun f c => by - funext a - push_cast - rfl - constructor - · rintro ⟨f, c, h⟩ - rw [e, decidableInTimeO_natCast_iff] at h - obtain ⟨g, hg, hA⟩ := h - exact ⟨g, ⟨f, c, hg⟩, hA⟩ - · rintro ⟨g, ⟨f, c, hg⟩, hA⟩ - refine ⟨f, c, ?_⟩ - rw [e, decidableInTimeO_natCast_iff] - exact ⟨g, hg, hA⟩ + ∃ g : α → Bool, ComputableInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by + have this : A ∈ FPT encA κ ↔ ∃ g : α → Bool, ComputableTidilyInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by + have e : ∀ (f : ℕ → ℕ) (c : ℕ), (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ c) = + fun a => ((f (κ a) * ((encA a).length + 1) ^ c : ℕ) : ℝ) := fun f c => by + funext a + push_cast + rfl + constructor + · rintro ⟨f, c, h⟩ + rw [e, decidableInTimeO_natCast_iff] at h + obtain ⟨g, hg, hA⟩ := h + exact ⟨g, ⟨f, c, hg⟩, hA⟩ + · rintro ⟨g, ⟨f, c, hg⟩, hA⟩ + refine ⟨f, c, ?_⟩ + rw [e, decidableInTimeO_natCast_iff] + exact ⟨g, hg, hA⟩ + simpa only [computableInFPTTime_iff_computableTidilyInFPTTime] using this /-- **`XP` in terms of tidy computability.** -/ -theorem mem_XP_iff_exists_computableTidilyInO {A : Set α} : - A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableTidilyInO g encA encBool +theorem mem_XP_iff_exists_computableInO {A : Set α} : + A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableInO g encA encBool (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) ∧ ∀ a, a ∈ A ↔ g a = true := by - have h : ∀ f e : ℕ → ℕ, (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ e (κ a)) = - fun a => ((f (κ a) * ((encA a).length + 1) ^ e (κ a) : ℕ) : ℝ) := fun f e => by - funext a - push_cast - rfl - constructor - · rintro ⟨f, e, hA⟩ - rw [h, decidableInTimeO_natCast_iff] at hA - obtain ⟨g, hg, hA⟩ := hA - exact ⟨g, f, e, hg, hA⟩ - · rintro ⟨g, f, e, hg, hA⟩ - refine ⟨f, e, ?_⟩ - rw [h, decidableInTimeO_natCast_iff] - exact ⟨g, hg, hA⟩ + have this : A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableTidilyInO g encA encBool (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) ∧ ∀ a, a ∈ A ↔ g a = true := by + have h : ∀ f e : ℕ → ℕ, (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ e (κ a)) = + fun a => ((f (κ a) * ((encA a).length + 1) ^ e (κ a) : ℕ) : ℝ) := fun f e => by + funext a + push_cast + rfl + constructor + · rintro ⟨f, e, hA⟩ + rw [h, decidableInTimeO_natCast_iff] at hA + obtain ⟨g, hg, hA⟩ := hA + exact ⟨g, f, e, hg, hA⟩ + · rintro ⟨g, f, e, hg, hA⟩ + refine ⟨f, e, ?_⟩ + rw [h, decidableInTimeO_natCast_iff] + exact ⟨g, hg, hA⟩ + simpa only [computableInO_iff_computableTidilyInO] using this /-- **Bounded parameters.** For a parameter bounded by a constant, `FPT` is `P`. -/ theorem FPT_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : FPT encA κ = P encA := by refine subset_antisymm (fun A hA => ?_) P_subset_FPT obtain ⟨g, ⟨f, c, hg⟩, hA⟩ := - mem_FPT_iff_computableTidilyInFPTTime.mp (FPT_subset_FPT_of_le_comp (κ' := fun _ => 0) + mem_FPT_iff_computableInFPTTime.mp (FPT_subset_FPT_of_le_comp (κ' := fun _ => 0) (h := fun _ => K) hκ hA) exact ⟨g, .of_tidy <| hg.computableTidilyInPolyTime (.of_forall_le (f 0) c fun _ => le_rfl) (.of_forall_le (f 0) c fun _ => le_rfl), hA⟩ @@ -467,7 +471,7 @@ theorem FPT_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : FPT encA κ = P enc theorem XP_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : XP encA κ = P encA := by refine subset_antisymm (fun A hA => ?_) P_subset_XP obtain ⟨g, f, e, hg, hA⟩ := - mem_XP_iff_exists_computableTidilyInO.mp (XP_subset_XP_of_le_comp (κ' := fun _ => 0) + mem_XP_iff_exists_computableInO.mp (XP_subset_XP_of_le_comp (κ' := fun _ => 0) (h := fun _ => K) hκ hA) exact ⟨g, .of_tidy <| hg.computableTidilyInPolyTime (.of_forall_le (f 0) (e 0) fun _ => le_rfl) (.of_forall_le (f 0) (e 0) fun _ => le_rfl), hA⟩ @@ -476,8 +480,8 @@ theorem XP_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : XP encA κ = P encA /-- **`FPT` is closed under complement.** -/ theorem compl_mem_FPT {A : Set α} (hA : A ∈ FPT encA κ) : Aᶜ ∈ FPT encA κ := by - obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp hA - refine mem_FPT_iff_computableTidilyInFPTTime.mpr ⟨_, hg.ite + obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA + refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg.ite ((ComputableTidilyInPolyTime.const false).computableTidilyInFPTTime κ) ((ComputableTidilyInPolyTime.const true).computableTidilyInFPTTime κ), fun a => ?_⟩ simp only [Set.mem_compl_iff, hA] @@ -486,9 +490,9 @@ theorem compl_mem_FPT {A : Set α} (hA : A ∈ FPT encA κ) : Aᶜ ∈ FPT encA /-- **`FPT` is closed under intersection.** -/ theorem inter_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT encA κ) : A ∩ B ∈ FPT encA κ := by - obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp hA - obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp hB - refine mem_FPT_iff_computableTidilyInFPTTime.mpr ⟨_, hg₁.ite hg₂ + obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA + obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB + refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite hg₂ ((ComputableTidilyInPolyTime.const false).computableTidilyInFPTTime κ), fun a => ?_⟩ simp only [Set.mem_inter_iff, hA, hB] cases g₁ a <;> simp @@ -496,19 +500,19 @@ theorem inter_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT en /-- **`FPT` is closed under union.** -/ theorem union_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT encA κ) : A ∪ B ∈ FPT encA κ := by - obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp hA - obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp hB - refine mem_FPT_iff_computableTidilyInFPTTime.mpr ⟨_, hg₁.ite + obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA + obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB + refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite ((ComputableTidilyInPolyTime.const true).computableTidilyInFPTTime κ) hg₂, fun a => ?_⟩ simp only [Set.mem_union, hA, hB] cases g₁ a <;> simp /-- **`XP` is closed under complement.** -/ theorem compl_mem_XP {A : Set α} (hA : A ∈ XP encA κ) : Aᶜ ∈ XP encA κ := by - obtain ⟨g, f, e, hg, hA⟩ := mem_XP_iff_exists_computableTidilyInO.mp hA + obtain ⟨g, f, e, hg, hA⟩ := mem_XP_iff_exists_computableInO.mp hA have h := hg.ite (ComputableTidilyInO.const (encMid := encBool) false) (ComputableTidilyInO.const (encMid := encBool) true) - refine mem_XP_iff_exists_computableTidilyInO.mpr ⟨_, fun k => f k + 1, fun k => e k + 1, + refine mem_XP_iff_exists_computableInO.mpr ⟨_, fun k => f k + 1, fun k => e k + 1, h.mono_le (fun a => ?_) (fun a => ?_), fun a => ?_⟩ rotate_left 2 · simp only [Set.mem_compl_iff, hA] @@ -571,10 +575,11 @@ theorem fptReducible_iff_tidy : rfl /-- **Polynomial-time reductions bounding the parameter are fpt-reductions.** -/ -theorem FPTReducible.of_computableTidilyInPolyTime {f : α → β} - (hf : ComputableTidilyInPolyTime f encA encB) {h : ℕ → ℕ} (hκ : ∀ a, κB (f a) ≤ h (κA a)) - (hfA : ∀ a, a ∈ A ↔ f a ∈ B) : FPTReducible encA encB κA κB A B := - ⟨f, ⟨(hf.computableTidilyInFPTTime κA).computableInFPTTime, h, hκ⟩, hfA⟩ +theorem FPTReducible.of_computableInPolyTime {f : α → β} + (hf : ComputableInPolyTime f encA encB) {h : ℕ → ℕ} (hκ : ∀ a, κB (f a) ≤ h (κA a)) + (hfA : ∀ a, a ∈ A ↔ f a ∈ B) : FPTReducible encA encB κA κB A B := by + have hf := hf.tidy + exact ⟨f, ⟨(hf.computableTidilyInFPTTime κA).computableInFPTTime, h, hκ⟩, hfA⟩ /-- Every parameterized problem reduces to itself by the identity. -/ @[refl] @@ -602,20 +607,20 @@ theorem FPTReducible.compl (h : FPTReducible encA encB κA κB A B) : /-- **`FPT` is closed under fpt-reductions.** -/ theorem FPTReducible.mem_FPT (hAB : FPTReducible encA encB κA κB A B) (hB : B ∈ FPT encB κB) : A ∈ FPT encA κA := - mem_FPT_iff_computableTidilyInFPTTime.mpr + mem_FPT_iff_computableInFPTTime.mpr (ManyOneReducibleBy.trans (C := {true}) (fun _ _ ⟨hf, _, hκ⟩ hg => hg.comp hf.tidy hκ) - hAB (mem_FPT_iff_computableTidilyInFPTTime.mp hB)) + hAB (mem_FPT_iff_computableInFPTTime.mp hB)) /-- **`XP` is closed under fpt-reductions.** -/ theorem FPTReducible.mem_XP (hAB : FPTReducible encA encB κA κB A B) (hB : B ∈ XP encB κB) : A ∈ XP encA κA := by obtain ⟨f, ⟨⟨F₁, c₁, hf⟩, h, hκ⟩, hAB⟩ := fptReducible_iff_tidy.mp hAB - obtain ⟨g, F₂, e₂, hg, hB⟩ := mem_XP_iff_exists_computableTidilyInO.mp hB + obtain ⟨g, F₂, e₂, hg, hB⟩ := mem_XP_iff_exists_computableInO.mp hB obtain ⟨l, hgf⟩ := computableTidilyInO_comp (F₂' := fun k => ∑ j ∈ Finset.range (h k + 1), F₂ j) (E := fun k => ∑ j ∈ Finset.range (h k + 1), e₂ j) hg hf (fun a => le_sum_range_succ (hκ a)) fun a => le_sum_range_succ (hκ a) - exact mem_XP_iff_exists_computableTidilyInO.mpr ⟨g ∘ f, + exact mem_XP_iff_exists_computableInO.mpr ⟨g ∘ f, fun k => F₁ k + (∑ j ∈ Finset.range (h k + 1), F₂ j) * ((l + 1) * (F₁ k + 1)) ^ ∑ j ∈ Finset.range (h k + 1), e₂ j, fun k => c₁ + c₁ * ∑ j ∈ Finset.range (h k + 1), e₂ j, hgf, diff --git a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean index 86ec730fa..30d417cc6 100644 --- a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean +++ b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean @@ -16,6 +16,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Ba import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Kernelization @@ -126,7 +127,7 @@ variable {α : Type} {enc : α ↪ List Bool} {κ : α → ℕ} {A : Set α} /-- Every kernelization of `(A, κ)` is an fpt-reduction from `(A, κ)` to itself. -/ theorem IsKernelization.fptReducible {K : α → α} {g : ℕ → ℕ} (hK : IsKernelization enc κ A K g) : FPTReducible enc enc κ κ A A := - .of_computableTidilyInPolyTime hK.polyTime.tidy hK.parameter_le fun a => (hK.mem_iff a).symm + FPTReducible.of_computableInPolyTime hK.polyTime.tidy hK.parameter_le fun a => (hK.mem_iff a).symm /-! ### Kernels give fixed-parameter tractability -/ @@ -151,7 +152,7 @@ theorem IsKernelization.mem_FPT {K : α → α} {g : ℕ → ℕ} (hK : IsKernel have h₁ := (htt' a).trans (Nat.le_mul_of_pos_right _ hP) rw [Nat.add_mul, Nat.one_mul] omega - exact mem_FPT_iff_computableTidilyInFPTTime.mpr ⟨dec ∘ K, + exact mem_FPT_iff_computableInFPTTime.mpr ⟨dec ∘ K, ⟨fun k => 1 + (c * (∑ j ∈ Finset.range (g k + 1), t j) + c), d, (hdec.comp hKd.inO).mono_le key key⟩, fun a => (hK.mem_iff a).symm.trans (hdecA (K a))⟩ @@ -225,7 +226,7 @@ theorem hasKernel_of_mem_FPT [Nonempty α] (hA : A ∈ FPT enc κ) : HasKernel e (ComputableTidilyInPolyTime.encode enc)).prod hN) have hr : ComputableTidilyInPolyTime r enc eOut := computableTidilyInPolyTime_universal.comp hin have hverdict : ComputableTidilyInPolyTime Diagonal.verdict eOut encBool := - Diagonal.computableTidilyInO_verdict.computableTidilyInPolyTime + Diagonal.computableInO_verdict.tidy.computableTidilyInPolyTime (.of_forall_le 1 2 fun _ => by simp) (.of_forall_le 1 1 fun _ => by simp) have hK : ComputableTidilyInPolyTime K enc enc := ComputableTidilyInPolyTime.ite' (hverdict.comp hr) diff --git a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean index 4fd53cd6a..84eeff974 100644 --- a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean +++ b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean @@ -17,6 +17,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Li import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Mathlib.Data.Nat.Bitwise +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Fixed-parameter tractability of vertex cover @@ -48,7 +49,7 @@ tractable in the target size `k` (`Cslib.Complexity.VertexCover_mem_FPT`). * `Cslib.Complexity.VertexCover.exists_lt_two_pow_isCover_foldBranch`: if a graph has a vertex cover of at most `m` vertices, one of the `2 ^ m` paths of length `m` finds a cover. * `Cslib.Complexity.VertexCover.search_eq_true_iff`: `VertexCover.search` decides `VertexCover`. -* `Cslib.Complexity.VertexCover.exists_computableTidilyInO_search`: its running time. +* `Cslib.Complexity.VertexCover.exists_computableInO_search`: its running time. * `Cslib.Complexity.VertexCover_decidableInExpTime_one`: `VertexCover` is decidable within time `2 ^ k` times a polynomial in the length of the encoded instance. * `Cslib.Complexity.VertexCover_mem_FPT`, `Cslib.Complexity.VertexCover_hasKernel`: `VertexCover` @@ -288,8 +289,9 @@ theorem search_eq_true_iff (x : Graph × ℕ) : search x = true ↔ x ∈ Vertex open ComputableTidilyInPolyTime in /-- The capped depth `cap` is computable in polynomial time in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_cap : - ComputableTidilyInPolyTime cap (encPair encGraph encNat) encUnary := by +theorem computableInPolyTime_cap : + ComputableInPolyTime cap (encPair encGraph encNat) encUnary := by + refine .of_tidy ?_ have heq : cap = fun x : Graph × ℕ => Cslib.BitString.boundedBinaryValue x.1.distinctVertices.length (encNat x.2).reverse := by funext x @@ -297,14 +299,14 @@ theorem computableTidilyInPolyTime_cap : Cslib.BitString.binaryValue_reverse_bits] rw [heq] exact bitsBoundedBinaryValueWithInput - ((length_list encNat).comp (Graph.computableTidilyInPolyTime_distinctVertices.comp (fst _ _))) + ((length_list encNat).comp (Graph.computableInPolyTime_distinctVertices.tidy.comp (fst _ _))) (bitsReverse.comp ((encode encNat).comp (snd _ _))) open ComputableTidilyInPolyTime in /-- A single step of the bounded search tree is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_branchStep : - ComputableTidilyInPolyTime (fun p : (Graph × List ℕ) × Bool => branchStep p.1.1 p.1.2 p.2) +theorem computableInPolyTime_branchStep : + ComputableInPolyTime (fun p : (Graph × List ℕ) × Bool => branchStep p.1.1 p.1.2 p.2) (encPair (encPair encGraph (encList encNat)) encBool) (encList encNat) := by unfold branchStep fun_prop @@ -362,7 +364,7 @@ private theorem computableTidilyInPolyTime_foldBranch : (fun s : State => 2 * (encGraph s.1.1.1).length + 2) := ((PolyBounded.const 2).mul hG.polyBounded_length).add (.const 2) exact foldlWith_of_bounded_growth hG computableTidilyInPolyTime_branchBits (const []) - computableTidilyInPolyTime_branchStep hgrowth_poly + computableInPolyTime_branchStep.tidy hgrowth_poly fun s C b _ => length_encList_branchStep_le s.1.1.1 C b open ComputableTidilyInPolyTime in @@ -372,7 +374,7 @@ private theorem computableTidilyInPolyTime_step have hcov : ComputableTidilyInPolyTime (fun s : State => isCover s.1.1.1 (foldBranch s.1.1.1 ((List.range s.1.2).map s.2.1.testBit))) encState encBool := - computableTidilyInPolyTime_isCover.comp + computableInPolyTime_isCover.tidy.comp ((show ComputableTidilyInPolyTime (fun s : State => s.1.1.1) encState encGraph by fun_prop).prod computableTidilyInPolyTime_foldBranch) have hor : ComputableTidilyInPolyTime @@ -407,71 +409,73 @@ private theorem computableTidilyInPolyTime_finish : /-- **Running time of the bounded search tree for `VertexCover`**: within time `2 ^ k` times a polynomial in the length of the encoded instance. -/ -theorem exists_computableTidilyInO_search : ∃ e, ComputableTidilyInO search +theorem exists_computableInO_search : ∃ e, ComputableInO search (encPair encGraph encNat) encBool (fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e) fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e := by - obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree - obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree - obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree - obtain ⟨d₂, _, hans⟩ := computableTidilyInPolyTime_finish.exists_degree - set size : Graph × ℕ → ℕ := fun x => (encPair encGraph encNat x).length - set B : Graph × ℕ → ℕ := fun x => 16 * (size x + 1) - have hcap (x : Graph × ℕ) : cap x ≤ size x := - (cap_le_length x).trans (by simp only [size, length_encPair]; omega) - have hstate : ∀ x, ∀ j ≤ 2 ^ cap x, - (encState (step^[j] (init x))).length ≤ B x := by - intro x j hj - have hK := ComputableTidilyInO.length_encNat_mono hj - rw [encNat_two_pow] at hK - have h₁ := hcap x - rw [iterate_step_init] - simp only [List.length_append, List.length_replicate, List.length_singleton] at hK - simp only [encState, length_encPair, encUnary_apply, List.length_replicate, encBool_apply, - List.length_singleton, B, size] at h₁ ⊢ - omega - have hiter := ComputableTidilyInO.iterate hcount.inO hinit.inO hstep.inO - (R := fun x => (B x + 1) ^ d) (Q := fun x => (B x + 1) ^ d) (B := B) - (fun x j hj => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x j hj) 1) d) - (fun x j hj => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x j hj) 1) d) hstate - have h := hans.inO.comp hiter - have hB : PolyBounded size B := .of_forall_le 16 1 fun _ => by simp [B] - have hpow (j : ℕ) : PolyBounded size fun x => (B x + 1) ^ j := - ((PolyBounded.of_polynomiallyBounded id (bound := fun n => (n + 1) ^ j) (by fun_prop)).comp - hB).mono fun _ => le_rfl - have hL (j : ℕ) : PolyBounded size fun x => (size x + 1) ^ j := - .of_forall_le 1 j fun _ => by simp - obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (size := size) (μ := Prod.snd) - ((hpow d).add (hB.add (.of_forall_le 4 2 fun _ => le_rfl))) - ((hL d₁).add ((hL d₀).add (hpow d₂))) - (T := fun x => ((encPair encGraph encNat x).length + 1) ^ d₁ + - ((encPair encGraph encNat x).length + 1) ^ d₀ + - (2 ^ cap x + 1) * ((B x + 1) ^ d + B x + ((encNat (2 ^ cap x)).length + 1) ^ 2) + - ((encState (step^[2 ^ cap x] (init x))).length + 1) ^ d₂) - (fun x => by - have hK : ((encNat (2 ^ cap x)).length + 1) ^ 2 ≤ 4 * (size x + 1) ^ 2 := by - rw [encNat_two_pow] - simp only [List.length_append, List.length_replicate, List.length_singleton] - calc (cap x + 1 + 1) ^ 2 ≤ (2 * (size x + 1)) ^ 2 := - Nat.pow_le_pow_left (by have := hcap x; omega) 2 - _ = 4 * (size x + 1) ^ 2 := by ring - have hS := Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x _ le_rfl) 1) d₂ - have h2 : 2 ^ cap x ≤ 2 ^ x.2 := Nat.pow_le_pow_right (by norm_num) (cap_le_snd x) - have h3 := Nat.mul_le_mul (Nat.add_le_add_right h2 1) - (Nat.add_le_add_left hK ((B x + 1) ^ d + B x)) - simp only [size] at h3 hS ⊢ - nlinarith) - refine ⟨e, (h.mono c (fun x => ?_) fun x => ?_).of_enc_eq fun x => rfl⟩ - all_goals - have h₁ := hT x - simp only [size] at h₁ - generalize 2 ^ cap x = N at h₁ ⊢ - generalize (encNat N).length = K at h₁ ⊢ - obtain ⟨X, hX⟩ : ∃ X, (B x + 1) ^ d + B x = X := ⟨_, rfl⟩ - rw [hX] at h₁ - have h₂ : K ≤ (K + 1) ^ 2 := by nlinarith - have h₃ : X + (K + 1) ^ 2 ≤ (N + 1) * (X + (K + 1) ^ 2) := Nat.le_mul_of_pos_left _ (by omega) - nlinarith + have this : ∃ e, ComputableTidilyInO search (encPair encGraph encNat) encBool (fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e) fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e := by + obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree + obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree + obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree + obtain ⟨d₂, _, hans⟩ := computableTidilyInPolyTime_finish.exists_degree + set size : Graph × ℕ → ℕ := fun x => (encPair encGraph encNat x).length + set B : Graph × ℕ → ℕ := fun x => 16 * (size x + 1) + have hcap (x : Graph × ℕ) : cap x ≤ size x := + (cap_le_length x).trans (by simp only [size, length_encPair]; omega) + have hstate : ∀ x, ∀ j ≤ 2 ^ cap x, + (encState (step^[j] (init x))).length ≤ B x := by + intro x j hj + have hK := ComputableTidilyInO.length_encNat_mono hj + rw [encNat_two_pow] at hK + have h₁ := hcap x + rw [iterate_step_init] + simp only [List.length_append, List.length_replicate, List.length_singleton] at hK + simp only [encState, length_encPair, encUnary_apply, List.length_replicate, encBool_apply, + List.length_singleton, B, size] at h₁ ⊢ + omega + have hiter := ComputableTidilyInO.iterate hcount.inO hinit.inO hstep.inO + (R := fun x => (B x + 1) ^ d) (Q := fun x => (B x + 1) ^ d) (B := B) + (fun x j hj => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x j hj) 1) d) + (fun x j hj => Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x j hj) 1) d) hstate + have h := hans.inO.comp hiter + have hB : PolyBounded size B := .of_forall_le 16 1 fun _ => by simp [B] + have hpow (j : ℕ) : PolyBounded size fun x => (B x + 1) ^ j := + ((PolyBounded.of_polynomiallyBounded id (bound := fun n => (n + 1) ^ j) (by fun_prop)).comp + hB).mono fun _ => le_rfl + have hL (j : ℕ) : PolyBounded size fun x => (size x + 1) ^ j := + .of_forall_le 1 j fun _ => by simp + obtain ⟨c, e, hT⟩ := exists_le_mul_two_pow_of_polyBounded (size := size) (μ := Prod.snd) + ((hpow d).add (hB.add (.of_forall_le 4 2 fun _ => le_rfl))) + ((hL d₁).add ((hL d₀).add (hpow d₂))) + (T := fun x => ((encPair encGraph encNat x).length + 1) ^ d₁ + + ((encPair encGraph encNat x).length + 1) ^ d₀ + + (2 ^ cap x + 1) * ((B x + 1) ^ d + B x + ((encNat (2 ^ cap x)).length + 1) ^ 2) + + ((encState (step^[2 ^ cap x] (init x))).length + 1) ^ d₂) + (fun x => by + have hK : ((encNat (2 ^ cap x)).length + 1) ^ 2 ≤ 4 * (size x + 1) ^ 2 := by + rw [encNat_two_pow] + simp only [List.length_append, List.length_replicate, List.length_singleton] + calc (cap x + 1 + 1) ^ 2 ≤ (2 * (size x + 1)) ^ 2 := + Nat.pow_le_pow_left (by have := hcap x; omega) 2 + _ = 4 * (size x + 1) ^ 2 := by ring + have hS := Nat.pow_le_pow_left (Nat.add_le_add_right (hstate x _ le_rfl) 1) d₂ + have h2 : 2 ^ cap x ≤ 2 ^ x.2 := Nat.pow_le_pow_right (by norm_num) (cap_le_snd x) + have h3 := Nat.mul_le_mul (Nat.add_le_add_right h2 1) + (Nat.add_le_add_left hK ((B x + 1) ^ d + B x)) + simp only [size] at h3 hS ⊢ + nlinarith) + refine ⟨e, (h.mono c (fun x => ?_) fun x => ?_).of_enc_eq fun x => rfl⟩ + all_goals + have h₁ := hT x + simp only [size] at h₁ + generalize 2 ^ cap x = N at h₁ ⊢ + generalize (encNat N).length = K at h₁ ⊢ + obtain ⟨X, hX⟩ : ∃ X, (B x + 1) ^ d + B x = X := ⟨_, rfl⟩ + rw [hX] at h₁ + have h₂ : K ≤ (K + 1) ^ 2 := by nlinarith + have h₃ : X + (K + 1) ^ 2 ≤ (N + 1) * (X + (K + 1) ^ 2) := Nat.le_mul_of_pos_left _ (by omega) + nlinarith + simpa only [computableInO_iff_computableTidilyInO] using this end VertexCover @@ -479,8 +483,8 @@ end VertexCover a polynomial in the length of the encoded instance, for target cover size `k`. -/ theorem VertexCover_decidableInExpTime_one : DecidableInExpTime VertexCover (encPair encGraph encNat) Prod.snd 1 := by - obtain ⟨e, h⟩ := VertexCover.exists_computableTidilyInO_search - refine .of_computableTidilyInO h (fun x => (VertexCover.search_eq_true_iff x).symm) 1 e + obtain ⟨e, h⟩ := VertexCover.exists_computableInO_search + refine DecidableInExpTime.of_computableInO h (fun x => (VertexCover.search_eq_true_iff x).symm) 1 e fun x => ?_ rw [one_mul, Real.rpow_natCast] push_cast diff --git a/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean b/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean index 048947f2c..4f5c9bafe 100644 --- a/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean +++ b/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean @@ -58,7 +58,7 @@ instance, with degrees and the capped target in unary. * `Cslib.Complexity.VertexCover.length_bussKernel_vertices_le`, `Cslib.Complexity.VertexCover.length_encode_bussKernel_le`: at most `k (k + 2)` vertices and encoded length at most `40 (k + 1) ^ 6`. -* `Cslib.Complexity.VertexCover.computableTidilyInPolyTime_bussKernel`: the kernel is +* `Cslib.Complexity.VertexCover.computableInPolyTime_bussKernel`: the kernel is polynomial-time. * `Cslib.Complexity.VertexCover.isKernelization_bussKernel`, `Cslib.Complexity.VertexCover_hasPolyKernel`: `VertexCover` has a polynomial kernel in the @@ -462,101 +462,103 @@ namespace VertexCover.Buss open ComputableTidilyInPolyTime /-- Testing adjacency between computed vertices of a computed graph is polynomial-time. This is -`Cslib.Complexity.Graph.computableTidilyInPolyTime_adjBool` in the compositional form that +`Cslib.Complexity.Graph.computableInPolyTime_adjBool` in the compositional form that `fun_prop` uses. -/ @[fun_prop] -theorem computableTidilyInPolyTime_adjBool_comp {γ : Type} {enc : γ ↪ List Bool} - {G : γ → Graph} {u v : γ → ℕ} (hG : ComputableTidilyInPolyTime G enc encGraph) - (hu : ComputableTidilyInPolyTime u enc encNat) (hv : ComputableTidilyInPolyTime v enc encNat) : - ComputableTidilyInPolyTime (fun c => (G c).adjBool (u c) (v c)) enc encBool := - Graph.computableTidilyInPolyTime_adjBool.comp ((hG.prod hu).prod hv) +theorem computableInPolyTime_adjBool_comp {γ : Type} {enc : γ ↪ List Bool} + {G : γ → Graph} {u v : γ → ℕ} (hG : ComputableInPolyTime G enc encGraph) + (hu : ComputableInPolyTime u enc encNat) (hv : ComputableInPolyTime v enc encNat) : + ComputableInPolyTime (fun c => (G c).adjBool (u c) (v c)) enc encBool := + Graph.computableInPolyTime_adjBool.comp ((hG.prod hu).prod hv) /-- Computing a degree is polynomial-time, with the degree in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_degree : - ComputableTidilyInPolyTime (fun p : Graph × ℕ => degree p.1 p.2) +theorem computableInPolyTime_degree : + ComputableInPolyTime (fun p : Graph × ℕ => degree p.1 p.2) (encPair encGraph encNat) encUnary := by unfold degree fun_prop /-- Testing for a high vertex is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isHigh : - ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => isHigh p.1 p.2) +theorem computableInPolyTime_isHigh : + ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => isHigh p.1 p.2) (encPair (encPair encGraph encNat) encNat) encBool := by unfold isHigh fun_prop /-- Listing the high vertices is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_high : - ComputableTidilyInPolyTime high (encPair encGraph encNat) (encList encNat) := by +theorem computableInPolyTime_high : + ComputableInPolyTime high (encPair encGraph encNat) (encList encNat) := by unfold high fun_prop /-- Listing the low vertices is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_low : - ComputableTidilyInPolyTime low (encPair encGraph encNat) (encList encNat) := by +theorem computableInPolyTime_low : + ComputableInPolyTime low (encPair encGraph encNat) (encList encNat) := by unfold low fun_prop /-- Testing for an active vertex is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isActive : - ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => isActive p.1 p.2) +theorem computableInPolyTime_isActive : + ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => isActive p.1 p.2) (encPair (encPair encGraph encNat) encNat) encBool := by unfold isActive fun_prop /-- Listing the active vertices is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_active : - ComputableTidilyInPolyTime active (encPair encGraph encNat) (encList encNat) := by +theorem computableInPolyTime_active : + ComputableInPolyTime active (encPair encGraph encNat) (encList encNat) := by unfold active fun_prop /-- The kernel target is computed in unary in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_param : - ComputableTidilyInPolyTime param (encPair encGraph encNat) encUnary := by +theorem computableInPolyTime_param : + ComputableInPolyTime param (encPair encGraph encNat) encUnary := by unfold param fun_prop /-- The number of kernel vertices is computed in unary in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_numVertices : - ComputableTidilyInPolyTime numVertices (encPair encGraph encNat) encUnary := by +theorem computableInPolyTime_numVertices : + ComputableInPolyTime numVertices (encPair encGraph encNat) encUnary := by unfold numVertices fun_prop /-- The tests of the kernel are polynomial-time. The capped target `cap x` is computed in unary and converted to binary to compare it with the binary target. -/ @[fun_prop] -theorem computableTidilyInPolyTime_accept : - ComputableTidilyInPolyTime accept (encPair encGraph encNat) encBool := by +theorem computableInPolyTime_accept : + ComputableInPolyTime accept (encPair encGraph encNat) encBool := by + refine .of_tidy ?_ unfold accept exact bool_and' (bool_and' - ((unary_to_binary.comp computableTidilyInPolyTime_cap).decide_eq' (snd _ _)) (by fun_prop)) + ((unary_to_binary.comp computableInPolyTime_cap.tidy).decide_eq' (snd _ _)) (by fun_prop)) (by fun_prop) /-- Listing the kernel edges is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_edges : - ComputableTidilyInPolyTime edges (encPair encGraph encNat) +theorem computableInPolyTime_edges : + ComputableInPolyTime edges (encPair encGraph encNat) (encList (encPair encNat encNat)) := by unfold edges polytime /-- Building the kernel graph is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_graph : - ComputableTidilyInPolyTime graph (encPair encGraph encNat) encGraph := by +theorem computableInPolyTime_graph : + ComputableInPolyTime graph (encPair encGraph encNat) encGraph := by + refine .of_tidy ?_ have hV : ComputableTidilyInPolyTime (fun x : Graph × ℕ => List.range (numVertices x)) (encPair encGraph encNat) (encList encNat) := by simpa only [Function.comp_def, List.map_id'] using - (map unary_to_binary).comp (range.comp computableTidilyInPolyTime_numVertices) - exact (hV.prod computableTidilyInPolyTime_edges).of_enc_eq fun _ => rfl + (map unary_to_binary).comp (range.comp computableInPolyTime_numVertices.tidy) + exact (hV.prod computableInPolyTime_edges.tidy).of_enc_eq fun _ => rfl end VertexCover.Buss @@ -605,12 +607,13 @@ theorem length_encode_bussKernel_le (x : Graph × ℕ) : /-- **Buss's kernel is polynomial-time.** -/ @[fun_prop] -theorem computableTidilyInPolyTime_bussKernel : - ComputableTidilyInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := by +theorem computableInPolyTime_bussKernel : + ComputableInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := by + refine .of_tidy ?_ unfold bussKernel - exact computableTidilyInPolyTime_accept.cond - (computableTidilyInPolyTime_graph.prod - (ComputableTidilyInPolyTime.unary_to_binary.comp computableTidilyInPolyTime_param)) + exact computableInPolyTime_accept.tidy.cond + (computableInPolyTime_graph.tidy.prod + (ComputableTidilyInPolyTime.unary_to_binary.comp computableInPolyTime_param.tidy)) (ComputableTidilyInPolyTime.const _) /-- Buss's kernel has target at most `k`, or `1`. -/ @@ -625,7 +628,7 @@ size bound `40 (k + 1) ^ 6`. -/ theorem isKernelization_bussKernel : IsKernelization (encPair encGraph encNat) Prod.snd VertexCover bussKernel fun k => 40 * (k + 1) ^ 6 where - polyTime := computableTidilyInPolyTime_bussKernel.computableInPolyTime + polyTime := computableInPolyTime_bussKernel mem_iff := bussKernel_mem_iff length_le := length_encode_bussKernel_le parameter_le x := by diff --git a/Complexity/Computability/Complexity/Problems/CircuitSAT.lean b/Complexity/Computability/Complexity/Problems/CircuitSAT.lean index 498dcf59a..d9096bc2e 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitSAT.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitSAT.lean @@ -103,8 +103,9 @@ private theorem verifier_eq_evalOutput (p : (Σ n, Circuit signature n 1) × Lis attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The `CircuitSAT` verifier is polynomial-time, on certificates of arbitrary length. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair (encCircuit 1) encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encCircuit 1) encBits) encBool := by + refine .of_tidy ?_ have hraw : ComputableTidilyInPolyTime (fun p : (Σ n, Circuit signature n 1) × List Bool => ((p.1.1, p.1.2.code), p.2)) (encPair (encCircuit 1) encBits) (encPair (encPair encUnary encCode) encBits) := @@ -120,7 +121,7 @@ theorem computableTidilyInPolyTime_verifier : /-- **Circuit satisfiability is in `NP`**, with certificates as long as the encoded circuit. -/ theorem mem_NP : CircuitSAT ∈ NP (encCircuit 1) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end CircuitSAT @@ -389,7 +390,7 @@ private theorem computableTidilyInPolyTime_circuitBlock : private theorem computableTidilyInPolyTime_circuitGates : ComputableTidilyInPolyTime circuitGates encCNF (encList encGate) := by have hsteps := computableTidilyInPolyTime_circuitSteps - have hvars := SAT.computableTidilyInPolyTime_vars + have hvars := SAT.computableInPolyTime_vars.tidy have hargs : ComputableTidilyInPolyTime (fun p : CNF ℕ × ((Literal ℕ × Bool) × ℕ) => (((p.1.vars.length + 3 * p.2.2, p.1.vars.idxOf p.2.1.1.1), p.2.1.1.2), p.2.1.2)) (encPair encCNF (encPair (encPair (encPair encNat encBool) encBool) encUnary)) @@ -405,7 +406,7 @@ private theorem computableTidilyInPolyTime_toCircuit : ComputableTidilyInPolyTime toCircuit encCNF (encCircuit 1) := by have hg := computableTidilyInPolyTime_circuitGates have hs := computableTidilyInPolyTime_circuitSteps - have hvars := SAT.computableTidilyInPolyTime_vars + have hvars := SAT.computableInPolyTime_vars.tidy have hn : ComputableTidilyInPolyTime (fun φ : CNF ℕ => φ.vars.length) encCNF encUnary := by fun_prop have hout : ComputableTidilyInPolyTime diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue.lean b/Complexity/Computability/Complexity/Problems/CircuitValue.lean index 611f52312..b8d6b0b15 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue.lean @@ -35,7 +35,7 @@ evaluates the gate list with the polynomial-time evaluator ## Main results -* `Cslib.Complexity.CircuitValue.computableTidilyInPolyTime_eval`: evaluation is polynomial-time. +* `Cslib.Complexity.CircuitValue.computableInPolyTime_eval`: evaluation is polynomial-time. * `Cslib.Complexity.CircuitValue.mem_P`: the circuit value problem is in `P`. ## References @@ -88,14 +88,14 @@ private theorem eval_eq_evalOutput (x : Σ n, Circuit signature n 1 × BitString attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Evaluating a circuit on an input is polynomial-time, on the encoding `encCircuitValue`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_eval : - ComputableTidilyInPolyTime (fun x : Σ n, Circuit signature n 1 × BitString n => +theorem computableInPolyTime_eval : + ComputableInPolyTime (fun x : Σ n, Circuit signature n 1 × BitString n => x.2.1.eval interpretation x.2.2 0) encCircuitValue encBool := by - have hraw : ComputableTidilyInPolyTime + have hraw : ComputableInPolyTime (fun x : Σ n, Circuit signature n 1 × BitString n => ((x.1, x.2.1.code), List.ofFn x.2.2)) encCircuitValue (encPair (encPair encUnary encCode) encBits) := .of_eq fun _ => rfl - have hout : ComputableTidilyInPolyTime + have hout : ComputableInPolyTime (fun r : (ℕ × (List (Op × List ℕ) × List ℕ)) × List Bool => evalOutput r.2 r.1.2.1 (r.1.2.2.headD 0)) (encPair (encPair encUnary encCode) encBits) encBool := by @@ -106,7 +106,7 @@ theorem computableTidilyInPolyTime_eval : /-- **The circuit value problem is in `P`**, for the binary encoding of circuits followed by the input bits. -/ theorem mem_P : CircuitValue ∈ P encCircuitValue := - ⟨_, .of_tidy computableTidilyInPolyTime_eval, fun _ => Iff.rfl⟩ + ⟨_, computableInPolyTime_eval, fun _ => Iff.rfl⟩ end CircuitValue diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean index 7ce11c35a..6667d23c1 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean @@ -137,38 +137,43 @@ widths. One polynomial-time constructor outputs the code for every instance. Out `j`th bit of the function value, defaulting to `false` when that value is shorter than `m a`. -/ theorem exists_uniformCircuitFamily {α : Type} {enc : α ↪ List Bool} {n m : α → ℕ} {F : α × List Bool → List Bool} - (hn : ComputableTidilyInPolyTime n enc encUnary) - (hm : ComputableTidilyInPolyTime m enc encUnary) - (hF : ComputableTidilyInPolyTime F (encPair enc encBits) encBits) : + (hn : ComputableInPolyTime n enc encUnary) + (hm : ComputableInPolyTime m enc encUnary) + (hF : ComputableInPolyTime F (encPair enc encBits) encBits) : ∃ circuits : (a : α) → Circuit signature (n a) (m a), - ComputableTidilyInPolyTime (fun a => (circuits a).code) enc encCode ∧ + ComputableInPolyTime (fun a => (circuits a).code) enc encCode ∧ ∀ a (x : Fin (n a) → Bool) (j : Fin (m a)), (circuits a).eval interpretation x j = (F (a, List.ofFn x)).getD j.val false := by - obtain ⟨bits, hbits, hsize, hsem⟩ := exists_uniformOutputBits hn hm hF - let circuits (a : α) : Circuit signature (n a) (m a) := - Circuit.pi (fun j : Fin (m a) => bits a j.val) - have hzero := hbits.comp ((ComputableTidilyInPolyTime.id' (encIn := enc)).prod - (ComputableTidilyInPolyTime.const 0)) - have hblock : ComputableTidilyInPolyTime (fun a => (bits a 0).size) enc encNat := by - have h := (ComputableInPolyTime.length_list_binary encGate).tidy.comp hzero.fst' - convert h using 1 - funext a - exact (Circuit.length_code_fst (bits a 0)).symm - have hlist := ComputableTidilyInPolyTime.mapWith hbits - (ComputableTidilyInPolyTime.id' (encIn := enc)) - (ComputableTidilyInPolyTime.range.comp hm) - have hlistEq (a : α) : (List.range (m a)).map (fun j => (bits a j).code) = - List.ofFn (fun j : Fin (m a) => (bits a j.val).code) := by - apply List.ext_getElem (by simp) - intro i hi hj - simp - have hcompiled := (computableInPolyTime_bundleCode - (.of_tidy (ComputableTidilyInPolyTime.unary_to_binary.comp hn)) (.of_tidy hblock) (.of_tidy - hlist)).tidy - refine ⟨circuits, hcompiled.of_enc_eq (fun a => ?_), fun a x j => ?_⟩ - · change encCode (circuits a).code = encCode - (bundleCode (n a) (bits a 0).size ((List.range (m a)).map (fun j => (bits a j).code))) - rw [hlistEq, bundleCode_code _ _ (fun j => hsize a j.val j.isLt.le)] - · exact (congrFun (Circuit.eval_pi _ x) j).trans (hsem a j.val x) + have hn := hn.tidy + have hm := hm.tidy + have hF := hF.tidy + have this : ∃ circuits : (a : α) → Circuit signature (n a) (m a), ComputableTidilyInPolyTime (fun a => (circuits a).code) enc encCode ∧ ∀ a (x : Fin (n a) → Bool) (j : Fin (m a)), (circuits a).eval interpretation x j = (F (a, List.ofFn x)).getD j.val false := by + obtain ⟨bits, hbits, hsize, hsem⟩ := exists_uniformOutputBits hn hm hF + let circuits (a : α) : Circuit signature (n a) (m a) := + Circuit.pi (fun j : Fin (m a) => bits a j.val) + have hzero := hbits.comp ((ComputableTidilyInPolyTime.id' (encIn := enc)).prod + (ComputableTidilyInPolyTime.const 0)) + have hblock : ComputableTidilyInPolyTime (fun a => (bits a 0).size) enc encNat := by + have h := (ComputableInPolyTime.length_list_binary encGate).tidy.comp hzero.fst' + convert h using 1 + funext a + exact (Circuit.length_code_fst (bits a 0)).symm + have hlist := ComputableTidilyInPolyTime.mapWith hbits + (ComputableTidilyInPolyTime.id' (encIn := enc)) + (ComputableTidilyInPolyTime.range.comp hm) + have hlistEq (a : α) : (List.range (m a)).map (fun j => (bits a j).code) = + List.ofFn (fun j : Fin (m a) => (bits a j.val).code) := by + apply List.ext_getElem (by simp) + intro i hi hj + simp + have hcompiled := (computableInPolyTime_bundleCode + (.of_tidy (ComputableTidilyInPolyTime.unary_to_binary.comp hn)) (.of_tidy hblock) (.of_tidy + hlist)).tidy + refine ⟨circuits, hcompiled.of_enc_eq (fun a => ?_), fun a x j => ?_⟩ + · change encCode (circuits a).code = encCode + (bundleCode (n a) (bits a 0).size ((List.range (m a)).map (fun j => (bits a j).code))) + rw [hlistEq, bundleCode_code _ _ (fun j => hsize a j.val j.isLt.le)] + · exact (congrFun (Circuit.eval_pi _ x) j).trans (hsem a j.val x) + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this end Cslib.Complexity.CircuitValue diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean index cebbbc008..dc0b598db 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean @@ -15,6 +15,7 @@ public import Complexity.Computability.Complexity.Problems.CircuitValue.Writer import Complexity.Computability.Machines.Turing.MultiTape.Plumbing.Tidy.Run import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # The circuit value problem is `P`-complete @@ -49,7 +50,7 @@ copies the input. * `Cslib.Complexity.CircuitValue.run_writer`: the writer writes the encoded instance. * `Cslib.Complexity.CircuitValue.computableInLogSpace_tableauInstance`: the instances are computable in logarithmic space. -* `Cslib.Complexity.CircuitValue.computableTidilyInPolyTime_tableauCode`: the whole code is +* `Cslib.Complexity.CircuitValue.computableInPolyTime_tableauCode`: the whole code is constructed in polynomial time from the unary input length. * `Cslib.Complexity.CircuitValue.exists_uniformCircuits`: polynomial-time Boolean functions admit polynomial-time circuit constructors, correct on the encoding's image. @@ -177,17 +178,19 @@ variable {α : Type} {encIn : α ↪ List Bool} {Bs : α → ℕ} include hin /-- Evaluating the fixed polynomial tableau time bound preserves a space budget. -/ -theorem timeBound_inSpace {n : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) : - ComputableTidilyInSpace (fun x => timeBound C d (n x)) encIn encNat Bs := - budget_natAdd (budget_natAdd (budget_natMul (budget_const C hin) - (budget_natPow (budget_natAdd hn (budget_const 1 hin)) hin d)) hn) (budget_const 1 hin) +theorem timeBound_inSpace {n : α → ℕ} (hn : ComputableInSpace n encIn encNat Bs) : + ComputableInSpace (fun x => timeBound C d (n x)) encIn encNat Bs := by + have hn := hn.tidy + exact .of_tidy (budget_natAdd (budget_natAdd (budget_natMul (budget_const C hin) + (budget_natPow (budget_natAdd hn (budget_const 1 hin)) hin d)) hn) (budget_const 1 hin)) omit [DecidableEq State] in /-- Computing the tableau gate count preserves a space budget. -/ -theorem numGates_inSpace {T : α → ℕ} (hT : ComputableTidilyInSpace T encIn encNat Bs) : - ComputableTidilyInSpace (fun x => numGates k State (T x)) encIn encNat Bs := - budget_natAdd (budget_const 2 hin) (budget_natMul (budget_natAdd hT (budget_const 1 hin)) - (blockSize_inSpace (k := k) (State := State) (.of_tidy hT) hin).tidy) +theorem numGates_inSpace {T : α → ℕ} (hT : ComputableInSpace T encIn encNat Bs) : + ComputableInSpace (fun x => numGates k State (T x)) encIn encNat Bs := by + have hT := hT.tidy + exact .of_tidy (budget_natAdd (budget_const 2 hin) (budget_natMul (budget_natAdd hT (budget_const 1 hin)) + (blockSize_inSpace (k := k) (State := State) (.of_tidy hT) hin).tidy)) private theorem gateChunk_inSpace {n i : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) (hi : ComputableTidilyInSpace i encIn encNat Bs) : @@ -197,13 +200,13 @@ private theorem gateChunk_inSpace {n i : α → ℕ} (hn : ComputableTidilyInSpa of_inO (.of_linear (.of_frame fun _ => rfl)) exact budget_comp_linear doubled_inSpace (budget_comp_linear doubled_inSpace (budget_comp_linear (g := fun g => frame (encGate g)) hframe - (gateCode_inSpace tm (.of_tidy hn) (.of_tidy (timeBound_inSpace C d hin hn)) hin + (gateCode_inSpace tm (.of_tidy hn) (timeBound_inSpace C d hin (.of_tidy hn)) hin (.of_tidy hi)).tidy)) omit [DecidableEq State] in private theorem trailer_inSpace {n : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) : ComputableTidilyInSpace (fun x => trailer k State C d (n x)) encIn encBits Bs := by - have hT := timeBound_inSpace C d hin hn + have hT := (timeBound_inSpace C d hin (.of_tidy hn)).tidy have ho : ComputableTidilyInSpace (fun x => outWire k State (n x) (timeBound C d (n x))) encIn encNat Bs := budget_natAdd (budget_natAdd (budget_natAdd hn (budget_const 2 hin)) @@ -225,6 +228,8 @@ private theorem trailer_inSpace {n : α → ℕ} (hn : ComputableTidilyInSpace n end Components +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **The instances are computable in logarithmic space**, from the framed input. -/ theorem computableInLogSpace_tableauInstance : ComputableInLogSpace (tableauInstance tm C d) (encFramed encBits) encCircuitValue := by @@ -237,9 +242,9 @@ theorem computableInLogSpace_tableauInstance : have hs := (ComputableTidilyInSpace.fst encWState encBool).weaken hin have hn := fst' (snd' hs) have hi := snd' (snd' hs) - refine (tableauSpec tm C d).computableInLogSpace (tableauSpec_output tm C d) - (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin hn)) - (gateChunk_inSpace tm C d hin hn hi) + refine (tableauSpec tm C d).computableInLogSpace (.of_tidy (tableauSpec_output tm C d)) + (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin (.of_tidy hn))) + (.of_tidy (gateChunk_inSpace tm C d hin hn hi)) (trailer_inSpace (k := k) (State := State) C d hin hn) ?_ change PolynomiallyBounded fun n => numGates k State (timeBound C d n) simp only [numGates, blockSize, colStart, gfStart, globStart, numCols, timeBound] @@ -261,8 +266,9 @@ noncomputable def tableauCode (n : ℕ) : List (Op × List ℕ) × List ℕ := /-- Writing the tableau code takes polynomial time in the unary input length. This reuses the certified logarithmic-space writer and discards its dummy input assignment. -/ -theorem computableTidilyInPolyTime_tableauCode : - ComputableTidilyInPolyTime (tableauCode tm C d) encUnary encCode := by +theorem computableInPolyTime_tableauCode : + ComputableInPolyTime (tableauCode tm C d) encUnary encCode := by + refine .of_tidy ?_ have hwriter := (computableInLogSpace_tableauInstance tm C d).computableTidilyInPolyTime have hcode := ComputableTidilyInPolyTime.dropFrame.comp (ComputableTidilyInPolyTime.unframe.comp hwriter.encoded) @@ -278,26 +284,29 @@ theorem computableTidilyInPolyTime_tableauCode : polynomial time from the unary encoded input length. Correctness is required on the encoding's image; no decoder or efficient membership test for that image is assumed. -/ theorem exists_uniformCircuits {α : Type} {enc : α ↪ List Bool} {f : α → Bool} - (hf : ComputableTidilyInPolyTime f enc encBool) : + (hf : ComputableInPolyTime f enc encBool) : ∃ circuits : (n : ℕ) → Circuit signature n 1, - ComputableTidilyInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ + ComputableInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval interpretation (fun i => (enc a)[i]) 0 = f a := by - obtain ⟨t, s, ht, -, tapes, Control, hfin, machine, hmachine⟩ := hf - have := Fintype.ofFinite Control - classical - obtain ⟨C, d, hbound⟩ := ht.exists_le - refine ⟨fun n => Tableau.circuit machine n (timeBound C d n), - computableTidilyInPolyTime_tableauCode machine C d, fun a => ?_⟩ - rw [Tableau.eval_circuit machine (by simp only [timeBound]; omega)] - have hw : List.ofFn (fun i : Fin (enc a).length => (enc a)[i]) = enc a := List.ofFn_getElem - rw [hw] - obtain ⟨hhalt, hout⟩ := ComputesTidilyInTimeAndSpace.runFrom_initCfg (hmachine a) - have hle : t a ≤ timeBound C d (enc a).length := by - have h := hbound a - dsimp only [timeBound] - omega - rw [MultiTapeTM.runFrom_eq_of_halt machine _ hle hhalt, hout, encBool_apply] - cases f a <;> simp [OutView.ofList] + have hf := hf.tidy + have this : ∃ circuits : (n : ℕ) → Circuit signature n 1, ComputableTidilyInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval interpretation (fun i => (enc a)[i]) 0 = f a := by + obtain ⟨t, s, ht, -, tapes, Control, hfin, machine, hmachine⟩ := hf + have := Fintype.ofFinite Control + classical + obtain ⟨C, d, hbound⟩ := ht.exists_le + refine ⟨fun n => Tableau.circuit machine n (timeBound C d n), + (computableInPolyTime_tableauCode machine C d).tidy, fun a => ?_⟩ + rw [Tableau.eval_circuit machine (by simp only [timeBound]; omega)] + have hw : List.ofFn (fun i : Fin (enc a).length => (enc a)[i]) = enc a := List.ofFn_getElem + rw [hw] + obtain ⟨hhalt, hout⟩ := ComputesTidilyInTimeAndSpace.runFrom_initCfg (hmachine a) + have hle : t a ≤ timeBound C d (enc a).length := by + have h := hbound a + dsimp only [timeBound] + omega + rw [MultiTapeTM.runFrom_eq_of_halt machine _ hle hhalt, hout, encBool_apply] + cases f a <;> simp [OutView.ofList] + simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this end Construction diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean index cd4762a31..1c8e102b3 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean @@ -13,6 +13,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpaceLib import Complexity.Computability.Machines.Turing.MultiTape.Plumbing.Tidy.Run import Complexity.Computability.Machines.Turing.MultiTape.Encodings.NatLength import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # Writing circuits chunk by chunk in logarithmic space @@ -347,14 +348,17 @@ private theorem stateS_le (w : List Bool) {q : (ℕ × ℕ × ℕ) × ℕ} and trailer are computed within the budget of its states. -/ theorem computableInLogSpace {β : Type} {encOut : β ↪ List Bool} {g : List Bool → β} (hg : ∀ w, encOut (g w) = S.output w) - (hN : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.numChunks p.1.2.1) encStepIn + (hN : ComputableInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.numChunks p.1.2.1) encStepIn encNat fun p => wBudget p.1) - (hC : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.chunk p.1.2.1 p.1.2.2) + (hC : ComputableInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.chunk p.1.2.1 p.1.2.2) encStepIn encBits fun p => wBudget p.1) - (hT : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.trailer p.1.2.1) encStepIn + (hT : ComputableInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.trailer p.1.2.1) encStepIn encBits fun p => wBudget p.1) (hpoly : PolynomiallyBounded S.numChunks) : ComputableInLogSpace g (encFramed encBits) encOut := by + have hN : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.numChunks p.1.2.1) encStepIn encNat fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hN + have hC : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.chunk p.1.2.1 p.1.2.2) encStepIn encBits fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hC + have hT : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.trailer p.1.2.1) encStepIn encBits fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hT obtain ⟨T, hT'⟩ := tidy_machine hN hC hT have hc (w : List Bool) : S.machine.toStepMachine.Computes (encFramed encBits w) (encOut (g w)) := by diff --git a/Complexity/Computability/Complexity/Problems/Clique.lean b/Complexity/Computability/Complexity/Problems/Clique.lean index 89a77a322..29a697be2 100644 --- a/Complexity/Computability/Complexity/Problems/Clique.lean +++ b/Complexity/Computability/Complexity/Problems/Clique.lean @@ -149,10 +149,10 @@ theorem isVerifier : /-- The `Clique` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := - Graph.computableTidilyInPolyTime_verifySubset Graph.computableTidilyInPolyTime_adjBool + Graph.computableInPolyTime_verifySubset Graph.computableInPolyTime_adjBool /-- `Clique` belongs to `NP`. -/ theorem mem_NP : Clique ∈ NP (encPair encGraph encNat) := diff --git a/Complexity/Computability/Complexity/Problems/Coloring.lean b/Complexity/Computability/Complexity/Problems/Coloring.lean index 238f34343..b7595e22b 100644 --- a/Complexity/Computability/Complexity/Problems/Coloring.lean +++ b/Complexity/Computability/Complexity/Problems/Coloring.lean @@ -57,7 +57,7 @@ remaining three, so `KColoring k` is `NP`-complete for every `k ≥ 3`. * `Cslib.Complexity.KColoring.isVerifier`, `Cslib.Complexity.KColoring.mem_NP`: `KColoring k ∈ NP encGraph` for every `k`. * `Cslib.Complexity.SAT.toThreeColoring_mem_iff`: `toThreeColoring φ ∈ ThreeColoring ↔ φ ∈ SAT`. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_toThreeColoring`: the reduction is +* `Cslib.Complexity.SAT.computableInPolyTime_toThreeColoring`: the reduction is polynomial-time. * `Cslib.Complexity.polyTimeReducible_SAT_ThreeColoring`, `Cslib.Complexity.polyTimeReducible_ThreeSAT_ThreeColoring`, @@ -155,9 +155,10 @@ theorem isVerifier (k : ℕ) : /-- Reading a color from a certificate is polynomial-time, with the color in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_colorOf (k : ℕ) : - ComputableTidilyInPolyTime (fun p : (List ℕ × List Bool) × ℕ => colorOf k p.1.1 p.1.2 p.2) +theorem computableInPolyTime_colorOf (k : ℕ) : + ComputableInPolyTime (fun p : (List ℕ × List Bool) × ℕ => colorOf k p.1.1 p.1.2 p.2) (encPair (encPair (encList encNat) encBits) encNat) encUnary := by + refine .of_tidy ?_ have hrange : ComputableTidilyInPolyTime (fun _ : (List ℕ × List Bool) × ℕ => List.range k) (encPair (encPair (encList encNat) encBits) encNat) (encList encUnary) := const _ have hk : ComputableTidilyInPolyTime (fun _ : ((List ℕ × List Bool) × ℕ) × ℕ => k) @@ -166,8 +167,9 @@ theorem computableTidilyInPolyTime_colorOf (k : ℕ) : /-- The `KColoring k` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier (k : ℕ) : - ComputableTidilyInPolyTime (verifier k) (encPair encGraph encBits) encBool := by +theorem computableInPolyTime_verifier (k : ℕ) : + ComputableInPolyTime (verifier k) (encPair encGraph encBits) encBool := by + refine .of_tidy ?_ have hV : ComputableTidilyInPolyTime (fun x : Graph × List Bool => x.1.1) (encPair encGraph encBits) (encList encNat) := by unfold encGraph @@ -175,7 +177,7 @@ theorem computableTidilyInPolyTime_verifier (k : ℕ) : have hcol : ComputableTidilyInPolyTime (fun p : (Graph × List Bool) × ℕ => colorOf k p.1.1.1 p.1.2 p.2) (encPair (encPair encGraph encBits) encNat) encUnary := - (computableTidilyInPolyTime_colorOf k).comp + (computableInPolyTime_colorOf k).tidy.comp (g := fun p : (Graph × List Bool) × ℕ => ((p.1.1.1, p.1.2), p.2)) (by unfold encGraph; fun_prop) have hproj : ComputableTidilyInPolyTime @@ -188,12 +190,12 @@ theorem computableTidilyInPolyTime_verifier (k : ℕ) : (encPair (encPair encGraph encBits) encNat) := by fun_prop exact allWithInput hV (bool_and' (unary_lt' hcol (const k)) (allWithInput (hV.comp (fst _ _)) (bool_not.comp - (bool_and' (Graph.computableTidilyInPolyTime_adjBool.comp hproj) + (bool_and' (Graph.computableInPolyTime_adjBool.tidy.comp hproj) ((hcol.comp (fst _ _)).decide_eq' (hcol.comp hproj')))))) /-- `KColoring k` belongs to `NP`. -/ theorem mem_NP (k : ℕ) : KColoring k ∈ NP encGraph := - ⟨_, verifier k, .of_tidy (computableTidilyInPolyTime_verifier k), isVerifier k⟩ + ⟨_, verifier k, (computableInPolyTime_verifier k), isVerifier k⟩ end KColoring @@ -506,8 +508,9 @@ theorem toThreeColoring_mem_iff (φ : CNF ℕ) : toThreeColoring φ ∈ ThreeCol /-- The reduction `toThreeColoring` is computable in polynomial time: vertex labels are computed in unary from clause, position and first-occurrence indices, then converted to binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toThreeColoring : - ComputableTidilyInPolyTime toThreeColoring encCNF encGraph := by +theorem computableInPolyTime_toThreeColoring : + ComputableInPolyTime toThreeColoring encCNF encGraph := by + refine .of_tidy ?_ have hlit : ComputableTidilyInPolyTime (fun p : CNF ℕ × Literal ℕ => literalVertex p.1 p.2) (encPair encCNF (encPair encNat encBool)) encNat := by unfold literalVertex @@ -717,9 +720,10 @@ theorem toKColoring_mem_iff (m : ℕ) (φ : CNF ℕ) : /-- The reduction `toKColoring m` is computable in polynomial time for every fixed `m`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toKColoring (m : ℕ) : - ComputableTidilyInPolyTime (toKColoring m) encCNF encGraph := by - have hG := computableTidilyInPolyTime_toThreeColoring +theorem computableInPolyTime_toKColoring (m : ℕ) : + ComputableInPolyTime (toKColoring m) encCNF encGraph := by + refine .of_tidy ?_ + have hG := computableInPolyTime_toThreeColoring.tidy have hU : ComputableTidilyInPolyTime (fun r => universalVertex r) encUnary encNat := unary_to_binary.comp (show ComputableTidilyInPolyTime (fun r => Nat.pair 3 r) _ _ by fun_prop) @@ -735,7 +739,7 @@ end SAT /-- `SAT` reduces to `ThreeColoring` in polynomial time via `SAT.toThreeColoring`. -/ theorem polyTimeReducible_SAT_ThreeColoring : PolyTimeReducible encCNF encGraph SAT ThreeColoring := - ⟨SAT.toThreeColoring, .of_tidy SAT.computableTidilyInPolyTime_toThreeColoring, + ⟨SAT.toThreeColoring, SAT.computableInPolyTime_toThreeColoring, fun φ => (SAT.toThreeColoring_mem_iff φ).symm⟩ /-- `ThreeSAT` reduces to `ThreeColoring` in polynomial time: a formula with a clause of more than @@ -767,7 +771,7 @@ theorem ThreeColoring_npComplete : NPComplete encGraph ThreeColoring := theorem polyTimeReducible_SAT_KColoring {k : ℕ} (hk : 3 ≤ k) : PolyTimeReducible encCNF encGraph SAT (KColoring k) := by obtain ⟨m, rfl⟩ : ∃ m, k = m + 3 := ⟨k - 3, by omega⟩ - exact ⟨SAT.toKColoring m, .of_tidy (SAT.computableTidilyInPolyTime_toKColoring m), + exact ⟨SAT.toKColoring m, (SAT.computableInPolyTime_toKColoring m), fun φ => (SAT.toKColoring_mem_iff m φ).symm⟩ /-- For `k ≥ 3`, `KColoring k` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/CountingSAT.lean b/Complexity/Computability/Complexity/Problems/CountingSAT.lean index eb715b6a9..8543f956f 100644 --- a/Complexity/Computability/Complexity/Problems/CountingSAT.lean +++ b/Complexity/Computability/Complexity/Problems/CountingSAT.lean @@ -179,12 +179,12 @@ private theorem computableTidilyInPolyTime_two_pow_add {α : Type} (enc : α ↪ /-- The number given with a formula, as a function in `#P`. -/ private theorem snd_mem_SharpP : (Prod.snd : CNF ℕ × ℕ → ℕ) ∈ SharpP (encPair encCNF encNat) := - mem_SharpP_of_polyTime (.snd encCNF encNat) + mem_SharpP_of_polyTime (.of_tidy (.snd encCNF encNat)) /-- The number of satisfying assignments of the formula of a pair, as a function in `#P`. -/ private theorem sharpSAT_fst_mem_SharpP : (fun x : CNF ℕ × ℕ => SharpSAT x.1) ∈ SharpP (encPair encCNF encNat) := - SharpP.comp_mem SharpSAT.mem_SharpP (.fst encCNF encNat) + SharpP.comp_mem SharpSAT.mem_SharpP (.of_tidy (.fst encCNF encNat)) /-- **Counting threshold is `PP`-complete**: whether a formula has at least `m` satisfying assignments, for `m` given in binary. -/ @@ -232,8 +232,8 @@ theorem compl_SharpSATExact_coCeqPComplete : /-- The number of assignments to the occurring variables of a formula, as a function in `#P`. -/ private theorem two_pow_card_vars_mem_SharpP : (fun φ : CNF ℕ => 2 ^ φ.vars.toFinset.card) ∈ SharpP encCNF := - mem_SharpP_of_polyTime (ComputableTidilyInPolyTime.binary_two_pow.comp - SharpSAT.computableTidilyInPolyTime_card_vars) + mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp + SharpSAT.computableInPolyTime_card_vars.tidy)) /-- **`MAJSAT` belongs to `PP`.** -/ theorem MAJSAT_mem_PP : MAJSAT ∈ PP encCNF := by @@ -279,9 +279,10 @@ private theorem computableTidilyInPolyTime_dummyClauses : /-- Padding a formula to a majority instance is computable in polynomial time, with `Q` in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_padMajority : - ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => padMajority p.1 p.2) +theorem computableInPolyTime_padMajority : + ComputableInPolyTime (fun p : CNF ℕ × ℕ => padMajority p.1 p.2) (encPair encCNF encUnary) encCNF := by + refine .of_tidy ?_ have hshift : ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => shiftOdd p.1) (encPair encCNF encUnary) (encList (encList (encPair encNat encBool))) := computableTidilyInPolyTime_shiftOdd.comp (.fst encCNF encUnary) @@ -529,7 +530,7 @@ theorem MAJSAT_ppHard : PolyTimeHard PP encCNF MAJSAT := by (ComputableTidilyInPolyTime.unary_eval q).comp (ComputableTidilyInPolyTime.encoding_length enc) refine ⟨fun a => padMajority (r a) (q.eval (enc a).length), - .of_tidy (computableTidilyInPolyTime_padMajority.comp (hr.tidy.prod hq)), fun a => ?_⟩ + .of_tidy (computableInPolyTime_padMajority.tidy.comp (hr.tidy.prod hq)), fun a => ?_⟩ have h := hfr a simp only [Pi.add_apply] at h rw [hA a, padMajority_mem_MAJSAT_iff, ← h] diff --git a/Complexity/Computability/Complexity/Problems/ExactThreeSAT.lean b/Complexity/Computability/Complexity/Problems/ExactThreeSAT.lean index 5a866d0f7..171bca0eb 100644 --- a/Complexity/Computability/Complexity/Problems/ExactThreeSAT.lean +++ b/Complexity/Computability/Complexity/Problems/ExactThreeSAT.lean @@ -101,8 +101,8 @@ theorem eval_padClause (σ : ℕ → Bool) (c : Clause ℕ) : /-- Padding a clause is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_padClause : - ComputableTidilyInPolyTime padClause (encList (encPair encNat encBool)) +theorem computableInPolyTime_padClause : + ComputableInPolyTime padClause (encList (encPair encNat encBool)) (encList (encPair encNat encBool)) := by unfold padClause fun_prop @@ -123,14 +123,14 @@ theorem isVerifier : IsVerifier encCNF Polynomial.X verifier ExactThreeSAT := by /-- Checking the clause widths and evaluating the formula is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encCNF encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by unfold verifier fun_prop /-- `ExactThreeSAT` belongs to `NP`. -/ theorem mem_NP : ExactThreeSAT ∈ NP encCNF := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end ExactThreeSAT @@ -141,9 +141,9 @@ def toExactThreeSAT (φ : CNF ℕ) : CNF ℕ := φ.map padClause /-- Padding every clause is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toExactThreeSAT : - ComputableTidilyInPolyTime toExactThreeSAT encCNF encCNF := - ComputableTidilyInPolyTime.map computableTidilyInPolyTime_padClause +theorem computableInPolyTime_toExactThreeSAT : + ComputableInPolyTime toExactThreeSAT encCNF encCNF := + .of_tidy (ComputableTidilyInPolyTime.map computableInPolyTime_padClause.tidy) /-- A formula is in `ThreeSAT` exactly when padding its clauses puts it in `ExactThreeSAT`. -/ theorem mem_ExactThreeSAT_toExactThreeSAT_iff (φ : CNF ℕ) : @@ -165,7 +165,7 @@ theorem mem_ExactThreeSAT_toExactThreeSAT_iff (φ : CNF ℕ) : /-- `ThreeSAT` reduces to `ExactThreeSAT` in polynomial time via `toExactThreeSAT`. -/ theorem polyTimeReducible_ThreeSAT_ExactThreeSAT : PolyTimeReducible encCNF encCNF ThreeSAT ExactThreeSAT := - ⟨toExactThreeSAT, .of_tidy computableTidilyInPolyTime_toExactThreeSAT, + ⟨toExactThreeSAT, computableInPolyTime_toExactThreeSAT, fun φ => (mem_ExactThreeSAT_toExactThreeSAT_iff φ).symm⟩ /-- `ExactThreeSAT` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/Graph.lean b/Complexity/Computability/Complexity/Problems/Graph.lean index d5bb22b2b..cc687ed03 100644 --- a/Complexity/Computability/Complexity/Problems/Graph.lean +++ b/Complexity/Computability/Complexity/Problems/Graph.lean @@ -64,14 +64,14 @@ This module holds the tools these problems share: * `Cslib.Complexity.Graph.toSimpleGraph_adj`, `Cslib.Complexity.Graph.induced_adj`, `Cslib.Complexity.Graph.adjBool_eq_true_iff`: adjacency. * `Cslib.Complexity.Graph.isVerifier_verifySubset`, - `Cslib.Complexity.Graph.computableTidilyInPolyTime_verifySubset`: the subset verifier is a + `Cslib.Complexity.Graph.computableInPolyTime_verifySubset`: the subset verifier is a polynomial-time verifier. * `Cslib.Complexity.Graph.length_vertices_le_encGraph`: a graph has no more declared vertices than the length of its encoding. * `Cslib.Complexity.countP_unaryBlocks`: counting the set bits of a block reads its number. * `Cslib.Complexity.Graph.exists_decodeVertexList_eq`, `Cslib.Complexity.Graph.isVerifier_verifyOrdering`, - `Cslib.Complexity.Graph.computableTidilyInPolyTime_verifyOrdering`: the ordering verifier is a + `Cslib.Complexity.Graph.computableInPolyTime_verifyOrdering`: the ordering verifier is a polynomial-time verifier with quadratic certificate length. ## References @@ -165,8 +165,8 @@ theorem natCard_vertexSubtype (G : Graph) : /-- Listing the distinct vertices is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_distinctVertices : - ComputableTidilyInPolyTime distinctVertices encGraph (encList encNat) := by +theorem computableInPolyTime_distinctVertices : + ComputableInPolyTime distinctVertices encGraph (encList encNat) := by unfold distinctVertices encGraph fun_prop @@ -190,8 +190,8 @@ theorem adjBool_eq_false_iff (G : Graph) (u v : ℕ) : /-- Testing adjacency in an encoded graph is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_adjBool : - ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => p.1.1.adjBool p.1.2 p.2) +theorem computableInPolyTime_adjBool : + ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => p.1.1.adjBool p.1.2 p.2) (encPair (encPair encGraph encNat) encNat) encBool := by unfold adjBool encGraph fun_prop @@ -265,13 +265,15 @@ private theorem bool_or' {α : Type} {encA : α ↪ List Bool} {left right : α /-- `verifySubset` is computable in polynomial time whenever the pairwise test `rel` is. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifySubset {rel : Graph → ℕ → ℕ → Bool} - (hrel : ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => rel p.1.1 p.1.2 p.2) +theorem computableInPolyTime_verifySubset {rel : Graph → ℕ → ℕ → Bool} + (hrel : ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => rel p.1.1 p.1.2 p.2) (encPair (encPair encGraph encNat) encNat) encBool) : - ComputableTidilyInPolyTime (verifySubset rel) + ComputableInPolyTime (verifySubset rel) (encPair (encPair encGraph encNat) encBits) encBool := by - refine computableTidilyInPolyTime_subsetVerifier (encγ := encNat) - (by unfold encGraph; fun_prop) (bool_and' ?_ ?_) + have hrel := hrel.tidy + refine .of_tidy ?_ + refine (computableInPolyTime_subsetVerifier (encγ := encNat) + (.of_tidy (by unfold encGraph; fun_prop)) (.of_tidy (bool_and' ?_ ?_))).tidy · exact (((ComputableInPolyTime.length_list_binary encNat).tidy.comp (snd _ _)).decide_eq' (by fun_prop)) · apply allWithInput (snd _ _) @@ -419,11 +421,13 @@ private theorem computableTidilyInPolyTime_enumeratesBool : attribute [local fun_prop] computableTidilyInPolyTime_enumeratesBool +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Decoding a list of vertices from a certificate is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_decodeVertexList : - ComputableTidilyInPolyTime (fun x : List ℕ × List Bool => decodeVertexList x.1 x.2) +theorem computableInPolyTime_decodeVertexList : + ComputableInPolyTime (fun x : List ℕ × List Bool => decodeVertexList x.1 x.2) (encPair (encList encNat) encBits) (encList encNat) := by + refine .of_tidy ?_ have hn : ComputableTidilyInPolyTime (fun x : List ℕ × List Bool => x.1.dedup.length) (encPair (encList encNat) encBits) encUnary := by simp only [← List.card_toFinset, ← length_selectDistinct_replicate] @@ -439,17 +443,20 @@ theorem computableTidilyInPolyTime_decodeVertexList : /-- `verifyOrdering` is polynomial-time whenever the vertex list and the test `check` are. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifyOrdering {α : Type} {enc : α ↪ List Bool} +theorem computableInPolyTime_verifyOrdering {α : Type} {enc : α ↪ List Bool} {V : α → List ℕ} {check : α → List ℕ → Bool} - (hV : ComputableTidilyInPolyTime V enc (encList encNat)) - (hcheck : ComputableTidilyInPolyTime (fun q : α × List ℕ => check q.1 q.2) + (hV : ComputableInPolyTime V enc (encList encNat)) + (hcheck : ComputableInPolyTime (fun q : α × List ℕ => check q.1 q.2) (encPair enc (encList encNat)) encBool) : - ComputableTidilyInPolyTime (verifyOrdering V check) (encPair enc encBits) encBool := by + ComputableInPolyTime (verifyOrdering V check) (encPair enc encBits) encBool := by + have hV := hV.tidy + have hcheck := hcheck.tidy + refine .of_tidy ?_ have hV' : ComputableTidilyInPolyTime (fun x : α × List Bool => V x.1) (encPair enc encBits) (encList encNat) := hV.comp (fst _ _) have hp : ComputableTidilyInPolyTime (fun x : α × List Bool => decodeVertexList (V x.1) x.2) (encPair enc encBits) (encList encNat) := - computableTidilyInPolyTime_decodeVertexList.comp (hV'.prod (snd _ _)) + computableInPolyTime_decodeVertexList.tidy.comp (hV'.prod (snd _ _)) exact (computableTidilyInPolyTime_enumeratesBool.comp (hV'.prod hp)).bool_and' (hcheck.comp ((fst _ _).prod hp)) diff --git a/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean b/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean index c66bb570a..c8deada5b 100644 --- a/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean +++ b/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.Complexity.Problems.Graph import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Graph isomorphism @@ -69,13 +70,17 @@ private theorem induced_adj_vertexEquiv (G : Graph) (i j : Fin G.distinctVertice /-- Adjacency of computed positions in a computed graph is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_adjIndex {γ : Type} {input : γ ↪ List Bool} {G : γ → Graph} - {i j : γ → ℕ} (hG : ComputableTidilyInPolyTime G input encGraph) - (hi : ComputableTidilyInPolyTime i input encUnary) - (hj : ComputableTidilyInPolyTime j input encUnary) : - ComputableTidilyInPolyTime (fun x => (G x).adjIndex (i x) (j x)) input encBool := by - have hV := computableTidilyInPolyTime_distinctVertices.comp hG - exact computableTidilyInPolyTime_adjBool.comp ((hG.prod +theorem computableInPolyTime_adjIndex {γ : Type} {input : γ ↪ List Bool} {G : γ → Graph} + {i j : γ → ℕ} (hG : ComputableInPolyTime G input encGraph) + (hi : ComputableInPolyTime i input encUnary) + (hj : ComputableInPolyTime j input encUnary) : + ComputableInPolyTime (fun x => (G x).adjIndex (i x) (j x)) input encBool := by + have hG := hG.tidy + have hi := hi.tidy + have hj := hj.tidy + refine .of_tidy ?_ + have hV := computableInPolyTime_distinctVertices.tidy.comp hG + exact computableInPolyTime_adjBool.tidy.comp ((hG.prod ((listGetD (encA := encNat) 0).comp (hV.prod hi))).prod ((listGetD (encA := encNat) 0).comp (hV.prod hj))) @@ -139,23 +144,25 @@ def verifier : (Graph × Graph) × List Bool → Bool := (List.range x.1.distinctVertices.length).all fun j => x.2.adjBool (p.getD i 0) (p.getD j 0) == x.1.adjIndex i j +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair (encPair encGraph encGraph) encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph encGraph) encBits) encBool := by + refine .of_tidy ?_ have hadj : ∀ {γ : Type} {enc : γ ↪ List Bool} {H : γ → Graph} {u v : γ → ℕ}, ComputableTidilyInPolyTime H enc encGraph → ComputableTidilyInPolyTime u enc encNat → ComputableTidilyInPolyTime v enc encNat → ComputableTidilyInPolyTime (fun x => (H x).adjBool (u x) (v x)) enc encBool := - fun hH hu hv => Graph.computableTidilyInPolyTime_adjBool.comp ((hH.prod hu).prod hv) - refine Graph.computableTidilyInPolyTime_verifyOrdering (by unfold encGraph; fun_prop) - (bool_and' + fun hH hu hv => Graph.computableInPolyTime_adjBool.tidy.comp ((hH.prod hu).prod hv) + refine (Graph.computableInPolyTime_verifyOrdering (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (bool_and' (((length_list encNat).comp (snd _ _)).decide_eq' - ((length_list encNat).comp (by fun_prop))) ?_) + ((length_list encNat).comp (by fun_prop))) ?_))).tidy refine allWithInput (by fun_prop) (allWithInput (by fun_prop) ?_) exact bool_beq.comp ((hadj (by fun_prop) (by fun_prop) (by fun_prop)).prod - (Graph.computableTidilyInPolyTime_adjIndex (by fun_prop) (by fun_prop) (by fun_prop))) + (Graph.computableInPolyTime_adjIndex (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop))).tidy) /-- `verifier` is a verifier for `GraphIsomorphism` with certificates whose length is the square of the length of the encoded pair of graphs. -/ @@ -207,9 +214,11 @@ theorem isVerifier : fun x p => ?_ simp only [Bool.and_eq_true, decide_eq_true_eq, List.all_eq_true, List.mem_range, beq_iff_eq] +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`GraphIsomorphism ∈ NP`.** -/ theorem mem_NP : GraphIsomorphism ∈ NP (encPair encGraph encGraph) := - ⟨Polynomial.X ^ 2, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X ^ 2, verifier, computableInPolyTime_verifier, isVerifier⟩ end GraphIsomorphism diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian.lean index 666499500..2ed5e15f4 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian.lean @@ -14,6 +14,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Bi import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Hamiltonian paths and cycles @@ -344,8 +345,8 @@ theorem arcBool_eq_true_iff (G : Graph) (u v : ℕ) : G.arcBool u v = true ↔ ( /-- Testing for an arc in an encoded graph is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_arcBool : - ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => p.1.1.arcBool p.1.2 p.2) +theorem computableInPolyTime_arcBool : + ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => p.1.1.arcBool p.1.2 p.2) (encPair (encPair encGraph encNat) encNat) encBool := by unfold arcBool encGraph fun_prop @@ -409,12 +410,15 @@ theorem cycleChainBool_eq_true_iff {r : ℕ → ℕ → Bool} {R : ℕ → ℕ /-- Testing whether `r` holds between consecutive entries of a computed list is polynomial-time, for an input-dependent polynomial-time test `r`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_chainBool {γ : Type} {encIn : γ ↪ List Bool} +theorem computableInPolyTime_chainBool {γ : Type} {encIn : γ ↪ List Bool} {r : γ → ℕ → ℕ → Bool} {p : γ → List ℕ} - (hr : ComputableTidilyInPolyTime (fun q : (γ × ℕ) × ℕ => r q.1.1 q.1.2 q.2) + (hr : ComputableInPolyTime (fun q : (γ × ℕ) × ℕ => r q.1.1 q.1.2 q.2) (encPair (encPair encIn encNat) encNat) encBool) - (hp : ComputableTidilyInPolyTime p encIn (encList encNat)) : - ComputableTidilyInPolyTime (fun x => chainBool (r x) (p x)) encIn encBool := by + (hp : ComputableInPolyTime p encIn (encList encNat)) : + ComputableInPolyTime (fun x => chainBool (r x) (p x)) encIn encBool := by + have hr := hr.tidy + have hp := hp.tidy + refine .of_tidy ?_ have hget : ∀ {i : γ × ℕ → ℕ}, ComputableTidilyInPolyTime i (encPair encIn encUnary) encUnary → ComputableTidilyInPolyTime (fun q => (p q.1).getD (i q) 0) (encPair encIn encUnary) encNat := fun hi => (listGetD 0).comp ((hp.comp (fst _ _)).prod hi) @@ -425,12 +429,15 @@ theorem computableTidilyInPolyTime_chainBool {γ : Type} {encIn : γ ↪ List Bo /-- Testing whether `r` holds between cyclically consecutive entries of a computed list is polynomial-time, for an input-dependent polynomial-time test `r`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_cycleChainBool {γ : Type} {encIn : γ ↪ List Bool} +theorem computableInPolyTime_cycleChainBool {γ : Type} {encIn : γ ↪ List Bool} {r : γ → ℕ → ℕ → Bool} {p : γ → List ℕ} - (hr : ComputableTidilyInPolyTime (fun q : (γ × ℕ) × ℕ => r q.1.1 q.1.2 q.2) + (hr : ComputableInPolyTime (fun q : (γ × ℕ) × ℕ => r q.1.1 q.1.2 q.2) (encPair (encPair encIn encNat) encNat) encBool) - (hp : ComputableTidilyInPolyTime p encIn (encList encNat)) : - ComputableTidilyInPolyTime (fun x => cycleChainBool (r x) (p x)) encIn encBool := by + (hp : ComputableInPolyTime p encIn (encList encNat)) : + ComputableInPolyTime (fun x => cycleChainBool (r x) (p x)) encIn encBool := by + have hr := hr.tidy + have hp := hp.tidy + refine .of_tidy ?_ have hget : ∀ {i : γ × ℕ → ℕ}, ComputableTidilyInPolyTime i (encPair encIn encUnary) encUnary → ComputableTidilyInPolyTime (fun q => (p q.1).getD (i q) 0) (encPair encIn encUnary) encNat := fun hi => (listGetD 0).comp ((hp.comp (fst _ _)).prod hi) @@ -453,6 +460,8 @@ private theorem length_vertices_le_encPath (x : Graph × ℕ × ℕ) : simp only [length_encPair] omega +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The endpoint and edge checks of the path verifiers are polynomial-time for a polynomial-time edge test `r`. -/ private theorem computableTidilyInPolyTime_pathCheck {r : Graph → ℕ → ℕ → Bool} @@ -480,8 +489,10 @@ private theorem computableTidilyInPolyTime_pathCheck {r : Graph → ℕ → ℕ simp only [← List.head?_reverse] exact bool_and' (bool_and' (((head? encNat).comp hp).decide_eq' hs) (((head? encNat).comp ((listReverse encNat).comp hp)).decide_eq' ht)) - (Graph.computableTidilyInPolyTime_chainBool (hr.comp hproj) hp) + (Graph.computableInPolyTime_chainBool (.of_tidy (hr.comp hproj)) (.of_tidy hp)).tidy +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The cyclic edge check of the cycle verifiers is polynomial-time for a polynomial-time edge test `r`. -/ private theorem computableTidilyInPolyTime_cycleCheck {r : Graph → ℕ → ℕ → Bool} @@ -494,7 +505,7 @@ private theorem computableTidilyInPolyTime_cycleCheck {r : Graph → ℕ → ℕ (encPair (encPair (encPair encGraph (encList encNat)) encNat) encNat) (encPair (encPair encGraph encNat) encNat) := by fun_prop - exact Graph.computableTidilyInPolyTime_cycleChainBool (hr.comp hproj) (snd _ _) + exact (Graph.computableInPolyTime_cycleChainBool (.of_tidy (hr.comp hproj)) (.of_tidy (snd _ _))).tidy namespace DirHamPath @@ -519,15 +530,15 @@ theorem isVerifier : /-- The `DirHamPath` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph (encPair encNat encNat)) encBits) encBool := - Graph.computableTidilyInPolyTime_verifyOrdering (by unfold encGraph; fun_prop) - (computableTidilyInPolyTime_pathCheck Graph.computableTidilyInPolyTime_arcBool) + (Graph.computableInPolyTime_verifyOrdering (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (computableTidilyInPolyTime_pathCheck Graph.computableInPolyTime_arcBool.tidy))) /-- `DirHamPath` belongs to `NP`. -/ theorem mem_NP : DirHamPath ∈ NP (encPair encGraph (encPair encNat encNat)) := - ⟨_, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨_, verifier, computableInPolyTime_verifier, isVerifier⟩ end DirHamPath @@ -551,15 +562,15 @@ theorem isVerifier : IsVerifier encGraph (Polynomial.X ^ 2) verifier DirHamCycle /-- The `DirHamCycle` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encGraph encBits) encBool := - Graph.computableTidilyInPolyTime_verifyOrdering (by unfold encGraph; fun_prop) - (bool_and' (by fun_prop) (computableTidilyInPolyTime_cycleCheck - Graph.computableTidilyInPolyTime_arcBool)) +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encGraph encBits) encBool := + (Graph.computableInPolyTime_verifyOrdering (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (bool_and' (by fun_prop) (computableTidilyInPolyTime_cycleCheck + Graph.computableInPolyTime_arcBool.tidy)))) /-- `DirHamCycle` belongs to `NP`. -/ theorem mem_NP : DirHamCycle ∈ NP encGraph := - ⟨_, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨_, verifier, computableInPolyTime_verifier, isVerifier⟩ end DirHamCycle @@ -588,15 +599,15 @@ theorem isVerifier : /-- The `HamPath` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph (encPair encNat encNat)) encBits) encBool := - Graph.computableTidilyInPolyTime_verifyOrdering (by unfold encGraph; fun_prop) - (computableTidilyInPolyTime_pathCheck Graph.computableTidilyInPolyTime_adjBool) + (Graph.computableInPolyTime_verifyOrdering (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (computableTidilyInPolyTime_pathCheck Graph.computableInPolyTime_adjBool.tidy))) /-- `HamPath` belongs to `NP`. -/ theorem mem_NP : HamPath ∈ NP (encPair encGraph (encPair encNat encNat)) := - ⟨_, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨_, verifier, computableInPolyTime_verifier, isVerifier⟩ end HamPath @@ -622,15 +633,15 @@ theorem isVerifier : IsVerifier encGraph (Polynomial.X ^ 2) verifier HamCycle := /-- The `HamCycle` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encGraph encBits) encBool := - Graph.computableTidilyInPolyTime_verifyOrdering (by unfold encGraph; fun_prop) - (bool_and' (by fun_prop) (computableTidilyInPolyTime_cycleCheck - Graph.computableTidilyInPolyTime_adjBool)) +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encGraph encBits) encBool := + (Graph.computableInPolyTime_verifyOrdering (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (bool_and' (by fun_prop) (computableTidilyInPolyTime_cycleCheck + Graph.computableInPolyTime_adjBool.tidy)))) /-- `HamCycle` belongs to `NP`. -/ theorem mem_NP : HamCycle ∈ NP encGraph := - ⟨_, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨_, verifier, computableInPolyTime_verifier, isVerifier⟩ end HamCycle diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean index 3fb2aeba3..fdbf89a06 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean @@ -57,8 +57,8 @@ polynomial-time computability. directions of its rows satisfying every clause. * `Cslib.Complexity.Diamond.mem_DirHamCycle_iff`: Hamiltonian cycles of a closed diamond graph likewise. -* `Cslib.Complexity.Diamond.computableTidilyInPolyTime_graph`, - `Cslib.Complexity.Diamond.computableTidilyInPolyTime_cycleGraph`: diamond graphs are computable +* `Cslib.Complexity.Diamond.computableInPolyTime_graph`, + `Cslib.Complexity.Diamond.computableInPolyTime_cycleGraph`: diamond graphs are computable in polynomial time from layouts computable in polynomial time. ## References @@ -557,45 +557,45 @@ abbrev encDetour : Detour ↪ List Bool := /-- The top nodes are computable in polynomial time from unary indices. -/ @[fun_prop] -theorem computableTidilyInPolyTime_topNode : - ComputableTidilyInPolyTime (fun i => topNode i) encUnary encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime (fun i => Nat.pair 0 i) _ _ by fun_prop) +theorem computableInPolyTime_topNode : + ComputableInPolyTime (fun i => topNode i) encUnary encNat := + .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun i => Nat.pair 0 i) _ _ by fun_prop)) /-- The row nodes are computable in polynomial time from unary indices. -/ @[fun_prop] -theorem computableTidilyInPolyTime_rowNode : - ComputableTidilyInPolyTime (fun p : ℕ × ℕ => rowNode p.1 p.2) (encPair encUnary encUnary) +theorem computableInPolyTime_rowNode : + ComputableInPolyTime (fun p : ℕ × ℕ => rowNode p.1 p.2) (encPair encUnary encUnary) encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime - (fun p : ℕ × ℕ => Nat.pair 1 (Nat.pair p.1 p.2)) _ _ by fun_prop) + .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime + (fun p : ℕ × ℕ => Nat.pair 1 (Nat.pair p.1 p.2)) _ _ by fun_prop)) /-- The clause nodes are computable in polynomial time from unary indices. -/ @[fun_prop] -theorem computableTidilyInPolyTime_clauseNode : - ComputableTidilyInPolyTime (fun j => clauseNode j) encUnary encNat := - unary_to_binary.comp (show ComputableTidilyInPolyTime (fun j => Nat.pair 2 j) _ _ by fun_prop) +theorem computableInPolyTime_clauseNode : + ComputableInPolyTime (fun j => clauseNode j) encUnary encNat := + .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun j => Nat.pair 2 j) _ _ by fun_prop)) /-- A diamond graph is computable in polynomial time from a layout computable in polynomial time, with the numbers of diamonds, slots and clauses in unary. -/ -theorem computableTidilyInPolyTime_graph {α : Type} {encIn : α ↪ List Bool} {N M : α → ℕ} - {slots : α → ℕ → ℕ} {D : α → List Detour} (hN : ComputableTidilyInPolyTime N encIn encUnary) - (hslots : ComputableTidilyInPolyTime (fun p : α × ℕ => slots p.1 p.2) +theorem computableInPolyTime_graph {α : Type} {encIn : α ↪ List Bool} {N M : α → ℕ} + {slots : α → ℕ → ℕ} {D : α → List Detour} (hN : ComputableInPolyTime N encIn encUnary) + (hslots : ComputableInPolyTime (fun p : α × ℕ => slots p.1 p.2) (encPair encIn encUnary) encUnary) - (hM : ComputableTidilyInPolyTime M encIn encUnary) - (hD : ComputableTidilyInPolyTime D encIn (encList encDetour)) : - ComputableTidilyInPolyTime (fun a => graph (N a) (slots a) (M a) (D a)) encIn encGraph := by + (hM : ComputableInPolyTime M encIn encUnary) + (hD : ComputableInPolyTime D encIn (encList encDetour)) : + ComputableInPolyTime (fun a => graph (N a) (slots a) (M a) (D a)) encIn encGraph := by unfold graph vertices arcs diamondArcs detourArcs rowLength encGraph fun_prop /-- A closed diamond graph is computable in polynomial time from a layout computable in polynomial time, with the numbers of diamonds, slots and clauses in unary. -/ -theorem computableTidilyInPolyTime_cycleGraph {α : Type} {encIn : α ↪ List Bool} {N M : α → ℕ} - {slots : α → ℕ → ℕ} {D : α → List Detour} (hN : ComputableTidilyInPolyTime N encIn encUnary) - (hslots : ComputableTidilyInPolyTime (fun p : α × ℕ => slots p.1 p.2) +theorem computableInPolyTime_cycleGraph {α : Type} {encIn : α ↪ List Bool} {N M : α → ℕ} + {slots : α → ℕ → ℕ} {D : α → List Detour} (hN : ComputableInPolyTime N encIn encUnary) + (hslots : ComputableInPolyTime (fun p : α × ℕ => slots p.1 p.2) (encPair encIn encUnary) encUnary) - (hM : ComputableTidilyInPolyTime M encIn encUnary) - (hD : ComputableTidilyInPolyTime D encIn (encList encDetour)) : - ComputableTidilyInPolyTime (fun a => cycleGraph (N a) (slots a) (M a) (D a)) encIn + (hM : ComputableInPolyTime M encIn encUnary) + (hD : ComputableInPolyTime D encIn (encList encDetour)) : + ComputableInPolyTime (fun a => cycleGraph (N a) (slots a) (M a) (D a)) encIn encGraph := by unfold cycleGraph vertices arcs diamondArcs detourArcs rowLength encGraph fun_prop diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean index 83ce0ca00..1164efd53 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean @@ -53,8 +53,8 @@ vertex that no arc enters. The top of the first diamond is such a vertex * `Cslib.Complexity.SAT.toDirHamPath_eq`: the graph as a diamond graph. * `Cslib.Complexity.SAT.toDirHamPath_mem_iff`: `toDirHamPath φ ∈ DirHamPath ↔ φ ∈ SAT`. * `Cslib.Complexity.SAT.toDirHamCycle_mem_iff`: `toDirHamCycle φ ∈ DirHamCycle ↔ φ ∈ SAT`. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_toDirHamPath`, - `Cslib.Complexity.SAT.computableTidilyInPolyTime_toDirHamCycle`: the reductions are +* `Cslib.Complexity.SAT.computableInPolyTime_toDirHamPath`, + `Cslib.Complexity.SAT.computableInPolyTime_toDirHamCycle`: the reductions are polynomial-time. * `Cslib.Complexity.polyTimeReducible_SAT_DirHamPath`, `Cslib.Complexity.polyTimeReducible_ThreeSAT_DirHamPath`, `Cslib.Complexity.DirHamPath_npHard`, @@ -184,24 +184,24 @@ namespace SAT /-- The detours of the diamond graph are computable in polynomial time. -/ private theorem computableTidilyInPolyTime_diamondDetours : ComputableTidilyInPolyTime diamondDetours encCNF (encList Diamond.encDetour) := by - have hvars := computableTidilyInPolyTime_vars + have hvars := computableInPolyTime_vars.tidy unfold diamondDetours fun_prop /-- The diamond graph is computable in polynomial time: node labels are computed in unary from diamond, row, clause and first-occurrence indices, then converted to binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_diamondGraph : - ComputableTidilyInPolyTime diamondGraph encCNF encGraph := - Diamond.computableTidilyInPolyTime_graph - ((length_list encNat).comp computableTidilyInPolyTime_vars) - ((length_list _).comp (fst _ _)) (length_list _) computableTidilyInPolyTime_diamondDetours +theorem computableInPolyTime_diamondGraph : + ComputableInPolyTime diamondGraph encCNF encGraph := + (Diamond.computableInPolyTime_graph + (.of_tidy ((length_list encNat).comp computableInPolyTime_vars.tidy)) + (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) (.of_tidy computableTidilyInPolyTime_diamondDetours)) /-- The reduction `toDirHamPath` is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toDirHamPath : - ComputableTidilyInPolyTime toDirHamPath encCNF (encPair encGraph (encPair encNat encNat)) := by - have hvars := computableTidilyInPolyTime_vars +theorem computableInPolyTime_toDirHamPath : + ComputableInPolyTime toDirHamPath encCNF (encPair encGraph (encPair encNat encNat)) := by + have hvars := computableInPolyTime_vars unfold toDirHamPath fun_prop @@ -213,18 +213,18 @@ theorem toDirHamCycle_mem_iff (φ : CNF ℕ) : toDirHamCycle φ ∈ DirHamCycle /-- The closed diamond graph is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toDirHamCycle : - ComputableTidilyInPolyTime toDirHamCycle encCNF encGraph := - Diamond.computableTidilyInPolyTime_cycleGraph - ((length_list encNat).comp computableTidilyInPolyTime_vars) - ((length_list _).comp (fst _ _)) (length_list _) computableTidilyInPolyTime_diamondDetours +theorem computableInPolyTime_toDirHamCycle : + ComputableInPolyTime toDirHamCycle encCNF encGraph := + (Diamond.computableInPolyTime_cycleGraph + (.of_tidy ((length_list encNat).comp computableInPolyTime_vars.tidy)) + (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) (.of_tidy computableTidilyInPolyTime_diamondDetours)) end SAT /-- `SAT` reduces to `DirHamPath` in polynomial time via `SAT.toDirHamPath`. -/ theorem polyTimeReducible_SAT_DirHamPath : PolyTimeReducible encCNF (encPair encGraph (encPair encNat encNat)) SAT DirHamPath := - ⟨SAT.toDirHamPath, .of_tidy SAT.computableTidilyInPolyTime_toDirHamPath, + ⟨SAT.toDirHamPath, SAT.computableInPolyTime_toDirHamPath, fun φ => (SAT.toDirHamPath_mem_iff φ).symm⟩ /-- `ThreeSAT` reduces to `DirHamPath` in polynomial time: a formula with a clause of more than @@ -250,7 +250,7 @@ theorem DirHamPath_npHard : NPHard (encPair encGraph (encPair encNat encNat)) Di /-- `SAT` reduces to `DirHamCycle` in polynomial time via `SAT.toDirHamCycle`. -/ theorem polyTimeReducible_SAT_DirHamCycle : PolyTimeReducible encCNF encGraph SAT DirHamCycle := - ⟨SAT.toDirHamCycle, .of_tidy SAT.computableTidilyInPolyTime_toDirHamCycle, + ⟨SAT.toDirHamCycle, SAT.computableInPolyTime_toDirHamCycle, fun φ => (SAT.toDirHamCycle_mem_iff φ).symm⟩ /-- `DirHamCycle` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean index d891064f2..4e868edf0 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean @@ -53,9 +53,9 @@ every vertex into three (`Cslib.Complexity.Graph.split`) gives undirected Hamilt * `Cslib.Complexity.SAT.toSparseDirHamPath_mem_iff`, `Cslib.Complexity.SAT.toSparseDirHamCycle_mem_iff`, `Cslib.Complexity.SAT.toSparseHamCycle_mem_iff`: correctness. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseDirHamPath`, - `Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseDirHamCycle`, - `Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseHamCycle`: the reductions are +* `Cslib.Complexity.SAT.computableInPolyTime_toSparseDirHamPath`, + `Cslib.Complexity.SAT.computableInPolyTime_toSparseDirHamCycle`, + `Cslib.Complexity.SAT.computableInPolyTime_toSparseHamCycle`: the reductions are polynomial-time. * `Cslib.Complexity.SAT.length_sparseDiamondGraph_le_length_vars`, `Cslib.Complexity.SAT.length_sparseDiamondGraph_le`, @@ -288,10 +288,11 @@ theorem length_toSparseHamCycle_le {k : ℕ} {φ : CNF ℕ} (hφ : ∀ c ∈ φ, /-! ### Polynomial-time reductions -/ /-- The positions of the occurrences of a variable are computable in polynomial time. -/ -theorem computableTidilyInPolyTime_occurrencePositions : - ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => occurrencePositions p.1 p.2) +theorem computableInPolyTime_occurrencePositions : + ComputableInPolyTime (fun p : CNF ℕ × ℕ => occurrencePositions p.1 p.2) (encPair encCNF encNat) (encList encUnary) := by - have hvars := computableTidilyInPolyTime_vars + refine .of_tidy ?_ + have hvars := computableInPolyTime_vars.tidy have htest : ComputableTidilyInPolyTime (fun p : (CNF ℕ × ℕ) × ℕ => decide (p.1.1.vars.getD p.2 0 = p.1.2)) (encPair (encPair encCNF encNat) encUnary) encBool := by @@ -307,19 +308,21 @@ theorem computableTidilyInPolyTime_occurrencePositions : exact filterWithInput hrange htest /-- The numbers of slots are computable in polynomial time, in unary. -/ -theorem computableTidilyInPolyTime_sparseSlots : - ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => sparseSlots p.1 p.2) +theorem computableInPolyTime_sparseSlots : + ComputableInPolyTime (fun p : CNF ℕ × ℕ => sparseSlots p.1 p.2) (encPair encCNF encUnary) encUnary := by + refine .of_tidy ?_ have hdv := computableInPolyTime_distinctVars.tidy - have hpos := computableTidilyInPolyTime_occurrencePositions + have hpos := computableInPolyTime_occurrencePositions.tidy unfold sparseSlots fun_prop /-- The detours are computable in polynomial time. -/ -theorem computableTidilyInPolyTime_sparseDetours : - ComputableTidilyInPolyTime sparseDetours encCNF (encList encDetour) := by +theorem computableInPolyTime_sparseDetours : + ComputableInPolyTime sparseDetours encCNF (encList encDetour) := by + refine .of_tidy ?_ have hdv := computableInPolyTime_distinctVars.tidy - have hpos := computableTidilyInPolyTime_occurrencePositions + have hpos := computableInPolyTime_occurrencePositions.tidy have hocc := computableInPolyTime_occurrences.tidy unfold encOccurrence Cslib.Logic.PL.encOccurrence at hocc unfold sparseDetours @@ -333,32 +336,33 @@ private theorem computableTidilyInPolyTime_numDiamonds : /-- The sparse diamond graph is computable in polynomial time: node labels are computed in unary from diamond, row, clause and occurrence indices, then converted to binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_sparseDiamondGraph : - ComputableTidilyInPolyTime sparseDiamondGraph encCNF encGraph := - computableTidilyInPolyTime_graph computableTidilyInPolyTime_numDiamonds - computableTidilyInPolyTime_sparseSlots (length_list _) computableTidilyInPolyTime_sparseDetours +theorem computableInPolyTime_sparseDiamondGraph : + ComputableInPolyTime sparseDiamondGraph encCNF encGraph := + (computableInPolyTime_graph (.of_tidy computableTidilyInPolyTime_numDiamonds) + computableInPolyTime_sparseSlots (.of_tidy (length_list _)) computableInPolyTime_sparseDetours) /-- The reduction `toSparseDirHamPath` is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toSparseDirHamPath : - ComputableTidilyInPolyTime toSparseDirHamPath encCNF +theorem computableInPolyTime_toSparseDirHamPath : + ComputableInPolyTime toSparseDirHamPath encCNF (encPair encGraph (encPair encNat encNat)) := by + refine .of_tidy ?_ have hn := computableTidilyInPolyTime_numDiamonds unfold toSparseDirHamPath fun_prop /-- The reduction `toSparseDirHamCycle` is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toSparseDirHamCycle : - ComputableTidilyInPolyTime toSparseDirHamCycle encCNF encGraph := - computableTidilyInPolyTime_cycleGraph computableTidilyInPolyTime_numDiamonds - computableTidilyInPolyTime_sparseSlots (length_list _) computableTidilyInPolyTime_sparseDetours +theorem computableInPolyTime_toSparseDirHamCycle : + ComputableInPolyTime toSparseDirHamCycle encCNF encGraph := + (computableInPolyTime_cycleGraph (.of_tidy computableTidilyInPolyTime_numDiamonds) + computableInPolyTime_sparseSlots (.of_tidy (length_list _)) computableInPolyTime_sparseDetours) /-- The reduction `toSparseHamCycle` is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toSparseHamCycle : - ComputableTidilyInPolyTime toSparseHamCycle encCNF encGraph := - Graph.computableTidilyInPolyTime_split.comp computableTidilyInPolyTime_toSparseDirHamCycle +theorem computableInPolyTime_toSparseHamCycle : + ComputableInPolyTime toSparseHamCycle encCNF encGraph := + Graph.computableInPolyTime_split.comp computableInPolyTime_toSparseDirHamCycle end SAT diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean index 2400b4acd..764be71ec 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean @@ -45,8 +45,8 @@ becomes a triangle. `Cslib.Complexity.DirHamPath.toHamPath_mem_iff`: `(G.split, G.splitVertex s 0, G.splitVertex t 2) ∈ HamPath ↔ (G, s, t) ∈ DirHamPath`. * `Cslib.Complexity.Graph.split_mem_HamCycle_iff`: `G.split ∈ HamCycle ↔ G ∈ DirHamCycle`. -* `Cslib.Complexity.Graph.computableTidilyInPolyTime_split`, - `Cslib.Complexity.DirHamPath.computableTidilyInPolyTime_toHamPath`: both reductions are +* `Cslib.Complexity.Graph.computableInPolyTime_split`, + `Cslib.Complexity.DirHamPath.computableInPolyTime_toHamPath`: both reductions are polynomial-time. * `Cslib.Complexity.polyTimeReducible_DirHamPath_HamPath`, `Cslib.Complexity.polyTimeReducible_DirHamCycle_HamCycle`. @@ -541,7 +541,8 @@ private theorem computableTidilyInPolyTime_splitVertex : /-- Splitting the vertices of a graph is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_split : ComputableTidilyInPolyTime split encGraph encGraph := by +theorem computableInPolyTime_split : ComputableInPolyTime split encGraph encGraph := by + refine .of_tidy ?_ have hsv := computableTidilyInPolyTime_splitVertex unfold split unfold encGraph at hsv ⊢ @@ -562,9 +563,10 @@ theorem toHamPath_mem_iff (x : Graph × ℕ × ℕ) : toHamPath x ∈ HamPath /-- The reduction `DirHamPath.toHamPath` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toHamPath : - ComputableTidilyInPolyTime toHamPath (encPair encGraph (encPair encNat encNat)) +theorem computableInPolyTime_toHamPath : + ComputableInPolyTime toHamPath (encPair encGraph (encPair encNat encNat)) (encPair encGraph (encPair encNat encNat)) := by + refine .of_tidy ?_ have hsv := Graph.computableTidilyInPolyTime_splitVertex unfold toHamPath fun_prop @@ -575,13 +577,13 @@ end DirHamPath theorem polyTimeReducible_DirHamPath_HamPath : PolyTimeReducible (encPair encGraph (encPair encNat encNat)) (encPair encGraph (encPair encNat encNat)) DirHamPath HamPath := - ⟨DirHamPath.toHamPath, .of_tidy DirHamPath.computableTidilyInPolyTime_toHamPath, + ⟨DirHamPath.toHamPath, DirHamPath.computableInPolyTime_toHamPath, fun x => (DirHamPath.toHamPath_mem_iff x).symm⟩ /-- `DirHamCycle` reduces to `HamCycle` in polynomial time via `Graph.split`. -/ theorem polyTimeReducible_DirHamCycle_HamCycle : PolyTimeReducible encGraph encGraph DirHamCycle HamCycle := - ⟨Graph.split, .of_tidy Graph.computableTidilyInPolyTime_split, + ⟨Graph.split, Graph.computableInPolyTime_split, fun G => (Graph.split_mem_HamCycle_iff G).symm⟩ /-- `HamPath` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/IndependentSet.lean b/Complexity/Computability/Complexity/Problems/IndependentSet.lean index 0c1e6476d..db12ec938 100644 --- a/Complexity/Computability/Complexity/Problems/IndependentSet.lean +++ b/Complexity/Computability/Complexity/Problems/IndependentSet.lean @@ -57,7 +57,7 @@ first-order interpretations. assignment satisfying as many clauses. * `Cslib.Complexity.Graph.le_indepNum_iff`: the independence number is the largest target of `IndependentSet`. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_toIndependentSet`: Karp's reduction is +* `Cslib.Complexity.SAT.computableInPolyTime_toIndependentSet`: Karp's reduction is polynomial-time. * `Cslib.Complexity.IndependentSet.isVerifier`, `Cslib.Complexity.IndependentSet.mem_NP`: `IndependentSet ∈ NP (encPair encGraph encNat)`. @@ -274,23 +274,25 @@ theorem toIndependentSet_mem_iff (φ : CNF ℕ) : toIndependentSet φ ∈ Indepe /-- Computing the binary vertex label of an occurrence from its unary indices is polynomial-time. -/ @[fun_prop] -theorem _root_.Cslib.Logic.PL.Occurrence.computableTidilyInPolyTime_vertex : - ComputableTidilyInPolyTime Occurrence.vertex encOccurrence encNat := by +theorem _root_.Cslib.Logic.PL.Occurrence.computableInPolyTime_vertex : + ComputableInPolyTime Occurrence.vertex encOccurrence encNat := by + refine .of_tidy ?_ unfold Occurrence.vertex encOccurrence Cslib.Logic.PL.encOccurrence exact unary_to_binary.comp (by fun_prop) /-- Testing whether two occurrences conflict is polynomial-time. -/ @[fun_prop] -theorem _root_.Cslib.Logic.PL.Occurrence.computableTidilyInPolyTime_conflict : - ComputableTidilyInPolyTime (fun p : Occurrence ℕ × Occurrence ℕ => decide (p.1.Conflict p.2)) +theorem _root_.Cslib.Logic.PL.Occurrence.computableInPolyTime_conflict : + ComputableInPolyTime (fun p : Occurrence ℕ × Occurrence ℕ => decide (p.1.Conflict p.2)) (encPair encOccurrence encOccurrence) encBool := by unfold Occurrence.Conflict encOccurrence Cslib.Logic.PL.encOccurrence fun_prop /-- Karp's reduction `toIndependentSet` is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toIndependentSet : - ComputableTidilyInPolyTime toIndependentSet encCNF (encPair encGraph encNat) := by +theorem computableInPolyTime_toIndependentSet : + ComputableInPolyTime toIndependentSet encCNF (encPair encGraph encNat) := by + refine .of_tidy ?_ have hocc := computableInPolyTime_occurrences.tidy have hlen : ComputableTidilyInPolyTime (fun φ : CNF ℕ => φ.length) encCNF encNat := (ComputableInPolyTime.length_list_binary _).tidy @@ -318,21 +320,21 @@ theorem isVerifier : /-- The `IndependentSet` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := - Graph.computableTidilyInPolyTime_verifySubset (by fun_prop) + Graph.computableInPolyTime_verifySubset (by fun_prop) /-- `IndependentSet` belongs to `NP`. -/ theorem mem_NP : IndependentSet ∈ NP (encPair encGraph encNat) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end IndependentSet /-- `SAT` reduces to `IndependentSet` in polynomial time via `SAT.toIndependentSet`. -/ theorem polyTimeReducible_SAT_IndependentSet : PolyTimeReducible encCNF (encPair encGraph encNat) SAT IndependentSet := - ⟨SAT.toIndependentSet, .of_tidy SAT.computableTidilyInPolyTime_toIndependentSet, + ⟨SAT.toIndependentSet, SAT.computableInPolyTime_toIndependentSet, fun φ => (SAT.toIndependentSet_mem_iff φ).symm⟩ /-- `IndependentSet` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/IndependentSet/Sparse.lean b/Complexity/Computability/Complexity/Problems/IndependentSet/Sparse.lean index c6f85f911..a0ea88e79 100644 --- a/Complexity/Computability/Complexity/Problems/IndependentSet/Sparse.lean +++ b/Complexity/Computability/Complexity/Problems/IndependentSet/Sparse.lean @@ -46,7 +46,7 @@ linear in `m` for fixed `k`. * `Cslib.Complexity.SAT.toSparseIndependentSet_mem_iff`: `toSparseIndependentSet φ ∈ IndependentSet ↔ φ ∈ SAT`. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseIndependentSet`: the reduction is +* `Cslib.Complexity.SAT.computableInPolyTime_toSparseIndependentSet`: the reduction is polynomial-time. * `Cslib.Complexity.SAT.length_toSparseIndependentSet_le`: the graph has linearly many vertices and edges for clauses of bounded width. @@ -448,8 +448,9 @@ open SparseIndependentSet in /-- The reduction `toSparseIndependentSet` is computable in polynomial time: vertex labels are computed in unary from clause, position and variable indices, then converted to binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toSparseIndependentSet : - ComputableTidilyInPolyTime toSparseIndependentSet encCNF (encPair encGraph encNat) := by +theorem computableInPolyTime_toSparseIndependentSet : + ComputableInPolyTime toSparseIndependentSet encCNF (encPair encGraph encNat) := by + refine .of_tidy ?_ have hdv : ComputableTidilyInPolyTime CNF.distinctVars (encList (encList (encPair encNat encBool))) (encList encNat) := (CNF.computableInPolyTime_distinctVars encNat).tidy diff --git a/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean b/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean index bedc314f4..c7ec340eb 100644 --- a/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean +++ b/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean @@ -94,16 +94,17 @@ theorem isVerifier : /-- The `ZeroOneIP` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encList (encPair (encList encNat) encNat)) encBits) encBool := by + refine .of_tidy ?_ unfold verifier apply allWithInput (by fun_prop) fun_prop /-- `ZeroOneIP` belongs to `NP`. -/ theorem mem_NP : ZeroOneIP ∈ NP (encList (encPair (encList encNat) encNat)) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end ZeroOneIP @@ -128,8 +129,8 @@ theorem toZeroOneIP_mem_iff (x : List ℕ × ℕ) : toZeroOneIP x ∈ ZeroOneIP /-- The reduction to `ZeroOneIP` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toZeroOneIP : - ComputableTidilyInPolyTime toZeroOneIP (encPair (encList encNat) encNat) +theorem computableInPolyTime_toZeroOneIP : + ComputableInPolyTime toZeroOneIP (encPair (encList encNat) encNat) (encList (encPair (encList encNat) encNat)) := by unfold toZeroOneIP fun_prop @@ -140,7 +141,7 @@ end SubsetSum theorem polyTimeReducible_SubsetSum_ZeroOneIP : PolyTimeReducible (encPair (encList encNat) encNat) (encList (encPair (encList encNat) encNat)) SubsetSum ZeroOneIP := - ⟨SubsetSum.toZeroOneIP, .of_tidy SubsetSum.computableTidilyInPolyTime_toZeroOneIP, + ⟨SubsetSum.toZeroOneIP, SubsetSum.computableInPolyTime_toZeroOneIP, fun x => (SubsetSum.toZeroOneIP_mem_iff x).symm⟩ /-- `ThreeSAT` reduces to `ZeroOneIP` in polynomial time, through Sipser's digit construction. -/ diff --git a/Complexity/Computability/Complexity/Problems/Knapsack.lean b/Complexity/Computability/Complexity/Problems/Knapsack.lean index 52447bae8..00c174b42 100644 --- a/Complexity/Computability/Complexity/Problems/Knapsack.lean +++ b/Complexity/Computability/Complexity/Problems/Knapsack.lean @@ -89,14 +89,14 @@ theorem isVerifier : IsVerifier encKnapsack Polynomial.X verifier Knapsack := by /-- The `Knapsack` verifier is polynomial-time: the sums and comparisons are in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encKnapsack encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encKnapsack encBits) encBool := by unfold verifier fun_prop /-- `Knapsack` belongs to `NP`. -/ theorem mem_NP : Knapsack ∈ NP encKnapsack := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end Knapsack @@ -122,8 +122,8 @@ theorem toKnapsack_mem_iff (x : List ℕ × ℕ) : toKnapsack x ∈ Knapsack ↔ /-- The reduction to `Knapsack` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toKnapsack : - ComputableTidilyInPolyTime toKnapsack (encPair (encList encNat) encNat) encKnapsack := by +theorem computableInPolyTime_toKnapsack : + ComputableInPolyTime toKnapsack (encPair (encList encNat) encNat) encKnapsack := by unfold toKnapsack fun_prop @@ -132,7 +132,7 @@ end SubsetSum /-- `SubsetSum` reduces to `Knapsack` in polynomial time. -/ theorem polyTimeReducible_SubsetSum_Knapsack : PolyTimeReducible (encPair (encList encNat) encNat) encKnapsack SubsetSum Knapsack := - ⟨SubsetSum.toKnapsack, .of_tidy SubsetSum.computableTidilyInPolyTime_toKnapsack, + ⟨SubsetSum.toKnapsack, SubsetSum.computableInPolyTime_toKnapsack, fun x => (SubsetSum.toKnapsack_mem_iff x).symm⟩ /-- `Knapsack` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean index e29832b96..f2753de39 100644 --- a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean @@ -222,7 +222,7 @@ private theorem dualChunk_inSpace {n j : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) (hj : ComputableTidilyInSpace j encIn encNat Bs) : ComputableTidilyInSpace (fun x => dualChunk tm C d (n x) (j x)) encIn encBits Bs := by - have hg := (Tableau.gateCode_inSpace tm (.of_tidy hn) (.of_tidy (timeBound_inSpace C d hin hn)) + have hg := (Tableau.gateCode_inSpace tm (.of_tidy hn) (timeBound_inSpace C d hin (.of_tidy hn)) hin (.of_tidy hj)).tidy have hframe : ComputableTidilyInSpace (fun g => frame (encGate g)) encGate encBits @@ -237,7 +237,7 @@ private theorem dualChunk_inSpace {n j : α → ℕ} private theorem dualTrailer_inSpace {n : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) : ComputableTidilyInSpace (fun x => (dualSpec tm C d).trailer (n x)) encIn encBits Bs := by - have hT := timeBound_inSpace C d hin hn + have hT := (timeBound_inSpace C d hin (.of_tidy hn)).tidy have ho : ComputableTidilyInSpace (fun x => Tableau.outWire k State (n x) (timeBound C d (n x))) encIn encNat Bs := budget_natAdd (budget_natAdd (budget_natAdd hn (budget_const 2 hin)) @@ -277,9 +277,9 @@ theorem computableInLogSpace_dualTableauInstance : have hn := fst' (snd' hs) have hi := snd' (snd' hs) refine (dualSpec tm C d).computableInLogSpace - (encMonotoneCircuitValue_dualTableauInstance tm C d) - (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin hn)) - (dualChunk_inSpace tm C d hin hn hi) (dualTrailer_inSpace tm C d hin hn) ?_ + (.of_tidy (encMonotoneCircuitValue_dualTableauInstance tm C d)) + (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin (.of_tidy hn))) + (.of_tidy (dualChunk_inSpace tm C d hin hn hi)) (dualTrailer_inSpace tm C d hin hn) ?_ change PolynomiallyBounded fun n => Tableau.numGates k State (timeBound C d n) simp only [Tableau.numGates, Tableau.blockSize, Tableau.colStart, Tableau.gfStart, Tableau.globStart, Tableau.numCols, timeBound] diff --git a/Complexity/Computability/Complexity/Problems/Partition.lean b/Complexity/Computability/Complexity/Problems/Partition.lean index 049e8c727..baf552245 100644 --- a/Complexity/Computability/Complexity/Problems/Partition.lean +++ b/Complexity/Computability/Complexity/Problems/Partition.lean @@ -89,14 +89,14 @@ theorem isVerifier : IsVerifier (encList encNat) Polynomial.X verifier Partition /-- The `Partition` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair (encList encNat) encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encList encNat) encBits) encBool := by unfold verifier fun_prop /-- `Partition` belongs to `NP`. -/ theorem mem_NP : Partition ∈ NP (encList encNat) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end Partition @@ -135,8 +135,8 @@ theorem toPartition_mem_iff (x : List ℕ × ℕ) : toPartition x ∈ Partition /-- The reduction to `Partition` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toPartition : - ComputableTidilyInPolyTime toPartition (encPair (encList encNat) encNat) (encList encNat) := by +theorem computableInPolyTime_toPartition : + ComputableInPolyTime toPartition (encPair (encList encNat) encNat) (encList encNat) := by unfold toPartition fun_prop @@ -145,7 +145,7 @@ end SubsetSum /-- `SubsetSum` reduces to `Partition` in polynomial time. -/ theorem polyTimeReducible_SubsetSum_Partition : PolyTimeReducible (encPair (encList encNat) encNat) (encList encNat) SubsetSum Partition := - ⟨SubsetSum.toPartition, .of_tidy SubsetSum.computableTidilyInPolyTime_toPartition, + ⟨SubsetSum.toPartition, SubsetSum.computableInPolyTime_toPartition, fun x => (SubsetSum.toPartition_mem_iff x).symm⟩ /-- `Partition` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean b/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean index 653d8d9ac..2af054674 100644 --- a/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean +++ b/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean @@ -33,14 +33,14 @@ Together with `Cslib.Complexity.SAT.isVerifier`, this proves membership in `NP` ## Main results -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_verifier`: the verifier is polynomial-time. +* `Cslib.Complexity.SAT.computableInPolyTime_verifier`: the verifier is polynomial-time. * `Cslib.Complexity.SAT.computableInPolyTime_distinctVars`, `Cslib.Complexity.SAT.computableInPolyTime_numVars`, `Cslib.Complexity.SAT.computableInPolyTime_occurrences`: distinct variables, their unary count, and literal occurrences for natural-number variables. -* `Cslib.Complexity.SAT.computableTidilyInPolyTime_clause_length`, - `Cslib.Complexity.SAT.computableTidilyInPolyTime_length`, - `Cslib.Complexity.SAT.computableTidilyInPolyTime_vars_length`: literal, clause and +* `Cslib.Complexity.SAT.computableInPolyTime_clause_length`, + `Cslib.Complexity.SAT.computableInPolyTime_length`, + `Cslib.Complexity.SAT.computableInPolyTime_vars_length`: literal, clause and variable-occurrence counts for natural-number variables, in unary (`fun_prop` versions of the generic `Cslib.Logic.PL.CNF` lemmas). * `Cslib.Complexity.SAT.mem_NP`: satisfiability belongs to NP. @@ -66,9 +66,9 @@ open ComputableTidilyInPolyTime /-- Listing the variables in order of occurrence is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_vars : - ComputableTidilyInPolyTime (CNF.vars (V := ℕ)) encCNF (encList encNat) := - (CNF.computableInPolyTime_vars encNat).tidy +theorem computableInPolyTime_vars : + ComputableInPolyTime (CNF.vars (V := ℕ)) encCNF (encList encNat) := + (CNF.computableInPolyTime_vars encNat) /-- Listing the distinct variables in order of first occurrence is polynomial-time. -/ @[fun_prop] @@ -95,59 +95,64 @@ theorem computableInPolyTime_occurrences : /-- The number of literals of a polynomial-time clause, in unary, is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_clause_length {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_clause_length {α : Type} {input : α ↪ List Bool} {c : α → Clause ℕ} - (hc : ComputableTidilyInPolyTime c input (encList (encPair encNat encBool))) : - ComputableTidilyInPolyTime (fun a => (c a).length) input encUnary := - (Clause.computableInPolyTime_length (.of_tidy hc)).tidy + (hc : ComputableInPolyTime c input (encList (encPair encNat encBool))) : + ComputableInPolyTime (fun a => (c a).length) input encUnary := by + have hc := hc.tidy + exact (Clause.computableInPolyTime_length (.of_tidy hc)) /-- The number of clauses of a polynomial-time formula, in unary, is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_length {α : Type} {input : α ↪ List Bool} {φ : α → CNF ℕ} - (hφ : ComputableTidilyInPolyTime φ input encCNF) : - ComputableTidilyInPolyTime (fun a => (φ a).length) input encUnary := - (CNF.computableInPolyTime_length (encV := encNat) (.of_tidy hφ)).tidy +theorem computableInPolyTime_length {α : Type} {input : α ↪ List Bool} {φ : α → CNF ℕ} + (hφ : ComputableInPolyTime φ input encCNF) : + ComputableInPolyTime (fun a => (φ a).length) input encUnary := by + have hφ := hφ.tidy + exact (CNF.computableInPolyTime_length (encV := encNat) (.of_tidy hφ)) /-- The number of variable occurrences of a polynomial-time formula, in unary, is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_vars_length {α : Type} {input : α ↪ List Bool} - {φ : α → CNF ℕ} (hφ : ComputableTidilyInPolyTime φ input encCNF) : - ComputableTidilyInPolyTime (fun a => (φ a).vars.length) input encUnary := - (CNF.computableInPolyTime_vars_length (encV := encNat) (.of_tidy hφ)).tidy +theorem computableInPolyTime_vars_length {α : Type} {input : α ↪ List Bool} + {φ : α → CNF ℕ} (hφ : ComputableInPolyTime φ input encCNF) : + ComputableInPolyTime (fun a => (φ a).vars.length) input encUnary := by + have hφ := hφ.tidy + exact (CNF.computableInPolyTime_vars_length (encV := encNat) (.of_tidy hφ)) /-- Reading the certificate at the first occurrence of a variable is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_assignment : - ComputableTidilyInPolyTime (fun p : (CNF ℕ × List Bool) × ℕ => assignment p.1.1 p.1.2 p.2) +theorem computableInPolyTime_assignment : + ComputableInPolyTime (fun p : (CNF ℕ × List Bool) × ℕ => assignment p.1.1 p.1.2 p.2) (encPair (encPair encCNF encBits) encNat) encBool := by fun_prop [assignment] /-- Evaluating a literal with the certificate assignment is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_literal : - ComputableTidilyInPolyTime +theorem computableInPolyTime_literal : + ComputableInPolyTime (fun p : (CNF ℕ × List Bool) × Literal ℕ => Literal.eval (assignment p.1.1 p.1.2) p.2) (encPair (encPair encCNF encBits) (encPair encNat encBool)) encBool := by fun_prop [Literal.eval, assignment] /-- Evaluating a clause with the certificate assignment is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_clause : - ComputableTidilyInPolyTime +theorem computableInPolyTime_clause : + ComputableInPolyTime (fun p : (CNF ℕ × List Bool) × Clause ℕ => Clause.eval (assignment p.1.1 p.1.2) p.2) (encPair (encPair encCNF encBits) (encList (encPair encNat encBool))) encBool := by fun_prop [Clause.eval, Literal.eval, assignment] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The SAT verifier is polynomial-time, including on certificates of arbitrary length. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encCNF encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by + refine .of_tidy ?_ fun_prop [verifier, CNF.eval] /-- Satisfiability is in NP, with certificates of length equal to the encoded formula length. -/ theorem mem_NP : SAT ∈ NP encCNF := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end SAT diff --git a/Complexity/Computability/Complexity/Problems/SharpSAT.lean b/Complexity/Computability/Complexity/Problems/SharpSAT.lean index c3d465bb7..3d53b91cb 100644 --- a/Complexity/Computability/Complexity/Problems/SharpSAT.lean +++ b/Complexity/Computability/Complexity/Problems/SharpSAT.lean @@ -47,9 +47,9 @@ satisfying assignment once for every setting of the ignored bits. The counting v `USAT` through `#SAT`. * `Cslib.Complexity.SharpSAT.acceptCount_verifier`: the verifier accepts one certificate for each satisfying assignment. -* `Cslib.Complexity.SharpSAT.computableTidilyInPolyTime_card_vars`: the number of occurring +* `Cslib.Complexity.SharpSAT.computableInPolyTime_card_vars`: the number of occurring variables is computable in polynomial time in unary. -* `Cslib.Complexity.SharpSAT.computableTidilyInPolyTime_verifier`: the verifier is +* `Cslib.Complexity.SharpSAT.computableInPolyTime_verifier`: the verifier is polynomial-time. * `Cslib.Complexity.SharpSAT.mem_SharpP`: `#SAT` belongs to `#P`. @@ -160,26 +160,26 @@ theorem acceptCount_verifier (φ : CNF ℕ) : /-- Testing for a first occurrence is polynomial-time, with the position in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isFirst : - ComputableTidilyInPolyTime (fun p : CNF ℕ × ℕ => isFirst p.1 p.2) +theorem computableInPolyTime_isFirst : + ComputableInPolyTime (fun p : CNF ℕ × ℕ => isFirst p.1 p.2) (encPair encCNF encUnary) encBool := by fun_prop [isFirst] /-- The number of distinct variables occurring in `φ` is computable in polynomial time in unary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_card_vars : - ComputableTidilyInPolyTime (fun φ : CNF ℕ => φ.vars.toFinset.card) encCNF encUnary := - (CNF.computableInPolyTime_numVars encNat).tidy +theorem computableInPolyTime_card_vars : + ComputableInPolyTime (fun φ : CNF ℕ => φ.vars.toFinset.card) encCNF encUnary := + (CNF.computableInPolyTime_numVars encNat) /-- The counting verifier is polynomial-time, including on certificates of arbitrary length. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encCNF encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by fun_prop [verifier, canonical] /-- **`#SAT` belongs to `#P`**, with certificates as long as the encoded formula. -/ theorem mem_SharpP : SharpSAT ∈ SharpP encCNF := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, fun φ => by + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, fun φ => by rw [Polynomial.eval_X, acceptCount_verifier]⟩ end SharpSAT diff --git a/Complexity/Computability/Complexity/Problems/SubsetSum.lean b/Complexity/Computability/Complexity/Problems/SubsetSum.lean index 543e1173f..7fb5c78cf 100644 --- a/Complexity/Computability/Complexity/Problems/SubsetSum.lean +++ b/Complexity/Computability/Complexity/Problems/SubsetSum.lean @@ -60,7 +60,7 @@ by both of its literal numbers. Formulas with a clause of more than three litera * `Cslib.Complexity.ThreeSAT.toSubsetSum_mem_iff`: correctness of Sipser's reduction. * `Cslib.Complexity.ThreeSAT.lt_of_mem_digitNumbers`, `Cslib.Complexity.ThreeSAT.digitTarget_lt`: the numbers have `O(n + m)` digits. -* `Cslib.Complexity.ThreeSAT.computableTidilyInPolyTime_toSubsetSum`: the reduction is +* `Cslib.Complexity.ThreeSAT.computableInPolyTime_toSubsetSum`: the reduction is polynomial-time. * `Cslib.Complexity.polyTimeReducible_ThreeSAT_SubsetSum`, `Cslib.Complexity.SubsetSum_npHard`, `Cslib.Complexity.SubsetSum_npComplete`: `SubsetSum` is `NP`-complete. @@ -137,15 +137,15 @@ theorem isVerifier : /-- The `SubsetSum` verifier is polynomial-time: it selects the masked numbers, adds them in binary and compares the sum with the target. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair (encList encNat) encNat) encBits) encBool := by unfold verifier fun_prop /-- `SubsetSum` belongs to `NP`. -/ theorem mem_NP : SubsetSum ∈ NP (encPair (encList encNat) encNat) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end SubsetSum @@ -572,10 +572,11 @@ attribute [local fun_prop] eight_pow ComputableInPolyTime.tidy /-- Testing whether a clause contains a literal is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_covers : - ComputableTidilyInPolyTime +theorem computableInPolyTime_covers : + ComputableInPolyTime (fun p : ((CNF ℕ × ℕ) × Bool) × ℕ => covers p.1.1.1 p.1.1.2 p.1.2 p.2) (encPair (encPair (encPair encCNF encUnary) encBool) encUnary) encBool := by + refine .of_tidy ?_ unfold covers encCNF apply anyWithInput (encA := encPair encNat encBool) · exact (listGetD (encA := encList (encPair encNat encBool)) []).comp @@ -585,34 +586,35 @@ theorem computableTidilyInPolyTime_covers : /-- Listing the digit positions of a literal number is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_literalDigits : - ComputableTidilyInPolyTime (fun p : (CNF ℕ × ℕ) × Bool => literalDigits p.1.1 p.1.2 p.2) +theorem computableInPolyTime_literalDigits : + ComputableInPolyTime (fun p : (CNF ℕ × ℕ) × Bool => literalDigits p.1.1 p.1.2 p.2) (encPair (encPair encCNF encUnary) encBool) (encList encUnary) := by unfold literalDigits fun_prop /-- Composition rule for `literalDigits`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_literalDigits' {α : Type} {input : α ↪ List Bool} +theorem computableInPolyTime_literalDigits' {α : Type} {input : α ↪ List Bool} {φ : α → CNF ℕ} {i : α → ℕ} {b : α → Bool} - (hφ : ComputableTidilyInPolyTime φ input encCNF) - (hi : ComputableTidilyInPolyTime i input encUnary) - (hb : ComputableTidilyInPolyTime b input encBool) : - ComputableTidilyInPolyTime (fun a => literalDigits (φ a) (i a) (b a)) input + (hφ : ComputableInPolyTime φ input encCNF) + (hi : ComputableInPolyTime i input encUnary) + (hb : ComputableInPolyTime b input encBool) : + ComputableInPolyTime (fun a => literalDigits (φ a) (i a) (b a)) input (encList encUnary) := - computableTidilyInPolyTime_literalDigits.comp ((hφ.prod hi).prod hb) + computableInPolyTime_literalDigits.comp ((hφ.prod hi).prod hb) /-- A number with digits zero and one is computed in binary from its unary digit positions. -/ @[fun_prop] -theorem computableTidilyInPolyTime_octal : - ComputableTidilyInPolyTime octal (encList encUnary) encNat := by +theorem computableInPolyTime_octal : + ComputableInPolyTime octal (encList encUnary) encNat := by unfold octal fun_prop /-- The numbers of the digit construction are computed in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_digitNumbers : - ComputableTidilyInPolyTime digitNumbers encCNF (encList encNat) := by +theorem computableInPolyTime_digitNumbers : + ComputableInPolyTime digitNumbers encCNF (encList encNat) := by + refine .of_tidy ?_ unfold digitNumbers apply listAppend' · apply flatMapWithInput (by fun_prop) @@ -622,15 +624,15 @@ theorem computableTidilyInPolyTime_digitNumbers : /-- The target of the digit construction is computed in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_digitTarget : - ComputableTidilyInPolyTime digitTarget encCNF encNat := by +theorem computableInPolyTime_digitTarget : + ComputableInPolyTime digitTarget encCNF encNat := by unfold digitTarget fun_prop /-- Sipser's reduction is computable in polynomial time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toSubsetSum : - ComputableTidilyInPolyTime toSubsetSum encCNF (encPair (encList encNat) encNat) := by +theorem computableInPolyTime_toSubsetSum : + ComputableInPolyTime toSubsetSum encCNF (encPair (encList encNat) encNat) := by unfold toSubsetSum encCNF fun_prop @@ -639,7 +641,7 @@ end ThreeSAT /-- `ThreeSAT` reduces to `SubsetSum` in polynomial time by Sipser's digit construction. -/ theorem polyTimeReducible_ThreeSAT_SubsetSum : PolyTimeReducible encCNF (encPair (encList encNat) encNat) ThreeSAT SubsetSum := - ⟨ThreeSAT.toSubsetSum, .of_tidy ThreeSAT.computableTidilyInPolyTime_toSubsetSum, + ⟨ThreeSAT.toSubsetSum, ThreeSAT.computableInPolyTime_toSubsetSum, fun φ => (ThreeSAT.toSubsetSum_mem_iff φ).symm⟩ /-- `SubsetSum` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/SubsetSum/Mask.lean b/Complexity/Computability/Complexity/Problems/SubsetSum/Mask.lean index da3972bca..7c95c6bc9 100644 --- a/Complexity/Computability/Complexity/Problems/SubsetSum/Mask.lean +++ b/Complexity/Computability/Complexity/Problems/SubsetSum/Mask.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List public import Mathlib.Data.Multiset.AddSub +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # Selecting list entries by a mask @@ -30,7 +31,7 @@ sub-multiset of the input numbers, such as subset sum, partition and knapsack. * `Cslib.Complexity.exists_le_iff_exists_maskSelect`: a property of sub-multisets holds for one of them exactly when it holds for the selection of some mask of any length at least the length of the list. -* `Cslib.Complexity.computableTidilyInPolyTime_maskSelect`: selection is polynomial-time. +* `Cslib.Complexity.computableInPolyTime_maskSelect`: selection is polynomial-time. -/ @[expose] public section @@ -120,9 +121,10 @@ theorem exists_le_iff_exists_maskSelect {l : List α} {n : ℕ} (hn : l.length /-- Selecting the entries of a list by a mask is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_maskSelect (enc : α ↪ List Bool) : - ComputableTidilyInPolyTime (fun p : List α × List Bool => maskSelect p.1 p.2) +theorem computableInPolyTime_maskSelect (enc : α ↪ List Bool) : + ComputableInPolyTime (fun p : List α × List Bool => maskSelect p.1 p.2) (encPair (encList enc) encBits) (encList enc) := by + refine .of_tidy ?_ unfold maskSelect fun_prop diff --git a/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean b/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean index 136b5e1ab..7bb71de48 100644 --- a/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean +++ b/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean @@ -23,7 +23,7 @@ connective joins the two lists on top of the stack, and a quantifier removes its list on top. On the tokens of a formula the scan ends with the list of its free variables (`Cslib.Logic.PL.QBF.foldl_freeVarStep_tokens`), so a formula is closed exactly when that list is empty (`Cslib.Logic.PL.QBF.isClosed_tokens`), and closedness is decided in polynomial time -(`Cslib.Complexity.TQBF.computableTidilyInPolyTime_decide_closed`). +(`Cslib.Complexity.TQBF.computableInPolyTime_decide_closed`). ## Main definitions @@ -34,7 +34,7 @@ empty (`Cslib.Logic.PL.QBF.isClosed_tokens`), and closedness is decided in polyn * `Cslib.Logic.PL.QBF.mem_freeVarList`: the list has the free variables as elements. * `Cslib.Logic.PL.QBF.isClosed_tokens`: the scan decides closedness. -* `Cslib.Complexity.TQBF.computableTidilyInPolyTime_decide_closed`: in polynomial time. +* `Cslib.Complexity.TQBF.computableInPolyTime_decide_closed`: in polynomial time. -/ @[expose] public section @@ -201,8 +201,9 @@ private theorem length_freeVarStep_le (stack : List (List ℕ)) (t : QBF.Kind × omega /-- **Closedness is decided in polynomial time.** -/ -theorem computableTidilyInPolyTime_decide_closed : - ComputableTidilyInPolyTime (fun φ : QBF ℕ => decide φ.Closed) encQBF encBool := by +theorem computableInPolyTime_decide_closed : + Turing.MultiTapeTM.ComputableInPolyTime (fun φ : QBF ℕ => decide φ.Closed) encQBF encBool := by + refine .of_tidy ?_ simp only [← QBF.isClosed_tokens] unfold QBF.isClosed have hfold : ComputableTidilyInPolyTime (fun φ : QBF ℕ => diff --git a/Complexity/Computability/Complexity/Problems/TSP.lean b/Complexity/Computability/Complexity/Problems/TSP.lean index 4559d338b..424acbd54 100644 --- a/Complexity/Computability/Complexity/Problems/TSP.lean +++ b/Complexity/Computability/Complexity/Problems/TSP.lean @@ -58,10 +58,10 @@ with fewer than three vertices have no Hamiltonian cycle and are mapped to a fix * `Cslib.Complexity.TSP.tourLength_eq_sum`: the tour length as a sum over the positions of the tour. -* `Cslib.Complexity.TSP.computableTidilyInPolyTime_tourLength`: tour lengths are polynomial-time. +* `Cslib.Complexity.TSP.computableInPolyTime_tourLength`: tour lengths are polynomial-time. * `Cslib.Complexity.TSP.isVerifier`, `Cslib.Complexity.TSP.mem_NP`: `TSP ∈ NP encTSP`. * `Cslib.Complexity.HamCycle.toTSP_mem_iff`: `toTSP G ∈ TSP ↔ G ∈ HamCycle`. -* `Cslib.Complexity.HamCycle.computableTidilyInPolyTime_toTSP`: the reduction is polynomial-time. +* `Cslib.Complexity.HamCycle.computableInPolyTime_toTSP`: the reduction is polynomial-time. * `Cslib.Complexity.polyTimeReducible_HamCycle_TSP`, `Cslib.Complexity.TSP_npHard`: `HamCycle` reduces to `TSP` in polynomial time, so `TSP` is `NP`-hard. * `Cslib.Complexity.TSP_npComplete`: `TSP` is `NP`-complete. @@ -133,9 +133,10 @@ theorem tourLength_eq_sum (D : List (List ℕ)) (p : List ℕ) : entries: it is a binary sum over the positions of the tour, and a city beyond the matrix is looked up at an index capped by the number of rows. -/ @[fun_prop] -theorem computableTidilyInPolyTime_tourLength : - ComputableTidilyInPolyTime (fun x : List (List ℕ) × List ℕ => tourLength x.1 x.2) +theorem computableInPolyTime_tourLength : + ComputableInPolyTime (fun x : List (List ℕ) × List ℕ => tourLength x.1 x.2) (encPair (encList (encList encNat)) (encList encNat)) encNat := by + refine .of_tidy ?_ have heq : (fun x : List (List ℕ) × List ℕ => tourLength x.1 x.2) = fun x => ((List.range x.2.length).map fun k => dist x.1 ((x.2 ++ [x.2.headD 0]).getD k 0) @@ -184,8 +185,9 @@ theorem isVerifier : IsVerifier encTSP (Polynomial.X ^ 2) verifier TSP := by /-- The `TSP` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encTSP encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encTSP encBits) encBool := by + refine .of_tidy ?_ have hV : ComputableTidilyInPolyTime (fun x : List (List ℕ) × ℕ => List.range x.1.length) encTSP (encList encNat) := by unfold encTSP @@ -199,12 +201,12 @@ theorem computableTidilyInPolyTime_verifier : (encPair encTSP (encList encNat)) encNat := by unfold encTSP exact (snd _ _).comp (fst _ _) - have hlen := computableTidilyInPolyTime_tourLength.comp (hD.prod (snd _ (encList encNat))) - exact Graph.computableTidilyInPolyTime_verifyOrdering hV (binary_le' hlen hb) + have hlen := computableInPolyTime_tourLength.tidy.comp (hD.prod (snd _ (encList encNat))) + exact (Graph.computableInPolyTime_verifyOrdering (.of_tidy hV) (.of_tidy (binary_le' hlen hb))).tidy /-- `TSP` belongs to `NP`. -/ theorem mem_NP : TSP ∈ NP encTSP := - ⟨_, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨_, verifier, computableInPolyTime_verifier, isVerifier⟩ end TSP @@ -381,16 +383,17 @@ theorem toTSP_mem_iff (G : Graph) : toTSP G ∈ TSP ↔ G ∈ HamCycle := by /-- The reduction `toTSP` is polynomial-time: the cities are selected from the declared vertices, and the distances and the budget are written in binary. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toTSP : ComputableTidilyInPolyTime toTSP encGraph encTSP := by +theorem computableInPolyTime_toTSP : ComputableInPolyTime toTSP encGraph encTSP := by + refine .of_tidy ?_ have hV : ComputableTidilyInPolyTime Graph.distinctVertices encGraph (encList encNat) := - Graph.computableTidilyInPolyTime_distinctVertices + Graph.computableInPolyTime_distinctVertices.tidy have hn : ComputableTidilyInPolyTime (fun G : Graph => G.distinctVertices.length) encGraph encUnary := (length_list _).comp hV have hrow : ComputableTidilyInPolyTime (fun p : Graph × ℕ => p.1.distinctVertices.map fun v => if p.1.adjBool p.2 v then 1 else 2) (encPair encGraph encNat) (encList encNat) := mapWithInput (hV.comp (fst _ _)) - (cond Graph.computableTidilyInPolyTime_adjBool (const 1) (const 2)) + (cond Graph.computableInPolyTime_adjBool.tidy (const 1) (const 2)) unfold toTSP encTSP exact ite_decide (unary_lt' hn (const 3)) (const _) ((mapWithInput hV hrow).prod (unary_to_binary.comp hn)) @@ -399,7 +402,7 @@ end HamCycle /-- `HamCycle` reduces to `TSP` in polynomial time via `HamCycle.toTSP`. -/ theorem polyTimeReducible_HamCycle_TSP : PolyTimeReducible encGraph encTSP HamCycle TSP := - ⟨HamCycle.toTSP, .of_tidy HamCycle.computableTidilyInPolyTime_toTSP, + ⟨HamCycle.toTSP, HamCycle.computableInPolyTime_toTSP, fun G => (HamCycle.toTSP_mem_iff G).symm⟩ /-- `TSP` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/ThreeSAT.lean b/Complexity/Computability/Complexity/Problems/ThreeSAT.lean index 677ba8023..b43d6b41b 100644 --- a/Complexity/Computability/Complexity/Problems/ThreeSAT.lean +++ b/Complexity/Computability/Complexity/Problems/ThreeSAT.lean @@ -37,7 +37,7 @@ relabelling and the Cook–Levin theorem proves that `ThreeSAT` is `NP`-complete ## Main results * `Cslib.Complexity.mem_ThreeSAT_toThreeSAT_iff`: `φ ∈ SAT ↔ toThreeSAT φ ∈ ThreeSAT`. -* `Cslib.Complexity.computableTidilyInPolyTime_toThreeSAT`: `toThreeSAT` is polynomial-time. +* `Cslib.Complexity.computableInPolyTime_toThreeSAT`: `toThreeSAT` is polynomial-time. * `Cslib.Complexity.ThreeSAT.isVerifier`, `Cslib.Complexity.ThreeSAT.mem_NP`: `ThreeSAT ∈ NP`. * `Cslib.Complexity.polyTimeReducible_SAT_ThreeSAT`, `Cslib.Complexity.ThreeSAT_npHard`, `Cslib.Complexity.ThreeSAT_npComplete`: `ThreeSAT` is `NP`-complete. @@ -141,9 +141,10 @@ private theorem sumElim {α β γ : Type} {left : α ↪ List Bool} {right : β /-- Variable numbering after clause splitting is polynomial-time: original binary variables shift by one bit, and unary fresh-variable pairs are paired and converted to odd binary numbers. -/ @[fun_prop] -theorem computableTidilyInPolyTime_splitVarToNat : - ComputableTidilyInPolyTime splitVarToNat +theorem computableInPolyTime_splitVarToNat : + ComputableInPolyTime splitVarToNat (encSum encNat (encPair encUnary encUnary)) encNat := by + refine .of_tidy ?_ have hdouble : ComputableTidilyInPolyTime (2 * ·) encNat encNat := (show ComputableTidilyInPolyTime (fun n : ℕ => if (encNat n).isEmpty then ([] : List Bool) else false :: encNat n) @@ -155,10 +156,10 @@ theorem computableTidilyInPolyTime_splitVarToNat : /-- The reduction `toThreeSAT` is computable in polynomial time under `encCNF`. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toThreeSAT : - ComputableTidilyInPolyTime toThreeSAT encCNF encCNF := - (CNF.computableInPolyTime_relabel (.of_tidy computableTidilyInPolyTime_splitVarToNat)).tidy.comp - (CNF.isPolyTime_to3CNF encNat).tidy +theorem computableInPolyTime_toThreeSAT : + ComputableInPolyTime toThreeSAT encCNF encCNF := + .of_tidy ((CNF.computableInPolyTime_relabel computableInPolyTime_splitVarToNat).tidy.comp + (CNF.isPolyTime_to3CNF encNat).tidy) namespace ThreeSAT @@ -178,20 +179,20 @@ theorem isVerifier : IsVerifier encCNF Polynomial.X verifier ThreeSAT := by /-- Checking the clause-width bound and evaluating the formula is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encCNF encBits) encBool := by +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by unfold verifier fun_prop /-- `ThreeSAT` belongs to `NP`. -/ theorem mem_NP : ThreeSAT ∈ NP encCNF := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end ThreeSAT /-- `SAT` reduces to `ThreeSAT` in polynomial time via `toThreeSAT`. -/ theorem polyTimeReducible_SAT_ThreeSAT : PolyTimeReducible encCNF encCNF SAT ThreeSAT := - ⟨toThreeSAT, .of_tidy computableTidilyInPolyTime_toThreeSAT, + ⟨toThreeSAT, computableInPolyTime_toThreeSAT, fun φ => (mem_ThreeSAT_toThreeSAT_iff φ).symm⟩ /-- `ThreeSAT` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Problems/VertexCover.lean b/Complexity/Computability/Complexity/Problems/VertexCover.lean index 6bc814228..5c497c646 100644 --- a/Complexity/Computability/Complexity/Problems/VertexCover.lean +++ b/Complexity/Computability/Complexity/Problems/VertexCover.lean @@ -57,7 +57,7 @@ first-order interpretations. `toVertexCover x ∈ VertexCover ↔ x ∈ IndependentSet`. * `Cslib.Complexity.Graph.vertexCoverNum_eq_card_sub_indepNum`: the vertex cover number is the number of distinct declared vertices minus the independence number. -* `Cslib.Complexity.IndependentSet.computableTidilyInPolyTime_toVertexCover`: the reduction is +* `Cslib.Complexity.IndependentSet.computableInPolyTime_toVertexCover`: the reduction is polynomial-time, with targets in binary. * `Cslib.Complexity.VertexCover.isCover_eq_true_iff`, `Cslib.Complexity.VertexCover.isVerifier`, `Cslib.Complexity.VertexCover.mem_NP`: @@ -164,14 +164,15 @@ theorem toVertexCover_mem_iff (x : Graph × ℕ) : /-- The reduction `toVertexCover` is polynomial-time: the vertex count is computed in unary, and the binary target is compared with it by saturating decoding. -/ @[fun_prop] -theorem computableTidilyInPolyTime_toVertexCover : - ComputableTidilyInPolyTime toVertexCover (encPair encGraph encNat) +theorem computableInPolyTime_toVertexCover : + ComputableInPolyTime toVertexCover (encPair encGraph encNat) (encPair encGraph encNat) := by + refine .of_tidy ?_ have hn : ComputableTidilyInPolyTime (fun x : Graph × ℕ => x.1.1.toFinset.card) (encPair encGraph encNat) encUnary := by simp_rw [← Graph.length_distinctVertices] exact (length_list encNat).comp - (Graph.computableTidilyInPolyTime_distinctVertices.comp (fst _ _)) + (Graph.computableInPolyTime_distinctVertices.tidy.comp (fst _ _)) -- `min n m`, decoded from the binary target under the unary cap `n`. have hmin : ComputableTidilyInPolyTime (fun x : Graph × ℕ => Cslib.BitString.boundedBinaryValue x.1.1.toFinset.card @@ -251,9 +252,10 @@ attribute [local fun_prop] computableTidilyInPolyTime_isUncoveredEdge /-- Listing the uncovered edges is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_uncoveredEdges : - ComputableTidilyInPolyTime (fun p : Graph × List ℕ => uncoveredEdges p.1 p.2) +theorem computableInPolyTime_uncoveredEdges : + ComputableInPolyTime (fun p : Graph × List ℕ => uncoveredEdges p.1 p.2) (encPair encGraph (encList encNat)) (encList (encPair encNat encNat)) := by + refine .of_tidy ?_ have hE : ComputableTidilyInPolyTime (fun p : Graph × List ℕ => p.1.2) (encPair encGraph (encList encNat)) (encList (encPair encNat encNat)) := by unfold encGraph @@ -262,10 +264,10 @@ theorem computableTidilyInPolyTime_uncoveredEdges : /-- Testing whether `C` is a cover of `G` is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_isCover : - ComputableTidilyInPolyTime (fun p : Graph × List ℕ => isCover p.1 p.2) +theorem computableInPolyTime_isCover : + ComputableInPolyTime (fun p : Graph × List ℕ => isCover p.1 p.2) (encPair encGraph (encList encNat)) encBool := - (listIsEmpty' (encPair encNat encNat)).comp computableTidilyInPolyTime_uncoveredEdges + .of_tidy ((listIsEmpty' (encPair encNat encNat)).comp computableInPolyTime_uncoveredEdges.tidy) /-- The verifier for `VertexCover`, a subset verifier (`Cslib.Complexity.subsetVerifier`): select distinct declared vertices by the certificate mask, check that their count equals `k`, and check @@ -292,17 +294,18 @@ theorem isVerifier : /-- The `VertexCover` verifier is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := by - refine computableTidilyInPolyTime_subsetVerifier (encγ := encNat) (by unfold encGraph; fun_prop) - (bool_and' ?_ (computableTidilyInPolyTime_isCover.comp - (((fst _ _).comp (fst _ _)).prod (snd _ _)))) +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := by + refine .of_tidy ?_ + refine (computableInPolyTime_subsetVerifier (encγ := encNat) (.of_tidy (by unfold encGraph; fun_prop)) + (.of_tidy (bool_and' ?_ (computableInPolyTime_isCover.tidy.comp + (((fst _ _).comp (fst _ _)).prod (snd _ _)))))).tidy exact (((ComputableInPolyTime.length_list_binary encNat).tidy.comp (snd _ _)).decide_eq' (by fun_prop)) /-- `VertexCover` belongs to `NP`. -/ theorem mem_NP : VertexCover ∈ NP (encPair encGraph encNat) := - ⟨Polynomial.X, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨Polynomial.X, verifier, computableInPolyTime_verifier, isVerifier⟩ end VertexCover @@ -311,7 +314,7 @@ end VertexCover theorem polyTimeReducible_IndependentSet_VertexCover : PolyTimeReducible (encPair encGraph encNat) (encPair encGraph encNat) IndependentSet VertexCover := - ⟨IndependentSet.toVertexCover, .of_tidy IndependentSet.computableTidilyInPolyTime_toVertexCover, + ⟨IndependentSet.toVertexCover, IndependentSet.computableInPolyTime_toVertexCover, fun x => (IndependentSet.toVertexCover_mem_iff x).symm⟩ /-- `VertexCover` is `NP`-hard. -/ diff --git a/Complexity/Computability/Complexity/Reduction/TruthTable.lean b/Complexity/Computability/Complexity/Reduction/TruthTable.lean index 7154d9f11..85b407d60 100644 --- a/Complexity/Computability/Complexity/Reduction/TruthTable.lean +++ b/Complexity/Computability/Complexity/Reduction/TruthTable.lean @@ -151,9 +151,11 @@ theorem PolyTimeTruthTableReducible.compl a computed unary batch of queries. -/ theorem truthTable_mem_P {A : Set (α × ℕ)} {r : α → ℕ} {d : α × List Bool → Bool} (hA : A ∈ P (encPair encA encUnary)) - (hr : ComputableTidilyInPolyTime r encA encUnary) - (hd : ComputableTidilyInPolyTime d (encPair encA encBits) encBool) : + (hr : ComputableInPolyTime r encA encUnary) + (hd : ComputableInPolyTime d (encPair encA encBits) encBool) : {a | d (a, truthTableAnswers A r a) = true} ∈ P encA := by + have hr := hr.tidy + have hd := hd.tidy classical obtain ⟨f, hf, hAf⟩ := mem_P_iff_tidy.mp hA have hans : ComputableTidilyInPolyTime @@ -169,7 +171,7 @@ theorem PolyTimeTruthTableReducible.mem_P obtain ⟨r, q, d, hr, hq, hd, hL⟩ := h have hqB : q ⁻¹' B ∈ P (encPair encA encUnary) := PolyTimeReducible.mem_P ⟨q, hq, fun _ => Iff.rfl⟩ hB - convert truthTable_mem_P hqB hr.tidy hd.tidy using 1 + convert truthTable_mem_P hqB hr hd using 1 ext a exact hL a diff --git a/Complexity/Computability/Kolmogorov/MINKT.lean b/Complexity/Computability/Kolmogorov/MINKT.lean index 2be9656c5..1fd58b8d9 100644 --- a/Complexity/Computability/Kolmogorov/MINKT.lean +++ b/Complexity/Computability/Kolmogorov/MINKT.lean @@ -14,6 +14,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Bi import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Option +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # The Time-Bounded Kolmogorov Complexity Problem (`MINKT`) @@ -251,6 +252,8 @@ theorem computableInPolyTime_check : ComputableInPolyTime check (encPair enc encBits) encBool := .of_tidy computableTidilyInPolyTime_check +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in +attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in /-- **`MINKT` is in `NP`** ([Ko][Ko1986]; [Hirahara][Hirahara2018]): a witness for `(x, 1^t, 1^s)` is a binary program `p` of length at most `s ≤ |(x, 1^t, 1^s)|`, verified in polynomial time by running the universal simulator for `t` steps (`check`). -/ diff --git a/Complexity/Computability/MCSP/NP.lean b/Complexity/Computability/MCSP/NP.lean index da515898b..9fe8f21d0 100644 --- a/Complexity/Computability/MCSP/NP.lean +++ b/Complexity/Computability/MCSP/NP.lean @@ -49,8 +49,8 @@ so they stay polynomially long in the length of the table. * `Cslib.MCSP.complexity_le_of_tableVerifier`, `Cslib.MCSP.exists_tableVerifier_append`: soundness and completeness of `tableVerifier` on truth-table lists of length `2 ^ m`. * `Cslib.MCSP.isVerifier`: the verifier is correct. -* `Cslib.MCSP.computableTidilyInPolyTime_verifier`, - `Cslib.MCSP.computableTidilyInPolyTime_tableVerifier`: the verifiers are polynomial-time. +* `Cslib.MCSP.computableInPolyTime_verifier`, + `Cslib.MCSP.computableInPolyTime_tableVerifier`: the verifiers are polynomial-time. * `Cslib.MCSP.mem_NP`: MCSP is in `NP`. ## References @@ -246,8 +246,9 @@ theorem exists_tableVerifier_append {m s : ℕ} {T : List Bool} (hT : T.length = rfl /-- The verifier on raw data is polynomial-time. -/ -theorem computableTidilyInPolyTime_tableVerifier : ComputableTidilyInPolyTime tableVerifier +theorem computableInPolyTime_tableVerifier : ComputableInPolyTime tableVerifier (encPair (encPair encBits encNat) encBits) encBool := by + refine .of_tidy ?_ have hn : ComputableTidilyInPolyTime (fun r : (List Bool × ℕ) × List Bool => Nat.log 2 r.1.1.length) (encPair (encPair encBits encNat) encBits) encUnary := unary_log_two.comp (by fun_prop) @@ -309,18 +310,18 @@ theorem computableTidilyInPolyTime_tableVerifier : ComputableTidilyInPolyTime ta (hn.prod ((length_list encGate).comp hc.fst')))))) (allWithInput henum htest) /-- The MCSP verifier is polynomial-time, on certificates of arbitrary length. -/ -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime verifier (encPair encInstance encBits) encBool := by - have hraw : ComputableTidilyInPolyTime +theorem computableInPolyTime_verifier : + ComputableInPolyTime verifier (encPair encInstance encBits) encBool := by + have hraw : ComputableInPolyTime (fun p : Instance × List Bool => ((List.ofFn p.1.table, p.1.threshold), p.2)) (encPair encInstance encBits) (encPair (encPair encBits encNat) encBits) := .of_eq fun _ => rfl rw [funext verifier_eq_tableVerifier] - exact computableTidilyInPolyTime_tableVerifier.comp hraw + exact computableInPolyTime_tableVerifier.comp hraw /-- **MCSP is in `NP`**, for instances encoded by their truth table and the threshold in binary. -/ theorem mem_NP : MCSP ∈ NP encInstance := - ⟨certPolynomial, verifier, .of_tidy computableTidilyInPolyTime_verifier, isVerifier⟩ + ⟨certPolynomial, verifier, computableInPolyTime_verifier, isVerifier⟩ end Cslib.MCSP diff --git a/Complexity/Computability/Machines/Turing/MultiTape/Complexity/PolySpace.lean b/Complexity/Computability/Machines/Turing/MultiTape/Complexity/PolySpace.lean index 77ae29e6e..4ec837ef1 100644 --- a/Complexity/Computability/Machines/Turing/MultiTape/Complexity/PolySpace.lean +++ b/Complexity/Computability/Machines/Turing/MultiTape/Complexity/PolySpace.lean @@ -24,7 +24,7 @@ counted in binary, as long as the states stay of polynomial size (`Turing.MultiTapeTM.ComputableTidilyInPolySpace.iterate`). It is also closed under composition, pairing and case distinction, and contains polynomial time; these closure properties are registered with `fun_prop`. A Boolean function computable within polynomial space decides a problem in `PSPACE` -(`Cslib.Complexity.mem_PSPACE_iff_computableTidilyInPolySpace`). +(`Cslib.Complexity.mem_PSPACE_iff_computableInPolySpace`). Exhaustive searches within polynomial space enumerate their candidates with the binary counter `Cslib.BitString.increment`, which is computable in linear time diff --git a/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean b/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean index b48f02d2d..5b3437cab 100644 --- a/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean +++ b/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean @@ -172,7 +172,7 @@ theorem mem_PSPACE_iff_tm2 {α : Type} {encIn : α ↪ List Bool} {A : Set α} : (∀ stack, Finite (h.tm.Γ stack)) ∧ (∃ space : α → ℕ, PolyBounded (fun a => (encIn a).length) space ∧ h.StacksBounded space) ∧ (∀ a, a ∈ A ↔ f a = true) := by - rw [mem_PSPACE_iff_computableTidilyInPolySpace] + rw [mem_PSPACE_iff_computableInPolySpace] constructor · rintro ⟨f, hf, hA⟩ obtain ⟨h, hfinite, hspace⟩ := (ComputableInPolySpace.of_tidy hf).exists_tm2Computable diff --git a/Complexity/Computability/PCP/Approximation/IndependentSet.lean b/Complexity/Computability/PCP/Approximation/IndependentSet.lean index 2a25d6afd..6626fed65 100644 --- a/Complexity/Computability/PCP/Approximation/IndependentSet.lean +++ b/Complexity/Computability/PCP/Approximation/IndependentSet.lean @@ -180,7 +180,7 @@ gives an assignment satisfying as many clauses. -/ theorem polyTimeReducible_GapThreeSAT_GapIndependentSet (hs : s < 1) : PromiseProblem.PolyTimeReducible encCNF (encPair encGraph encNat) (GapThreeSAT s) (GapIndependentSet s) := by - refine ⟨SAT.toIndependentSet, .of_tidy SAT.computableTidilyInPolyTime_toIndependentSet, + refine ⟨SAT.toIndependentSet, SAT.computableInPolyTime_toIndependentSet, fun φ hφ => ?_, fun φ hφ => ?_⟩ · rw [yes_GapThreeSAT] at hφ rw [yes_GapIndependentSet] @@ -228,8 +228,8 @@ theorem polyTimeReducible_GapExactThreeSAT_GapVertexCover (hs : s < 1) : push_cast ring refine ⟨fun φ => IndependentSet.toVertexCover (SAT.toIndependentSet φ), - .of_tidy (IndependentSet.computableTidilyInPolyTime_toVertexCover.comp - SAT.computableTidilyInPolyTime_toIndependentSet), fun φ hφ => ?_, fun φ hφ => ?_⟩ + .of_tidy (IndependentSet.computableInPolyTime_toVertexCover.tidy.comp + SAT.computableInPolyTime_toIndependentSet.tidy), fun φ hφ => ?_, fun φ hφ => ?_⟩ · rw [yes_GapExactThreeSAT] at hφ obtain ⟨h3, hsat⟩ := hφ have hα : (φ.length : ℝ) ≤ (SAT.toIndependentSet φ).1.indepNum := by diff --git a/Complexity/Computability/PCP/Approximation/MaxCSP.lean b/Complexity/Computability/PCP/Approximation/MaxCSP.lean index dc490a243..fc8618719 100644 --- a/Complexity/Computability/PCP/Approximation/MaxCSP.lean +++ b/Complexity/Computability/PCP/Approximation/MaxCSP.lean @@ -83,7 +83,7 @@ theorem GapTwoCSP_npHard : PromiseProblem.NPHard (Graph.encoding (encPi (encPi encBool))) (GapTwoCSP (Bool × (Fin 6 → Bool)) (1 - 1 / 2 ^ 61)) := by refine PromiseProblem.npHard_of_polyTimeReducible_SAT - ⟨gapGraph, .of_tidy (isPolyTime_gapGraph ComputableTidilyInPolyTime.id'), fun φ hφ => ?_, + ⟨gapGraph, (isPolyTime_gapGraph (.of_tidy ComputableTidilyInPolyTime.id')), fun φ hφ => ?_, fun φ hφ => ?_⟩ · exact mem_yes_GapTwoCSP.2 ((satisfiable_gapGraph_iff φ).2 hφ) · refine (mem_no_GapTwoCSP (by norm_num)).2 ?_ diff --git a/Complexity/Computability/PCP/Approximation/MaxExactThreeSAT.lean b/Complexity/Computability/PCP/Approximation/MaxExactThreeSAT.lean index fcbf9f133..68e09218f 100644 --- a/Complexity/Computability/PCP/Approximation/MaxExactThreeSAT.lean +++ b/Complexity/Computability/PCP/Approximation/MaxExactThreeSAT.lean @@ -130,14 +130,15 @@ private theorem unsatVal_toExactThreeSAT (φ : CNF ℕ) : /-- The reduction is polynomial-time. -/ @[fun_prop] -theorem computableTidilyInPolyTime_reduce : ComputableTidilyInPolyTime reduce encCNF encCNF := by +theorem computableInPolyTime_reduce : ComputableInPolyTime reduce encCNF encCNF := by + refine .of_tidy ?_ unfold reduce have hany : ComputableTidilyInPolyTime (fun φ : CNF ℕ => φ.any List.isEmpty) encCNF encBool := ComputableTidilyInPolyTime.anyWithInput (ComputableTidilyInPolyTime.id' (encIn := encCNF)) ((ComputableTidilyInPolyTime.listIsEmpty' (encPair encNat encBool)).comp (ComputableTidilyInPolyTime.snd _ _)) exact ComputableTidilyInPolyTime.cond hany (.const _) - computableTidilyInPolyTime_toExactThreeSAT + computableInPolyTime_toExactThreeSAT.tidy end GapExactThreeSAT @@ -147,7 +148,7 @@ open GapExactThreeSAT soundness `1 / 2 ≤ s < 1`, by `GapExactThreeSAT.reduce`. -/ theorem polyTimeReducible_GapThreeSAT_GapExactThreeSAT (hs : 1 / 2 ≤ s) (hs1 : s < 1) : PromiseProblem.PolyTimeReducible encCNF encCNF (GapThreeSAT s) (GapExactThreeSAT s) := by - refine ⟨reduce, .of_tidy computableTidilyInPolyTime_reduce, fun φ hφ => ?_, fun φ hφ => ?_⟩ + refine ⟨reduce, computableInPolyTime_reduce, fun φ hφ => ?_, fun φ hφ => ?_⟩ · rw [yes_GapThreeSAT] at hφ rw [yes_GapExactThreeSAT] have hne : φ.any List.isEmpty = false := by diff --git a/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean b/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean index 09e46a1b5..f76d93847 100644 --- a/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean +++ b/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean @@ -253,7 +253,8 @@ variable [Fintype α] fixed list `pairs` is tested against its constraint table. -/ @[fun_prop] theorem isPolyTime_toCNF : - ComputableTidilyInPolyTime (toCNF e pairs) (encoding (encPi (encPi encBool))) encCNF := by + ComputableInPolyTime (toCNF e pairs) (encoding (encPi (encPi encBool))) encCNF := by + refine .of_tidy ?_ have hclause (p : α × α) : ComputableTidilyInPolyTime (fun d : Edge (α → α → Bool) => excludeClause e d.src d.dst p) (Edge.encoding (encPi (encPi encBool))) (encList (encPair encNat encBool)) := by @@ -266,7 +267,7 @@ theorem isPolyTime_toCNF : have hedge : ComputableTidilyInPolyTime (edgeCNF e pairs) (Edge.encoding (encPi (encPi encBool))) encCNF := mapFilterConst pairs (fun p _ => htest p) (fun p _ => hclause p) - exact flatMapWithInput (isPolyTime_edges id') (hedge.comp (snd _ _)) + exact flatMapWithInput (isPolyTime_edges (.of_tidy id')).tidy (hedge.comp (snd _ _)) end Cslib.PCP.Encoded.Graph @@ -324,7 +325,7 @@ theorem polyTimeReducible_GapTwoCSP_GapThreeSAT {α : Type} [Fintype α] {k : have hlen : pairs.length = Fintype.card α ^ 2 := by simp [pairs, Fintype.card_prod, sq] refine ⟨fun g => toThreeSAT (Graph.toCNF e pairs g), - .of_tidy (computableTidilyInPolyTime_toThreeSAT.comp (Graph.isPolyTime_toCNF e pairs)), + .of_tidy (computableInPolyTime_toThreeSAT.tidy.comp (Graph.isPolyTime_toCNF e pairs).tidy), fun g hg => ?_, fun g hg => ?_⟩ · rw [yes_GapThreeSAT, mem_ThreeSAT_toThreeSAT_iff] exact Graph.satisfiable_toCNF e pairs (mem_yes_GapTwoCSP.1 hg) diff --git a/Complexity/Computability/PCP/Completeness.lean b/Complexity/Computability/PCP/Completeness.lean index f62c66541..9fce4a820 100644 --- a/Complexity/Computability/PCP/Completeness.lean +++ b/Complexity/Computability/PCP/Completeness.lean @@ -68,7 +68,7 @@ theorem NP_subset_PCP_log {Input : Type} (input : Input ↪ List Bool) : (encPair (encPair encBool (encPi encBool)) (encPair encBool (encPi encBool)))) encBool := by fun_prop exact Graph.mem_PCP_of_gapReduction (FinEnum.card (Fin 6) + 1) - encodeLabel decodeLabel decode_encodeLabel (isPolyTime_gapGraph hreduce.tidy) heval + encodeLabel decodeLabel decode_encodeLabel (isPolyTime_gapGraph hreduce) (.of_tidy heval) (fun x => wellFormed_gapGraph (reduce x)) (fun x hx => (satisfiable_gapGraph_iff _).mpr ((hmem x).mp hx)) (gap := gap) gap_pos diff --git a/Complexity/Computability/PCP/Encoded/AddTrivial.lean b/Complexity/Computability/PCP/Encoded/AddTrivial.lean index f63d1f016..6807dc2d1 100644 --- a/Complexity/Computability/PCP/Encoded/AddTrivial.lean +++ b/Complexity/Computability/PCP/Encoded/AddTrivial.lean @@ -58,7 +58,7 @@ def addLoops (truth : C) (g : Graph C) : Graph C := /-- Appending explicitly listed trivial edges is uniformly polynomial-time in both lists. -/ @[fun_prop] theorem isPolyTime_addTrivial (enc : C ↪ List Bool) (truth : C) : - ComputableTidilyInPolyTime (fun p : Graph C × List (ℕ × ℕ) => + ComputableInPolyTime (fun p : Graph C × List (ℕ × ℕ) => p.1.addTrivial truth p.2) (encPair (encoding enc) (encList (encPair encUnary encUnary))) (encoding enc) := by unfold addTrivial @@ -67,7 +67,7 @@ theorem isPolyTime_addTrivial (enc : C ↪ List Bool) (truth : C) : /-- Constructing all self-loops, including enumerating their endpoints, is polynomial-time. -/ @[fun_prop] theorem isPolyTime_addLoops (enc : C ↪ List Bool) (truth : C) : - ComputableTidilyInPolyTime (addLoops truth) (encoding enc) (encoding enc) := by + ComputableInPolyTime (addLoops truth) (encoding enc) (encoding enc) := by unfold addLoops polytime diff --git a/Complexity/Computability/PCP/Encoded/Amplification.lean b/Complexity/Computability/PCP/Encoded/Amplification.lean index 74c1e0b54..e297dfb68 100644 --- a/Complexity/Computability/PCP/Encoded/Amplification.lean +++ b/Complexity/Computability/PCP/Encoded/Amplification.lean @@ -62,15 +62,15 @@ def amplify (eval : C → α → α → Bool) (fallback : C) theorem isPolyTime_amplify {Input : Type} {input : Input ↪ List Bool} {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {labelEncoding : D ↪ List Bool} {graph : Input → Graph C} {eval : C → α → α → Bool} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hrotate : ComputableTidilyInPolyTime rotate + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) - (heval : ComputableTidilyInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) (fallback : C) (T q : ℕ) [NeZero q] (walks : List (PowerLabel D T q)) (number : SelectedComposeSlot (PowerAlphabet D α T) ≃ Fin width) (coins : List (Fin 5 × Rand (PowerAlphabet D α T))) (queries : List (Fin 6)) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => (graph x).amplify eval fallback rotate T q walks number coins queries) input (encoding (encPi (encPi encBool))) := by unfold amplify diff --git a/Complexity/Computability/PCP/Encoded/Amplification/Arithmetic.lean b/Complexity/Computability/PCP/Encoded/Amplification/Arithmetic.lean index 850211b6e..12587d2eb 100644 --- a/Complexity/Computability/PCP/Encoded/Amplification/Arithmetic.lean +++ b/Complexity/Computability/PCP/Encoded/Amplification/Arithmetic.lean @@ -13,6 +13,7 @@ public import Complexity.Computability.PCP.Amplification.Arithmetic public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.RotationMap.TowerTable.Family import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.RotationMap.Family import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # A concrete executable gap amplifier @@ -67,16 +68,18 @@ def arithmeticAmplify (g : Graph Constraint) : Graph Constraint := @[fun_prop] theorem isPolyTime_arithmeticAmplify {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Constraint} - (hgraph : ComputableTidilyInPolyTime graph input (encoding (encPi (encPi encBool)))) + (hgraph : ComputableInPolyTime graph input (encoding (encPi (encPi encBool)))) (hwellFormed : ∀ x, (graph x).WellFormed) : - ComputableTidilyInPolyTime (fun x => arithmeticAmplify (graph x)) + ComputableInPolyTime (fun x => arithmeticAmplify (graph x)) input (encoding (encPi (encPi encBool))) := by + have hgraph := hgraph.tidy + refine .of_tidy ?_ have hcost := RotationMap.polytime_arithmeticExpanderRotate (encFinEnum Label) unfold arithmeticAmplify - exact isPolyTime_amplifyIter_clog hgraph hwellFormed RotationMap.arithmeticExpander - RotationMap.arithmeticExpanderRotate RotationMap.arithmeticExpanderRotate_eq hcost + exact (isPolyTime_amplifyIter_clog (.of_tidy hgraph) hwellFormed RotationMap.arithmeticExpander + RotationMap.arithmeticExpanderRotate RotationMap.arithmeticExpanderRotate_eq (.of_tidy hcost) (fun _ _ => true) walkLength killRate (FinEnum.toList _) FinEnum.equiv - (FinEnum.toList _) (FinEnum.toList _) + (FinEnum.toList _) (FinEnum.toList _)).tidy /-- Valid endpoint indices are preserved, including when the program performs no rounds. -/ theorem wellFormed_arithmeticAmplify {g : Graph Constraint} (hg : g.WellFormed) : diff --git a/Complexity/Computability/PCP/Encoded/Amplification/Enumeration.lean b/Complexity/Computability/PCP/Encoded/Amplification/Enumeration.lean index 00325b710..225fd1364 100644 --- a/Complexity/Computability/PCP/Encoded/Amplification/Enumeration.lean +++ b/Complexity/Computability/PCP/Encoded/Amplification/Enumeration.lean @@ -59,13 +59,13 @@ def amplifyEnumerated (eval : C → α → α → Bool) (fallback : C) theorem isPolyTime_amplifyEnumerated {Input : Type} {input : Input ↪ List Bool} {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {labelEncoding : D ↪ List Bool} {graph : Input → Graph C} {eval : C → α → α → Bool} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hrotate : ComputableTidilyInPolyTime rotate + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) - (heval : ComputableTidilyInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) (fallback : C) (T q : ℕ) [NeZero q] : - ComputableTidilyInPolyTime (fun x => (graph x).amplifyEnumerated eval fallback rotate T q) + ComputableInPolyTime (fun x => (graph x).amplifyEnumerated eval fallback rotate T q) input (encoding (encPi (encPi encBool))) := by unfold amplifyEnumerated fun_prop diff --git a/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean b/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean index 757256404..f7650a456 100644 --- a/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean +++ b/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.PCP.Encoded.Amplification public import Complexity.Computability.PCP.Encoded.Iteration import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Iteration import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Log +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # Iterating executable amplification rounds @@ -67,20 +68,23 @@ encoding. Well-formed endpoints and the full table bound supply the loop's size @[fun_prop] theorem isPolyTime_amplifyIter_clog {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Constraint} {labelEncoding : D ↪ List Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding (encPi (encPi encBool)))) + (hgraph : ComputableInPolyTime graph input (encoding (encPi (encPi encBool)))) (hwellFormed : ∀ x, (graph x).WellFormed) (family : (n : ℕ) → RotationMap (Fin n) D) (rotate : ℕ × (ℕ × D) → ℕ × D) (hrotate : ∀ n (v : Fin n) d, rotate (n, v.val, d) = (((family n).rot (v, d)).1.val, ((family n).rot (v, d)).2)) - (hcost : ComputableTidilyInPolyTime rotate + (hcost : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) (fallback : Constraint) (T q : ℕ) [NeZero q] (walks : List (PowerLabel D T q)) (number : SelectedComposeSlot (PowerAlphabet D SelectedAlphabet T) ≃ Fin width) (coins : List (Fin 5 × Rand (PowerAlphabet D SelectedAlphabet T))) (queries : List (Fin 6)) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => amplifyIter fallback rotate T q walks number coins queries (Nat.clog 2 (graph x).edges.length) (graph x)) input (encoding (encPi (encPi encBool))) := by + have hgraph := hgraph.tidy + have hcost := hcost.tidy + refine .of_tidy ?_ let factor := (2 + 2 * walks.length) * width + 2 * walks.length * coins.length * queries.length let descriptorBound := Fintype.card SelectedAlphabet * (6 * Fintype.card SelectedAlphabet + 1) have hgrowth (g : Graph Constraint) : @@ -92,10 +96,10 @@ theorem isPolyTime_amplifyIter_clog {Input : Type} {input : Input ↪ List Bool} ring _ ≤ _ := Nat.mul_le_mul_left _ (Nat.le_add_left _ _) have heval := - isPolyTime_constraintTableEval (α := SelectedAlphabet) (encPair encBool (encPi encBool)) + (isPolyTime_constraintTableEval (α := SelectedAlphabet) (encPair encBool (encPi encBool))).tidy unfold amplifyIter apply ComputableTidilyInPolyTime.iterate (by fun_prop) hgraph (by fun_prop) - (polyBounded_iterationSize_clog hgraph factor descriptorBound) + (polyBounded_iterationSize_clog (.of_tidy hgraph) factor descriptorBound) exact fun x _ hi => iterate_length_encoding_le (valid := WellFormed) factor descriptorBound (fun g _ => g.wellFormed_amplify id fallback family rotate hrotate T q walks number coins queries) diff --git a/Complexity/Computability/PCP/Encoded/AssignmentTester.lean b/Complexity/Computability/PCP/Encoded/AssignmentTester.lean index 9caac1a3f..1c3e5d18a 100644 --- a/Complexity/Computability/PCP/Encoded/AssignmentTester.lean +++ b/Complexity/Computability/PCP/Encoded/AssignmentTester.lean @@ -10,6 +10,7 @@ module public import Complexity.Computability.PCP.AssignmentTester public import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Pi public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime +public import Complexity.Computability.Machines.Turing.MultiTape.PolyTime import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Basic /-! @@ -117,17 +118,17 @@ theorem accepts_eq_true (constraint : α → α → Bool) (coins : Rand α) @[fun_prop] theorem isPolyTime_query (coinsEncoding : Rand α ↪ List Bool) (queryEncoding : Query ↪ List Bool) (positionEncoding : Pos α ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : (α → α → Bool) × Rand α × Query => query p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding)) positionEncoding := - ComputableTidilyInPolyTime.of_finite _ + ComputableInPolyTime.of_finite _ /-- Fixed-alphabet acceptance charges the supplied constraint, coins, and all query answers. -/ @[fun_prop] theorem isPolyTime_accepts (coinsEncoding : Rand α ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : (α → α → Bool) × Rand α × (Query → Bool) => accepts p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair coinsEncoding (encPi encBool))) encBool := - ComputableTidilyInPolyTime.of_finite _ + ComputableInPolyTime.of_finite _ end Cslib.PCP.Encoded.HadamardTester diff --git a/Complexity/Computability/PCP/Encoded/Basic.lean b/Complexity/Computability/PCP/Encoded/Basic.lean index 42425fecf..a2739b5b6 100644 --- a/Complexity/Computability/PCP/Encoded/Basic.lean +++ b/Complexity/Computability/PCP/Encoded/Basic.lean @@ -83,34 +83,40 @@ private theorem isPolyTime_toPair (enc : C ↪ List Bool) : /-- Reading an edge's first endpoint is polynomial-time. -/ @[fun_prop] theorem isPolyTime_src {edge : Input → Edge C} - (hedge : ComputableTidilyInPolyTime edge input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (edge x).src) input encUnary := - (isPolyTime_toPair enc).fst'.comp hedge + (hedge : ComputableInPolyTime edge input (encoding enc)) : + ComputableInPolyTime (fun x => (edge x).src) input encUnary := by + have hedge := hedge.tidy + exact .of_tidy ((isPolyTime_toPair enc).fst'.comp hedge) /-- Reading an edge's second endpoint is polynomial-time. -/ @[fun_prop] theorem isPolyTime_dst {edge : Input → Edge C} - (hedge : ComputableTidilyInPolyTime edge input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (edge x).dst) input encUnary := - (isPolyTime_toPair enc).snd'.fst'.comp hedge + (hedge : ComputableInPolyTime edge input (encoding enc)) : + ComputableInPolyTime (fun x => (edge x).dst) input encUnary := by + have hedge := hedge.tidy + exact .of_tidy ((isPolyTime_toPair enc).snd'.fst'.comp hedge) /-- Reading an edge's constraint descriptor is polynomial-time. -/ @[fun_prop] theorem isPolyTime_constraint {edge : Input → Edge C} - (hedge : ComputableTidilyInPolyTime edge input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (edge x).constraint) input enc := - (isPolyTime_toPair enc).snd'.snd'.comp hedge + (hedge : ComputableInPolyTime edge input (encoding enc)) : + ComputableInPolyTime (fun x => (edge x).constraint) input enc := by + have hedge := hedge.tidy + exact .of_tidy ((isPolyTime_toPair enc).snd'.snd'.comp hedge) /-- Assemble computed endpoints and a computed constraint into an edge. -/ @[fun_prop] theorem isPolyTime_mk {Input : Type} {input : Input ↪ List Bool} {enc : C ↪ List Bool} {src dst : Input → ℕ} {constraint : Input → C} - (hsrc : ComputableTidilyInPolyTime src input encUnary) - (hdst : ComputableTidilyInPolyTime dst input encUnary) - (hconstraint : ComputableTidilyInPolyTime constraint input enc) : - ComputableTidilyInPolyTime (fun x => Edge.mk (src x) (dst x) (constraint x)) - input (encoding enc) := - (hsrc.prod (hdst.prod hconstraint)).of_enc_eq fun _ => rfl + (hsrc : ComputableInPolyTime src input encUnary) + (hdst : ComputableInPolyTime dst input encUnary) + (hconstraint : ComputableInPolyTime constraint input enc) : + ComputableInPolyTime (fun x => Edge.mk (src x) (dst x) (constraint x)) + input (encoding enc) := by + have hsrc := hsrc.tidy + have hdst := hdst.tidy + have hconstraint := hconstraint.tidy + exact .of_tidy ((hsrc.prod (hdst.prod hconstraint)).of_enc_eq fun _ => rfl) end Edge @@ -143,25 +149,29 @@ private theorem isPolyTime_toPair (enc : C ↪ List Bool) : /-- Reading the declared vertex count is polynomial-time. -/ @[fun_prop] theorem isPolyTime_vertices {graph : Input → Graph C} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (graph x).vertices) input encUnary := - (isPolyTime_toPair enc).fst'.comp hgraph + (hgraph : ComputableInPolyTime graph input (encoding enc)) : + ComputableInPolyTime (fun x => (graph x).vertices) input encUnary := by + have hgraph := hgraph.tidy + exact .of_tidy ((isPolyTime_toPair enc).fst'.comp hgraph) /-- Reading the edge list is polynomial-time. -/ @[fun_prop] theorem isPolyTime_edges {graph : Input → Graph C} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (graph x).edges) input (encList (Edge.encoding enc)) := - (isPolyTime_toPair enc).snd'.comp hgraph + (hgraph : ComputableInPolyTime graph input (encoding enc)) : + ComputableInPolyTime (fun x => (graph x).edges) input (encList (Edge.encoding enc)) := by + have hgraph := hgraph.tidy + exact .of_tidy ((isPolyTime_toPair enc).snd'.comp hgraph) /-- Assemble a computed vertex count and edge list into a graph. -/ @[fun_prop] theorem isPolyTime_mk {Input : Type} {input : Input ↪ List Bool} {enc : C ↪ List Bool} {vertices : Input → ℕ} {edges : Input → List (Edge C)} - (hvertices : ComputableTidilyInPolyTime vertices input encUnary) - (hedges : ComputableTidilyInPolyTime edges input (encList (Edge.encoding enc))) : - ComputableTidilyInPolyTime (fun x => Graph.mk (vertices x) (edges x)) input (encoding enc) := - (hvertices.prod hedges).of_enc_eq fun _ => rfl + (hvertices : ComputableInPolyTime vertices input encUnary) + (hedges : ComputableInPolyTime edges input (encList (Edge.encoding enc))) : + ComputableInPolyTime (fun x => Graph.mk (vertices x) (edges x)) input (encoding enc) := by + have hvertices := hvertices.tidy + have hedges := hedges.tidy + exact .of_tidy ((hvertices.prod hedges).of_enc_eq fun _ => rfl) /-- All listed endpoints are among the declared vertices. -/ def WellFormed (g : Graph C) : Prop := @@ -176,10 +186,12 @@ def isWellFormed (g : Graph C) : Bool := theorem isWellFormed_eq_true (g : Graph C) : g.isWellFormed = true ↔ g.WellFormed := by simp [isWellFormed, WellFormed] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Checking all endpoint bounds is uniformly polynomial-time. -/ @[fun_prop] theorem isPolyTime_isWellFormed (enc : C ↪ List Bool) : - ComputableTidilyInPolyTime (isWellFormed (C := C)) (encoding enc) encBool := by + ComputableInPolyTime (isWellFormed (C := C)) (encoding enc) encBool := by + refine .of_tidy ?_ unfold isWellFormed polytime @@ -190,13 +202,15 @@ def edgeAt (fallback : C) (g : Graph C) (i : ℕ) : Edge C := /-- A computed graph determines the edge encoding before the index is checked. -/ @[fun_prop] theorem isPolyTime_edgeAt {graph : Input → Graph C} {index : Input → ℕ} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hindex : ComputableTidilyInPolyTime index input encUnary) (fallback : C) : - ComputableTidilyInPolyTime (fun x => (graph x).edgeAt fallback (index x)) - input (Edge.encoding enc) := - (ComputableTidilyInPolyTime.listGetD (encA := Edge.encoding enc) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hindex : ComputableInPolyTime index input encUnary) (fallback : C) : + ComputableInPolyTime (fun x => (graph x).edgeAt fallback (index x)) + input (Edge.encoding enc) := by + have hgraph := hgraph.tidy + have hindex := hindex.tidy + exact .of_tidy ((ComputableTidilyInPolyTime.listGetD (encA := Edge.encoding enc) (Edge.mk 0 0 fallback)).comp - ((isPolyTime_edges hgraph).prod hindex) + ((isPolyTime_edges (.of_tidy hgraph)).tidy.prod hindex)) /-- Check a numbered edge against a list of labels. Both lookups are total, with explicit fallbacks; the correctness theorem applies to valid edge indices. -/ @@ -210,12 +224,12 @@ def checkEdge (eval : C → α → α → Bool) (fallback : C) (label : α) theorem isPolyTime_checkEdge {alphabet : α ↪ List Bool} {graph : Input → Graph C} {labels : Input → List α} {index : Input → ℕ} {eval : C → α → α → Bool} (fallback : C) (label : α) - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) - (hlabels : ComputableTidilyInPolyTime labels input (encList alphabet)) - (hindex : ComputableTidilyInPolyTime index input encUnary) : - ComputableTidilyInPolyTime + (hlabels : ComputableInPolyTime labels input (encList alphabet)) + (hindex : ComputableInPolyTime index input encUnary) : + ComputableInPolyTime (fun x => checkEdge eval fallback label (graph x) (labels x) (index x)) input encBool := by unfold checkEdge polytime diff --git a/Complexity/Computability/PCP/Encoded/Cloud.lean b/Complexity/Computability/PCP/Encoded/Cloud.lean index 4e81aad25..707ece55b 100644 --- a/Complexity/Computability/PCP/Encoded/Cloud.lean +++ b/Complexity/Computability/PCP/Encoded/Cloud.lean @@ -68,8 +68,8 @@ def cloud (fallback : C) (g : Graph C) (vertex : ℕ) : List (ℕ × Bool) := /-- Enumerating both ends of every edge is polynomial-time. -/ @[fun_prop] theorem isPolyTime_halfEdges {graph : Input → Graph C} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) : - ComputableTidilyInPolyTime (fun x => (graph x).halfEdges) + (hgraph : ComputableInPolyTime graph input (encoding enc)) : + ComputableInPolyTime (fun x => (graph x).halfEdges) input (encList (encPair encUnary encBool)) := by unfold halfEdges List.product polytime @@ -77,10 +77,10 @@ theorem isPolyTime_halfEdges {graph : Input → Graph C} /-- Endpoint lookup is uniform in the graph and the half-edge. -/ @[fun_prop] theorem isPolyTime_endpoint {graph : Input → Graph C} {halfEdge : Input → ℕ × Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hhalfEdge : ComputableTidilyInPolyTime halfEdge input (encPair encUnary encBool)) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hhalfEdge : ComputableInPolyTime halfEdge input (encPair encUnary encBool)) (fallback : C) : - ComputableTidilyInPolyTime (fun x => (graph x).endpoint fallback (halfEdge x)) + ComputableInPolyTime (fun x => (graph x).endpoint fallback (halfEdge x)) input encUnary := by unfold endpoint polytime @@ -88,9 +88,9 @@ theorem isPolyTime_endpoint {graph : Input → Graph C} {halfEdge : Input → /-- Cloud enumeration charges each endpoint lookup and the entire filtered output. -/ @[fun_prop] theorem isPolyTime_cloud {graph : Input → Graph C} {vertex : Input → ℕ} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hvertex : ComputableTidilyInPolyTime vertex input encUnary) (fallback : C) : - ComputableTidilyInPolyTime (fun x => (graph x).cloud fallback (vertex x)) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hvertex : ComputableInPolyTime vertex input encUnary) (fallback : C) : + ComputableInPolyTime (fun x => (graph x).cloud fallback (vertex x)) input (encList (encPair encUnary encBool)) := by unfold cloud polytime diff --git a/Complexity/Computability/PCP/Encoded/CloudRotation.lean b/Complexity/Computability/PCP/Encoded/CloudRotation.lean index 145d16f31..f25875e7c 100644 --- a/Complexity/Computability/PCP/Encoded/CloudRotation.lean +++ b/Complexity/Computability/PCP/Encoded/CloudRotation.lean @@ -60,13 +60,13 @@ vertex and label. A separate machine for each size is insufficient. -/ @[fun_prop] theorem isPolyTime_cloudRotation {graph : Input → Graph C} {halfEdge : Input → (ℕ × Bool) × D} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hhalfEdge : ComputableTidilyInPolyTime halfEdge input + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hhalfEdge : ComputableInPolyTime halfEdge input (encPair (encPair encUnary encBool) labelEncoding)) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) (fallback : C) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => (graph x).cloudRotation fallback rotate (halfEdge x)) input (encPair (encPair encUnary encBool) labelEncoding) := by unfold cloudRotation diff --git a/Complexity/Computability/PCP/Encoded/Composition.lean b/Complexity/Computability/PCP/Encoded/Composition.lean index f3cfd189b..f415bff2d 100644 --- a/Complexity/Computability/PCP/Encoded/Composition.lean +++ b/Complexity/Computability/PCP/Encoded/Composition.lean @@ -112,11 +112,11 @@ alphabet's local proof position. -/ theorem isPolyTime_composePosition [Finite α] (number : ComposeSlot α ≃ Fin width) {edge src dst : Input → ℕ} {position : Input → Pos α} {positionEncoding : Pos α ↪ List Bool} - (hedge : ComputableTidilyInPolyTime edge input encUnary) - (hsrc : ComputableTidilyInPolyTime src input encUnary) - (hdst : ComputableTidilyInPolyTime dst input encUnary) - (hposition : ComputableTidilyInPolyTime position input positionEncoding) : - ComputableTidilyInPolyTime + (hedge : ComputableInPolyTime edge input encUnary) + (hsrc : ComputableInPolyTime src input encUnary) + (hdst : ComputableInPolyTime dst input encUnary) + (hposition : ComputableInPolyTime position input positionEncoding) : + ComputableInPolyTime (fun x => composePosition number (edge x) (src x) (dst x) (position x)) input encUnary := AssignmentTester.Implementation.isPolyTime_composePosition number hedge hsrc hdst hposition @@ -126,11 +126,11 @@ theorem isPolyTime_composeEdge (number : ComposeSlot α ≃ Fin width) {edge : Input → Edge (α → α → Bool)} {index : Input → ℕ} {coins : Input → Rand α} {query : Input → Query} {coinsEncoding : Rand α ↪ List Bool} {queryEncoding : Query ↪ List Bool} - (hedge : ComputableTidilyInPolyTime edge input (Edge.encoding (encPi (encPi encBool)))) - (hindex : ComputableTidilyInPolyTime index input encUnary) - (hcoins : ComputableTidilyInPolyTime coins input coinsEncoding) - (hquery : ComputableTidilyInPolyTime query input queryEncoding) : - ComputableTidilyInPolyTime (fun x => composeEdge number (edge x) (index x) (coins x) (query x)) + (hedge : ComputableInPolyTime edge input (Edge.encoding (encPi (encPi encBool)))) + (hindex : ComputableInPolyTime index input encUnary) + (hcoins : ComputableInPolyTime coins input coinsEncoding) + (hquery : ComputableInPolyTime query input queryEncoding) : + ComputableInPolyTime (fun x => composeEdge number (edge x) (index x) (coins x) (query x)) input (Edge.encoding (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding))) := Encoded.HadamardTester.implementation.isPolyTime_composeEdge number hedge hindex hcoins hquery @@ -139,7 +139,7 @@ theorem isPolyTime_composeEdge (number : ComposeSlot α ≃ Fin width) @[fun_prop] theorem isPolyTime_composeEval (coinsEncoding : Rand α ↪ List Bool) (queryEncoding : Query ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : ((α → α → Bool) × Rand α × Query) × (Bool × (Query → Bool)) × (Bool × (Query → Bool)) => composeEval p.1 p.2.1 p.2.2) (encPair (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding)) @@ -152,7 +152,7 @@ and the complete output graph. The finite alphabet and supplied lists are fixed. theorem isPolyTime_compose (number : ComposeSlot α ≃ Fin width) (coins : List (Rand α)) (queries : List Query) (coinsEncoding : Rand α ↪ List Bool) (queryEncoding : Query ↪ List Bool) : - ComputableTidilyInPolyTime (compose number coins queries) + ComputableInPolyTime (compose number coins queries) (encoding (encPi (encPi encBool))) (encoding (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding))) := Encoded.HadamardTester.implementation.isPolyTime_compose number coins queries coinsEncoding @@ -168,9 +168,9 @@ def composeTabulated (number : ComposeSlot α ≃ Fin width) (coins : List (Rand input graph in their own input representation. Every output constraint table is charged. -/ @[fun_prop] theorem isPolyTime_composeTabulated {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding (encPi (encPi encBool)))) + (hgraph : ComputableInPolyTime graph input (encoding (encPi (encPi encBool)))) (number : ComposeSlot α ≃ Fin width) (coins : List (Rand α)) (queries : List Query) : - ComputableTidilyInPolyTime (fun x => (graph x).composeTabulated number coins queries) + ComputableInPolyTime (fun x => (graph x).composeTabulated number coins queries) input (encoding (encPi (encPi encBool))) := Encoded.HadamardTester.implementation.isPolyTime_composeTabulated hgraph number coins queries diff --git a/Complexity/Computability/PCP/Encoded/Composition/Enumeration.lean b/Complexity/Computability/PCP/Encoded/Composition/Enumeration.lean index 297bc0c27..a93a16f56 100644 --- a/Complexity/Computability/PCP/Encoded/Composition/Enumeration.lean +++ b/Complexity/Computability/PCP/Encoded/Composition/Enumeration.lean @@ -69,8 +69,8 @@ and every output table. The input need not use the implementation's finite enume theorem isPolyTime_composeEnumerated {Input : Type} {input : Input ↪ List Bool} {constraintEncoding : (α → α → Bool) ↪ List Bool} {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding constraintEncoding)) : - ComputableTidilyInPolyTime (fun x => (graph x).composeEnumerated) + (hgraph : ComputableInPolyTime graph input (encoding constraintEncoding)) : + ComputableInPolyTime (fun x => (graph x).composeEnumerated) input (encoding (encPi (encPi encBool))) := Encoded.HadamardTester.implementation.isPolyTime_composeEnumerated hgraph diff --git a/Complexity/Computability/PCP/Encoded/Constraints.lean b/Complexity/Computability/PCP/Encoded/Constraints.lean index 00d41449f..e6977996d 100644 --- a/Complexity/Computability/PCP/Encoded/Constraints.lean +++ b/Complexity/Computability/PCP/Encoded/Constraints.lean @@ -104,9 +104,9 @@ theorem satisfiable_mapConstraints_iff (g : Graph C) (f : C → C') /-- Changing every descriptor charges the transformation, copying endpoints, and the output list. -/ @[fun_prop] theorem isPolyTime_mapConstraints {graph : Input → Graph C} {f : C → C'} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hf : ComputableTidilyInPolyTime f enc enc') : - ComputableTidilyInPolyTime (fun x => (graph x).mapConstraints f) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hf : ComputableInPolyTime f enc enc') : + ComputableInPolyTime (fun x => (graph x).mapConstraints f) input (encoding enc') := by unfold mapConstraints polytime @@ -115,9 +115,11 @@ theorem isPolyTime_mapConstraints {graph : Input → Graph C} {f : C → C'} @[fun_prop] theorem isPolyTime_constraintTable [Fintype α] {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime eval enc (encPi (encPi encBool)) := by + ComputableInPolyTime eval enc (encPi (encPi encBool)) := by + have heval := heval.tidy + refine .of_tidy ?_ apply ComputableTidilyInPolyTime.pi intro a apply ComputableTidilyInPolyTime.pi @@ -129,16 +131,16 @@ The source descriptor may have unbounded encoded size. -/ @[fun_prop] theorem isPolyTime_tabulateConstraints [Fintype α] {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime (mapConstraints eval) (encoding enc) + ComputableInPolyTime (mapConstraints eval) (encoding enc) (encoding (encPi (encPi encBool))) := isPolyTime_mapConstraints (.id' (encIn := encoding enc)) (isPolyTime_constraintTable heval) /-- Evaluate a stored constraint table at both runtime alphabet symbols. -/ @[fun_prop] theorem isPolyTime_constraintTableEval [Fintype α] (alphabet : α ↪ List Bool) : - ComputableTidilyInPolyTime (fun p : (α → α → Bool) × α × α => p.1 p.2.1 p.2.2) + ComputableInPolyTime (fun p : (α → α → Bool) × α × α => p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair alphabet alphabet)) encBool := by polytime diff --git a/Complexity/Computability/PCP/Encoded/DegreeReduction.lean b/Complexity/Computability/PCP/Encoded/DegreeReduction.lean index c6ddf77d2..1ee8b4916 100644 --- a/Complexity/Computability/PCP/Encoded/DegreeReduction.lean +++ b/Complexity/Computability/PCP/Encoded/DegreeReduction.lean @@ -54,7 +54,7 @@ def halfEdgeNumber (p : ℕ × Bool) : ℕ := /-- Numbering half-edges uses only unary arithmetic. -/ @[fun_prop] theorem isPolyTime_halfEdgeNumber : - ComputableTidilyInPolyTime halfEdgeNumber (encPair encUnary encBool) encUnary := by + ComputableInPolyTime halfEdgeNumber (encPair encUnary encBool) encUnary := by unfold halfEdgeNumber polytime @@ -97,25 +97,30 @@ def degreeReduceEval [DecidableEq α] (eval : C → α → α → Bool) /-- Enumerating all darts of degree reduction charges the full output list. -/ @[fun_prop] theorem isPolyTime_degreeReduceDarts {graph : Input → Graph C} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) (labels : List D) : - ComputableTidilyInPolyTime (fun x => (graph x).degreeReduceDarts labels) + (hgraph : ComputableInPolyTime graph input (encoding enc)) (labels : List D) : + ComputableInPolyTime (fun x => (graph x).degreeReduceDarts labels) input (encList (encPair (encPair encUnary encBool) (encOption labelEncoding))) := by unfold degreeReduceDarts List.product polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Every output edge is computed uniformly in the input graph and dart. -/ @[fun_prop] theorem isPolyTime_degreeReduceEdge {graph : Input → Graph C} {dart : Input → (ℕ × Bool) × Option D} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hdart : ComputableTidilyInPolyTime dart input + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hdart : ComputableInPolyTime dart input (encPair (encPair encUnary encBool) (encOption labelEncoding))) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) (fallback : C) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => (graph x).degreeReduceEdge fallback rotate (dart x)) input (Edge.encoding (encOption (encPair encBool enc))) := by + have hgraph := hgraph.tidy + have hdart := hdart.tidy + have hrotate := hrotate.tidy + refine .of_tidy ?_ unfold degreeReduceEdge polytime @@ -124,12 +129,12 @@ scans, searches, rotation calls, copying, and storage of the resulting graph. -/ @[fun_prop] theorem isPolyTime_degreeReduce (fallback : C) (labels : List D) (rotate : ℕ × (ℕ × D) → ℕ × D) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) : - ComputableTidilyInPolyTime (degreeReduce fallback rotate labels) + ComputableInPolyTime (degreeReduce fallback rotate labels) (encoding enc) (encoding (encOption (encPair encBool enc))) := by have hdarts := isPolyTime_degreeReduceDarts (enc := enc) - (labelEncoding := labelEncoding) (ComputableTidilyInPolyTime.id' (encIn := encoding enc)) labels + (labelEncoding := labelEncoding) (ComputableInPolyTime.id' (encIn := encoding enc)) labels unfold degreeReduce fun_prop @@ -138,9 +143,9 @@ of encoded labels. -/ @[fun_prop] theorem isPolyTime_degreeReduceEval [DecidableEq α] {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : Option (Bool × C) × α × α => degreeReduceEval eval p.1 p.2.1 p.2.2) (encPair (encOption (encPair encBool enc)) (encPair alphabet alphabet)) encBool := by unfold degreeReduceEval diff --git a/Complexity/Computability/PCP/Encoded/GapTheorem.lean b/Complexity/Computability/PCP/Encoded/GapTheorem.lean index 7d7e58f79..dcb20b867 100644 --- a/Complexity/Computability/PCP/Encoded/GapTheorem.lean +++ b/Complexity/Computability/PCP/Encoded/GapTheorem.lean @@ -65,14 +65,16 @@ names retain their supplied encoding until compaction, including sparse or repea @[fun_prop] theorem isPolyTime_gapGraph {V Input : Type} [DecidableEq V] {enc : V ↪ List Bool} {input : Input ↪ List Bool} {formula : Input → CNF V} - (hformula : ComputableTidilyInPolyTime formula input + (hformula : ComputableInPolyTime formula input (encList (encList (encPair enc encBool)))) : - ComputableTidilyInPolyTime (fun x => gapGraph (formula x)) input + ComputableInPolyTime (fun x => gapGraph (formula x)) input (Graph.encoding (encPi (encPi encBool))) := by + have hformula := hformula.tidy + refine .of_tidy ?_ unfold gapGraph apply Graph.isPolyTime_arithmeticAmplify - · exact Graph.isPolyTime_composeSelectedEnumerated - (Graph.isPolyTime_ofCompactCNF ((CNF.isPolyTime_to3CNF enc).tidy.comp hformula)) + · exact (Graph.isPolyTime_composeSelectedEnumerated + (Graph.isPolyTime_ofCompactCNF (.of_tidy ((CNF.isPolyTime_to3CNF enc).tidy.comp hformula)))).tidy · exact fun x => (Graph.wellFormed_ofCompactCNF (formula x).to3CNF).composeSelectedEnumerated /-- Every output edge has endpoints in the declared finite vertex range. -/ diff --git a/Complexity/Computability/PCP/Encoded/GenericComposition.lean b/Complexity/Computability/PCP/Encoded/GenericComposition.lean index 7fa361377..2c49b5cc3 100644 --- a/Complexity/Computability/PCP/Encoded/GenericComposition.lean +++ b/Complexity/Computability/PCP/Encoded/GenericComposition.lean @@ -119,12 +119,17 @@ alphabet's local proof position. -/ theorem isPolyTime_composePosition [Finite I] [Finite P] (number : ComposeSlot I P R ≃ Fin width) {edge src dst : Input → ℕ} {position : Input → ((Fin 2 × I) ⊕ P)} {positionEncoding : ((Fin 2 × I) ⊕ P) ↪ List Bool} - (hedge : ComputableTidilyInPolyTime edge input encUnary) - (hsrc : ComputableTidilyInPolyTime src input encUnary) - (hdst : ComputableTidilyInPolyTime dst input encUnary) - (hposition : ComputableTidilyInPolyTime position input positionEncoding) : - ComputableTidilyInPolyTime + (hedge : ComputableInPolyTime edge input encUnary) + (hsrc : ComputableInPolyTime src input encUnary) + (hdst : ComputableInPolyTime dst input encUnary) + (hposition : ComputableInPolyTime position input positionEncoding) : + ComputableInPolyTime (fun x => composePosition number (edge x) (src x) (dst x) (position x)) input encUnary := by + have hedge := hedge.tidy + have hsrc := hsrc.tidy + have hdst := hdst.tidy + have hposition := hposition.tidy + refine .of_tidy ?_ apply ComputableTidilyInPolyTime.finite_cases (branch := fun p x => composePosition number (edge x) (src x) (dst x) p) hposition rintro (⟨b, r⟩ | p) @@ -140,17 +145,17 @@ theorem isPolyTime_composeEdge [Fintype α] [Finite I] [Finite P] [Finite R] [Fi {edge : Input → Edge (α → α → Bool)} {index : Input → ℕ} {coins : Input → R} {query : Input → Q} {coinsEncoding : R ↪ List Bool} {queryEncoding : Q ↪ List Bool} - (hedge : ComputableTidilyInPolyTime edge input (Edge.encoding (encPi (encPi encBool)))) - (hindex : ComputableTidilyInPolyTime index input encUnary) - (hcoins : ComputableTidilyInPolyTime coins input coinsEncoding) - (hquery : ComputableTidilyInPolyTime query input queryEncoding) : - ComputableTidilyInPolyTime + (hedge : ComputableInPolyTime edge input (Edge.encoding (encPi (encPi encBool)))) + (hindex : ComputableInPolyTime index input encUnary) + (hcoins : ComputableInPolyTime coins input coinsEncoding) + (hquery : ComputableInPolyTime query input queryEncoding) : + ComputableInPolyTime (fun x => composeEdge impl number (edge x) (index x) (coins x) (query x)) input (Edge.encoding (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding))) := by - have hnumber : ComputableTidilyInPolyTime (fun ω => (number (.inr (.inr ω))).val) + have hnumber : ComputableInPolyTime (fun ω => (number (.inr (.inr ω))).val) coinsEncoding encUnary := .of_finite _ - have hposition : ComputableTidilyInPolyTime + have hposition : ComputableInPolyTime (fun p : (α → α → Bool) × R × Q => impl.query p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding)) (encFinite ((Fin 2 × I) ⊕ P)) := .of_finite _ @@ -159,8 +164,8 @@ theorem isPolyTime_composeEdge [Fintype α] [Finite I] [Finite P] [Finite R] [Fi have hdst' := isPolyTime_composePosition number hindex (Edge.isPolyTime_src hedge) (Edge.isPolyTime_dst hedge) hposition' exact Edge.isPolyTime_mk - (ComputableTidilyInPolyTime.unary_add.comp - ((ComputableTidilyInPolyTime.unary_mul.comp (hindex.prod (.const width))).prod + (ComputableInPolyTime.unary_add.comp + ((ComputableInPolyTime.unary_mul.comp (hindex.prod (.const width))).prod (hnumber.comp hcoins))) hdst' ((Edge.isPolyTime_constraint hedge).prod (hcoins.prod hquery)) @@ -169,7 +174,7 @@ theorem isPolyTime_composeEdge [Fintype α] [Finite I] [Finite P] [Finite R] [Fi theorem isPolyTime_composeEval [Fintype α] [Fintype Q] [Finite R] [Finite Γ] [BEq Γ] (symbolEncoding : Γ ↪ List Bool) (coinsEncoding : R ↪ List Bool) (queryEncoding : Q ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : ((α → α → Bool) × R × Q) × (Γ × (Q → Γ)) × (Γ × (Q → Γ)) => composeEval impl p.1 p.2.1 p.2.2) (encPair (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding)) @@ -184,10 +189,10 @@ theorem isPolyTime_compose [Fintype α] [Finite I] [Finite P] [Finite R] [Finite (number : ComposeSlot I P R ≃ Fin width) (coins : List R) (queries : List Q) (coinsEncoding : R ↪ List Bool) (queryEncoding : Q ↪ List Bool) : - ComputableTidilyInPolyTime (compose impl number coins queries) + ComputableInPolyTime (compose impl number coins queries) (encoding (encPi (encPi encBool))) (encoding (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding))) := by - have hdarts : ComputableTidilyInPolyTime (composeDarts (α := α) coins queries) + have hdarts : ComputableInPolyTime (composeDarts (α := α) coins queries) (encoding (encPi (encPi encBool))) (encList (encPair (encPair encUnary coinsEncoding) queryEncoding)) := by unfold composeDarts List.product @@ -206,9 +211,9 @@ input graph in their own input representation. Every output constraint table is @[fun_prop] theorem isPolyTime_composeTabulated [Fintype α] [Finite I] [Finite P] [Finite R] [Fintype Q] [DecidableEq Q] [Fintype Γ] [BEq Γ] {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding (encPi (encPi encBool)))) + (hgraph : ComputableInPolyTime graph input (encoding (encPi (encPi encBool)))) (number : ComposeSlot I P R ≃ Fin width) (coins : List R) (queries : List Q) : - ComputableTidilyInPolyTime (fun x => composeTabulated impl number coins queries (graph x)) + ComputableInPolyTime (fun x => composeTabulated impl number coins queries (graph x)) input (encoding (encPi (encPi encBool))) := (isPolyTime_tabulateConstraints (isPolyTime_composeEval impl (encFinite Γ) (encFinite R) (encFinite Q))).comp diff --git a/Complexity/Computability/PCP/Encoded/GenericComposition/Enumeration.lean b/Complexity/Computability/PCP/Encoded/GenericComposition/Enumeration.lean index 17a7a7815..dca6bc85b 100644 --- a/Complexity/Computability/PCP/Encoded/GenericComposition/Enumeration.lean +++ b/Complexity/Computability/PCP/Encoded/GenericComposition/Enumeration.lean @@ -55,11 +55,11 @@ theorem isPolyTime_composeEnumerated [Finite α] [Fintype Γ] {Input : Type} {input : Input ↪ List Bool} {constraintEncoding : (α → α → Bool) ↪ List Bool} {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding constraintEncoding)) : - ComputableTidilyInPolyTime (fun x => impl.composeEnumerated (graph x)) + (hgraph : ComputableInPolyTime graph input (encoding constraintEncoding)) : + ComputableInPolyTime (fun x => impl.composeEnumerated (graph x)) input (encoding (encPi (encPi encBool))) := by let := Fintype.ofFinite α - have hconvert : ComputableTidilyInPolyTime (id : (α → α → Bool) → _) + have hconvert : ComputableInPolyTime (id : (α → α → Bool) → _) constraintEncoding (encPi (encPi encBool)) := .of_finite _ simpa only [composeEnumerated, mapConstraints_id] using impl.isPolyTime_composeTabulated (isPolyTime_mapConstraints hgraph hconvert) diff --git a/Complexity/Computability/PCP/Encoded/Iteration.lean b/Complexity/Computability/PCP/Encoded/Iteration.lean index d79373ef1..5050e39cb 100644 --- a/Complexity/Computability/PCP/Encoded/Iteration.lean +++ b/Complexity/Computability/PCP/Encoded/Iteration.lean @@ -53,14 +53,16 @@ def iterationSize (factor descriptorBound rounds : ℕ) (g : Graph C) : ℕ := let size := max factor 1 ^ rounds * (g.vertices + g.edges.length) 2 * size + 1 + size * (8 * size + 2 * descriptorBound + 5) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The logarithmic-round state bound is polynomial in any efficiently computed initial graph. Its fixed-factor power is computed by the existing charged logarithm/power certificate. -/ theorem polyBounded_iterationSize_clog {graph : Input → Graph C} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) + (hgraph : ComputableInPolyTime graph input (encoding enc)) (factor descriptorBound : ℕ) : PolyBounded (fun x => (input x).length) (fun x => iterationSize factor descriptorBound (Nat.clog 2 (graph x).edges.length) (graph x)) := by + have hgraph := hgraph.tidy apply ComputableTidilyInPolyTime.polyBounded unfold iterationSize polytime diff --git a/Complexity/Computability/PCP/Encoded/Power.lean b/Complexity/Computability/PCP/Encoded/Power.lean index 9ccd43fc9..cd8dd9886 100644 --- a/Complexity/Computability/PCP/Encoded/Power.lean +++ b/Complexity/Computability/PCP/Encoded/Power.lean @@ -12,6 +12,7 @@ public import Complexity.Computability.PCP.Power.Complexity import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Computability.PCP.Encoded.Constraints +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # Executable powering after preprocessing @@ -224,12 +225,12 @@ private theorem polytime_powerPreprocessEdge (eval : C → α → α → Bool) ( (encPair alphabet alphabet))) encBool := by fun_prop have hwalk := rotationMap_killedPowRotWithInput hr T q (encFinEnum (Fin q)) - have hrel := RegularConstraintGraph.isPolyTime_powerRelationWithInput - hr he T q (encFinEnum (Fin q)) + have hrel := (RegularConstraintGraph.isPolyTime_powerRelationWithInput + (.of_tidy hr) (.of_tidy he) T q (encFinEnum (Fin q))).tidy unfold powerPreprocessEdge apply Edge.isPolyTime_mk · fun_prop - · exact isPolyTime_halfEdgeNumber.comp hwalk.fst' + · exact isPolyTime_halfEdgeNumber.tidy.comp hwalk.fst' · apply pi intro a apply pi @@ -265,16 +266,20 @@ internal enumeration, so matching an ordinary graph expression never unfolds tha @[fun_prop] theorem isPolyTime_powerPreprocess [Finite D] [Finite α] {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph C} {eval : C → α → α → Bool} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hrotate : ComputableTidilyInPolyTime rotate + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) - (heval : ComputableTidilyInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) (fallback : C) (T q : ℕ) [NeZero q] (walks : List (PowerLabel D T q)) {output : (PowerAlphabet D α T → PowerAlphabet D α T → Bool) ↪ List Bool} : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => (graph x).powerPreprocess eval fallback rotate T q walks) input (encoding output) := by + have hgraph := hgraph.tidy + have hrotate := hrotate.tidy + have heval := heval.tidy + refine .of_tidy ?_ classical let _ := Fintype.ofFinite D let _ := Fintype.ofFinite α @@ -282,7 +287,7 @@ theorem isPolyTime_powerPreprocess [Finite D] [Finite α] {Input : Type} {input have hconvert : ComputableTidilyInPolyTime (id : (PowerAlphabet D α T → PowerAlphabet D α T → Bool) → _) (encPi (encPi encBool)) output := .of_finite _ - simpa only [mapConstraints_id, Function.comp_def] using isPolyTime_mapConstraints hp hconvert + simpa only [mapConstraints_id, Function.comp_def] using (isPolyTime_mapConstraints (.of_tidy hp) (.of_tidy hconvert)).tidy end Complexity diff --git a/Complexity/Computability/PCP/Encoded/Preprocess.lean b/Complexity/Computability/PCP/Encoded/Preprocess.lean index dc2a1c762..cc158e343 100644 --- a/Complexity/Computability/PCP/Encoded/Preprocess.lean +++ b/Complexity/Computability/PCP/Encoded/Preprocess.lean @@ -68,9 +68,9 @@ def preprocess (fallback truth : C) (rotate : ℕ × (ℕ × D) → ℕ × D) /-- Enumerating all edges charges the runtime vertex count and every rotation call. -/ @[fun_prop] theorem isPolyTime_rotationEdges (rotate : ℕ × (ℕ × D) → ℕ × D) (labels : List D) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) : - ComputableTidilyInPolyTime (rotationEdges rotate labels) encUnary + ComputableInPolyTime (rotationEdges rotate labels) encUnary (encList (encPair encUnary encUnary)) := by unfold rotationEdges polytime @@ -80,9 +80,9 @@ all edge checks used by cloud search, and materializing every intermediate graph @[fun_prop] theorem isPolyTime_preprocess (fallback truth : C) (rotate : ℕ × (ℕ × D) → ℕ × D) (labels : List D) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) : - ComputableTidilyInPolyTime (preprocess fallback truth rotate labels) + ComputableInPolyTime (preprocess fallback truth rotate labels) (encoding enc) (encoding (encOption (encPair encBool enc))) := by have hdegree := isPolyTime_degreeReduce (enc := enc) fallback labels rotate hrotate unfold preprocess diff --git a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean index 2cdc689c6..8c0b987eb 100644 --- a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean +++ b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.PCP.Encoded.Preprocess import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Div import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Finite import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Rotation and constraint programs for preprocessing @@ -69,7 +70,7 @@ private theorem halfEdgeOfNumber_eq (edges : ℕ) (v : Fin (2 * edges)) : /-- Dividing by two and reading the low bit are polynomial-time in the unary vertex name. -/ @[fun_prop] -theorem isPolyTime_halfEdgeOfNumber : ComputableTidilyInPolyTime halfEdgeOfNumber +theorem isPolyTime_halfEdgeOfNumber : ComputableInPolyTime halfEdgeOfNumber encUnary (encPair encUnary encBool) := by unfold halfEdgeOfNumber fun_prop @@ -145,6 +146,8 @@ theorem preprocessRelation_eq_true [DecidableEq α] (g : Graph C) variable {enc : C ↪ List Bool} {labelEncoding : D ↪ List Bool} {dartEncoding : PreprocessLabel D ↪ List Bool} +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A fixed finite dart label selects a branch; each branch charges the runtime graph and vertex. The numerical rotation certificate is joint in size, vertex and edge label. -/ private theorem polytime_preprocessRotation [Finite D] (fallback : C) @@ -183,11 +186,13 @@ private theorem polytime_preprocessRotation [Finite D] (fallback : C) have hlabel : ComputableTidilyInPolyTime (fun d : D => (Sum.inl (Sum.inr d) : PreprocessLabel D)) labelEncoding dartEncoding := .of_finite _ - exact (isPolyTime_halfEdgeOfNumber.comp hnext.fst').prod (hlabel.comp hnext.snd') + exact (isPolyTime_halfEdgeOfNumber.tidy.comp hnext.fst').prod (hlabel.comp hnext.snd') · simp only [preprocessRotation] fun_prop exact ((ComputableTidilyInPolyTime.snd _ _).snd').finite_cases hbranch +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Constraint evaluation charges the original descriptor and both endpoint labels. -/ private theorem polytime_preprocessRelation [Finite D] [DecidableEq α] {alphabet : α ↪ List Bool} (eval : C → α → α → Bool) (fallback : C) @@ -213,14 +218,18 @@ private theorem polytime_preprocessRelation [Finite D] [DecidableEq α] theorem isPolyTime_preprocessRotation [Finite D] {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph C} {dart : Input → (ℕ × Bool) × PreprocessLabel D} {rotate : ℕ × (ℕ × D) → ℕ × D} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hdart : ComputableTidilyInPolyTime dart input + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hdart : ComputableInPolyTime dart input (encPair (encPair encUnary encBool) dartEncoding)) - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary labelEncoding)) (encPair encUnary labelEncoding)) - (fallback : C) : ComputableTidilyInPolyTime + (fallback : C) : ComputableInPolyTime (fun x => (graph x).preprocessRotation fallback rotate (dart x)) input (encPair (encPair encUnary encBool) dartEncoding) := by + have hgraph := hgraph.tidy + have hdart := hdart.tidy + have hrotate := hrotate.tidy + refine .of_tidy ?_ have hf := polytime_preprocessRotation (enc := enc) (dartEncoding := dartEncoding) fallback rotate hrotate have hg := hgraph.prod hdart @@ -232,17 +241,22 @@ theorem isPolyTime_preprocessRelation [Finite D] [DecidableEq α] {Input : Type} {input : Input ↪ List Bool} {alphabet : α ↪ List Bool} {graph : Input → Graph C} {dart : Input → (ℕ × Bool) × PreprocessLabel D} {left right : Input → α} {eval : C → α → α → Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hdart : ComputableTidilyInPolyTime dart input + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hdart : ComputableInPolyTime dart input (encPair (encPair encUnary encBool) dartEncoding)) - (heval : ComputableTidilyInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) - (hleft : ComputableTidilyInPolyTime left input alphabet) - (hright : ComputableTidilyInPolyTime right input alphabet) (fallback : C) : - ComputableTidilyInPolyTime + (hleft : ComputableInPolyTime left input alphabet) + (hright : ComputableInPolyTime right input alphabet) (fallback : C) : + ComputableInPolyTime (fun x => (graph x).preprocessRelation eval fallback (dart x) (left x) (right x)) - input encBool := - (polytime_preprocessRelation (dartEncoding := dartEncoding) eval fallback heval).comp - (hgraph.prod (hdart.prod (hleft.prod hright))) + input encBool := by + have hgraph := hgraph.tidy + have hdart := hdart.tidy + have heval := heval.tidy + have hleft := hleft.tidy + have hright := hright.tidy + exact .of_tidy ((polytime_preprocessRelation (dartEncoding := dartEncoding) eval fallback heval).comp + (hgraph.prod (hdart.prod (hleft.prod hright)))) end Cslib.PCP.Encoded.Graph diff --git a/Complexity/Computability/PCP/Encoded/SelectedAssignmentTester.lean b/Complexity/Computability/PCP/Encoded/SelectedAssignmentTester.lean index fad1cea7c..1d2e482a9 100644 --- a/Complexity/Computability/PCP/Encoded/SelectedAssignmentTester.lean +++ b/Complexity/Computability/PCP/Encoded/SelectedAssignmentTester.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.PCP.Encoded.AssignmentTester public import Complexity.Computability.PCP.AssignmentTester.Selection +public import Complexity.Computability.Machines.Turing.MultiTape.PolyTime import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Basic /-! @@ -88,17 +89,17 @@ theorem accepts_eq_true (constraint : α → α → Bool) (coins : Fin 5 × Rand @[fun_prop] theorem isPolyTime_query (coinsEncoding : (Fin 5 × Rand α) ↪ List Bool) (queryEncoding : Fin 6 ↪ List Bool) (positionEncoding : Pos α ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : (α → α → Bool) × (Fin 5 × Rand α) × Fin 6 ↦ query p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair coinsEncoding queryEncoding)) positionEncoding := - ComputableTidilyInPolyTime.of_finite _ + ComputableInPolyTime.of_finite _ /-- Acceptance charges the full supplied input, including all six answers. -/ @[fun_prop] theorem isPolyTime_accepts (coinsEncoding : (Fin 5 × Rand α) ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : (α → α → Bool) × (Fin 5 × Rand α) × (Fin 6 → Bool) ↦ accepts p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair coinsEncoding (encPi encBool))) encBool := - ComputableTidilyInPolyTime.of_finite _ + ComputableInPolyTime.of_finite _ end Cslib.PCP.Encoded.SelectedHadamardTester diff --git a/Complexity/Computability/PCP/Encoded/SelectedComposition.lean b/Complexity/Computability/PCP/Encoded/SelectedComposition.lean index be35886b6..19755300d 100644 --- a/Complexity/Computability/PCP/Encoded/SelectedComposition.lean +++ b/Complexity/Computability/PCP/Encoded/SelectedComposition.lean @@ -74,10 +74,10 @@ def composeSelectedTabulated (number : SelectedComposeSlot α ≃ Fin width) @[fun_prop] theorem isPolyTime_composeSelectedTabulated {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding (encPi (encPi encBool)))) + (hgraph : ComputableInPolyTime graph input (encoding (encPi (encPi encBool)))) (number : SelectedComposeSlot α ≃ Fin width) (coins : List (Fin 5 × Rand α)) (queries : List (Fin 6)) : - ComputableTidilyInPolyTime (fun x => (graph x).composeSelectedTabulated number coins queries) + ComputableInPolyTime (fun x => (graph x).composeSelectedTabulated number coins queries) input (encoding (encPi (encPi encBool))) := SelectedHadamardTester.implementation.isPolyTime_composeTabulated hgraph number coins queries diff --git a/Complexity/Computability/PCP/Encoded/SelectedComposition/Enumeration.lean b/Complexity/Computability/PCP/Encoded/SelectedComposition/Enumeration.lean index 2c0bbde5f..9efdfefb3 100644 --- a/Complexity/Computability/PCP/Encoded/SelectedComposition/Enumeration.lean +++ b/Complexity/Computability/PCP/Encoded/SelectedComposition/Enumeration.lean @@ -60,8 +60,8 @@ def composeSelectedEnumerated (g : Graph (α → α → Bool)) : theorem isPolyTime_composeSelectedEnumerated {Input : Type} {input : Input ↪ List Bool} {constraintEncoding : (α → α → Bool) ↪ List Bool} {graph : Input → Graph (α → α → Bool)} - (hgraph : ComputableTidilyInPolyTime graph input (encoding constraintEncoding)) : - ComputableTidilyInPolyTime (fun x => (graph x).composeSelectedEnumerated) + (hgraph : ComputableInPolyTime graph input (encoding constraintEncoding)) : + ComputableInPolyTime (fun x => (graph x).composeSelectedEnumerated) input (encoding (encPi (encPi encBool))) := SelectedHadamardTester.implementation.isPolyTime_composeEnumerated hgraph diff --git a/Complexity/Computability/PCP/Encoded/ThreeSAT.lean b/Complexity/Computability/PCP/Encoded/ThreeSAT.lean index cb23e097a..08434e849 100644 --- a/Complexity/Computability/PCP/Encoded/ThreeSAT.lean +++ b/Complexity/Computability/PCP/Encoded/ThreeSAT.lean @@ -81,8 +81,9 @@ def ofCompactCNF {V : Type} [DecidableEq V] (φ : CNF V) : /-- Checking a clause label includes lookup of the literals at its three positions. -/ @[fun_prop] theorem isPolyTime_clauseHolds : - ComputableTidilyInPolyTime (fun p : Clause ℕ × (Fin 3 → Bool) => clauseHolds p.1 p.2) + ComputableInPolyTime (fun p : Clause ℕ × (Fin 3 → Bool) => clauseHolds p.1 p.2) (encPair (encList (encPair encUnary encBool)) (encPi encBool)) encBool := by + refine .of_tidy ?_ unfold clauseHolds apply anyWithInput (encA := encFinEnum (Fin 3)) (by fun_prop) apply finite_cases (branch := fun (i : Fin 3) (p : (Clause ℕ × (Fin 3 → Bool)) × Fin 3) => @@ -90,13 +91,15 @@ theorem isPolyTime_clauseHolds : intro i apply optionElimWithInput (encB := encPair encUnary encBool) <;> fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The per-edge program charges clause lookup, endpoints, and all 64 entries of its relation. -/ @[fun_prop] theorem isPolyTime_cnfEdge : - ComputableTidilyInPolyTime (fun p : CNF ℕ × (ℕ × Fin 3) => cnfEdge p.1 p.2) + ComputableInPolyTime (fun p : CNF ℕ × (ℕ × Fin 3) => cnfEdge p.1 p.2) (encPair (encList (encList (encPair encUnary encBool))) (encPair encUnary (encFinEnum (Fin 3)))) (Edge.encoding (encPi (encPi encBool))) := by + refine .of_tidy ?_ have hindex : ComputableTidilyInPolyTime (Fin.val (n := 3)) (encFinEnum (Fin 3)) encUnary := .of_finite _ have hclause : ComputableTidilyInPolyTime @@ -115,10 +118,10 @@ theorem isPolyTime_cnfEdge : /-- Constructing all edges and copying their constraints is polynomial-time. -/ @[fun_prop] theorem isPolyTime_ofCNF : - ComputableTidilyInPolyTime (fun p : ℕ × CNF ℕ => ofCNF p.1 p.2) + ComputableInPolyTime (fun p : ℕ × CNF ℕ => ofCNF p.1 p.2) (encPair encUnary (encList (encList (encPair encUnary encBool)))) (encoding (encPi (encPi encBool))) := by - have hdarts : ComputableTidilyInPolyTime + have hdarts : ComputableInPolyTime (fun p : ℕ × CNF ℕ => (List.range p.2.length).product (List.finRange 3)) (encPair encUnary (encList (encList (encPair encUnary encBool)))) (encList (encPair encUnary (encFinEnum (Fin 3)))) := by @@ -132,9 +135,9 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] theorem isPolyTime_ofCompactCNF {V Input : Type} [DecidableEq V] {enc : V ↪ List Bool} {input : Input ↪ List Bool} {formula : Input → CNF V} - (hformula : ComputableTidilyInPolyTime formula input + (hformula : ComputableInPolyTime formula input (encList (encList (encPair enc encBool)))) : - ComputableTidilyInPolyTime (fun x => ofCompactCNF (formula x)) + ComputableInPolyTime (fun x => ofCompactCNF (formula x)) input (encoding (encPi (encPi encBool))) := by unfold ofCompactCNF polytime diff --git a/Complexity/Computability/PCP/Encoded/Verifier.lean b/Complexity/Computability/PCP/Encoded/Verifier.lean index ed39bb3e3..0328d14d1 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier.lean @@ -79,11 +79,13 @@ theorem proofVerdict_answers (width : ℕ) (decode : (Fin width → Bool) → α · simp [PCPVerifier.answers, proofQueries, List.getElem?_append, i.isLt] · simp [PCPVerifier.answers, proofQueries, i.isLt] +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Query construction is efficient, with positions returned in binary. -/ @[fun_prop] theorem isPolyTime_proofQueries (width : ℕ) (enc : C ↪ List Bool) : - ComputableTidilyInPolyTime (proofQueries width : Edge C → List ℕ) + ComputableInPolyTime (proofQueries width : Edge C → List ℕ) (encoding enc) (encList encNat) := by + refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (proofQueries width : Edge C → List ℕ) (encoding enc) (encList encUnary) := by unfold proofQueries @@ -91,15 +93,18 @@ theorem isPolyTime_proofQueries (width : ℕ) (enc : C ↪ List Bool) : simpa only [List.map_id', Function.comp_def] using ComputableTidilyInPolyTime.unary_to_binary.map.comp h +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A fixed finite decoder and a joint evaluator give an efficient verdict on arbitrary answers. -/ @[fun_prop] theorem isPolyTime_proofVerdict (width : ℕ) (decode : (Fin width → Bool) → α) {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : Edge C × List Bool => p.1.proofVerdict width decode eval p.2) (encPair (encoding enc) encBits) encBool := by + have heval := heval.tidy + refine .of_tidy ?_ have hdecode : ComputableTidilyInPolyTime decode (encPi encBool) alphabet := .of_finite _ unfold proofVerdict fun_prop @@ -118,9 +123,9 @@ def sampleEdge (g : Graph C) (random : List Bool) : Option (Edge C) := @[fun_prop] theorem isPolyTime_sampleEdge {Input : Type} {input : Input ↪ List Bool} {enc : C ↪ List Bool} {graph : Input → Graph C} {random : Input → List Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (hrandom : ComputableTidilyInPolyTime random input encBits) : - ComputableTidilyInPolyTime (fun x => (graph x).sampleEdge (random x)) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (hrandom : ComputableInPolyTime random input encBits) : + ComputableInPolyTime (fun x => (graph x).sampleEdge (random x)) input (encOption (Edge.encoding enc)) := by unfold sampleEdge fun_prop @@ -225,12 +230,14 @@ theorem accepts_proofOfLabels (width : ℕ) (encode : α → Fin width → Bool) obtain ⟨i, hi⟩ := List.get_of_mem hmem simpa only [ConstraintGraph.Satisfies, toGraph, hi] using hsat i +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- All verifier functions are polynomial-time, including on random strings of the wrong length. -/ theorem polyTime_edgeVerifier (width : ℕ) (decode : (Fin width → Bool) → α) {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : (edgeVerifier width decode eval).PolyTime (encoding enc) := by + have heval := heval.tidy refine ⟨.of_tidy ?_, .of_tidy ?_, .of_tidy ?_⟩ · exact ComputableTidilyInPolyTime.unary_to_binary.comp (by change ComputableTidilyInPolyTime (fun g : Graph C => Nat.clog 2 g.edges.length) diff --git a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean index 68e5b0f76..da5ac0f33 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean @@ -60,11 +60,13 @@ theorem polyTime_reductionVerifier {graph : Input → Graph C} (width repeats : (decode : (Fin width → Bool) → α) {input : Input ↪ List Bool} {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : (reductionVerifier graph width repeats decode eval).PolyTime input := by - obtain ⟨hcoins, hqueries, hverdict⟩ := polyTime_repeatedEdgeVerifier width repeats decode heval + have hgraph := hgraph.tidy + have heval := heval.tidy + obtain ⟨hcoins, hqueries, hverdict⟩ := polyTime_repeatedEdgeVerifier width repeats decode (.of_tidy heval) exact ⟨hcoins.comp (.of_tidy hgraph), .of_tidy (hqueries.tidy.comp (by fun_prop)), .of_tidy (hverdict.tidy.comp (by fun_prop))⟩ @@ -76,8 +78,8 @@ theorem mem_PCP_of_gapReduction {graph : Input → Graph C} (width : ℕ) (hdecode : Function.LeftInverse decode encode) {input : Input ↪ List Bool} {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (hgraph : ComputableTidilyInPolyTime graph input (encoding enc)) - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (hgraph : ComputableInPolyTime graph input (encoding enc)) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) (hwellFormed : ∀ x, (graph x).WellFormed) {A : Set Input} (hcomplete : ∀ x ∈ A, ((graph x).toGraph eval).Satisfiable) @@ -86,7 +88,7 @@ theorem mem_PCP_of_gapReduction {graph : Input → Graph C} (width : ℕ) A ∈ PCP (fun n => Nat.log 2 n + 1) (fun _ => 1) input := by obtain ⟨repeats, hrepeats⟩ := exists_pow_lt_of_lt_one (by norm_num : (0 : ℝ) < 1 / 2) (by linarith : 1 - gap / 2 < 1) - have hlength : ComputableTidilyInPolyTime (fun x => (graph x).edges.length) + have hlength : ComputableInPolyTime (fun x => (graph x).edges.length) input encUnary := by fun_prop obtain ⟨c, d, hbound⟩ := hlength.polyBounded_length.exists_le have hpoly : PolynomiallyBounded (fun n => c * (n + 1) ^ d) := by fun_prop diff --git a/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean b/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean index f5ef6ccfe..0fd536b93 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean @@ -132,13 +132,15 @@ theorem query_repeatedEdgeVerifier_lt (width repeats : ℕ) obtain ⟨i, _, hi⟩ := List.mem_flatMap.mp hindex exact query_edgeVerifier_lt width decode eval hg _ hi +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Repetition charges construction of every query, every extracted bit block, and every verdict. -/ theorem polyTime_repeatedEdgeVerifier (width repeats : ℕ) (decode : (Fin width → Bool) → α) {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {eval : C → α → α → Bool} - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : (repeatedEdgeVerifier width repeats decode eval).PolyTime (encoding enc) := by - obtain ⟨_, hqueries, hverdict⟩ := polyTime_edgeVerifier width decode heval + have heval := heval.tidy + obtain ⟨_, hqueries, hverdict⟩ := polyTime_edgeVerifier width decode (.of_tidy heval) have hqueries := hqueries.tidy have hverdict := hverdict.tidy refine ⟨.of_tidy ?_, .of_tidy ?_, .of_tidy ?_⟩ diff --git a/Complexity/Computability/PCP/Power/Complexity.lean b/Complexity/Computability/PCP/Power/Complexity.lean index 07e724774..7d060f7e5 100644 --- a/Complexity/Computability/PCP/Power/Complexity.lean +++ b/Complexity/Computability/PCP/Power/Complexity.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.PCP.Power.WithInput public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.RotationMap.Walk import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Finite import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! # Polynomial-time evaluation of powered constraints @@ -51,13 +52,16 @@ variable {input : P ↪ List Bool} {vertex : W ↪ List Bool} lookup is charged. The finite dispatch depends only on the fixed walk parameters. -/ @[fun_prop] theorem isPolyTime_powerRelationWithInput - (hrotate : ComputableTidilyInPolyTime rotate + (hrotate : ComputableInPolyTime rotate (encPair input (encPair vertex label)) (encPair vertex label)) - (hrel : ComputableTidilyInPolyTime rel + (hrel : ComputableInPolyTime rel (encPair input (encPair (encPair vertex label) (encPair alphabet alphabet))) encBool) (T q : ℕ) [NeZero q] (signal : Fin q ↪ List Bool) : - ComputableTidilyInPolyTime (powerRelationWithInput rotate rel T q) + ComputableInPolyTime (powerRelationWithInput rotate rel T q) (powerInputEncoding input vertex label alphabet T q signal) encBool := by + have hrotate := hrotate.tidy + have hrel := hrel.tidy + refine .of_tidy ?_ let enc := powerInputEncoding input vertex label alphabet T q signal have hbranch (s : (Fin T → D) × (Fin T → Fin q)) : ComputableTidilyInPolyTime (fun p : PowerInput P W D α T q => diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean index e00a6aa25..448418c1d 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.TreeEval.Reader.Cert.Step public import Complexity.Computability.Machines.ReadMachine.Tidy +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # The Tree Evaluation read machine within its space budget @@ -42,9 +43,11 @@ open Turing MultiTapeTM ComputableTidilyInSpace Iter /-- The tuple with the bit `false`, as an input of a step. -/ theorem pairFalse_inSpace : - ComputableTidilyInSpace (fun x : Tuple => (x, false)) encTuple encStepInT - fun x => stepBudget (x, false) := - ReadMachine.pairFalse_inSpace fun x => by simp only [stepBudget, encStepInT]; omega + ComputableInSpace (fun x : Tuple => (x, false)) encTuple encStepInT + fun x => stepBudget (x, false) := by + have this : ComputableTidilyInSpace (fun x : Tuple => (x, false)) encTuple encStepInT fun x => stepBudget (x, false) := + ReadMachine.pairFalse_inSpace fun x => by simp only [stepBudget, encStepInT]; omega + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- A function of the tuple with the bit `false` within the budget of the step. -/ private theorem onTuple {β : Type} {encB : β ↪ List Bool} {f : Tuple × Bool → β} @@ -56,18 +59,18 @@ private theorem onTuple {β : Type} {encB : β ↪ List Bool} {f : Tuple × Bool /-- **The halting test** on tuples. -/ private theorem haltT_inSpace : ComputableTidilyInSpace haltT encTuple encBool fun x => stepBudget (x, false) := - onTuple (budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = 6)) tag_inSpace) + onTuple (budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = 6)) tag_inSpace.tidy) /-- The offset of the node at the path of a stack. -/ private theorem offsetT_inSpace {st : Tuple × Bool → List Frame} (hst : ComputableTidilyInSpace st encStepInT (encList encFrame) stepBudget) : ComputableTidilyInSpace (fun y => offsetT y.1 (st y)) encStepInT encNat stepBudget := by - have hdirs := budget_comp dirs_inSpace hst (.const_mul 64 ((length_le hst).add (.const 1 _))) - have harg := budget_prod (budget_prod ell_inSpace height_inSpace) hdirs - have hpo := budget_comp pathOffset_inSpace harg (.const_mul (2 ^ 30) + have hdirs := budget_comp dirs_inSpace.tidy hst (.const_mul 64 ((length_le hst).add (.const 1 _))) + have harg := budget_prod (budget_prod ell_inSpace.tidy height_inSpace.tidy) hdirs + have hpo := budget_comp pathOffset_inSpace.tidy harg (.const_mul (2 ^ 30) (((ell_le_stepBudget.add height_le_stepBudget).add (length_le harg)).add (.const 1 _))) - have h₂ := succ_inSpace (succ_inSpace - (budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace height_inSpace))) + have h₂ := (succ_inSpace (succ_inSpace + (.of_tidy (budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace.tidy height_inSpace.tidy))))).tidy refine (budget_comp_lin natAdd linear_succ (budget_prod h₂ hpo)).of_enc_eq fun y => ?_ simp only [offsetT, path_eq_reverse, foldl_cons_dir, List.append_nil] @@ -78,15 +81,15 @@ private theorem addrT_inSpace : ComputableTidilyInSpace (fun y => some (n y)) encStepInT (encOption encNat) stepBudget := budget_comp_linear (of_inO (ComputableTidilyInDegree.optionSome (enc₁ := encNat)).inO_one) hn have ht (k : Fin 7) := - budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = k)) tag_inSpace + budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = k)) tag_inSpace.tidy have hadd {a b : Tuple × Bool → ℕ} (ha : ComputableTidilyInSpace a encStepInT encNat stepBudget) (hb : ComputableTidilyInSpace b encStepInT encNat stepBudget) : ComputableTidilyInSpace (fun y => a y + b y) encStepInT encNat stepBudget := budget_comp_lin natAdd linear_succ (budget_prod ha hb) - have h := budget_ite (ht 0) (hsome n₁_inSpace) - (budget_ite (ht 1) (hsome (hadd (succ_inSpace ell_inSpace) n₁_inSpace)) - (budget_ite (ht 4) (hsome (hadd (offsetT_inSpace stack_inSpace) n₁_inSpace)) - (budget_ite (ht 5) (hsome (hadd (offsetT_inSpace rest_inSpace) n₁_inSpace)) + have h := budget_ite (ht 0) (hsome n₁_inSpace.tidy) + (budget_ite (ht 1) (hsome (hadd (succ_inSpace ell_inSpace).tidy n₁_inSpace.tidy)) + (budget_ite (ht 4) (hsome (hadd (offsetT_inSpace stack_inSpace.tidy) n₁_inSpace.tidy)) + (budget_ite (ht 5) (hsome (hadd (offsetT_inSpace rest_inSpace.tidy) n₁_inSpace.tidy)) (budget_const (encB := encOption encNat) none len_le_stepBudget)))) refine (onTuple h).of_enc_eq fun x => ?_ simp only [addrT, decide_eq_true_eq] @@ -112,7 +115,7 @@ private theorem addr_inSpace : ComputableTidilyInSpace machine.addr encState (en private theorem step_inSpace : ComputableTidilyInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by - have h := stepT_inSpace.of_encIn_eq (fun p : State × Bool => (p.1.toTuple, p.2)) fun p => by + have h := stepT_inSpace.tidy.of_encIn_eq (fun p : State × Bool => (p.1.toTuple, p.2)) fun p => by rw [encPair_apply, encPair_apply, encState_apply] refine (h.mono_le fun p => ?_).of_enc_eq fun p => ?_ · simp only [stateBudget, stepBudget_bool]; exact le_rfl diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean index b86a8b20b..094ed441d 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.TreeEval.Reader.Encode public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpaceLib +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # Offsets of nodes within linear work space @@ -107,24 +108,26 @@ private theorem iterate_mul_four (k : ℕ) : (fun x => x * 4)^[k] 1 = 4 ^ k := b /-- **The length of a table**, `4^ℓ * ℓ` from `ℓ`. -/ theorem tableLength_inSpace : - ComputableTidilyInSpace tableLength encNat encNat fun ℓ => 4096 * (ℓ + 1) := by - have hl : (fun ℓ => (encNat ℓ).length) ≼ fun ℓ => 1024 * (ℓ + 1) := - .of_le fun ℓ => by have := length_encNat_le_self ℓ; omega - have hid : ComputableTidilyInSpace (fun ℓ : ℕ => ℓ) encNat encNat fun ℓ => 1024 * (ℓ + 1) := - (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))).weaken hl - have hstep : ComputableTidilyInSpace (fun x : ℕ => x * 4) encNat encNat - fun x => 64 * ((encNat x).length + 1) := - (budget_comp_lin natMul (linear_mul _) (budget_prod - (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) - (budget_const (encB := encNat) 4 (.refl _)))).weaken (.of_le fun x => by omega) - have h := iterate (n := fun ℓ : ℕ => ℓ) hid (budget_const (encB := encNat) 1 hl) hstep - (Q := fun ℓ => 64 * (2 * ℓ + 2)) (B := fun ℓ => 2 * ℓ + 1) - (fun ℓ k hk => by rw [iterate_mul_four]; have := length_encNat_pow_four k; omega) - (fun ℓ k hk => by rw [iterate_mul_four]; have := length_encNat_pow_four k; omega) - have hl' : (fun ℓ => 1024 * (ℓ + 1)) ≼ fun ℓ => 4096 * (ℓ + 1) := .of_le fun _ => by omega - refine (budget_comp_lin natMul (linear_mul _) (budget_prod (h.mono_le fun ℓ => ?_) - (hid.weaken hl'))).of_enc_eq fun ℓ => by rw [iterate_mul_four]; rfl - have := length_encNat_le_self ℓ; omega + ComputableInSpace tableLength encNat encNat fun ℓ => 4096 * (ℓ + 1) := by + have this : ComputableTidilyInSpace tableLength encNat encNat fun ℓ => 4096 * (ℓ + 1) := by + have hl : (fun ℓ => (encNat ℓ).length) ≼ fun ℓ => 1024 * (ℓ + 1) := + .of_le fun ℓ => by have := length_encNat_le_self ℓ; omega + have hid : ComputableTidilyInSpace (fun ℓ : ℕ => ℓ) encNat encNat fun ℓ => 1024 * (ℓ + 1) := + (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))).weaken hl + have hstep : ComputableTidilyInSpace (fun x : ℕ => x * 4) encNat encNat + fun x => 64 * ((encNat x).length + 1) := + (budget_comp_lin natMul (linear_mul _) (budget_prod + (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) + (budget_const (encB := encNat) 4 (.refl _)))).weaken (.of_le fun x => by omega) + have h := iterate (n := fun ℓ : ℕ => ℓ) hid (budget_const (encB := encNat) 1 hl) hstep + (Q := fun ℓ => 64 * (2 * ℓ + 2)) (B := fun ℓ => 2 * ℓ + 1) + (fun ℓ k hk => by rw [iterate_mul_four]; have := length_encNat_pow_four k; omega) + (fun ℓ k hk => by rw [iterate_mul_four]; have := length_encNat_pow_four k; omega) + have hl' : (fun ℓ => 1024 * (ℓ + 1)) ≼ fun ℓ => 4096 * (ℓ + 1) := .of_le fun _ => by omega + refine (budget_comp_lin natMul (linear_mul _) (budget_prod (h.mono_le fun ℓ => ?_) + (hid.weaken hl'))).of_enc_eq fun ℓ => by rw [iterate_mul_four]; rfl + have := length_encNat_le_self ℓ; omega + simpa only [computableInSpace_iff_computableTidilyInSpace] using this private theorem length_encNat_two_pow (k : ℕ) : (encNat (2 ^ k)).length ≤ k + 1 := by rw [length_encNat_eq_size] @@ -168,7 +171,7 @@ private theorem bodyLength_inSpace : have h2b := budget_comp_lin natAdd linear_succ (budget_prod hb hb) have hsum := budget_comp_lin natAdd linear_succ (budget_prod hG h2b) exact (budget_prod hG hsum).of_enc_eq fun q => by simp [bodyStep, two_mul] - have hG := budget_comp tableLength_inSpace ((fst encNat encNat).weaken hl) + have hG := budget_comp tableLength_inSpace.tidy ((fst encNat encNat).weaken hl) (.of_le_linear 1 0 fun q => by omega) have hinit := budget_prod hG ((fst encNat encNat).weaken hl) have hlen (q : ℕ × ℕ) (k : ℕ) (hk : k ≤ q.2) : @@ -196,16 +199,20 @@ theorem encFrame_apply (fr : Frame) : encFrame fr = encFrameTuple (Frame.equiv f /-- **A function of the finite fields of a frame.** -/ theorem frameFinite_inSpace {β : Type} {encB : β ↪ List Bool} (g : Fin 4 × Bool × Fin 3 → β) : - ComputableTidilyInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB + ComputableInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB fun fr => (encFrame fr).length := by - have h := budget_finite (encC := encB) g (snd encNat (encFinEnum (Fin 4 × Bool × Fin 3))) - exact h.of_encIn_eq Frame.equiv fun _ => rfl + have this : ComputableTidilyInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB fun fr => (encFrame fr).length := by + have h := budget_finite (encC := encB) g (snd encNat (encFinEnum (Fin 4 × Bool × Fin 3))) + exact h.of_encIn_eq Frame.equiv fun _ => rfl + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- The round of a frame. -/ theorem round_inSpace : - ComputableTidilyInSpace (fun fr : Frame => fr.round) encFrame encNat - fun fr => (encFrame fr).length := - (fst encNat (encFinEnum (Fin 4 × Bool × Fin 3))).of_encIn_eq Frame.equiv fun _ => rfl + ComputableInSpace (fun fr : Frame => fr.round) encFrame encNat + fun fr => (encFrame fr).length := by + have this : ComputableTidilyInSpace (fun fr : Frame => fr.round) encFrame encNat fun fr => (encFrame fr).length := + (fst encNat (encFinEnum (Fin 4 × Bool × Fin 3))).of_encIn_eq Frame.equiv fun _ => rfl + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-! ### The offset of the node at the path of a stack -/ @@ -226,42 +233,44 @@ private theorem length_encList_bools (l : List Bool) : | cons b l ih => rw [length_encList] at ih ⊢; simp; ring theorem dirs_inSpace : - ComputableTidilyInSpace (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) + ComputableInSpace (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) (encList encFrame) (encList encBool) fun st => 64 * ((encList encFrame st).length + 1) := by - have hl : (fun st => (encList encFrame st).length) ≼ - fun st => 8 * ((encList encFrame st).length + 1) := .of_le fun _ => by omega - have hstep : ComputableTidilyInSpace (fun q : List Bool × Frame => q.2.dir :: q.1) - (encPair (encList encBool) encFrame) (encList encBool) - fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := by - have hl₀ : (fun q => (encPair (encList encBool) encFrame q).length) ≼ - fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := .of_le fun _ => by omega - have hd := budget_comp (frameFinite_inSpace (encB := encBool) - fun y : Fin 4 × Bool × Fin 3 => y.1.val % 2 == 1) - ((snd (encList encBool) encFrame).weaken hl₀) (.of_le fun x => by - simp only [length_encPair]; omega) - have hc : ComputableTidilyInSpace (fun p : Bool × List Bool => p.1 :: p.2) - (encPair encBool (encList encBool)) (encList encBool) - fun p => (encPair encBool (encList encBool) p).length := - of_inO (ComputableTidilyInDegree.cons encBool).inO_one - exact (budget_comp_linear hc (budget_prod hd ((fst (encList encBool) encFrame).weaken hl₀))) - |>.of_enc_eq fun q => rfl - have hlen (st : List Frame) (i : ℕ) : - (encList encBool ((st.take i).foldl (fun acc fr => fr.dir :: acc) [])).length ≤ - (encList encFrame st).length := by - rw [foldl_cons_dir, List.append_nil, length_encList_reverse, length_encList_bools, - List.length_map] - exact (Nat.mul_le_mul_left 3 (List.length_take_le' i st)).trans (three_mul_length_le st) - have h := foldl (encL := encList encFrame) (list := fun st : List Frame => st) - (init := fun _ => ([] : List Bool)) (step := fun acc fr => fr.dir :: acc) - (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) (budget_const [] (.refl _)) hstep - (Q := fun st => 2 * (3 * (encList encFrame st).length + 2)) - (B := fun st => (encList encFrame st).length) - (fun st i hi => by - have h₁ := hlen st i - have h₂ := length_le_encList_of_mem encFrame (List.getElem_mem hi) - rw [length_encPair]; dsimp only; omega) - (fun st i _ => hlen st i) - exact h.mono_le fun st => by omega + have this : ComputableTidilyInSpace (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) (encList encFrame) (encList encBool) fun st => 64 * ((encList encFrame st).length + 1) := by + have hl : (fun st => (encList encFrame st).length) ≼ + fun st => 8 * ((encList encFrame st).length + 1) := .of_le fun _ => by omega + have hstep : ComputableTidilyInSpace (fun q : List Bool × Frame => q.2.dir :: q.1) + (encPair (encList encBool) encFrame) (encList encBool) + fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := by + have hl₀ : (fun q => (encPair (encList encBool) encFrame q).length) ≼ + fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := .of_le fun _ => by omega + have hd := budget_comp (frameFinite_inSpace (encB := encBool) + fun y : Fin 4 × Bool × Fin 3 => y.1.val % 2 == 1) + ((snd (encList encBool) encFrame).weaken hl₀) (.of_le fun x => by + simp only [length_encPair]; omega) + have hc : ComputableTidilyInSpace (fun p : Bool × List Bool => p.1 :: p.2) + (encPair encBool (encList encBool)) (encList encBool) + fun p => (encPair encBool (encList encBool) p).length := + of_inO (ComputableTidilyInDegree.cons encBool).inO_one + exact (budget_comp_linear hc (budget_prod hd ((fst (encList encBool) encFrame).weaken hl₀))) + |>.of_enc_eq fun q => rfl + have hlen (st : List Frame) (i : ℕ) : + (encList encBool ((st.take i).foldl (fun acc fr => fr.dir :: acc) [])).length ≤ + (encList encFrame st).length := by + rw [foldl_cons_dir, List.append_nil, length_encList_reverse, length_encList_bools, + List.length_map] + exact (Nat.mul_le_mul_left 3 (List.length_take_le' i st)).trans (three_mul_length_le st) + have h := foldl (encL := encList encFrame) (list := fun st : List Frame => st) + (init := fun _ => ([] : List Bool)) (step := fun acc fr => fr.dir :: acc) + (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) (budget_const [] (.refl _)) hstep + (Q := fun st => 2 * (3 * (encList encFrame st).length + 2)) + (B := fun st => (encList encFrame st).length) + (fun st i hi => by + have h₁ := hlen st i + have h₂ := length_le_encList_of_mem encFrame (List.getElem_mem hi) + rw [length_encPair]; dsimp only; omega) + (fun st i _ => hlen st i) + exact h.mono_le fun st => by omega + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- A step of the offset along a path, with the value length in the state. -/ private def pathStep' (q : ℕ × ℕ × ℕ) (b : Bool) : ℕ × ℕ × ℕ := (q.1, pathStep q.1 q.2 b) @@ -286,7 +295,7 @@ private theorem pathStep'_inSpace : have hacc := snd' (snd' hs) have hz := budget_comp_linear natIsZero hd have hd₁ := budget_comp_lin natPred linear_succ hd - have hG := budget_comp tableLength_inSpace hℓ (.of_le_linear 1 0 fun q => by omega) + have hG := budget_comp tableLength_inSpace.tidy hℓ (.of_le_linear 1 0 fun q => by omega) have hB := budget_comp bodyLength_inSpace (budget_prod hℓ hd₁) (.of_le_linear 1 0 fun q => by dsimp only; omega) have hBif := budget_ite hb hB (budget_const (encB := encNat) 0 hl) @@ -303,41 +312,43 @@ private theorem length_pathOffset_le (ℓ d : ℕ) (P : List Bool) : /-- **The offset of the node at a path**, `pathOffset ℓ d P` from `((ℓ, d), P)`. -/ theorem pathOffset_inSpace : - ComputableTidilyInSpace (fun q : (ℕ × ℕ) × List Bool => pathOffset q.1.1 q.1.2 q.2) + ComputableInSpace (fun q : (ℕ × ℕ) × List Bool => pathOffset q.1.1 q.1.2 q.2) (encPair (encPair encNat encNat) (encList encBool)) encNat fun q => 2 ^ 30 * (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := by - have hl : (fun q => (encPair (encPair encNat encNat) (encList encBool) q).length) ≼ - fun q => 2 ^ 22 * (q.1.1 + q.1.2 + - (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := - .of_le fun _ => by omega - have hld := (fst (encPair encNat encNat) (encList encBool)).weaken hl - have hinit := budget_prod (fst' hld) (budget_prod (snd' hld) (budget_const (encB := encNat) 0 hl)) - have hstate (q : (ℕ × ℕ) × List Bool) (j : ℕ) : - (encNat3 ((q.2.take j).foldl pathStep' (q.1.1, q.1.2, 0))).length ≤ - 8 * (q.1.1 + q.1.2 + 1) := by - rw [foldl_pathStep', foldl_pathStep] - have h₁ := length_pathOffset_le q.1.1 q.1.2 (q.2.take j) - have h₂ := length_encNat_le_self q.1.1 - have h₃ := length_encNat_le_self (q.1.2 - (q.2.take j).length) - simp only [length_encPair, zero_add] at * + have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × List Bool => pathOffset q.1.1 q.1.2 q.2) (encPair (encPair encNat encNat) (encList encBool)) encNat fun q => 2 ^ 30 * (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := by + have hl : (fun q => (encPair (encPair encNat encNat) (encList encBool) q).length) ≼ + fun q => 2 ^ 22 * (q.1.1 + q.1.2 + + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := + .of_le fun _ => by omega + have hld := (fst (encPair encNat encNat) (encList encBool)).weaken hl + have hinit := budget_prod (fst' hld) (budget_prod (snd' hld) (budget_const (encB := encNat) 0 hl)) + have hstate (q : (ℕ × ℕ) × List Bool) (j : ℕ) : + (encNat3 ((q.2.take j).foldl pathStep' (q.1.1, q.1.2, 0))).length ≤ + 8 * (q.1.1 + q.1.2 + 1) := by + rw [foldl_pathStep', foldl_pathStep] + have h₁ := length_pathOffset_le q.1.1 q.1.2 (q.2.take j) + have h₂ := length_encNat_le_self q.1.1 + have h₃ := length_encNat_le_self (q.1.2 - (q.2.take j).length) + simp only [length_encPair, zero_add] at * + omega + have h := foldl (encL := encList encBool) (list := fun q : (ℕ × ℕ) × List Bool => q.2) + (step := pathStep') ((snd (encPair encNat encNat) (encList encBool)).weaken hl) hinit + pathStep'_inSpace + (Q := fun q => 2 ^ 20 * (q.1.1 + q.1.2 + 2 * (8 * (q.1.1 + q.1.2 + 1)) + 4 + 1)) + (B := fun q => 8 * (q.1.1 + q.1.2 + 1)) + (fun q i hi => by + have h₁ := hstate q i + rw [foldl_pathStep', foldl_pathStep] at h₁ ⊢ + simp only [length_encPair, encBool_apply, List.length_singleton] at h₁ ⊢ + omega) + (fun q i _ => hstate q i) + refine (snd' (snd' h)).mono_le (fun q => ?_) |>.of_enc_eq fun q => by + rw [foldl_pathStep', foldl_pathStep, zero_add] + have := length_encNat_le_self q.1.1 + simp only [length_encPair] at * omega - have h := foldl (encL := encList encBool) (list := fun q : (ℕ × ℕ) × List Bool => q.2) - (step := pathStep') ((snd (encPair encNat encNat) (encList encBool)).weaken hl) hinit - pathStep'_inSpace - (Q := fun q => 2 ^ 20 * (q.1.1 + q.1.2 + 2 * (8 * (q.1.1 + q.1.2 + 1)) + 4 + 1)) - (B := fun q => 8 * (q.1.1 + q.1.2 + 1)) - (fun q i hi => by - have h₁ := hstate q i - rw [foldl_pathStep', foldl_pathStep] at h₁ ⊢ - simp only [length_encPair, encBool_apply, List.length_singleton] at h₁ ⊢ - omega) - (fun q i _ => hstate q i) - refine (snd' (snd' h)).mono_le (fun q => ?_) |>.of_enc_eq fun q => by - rw [foldl_pathStep', foldl_pathStep, zero_add] - have := length_encNat_le_self q.1.1 - simp only [length_encPair] at * - omega + simpa only [computableInSpace_iff_computableTidilyInSpace] using this end Reader diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean index 544937482..7a05d816e 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.TreeEval.Reader.Cert.Residue public import Complexity.Computability.TreeEval.Reader.Encode +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # Register operations within linear work space @@ -38,9 +39,12 @@ variable {α : Type} {encIn : α ↪ List Bool} {Bs : α → ℕ} /-- **Selecting a register**, given the registers and the index within a budget. -/ theorem get_inSpace {R : α → Regs} {t : α → Fin 3} - (hR : ComputableTidilyInSpace R encIn encRegs Bs) - (ht : ComputableTidilyInSpace t encIn encReg Bs) : - ComputableTidilyInSpace (fun x => (R x).get (t x)) encIn (encList encNat) Bs := by + (hR : ComputableInSpace R encIn encRegs Bs) + (ht : ComputableInSpace t encIn encReg Bs) : + ComputableInSpace (fun x => (R x).get (t x)) encIn (encList encNat) Bs := by + have hR := hR.tidy + have ht := ht.tidy + refine .of_tidy ?_ have h₀ := fst' hR have h₁ := fst' (snd' hR) have h₂ := snd' (snd' hR) @@ -53,10 +57,14 @@ theorem get_inSpace {R : α → Regs} {t : α → Fin 3} /-- **Replacing a register.** -/ theorem set_inSpace {R : α → Regs} {t : α → Fin 3} {l : α → List ℕ} - (hR : ComputableTidilyInSpace R encIn encRegs Bs) - (ht : ComputableTidilyInSpace t encIn encReg Bs) - (hl : ComputableTidilyInSpace l encIn (encList encNat) Bs) : - ComputableTidilyInSpace (fun x => (R x).set (t x) (l x)) encIn encRegs Bs := by + (hR : ComputableInSpace R encIn encRegs Bs) + (ht : ComputableInSpace t encIn encReg Bs) + (hl : ComputableInSpace l encIn (encList encNat) Bs) : + ComputableInSpace (fun x => (R x).set (t x) (l x)) encIn encRegs Bs := by + have hR := hR.tidy + have ht := ht.tidy + have hl := hl.tidy + refine .of_tidy ?_ have h₀ := fst' hR have h₁ := fst' (snd' hR) have h₂ := snd' (snd' hR) @@ -87,15 +95,20 @@ private theorem length_encList_map_mulMod_le (p a : ℕ) (l : List ℕ) : /-- **Multiplying a register by a residue**, within a budget that covers the register with every entry as long as the prime and the factor together. -/ theorem scale_inSpace {p a : α → ℕ} {R : α → Regs} {r : α → Fin 3} - (hp : ComputableTidilyInSpace p encIn encNat Bs) - (ha : ComputableTidilyInSpace a encIn encNat Bs) - (hR : ComputableTidilyInSpace R encIn encRegs Bs) - (hr : ComputableTidilyInSpace r encIn encReg Bs) + (hp : ComputableInSpace p encIn encNat Bs) + (ha : ComputableInSpace a encIn encNat Bs) + (hR : ComputableInSpace R encIn encRegs Bs) + (hr : ComputableInSpace r encIn encReg Bs) (hin : (fun x => (encIn x).length) ≼ Bs) (hB : (fun x => ((R x).get (r x)).length * ((encNat (p x)).length + (encNat (a x)).length)) ≼ Bs) : - ComputableTidilyInSpace (fun x => (R x).scale (p x) (r x) (a x)) encIn encRegs Bs := by - have hl := get_inSpace hR hr + ComputableInSpace (fun x => (R x).scale (p x) (r x) (a x)) encIn encRegs Bs := by + have hp := hp.tidy + have ha := ha.tidy + have hR := hR.tidy + have hr := hr.tidy + refine .of_tidy ?_ + have hl := (get_inSpace (.of_tidy hR) (.of_tidy hr)).tidy have hpa := budget_prod hp ha have hf : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × ℕ => mulMod q.1.1 q.1.2 q.2) (encPair (encPair encNat encNat) encNat) encNat @@ -104,7 +117,7 @@ theorem scale_inSpace {p a : α → ℕ} {R : α → Regs} {r : α → Fin 3} fun q => (encPair (encPair encNat encNat) encNat q).length + 1 := .of_le fun _ => by omega have h₁ := (fst (encPair encNat encNat) encNat).weaken hl₀ have h₂ := (snd (encPair encNat encNat) encNat).weaken hl₀ - exact budget_comp_linear mulMod_inSpace (budget_prod (fst' h₁) (budget_prod (snd' h₁) h₂)) + exact budget_comp_linear mulMod_inSpace.tidy (budget_prod (fst' h₁) (budget_prod (snd' h₁) h₂)) have hmap := mapWith hf hpa hl have hmap' : ComputableTidilyInSpace (fun x => ((R x).get (r x)).map (mulMod (p x) (a x))) encIn (encList encNat) Bs := by @@ -130,18 +143,23 @@ theorem scale_inSpace {p a : α → ℕ} {R : α → Regs} {r : α → Fin 3} rw [length_encPair] at ⊢ have : (encNat v).length ≤ c₂ * (Bs x + 1) := hv'.trans h₂ nlinarith - exact set_inSpace hR hr hmap' + exact (set_inSpace (.of_tidy hR) (.of_tidy hr) (.of_tidy hmap')).tidy /-- **Changing one entry by adding a residue**, `modifyAt l i (addMod p c)`. -/ theorem modifyAt_inSpace {l : α → List ℕ} {i p c : α → ℕ} - (hl : ComputableTidilyInSpace l encIn (encList encNat) Bs) - (hi : ComputableTidilyInSpace i encIn encNat Bs) - (hp : ComputableTidilyInSpace p encIn encNat Bs) - (hc : ComputableTidilyInSpace c encIn encNat Bs) : - ComputableTidilyInSpace (fun x => modifyAt (l x) (i x) (addMod (p x) (c x))) encIn + (hl : ComputableInSpace l encIn (encList encNat) Bs) + (hi : ComputableInSpace i encIn encNat Bs) + (hp : ComputableInSpace p encIn encNat Bs) + (hc : ComputableInSpace c encIn encNat Bs) : + ComputableInSpace (fun x => modifyAt (l x) (i x) (addMod (p x) (c x))) encIn (encList encNat) Bs := by + have hl := hl.tidy + have hi := hi.tidy + have hp := hp.tidy + have hc := hc.tidy + refine .of_tidy ?_ have hv := budget_comp_lin getD (linear_mul _) (budget_prod hl hi) - have hv' := budget_comp_linear addMod_inSpace (budget_prod hp (budget_prod hc hv)) + have hv' := budget_comp_linear addMod_inSpace.tidy (budget_prod hp (budget_prod hc hv)) refine (budget_comp set (budget_prod hl (budget_prod hi hv')) ?_).of_enc_eq fun x => rfl obtain ⟨c₁, h₁⟩ := length_le (budget_prod hl hi) obtain ⟨c₂, h₂⟩ := length_le hv' @@ -210,9 +228,9 @@ private theorem subStep_inSpace : have hj := fst' (snd' hs) have hout := snd' (snd' hs) have ha := budget_comp_lin getD (linear_mul _) (budget_prod hacc hj) - have hm := budget_comp_linear mulMod_inSpace (budget_prod hp (budget_prod hc ha)) - have hn := budget_comp_linear negMod_inSpace (budget_prod hp hm) - have he := budget_comp_linear addMod_inSpace (budget_prod hp (budget_prod hv hn)) + have hm := budget_comp_linear mulMod_inSpace.tidy (budget_prod hp (budget_prod hc ha)) + have hn := budget_comp_linear negMod_inSpace.tidy (budget_prod hp hm) + have he := budget_comp_linear addMod_inSpace.tidy (budget_prod hp (budget_prod hv hn)) have hsnoc : ComputableTidilyInSpace (fun p : List ℕ × ℕ => p.1 ++ [p.2]) (encPair (encList encNat) encNat) (encList encNat) fun p => (encPair (encList encNat) encNat p).length := @@ -292,62 +310,70 @@ private theorem subtractList_inSpace : /-- **Subtracting `c` times the sums of a pass from a register**, within a budget that covers the register with every entry as long as the prime. -/ theorem subtractSums_inSpace {p c : α → ℕ} {t : α → Fin 3} {acc : α → List ℕ} {R : α → Regs} - (hp : ComputableTidilyInSpace p encIn encNat Bs) - (hc : ComputableTidilyInSpace c encIn encNat Bs) - (ht : ComputableTidilyInSpace t encIn encReg Bs) - (hacc : ComputableTidilyInSpace acc encIn (encList encNat) Bs) - (hR : ComputableTidilyInSpace R encIn encRegs Bs) + (hp : ComputableInSpace p encIn encNat Bs) + (hc : ComputableInSpace c encIn encNat Bs) + (ht : ComputableInSpace t encIn encReg Bs) + (hacc : ComputableInSpace acc encIn (encList encNat) Bs) + (hR : ComputableInSpace R encIn encRegs Bs) (hB : (fun x => ((R x).get (t x)).length * ((encNat (p x)).length + 1)) ≼ Bs) : - ComputableTidilyInSpace (fun x => subtractSums (p x) (c x) (t x) (acc x) (R x)) encIn encRegs Bs + ComputableInSpace (fun x => subtractSums (p x) (c x) (t x) (acc x) (R x)) encIn encRegs Bs := by - have harg := budget_prod (budget_prod hp (budget_prod hc hacc)) (get_inSpace hR ht) + have hp := hp.tidy + have hc := hc.tidy + have ht := ht.tidy + have hacc := hacc.tidy + have hR := hR.tidy + refine .of_tidy ?_ + have harg := budget_prod (budget_prod hp (budget_prod hc hacc)) (get_inSpace (.of_tidy hR) (.of_tidy ht)).tidy have hsub := budget_comp subtractList_inSpace harg (by refine .const_mul 8192 (((length_le harg).add hB).add (.const 1 _))) - exact (set_inSpace hR ht hsub).of_enc_eq fun x => by rw [subtractSums_eq] + exact (set_inSpace (.of_tidy hR) (.of_tidy ht) (.of_tidy hsub)).tidy.of_enc_eq fun x => by rw [subtractSums_eq] /-- **The bits of a register**, `l.map (· == 1)`, encoded as themselves. -/ theorem mapEqOne_inSpace : - ComputableTidilyInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits + ComputableInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits fun l => 64 * ((encList encNat l).length + 1) := by - have hstep : ComputableTidilyInSpace (fun q : List Bool × ℕ => q.1 ++ [q.2 == 1]) - (encPair encBits encNat) encBits fun q => 8 * ((encPair encBits encNat q).length + 1) := by - have hl : (fun q => (encPair encBits encNat q).length) ≼ - fun q => 4 * ((encPair encBits encNat q).length + 1) := .of_le fun _ => by omega - have he := budget_comp_linear natEq (budget_prod ((snd encBits encNat).weaken hl) - (budget_const (encB := encNat) 1 hl)) - have h := ComputableTidilyInSpace.append ((fst encBits encNat).weaken hl) he - (g := fun q : List Bool × ℕ => q.1 ++ [q.2 == 1]) (encD := encBits) fun q => by - cases hq : q.2 == 1 <;> simp_all [encBits_apply, encBool_apply] - exact h.weaken (.of_le fun _ => by omega) - have hlen (l : List ℕ) (i : ℕ) (hi : i ≤ l.length) : - (encBits ((l.take i).foldl (fun acc v => acc ++ [v == 1]) [])).length ≤ - (encList encNat l).length := by + have this : ComputableTidilyInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits fun l => 64 * ((encList encNat l).length + 1) := by + have hstep : ComputableTidilyInSpace (fun q : List Bool × ℕ => q.1 ++ [q.2 == 1]) + (encPair encBits encNat) encBits fun q => 8 * ((encPair encBits encNat q).length + 1) := by + have hl : (fun q => (encPair encBits encNat q).length) ≼ + fun q => 4 * ((encPair encBits encNat q).length + 1) := .of_le fun _ => by omega + have he := budget_comp_linear natEq (budget_prod ((snd encBits encNat).weaken hl) + (budget_const (encB := encNat) 1 hl)) + have h := ComputableTidilyInSpace.append ((fst encBits encNat).weaken hl) he + (g := fun q : List Bool × ℕ => q.1 ++ [q.2 == 1]) (encD := encBits) fun q => by + cases hq : q.2 == 1 <;> simp_all [encBits_apply, encBool_apply] + exact h.weaken (.of_le fun _ => by omega) + have hlen (l : List ℕ) (i : ℕ) (hi : i ≤ l.length) : + (encBits ((l.take i).foldl (fun acc v => acc ++ [v == 1]) [])).length ≤ + (encList encNat l).length := by + have hf (m : List ℕ) (acc : List Bool) : + (m.foldl (fun acc v => acc ++ [v == 1]) acc) = acc ++ m.map (· == 1) := by + induction m generalizing acc with + | nil => simp + | cons v m ih => simp [ih] + rw [hf, encBits_apply, List.nil_append, List.length_map] + have := List.length_take_le' i l + have := length_le_length_encList encNat l + omega + have h := foldl (encL := encList encNat) (list := fun l : List ℕ => l) + (init := fun _ => ([] : List Bool)) (step := fun acc v => acc ++ [v == 1]) + (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) (budget_const [] (.refl _)) hstep + (Q := fun l => 8 * (3 * (encList encNat l).length + 2)) + (B := fun l => (encList encNat l).length) + (fun l i hi => by + have h₁ := hlen l i hi.le + have h₂ := length_le_encList_of_mem encNat (List.getElem_mem hi) + rw [length_encPair]; dsimp only; omega) + (fun l i hi => hlen l i hi) + refine h.mono_le (fun l => by omega) |>.of_enc_eq fun l => ?_ have hf (m : List ℕ) (acc : List Bool) : (m.foldl (fun acc v => acc ++ [v == 1]) acc) = acc ++ m.map (· == 1) := by induction m generalizing acc with | nil => simp | cons v m ih => simp [ih] - rw [hf, encBits_apply, List.nil_append, List.length_map] - have := List.length_take_le' i l - have := length_le_length_encList encNat l - omega - have h := foldl (encL := encList encNat) (list := fun l : List ℕ => l) - (init := fun _ => ([] : List Bool)) (step := fun acc v => acc ++ [v == 1]) - (of_inO (.of_linear (.of_eq (f := id) fun _ => rfl))) (budget_const [] (.refl _)) hstep - (Q := fun l => 8 * (3 * (encList encNat l).length + 2)) - (B := fun l => (encList encNat l).length) - (fun l i hi => by - have h₁ := hlen l i hi.le - have h₂ := length_le_encList_of_mem encNat (List.getElem_mem hi) - rw [length_encPair]; dsimp only; omega) - (fun l i hi => hlen l i hi) - refine h.mono_le (fun l => by omega) |>.of_enc_eq fun l => ?_ - have hf (m : List ℕ) (acc : List Bool) : - (m.foldl (fun acc v => acc ++ [v == 1]) acc) = acc ++ m.map (· == 1) := by - induction m generalizing acc with - | nil => simp - | cons v m ih => simp [ih] - rw [hf, List.nil_append] + rw [hf, List.nil_append] + simpa only [computableInSpace_iff_computableTidilyInSpace] using this end Reader diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean index 5280fb359..157c6d0fb 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.TreeEval.Reader.Defs public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpaceLib +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # Residues within linear work space @@ -43,41 +44,49 @@ private theorem proj3 : /-- The sum modulo `p`, from `(p, a, b)`. -/ theorem addMod_inSpace : - ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat + ComputableInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by - obtain ⟨hp, ha, hb⟩ := proj3 - exact budget_comp_lin natMod (linear_mul _) - (budget_prod (budget_comp_lin natAdd linear_succ (budget_prod ha hb)) hp) + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by + obtain ⟨hp, ha, hb⟩ := proj3 + exact budget_comp_lin natMod (linear_mul _) + (budget_prod (budget_comp_lin natAdd linear_succ (budget_prod ha hb)) hp) + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- The product modulo `p`, from `(p, a, b)`. -/ theorem mulMod_inSpace : - ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat + ComputableInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by - obtain ⟨hp, ha, hb⟩ := proj3 - exact budget_comp_lin natMod (linear_mul _) - (budget_prod (budget_comp_lin natMul (linear_mul _) (budget_prod ha hb)) hp) + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by + obtain ⟨hp, ha, hb⟩ := proj3 + exact budget_comp_lin natMod (linear_mul _) + (budget_prod (budget_comp_lin natMul (linear_mul _) (budget_prod ha hb)) hp) + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- The negation modulo `p`, from `(p, a)`. -/ theorem negMod_inSpace : - ComputableTidilyInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) encNat + ComputableInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by - have hp := fst encNat encNat - have hm := budget_comp_lin natMod (linear_mul _) (budget_prod (snd encNat encNat) hp) - exact budget_comp_lin natMod (linear_mul _) - (budget_prod (budget_comp_lin natSub linear_succ (budget_prod hm hp)) hp) + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by + have hp := fst encNat encNat + have hm := budget_comp_lin natMod (linear_mul _) (budget_prod (snd encNat encNat) hp) + exact budget_comp_lin natMod (linear_mul _) + (budget_prod (budget_comp_lin natSub linear_succ (budget_prod hm hp)) hp) + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- The residue of `x` or of `1 - x` modulo `p`, from `((p, x), b)`. -/ theorem chi_inSpace : - ComputableTidilyInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) + ComputableInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) (encPair (encPair encNat encNat) encBool) encNat fun q => (encPair (encPair encNat encNat) encBool q).length := by - have hpx := fst (encPair encNat encNat) encBool - have hp := fst' hpx - have hmod := budget_comp_lin natMod (linear_mul _) (budget_prod (snd' hpx) hp) - have hneg := budget_comp_linear negMod_inSpace hpx - have hadd := budget_comp_linear addMod_inSpace - (budget_prod hp (budget_prod (budget_const 1 (.refl _)) hneg)) - exact (budget_ite (snd _ _) hmod hadd).of_enc_eq fun q => by simp only [chi] + have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) (encPair (encPair encNat encNat) encBool) encNat fun q => (encPair (encPair encNat encNat) encBool q).length := by + have hpx := fst (encPair encNat encNat) encBool + have hp := fst' hpx + have hmod := budget_comp_lin natMod (linear_mul _) (budget_prod (snd' hpx) hp) + have hneg := budget_comp_linear negMod_inSpace.tidy hpx + have hadd := budget_comp_linear addMod_inSpace.tidy + (budget_prod hp (budget_prod (budget_const 1 (.refl _)) hneg)) + exact (budget_ite (snd _ _) hmod hadd).of_enc_eq fun q => by simp only [chi] + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- One factor of a power modulo `p`, on `(p, a, acc)`. -/ private def powStep (q : ℕ × ℕ × ℕ) : ℕ × ℕ × ℕ := (q.1, q.2.1, mulMod q.1 q.2.2 q.2.1) @@ -97,26 +106,28 @@ theorem powMod_le {p a : ℕ} {k : ℕ} (hk : k ≤ p - 2) : powMod p a k ≤ p /-- **The inverse of the unit of round `j`**, `unitInv p j` from `(p, j)`. -/ theorem unitInv_inSpace : - ComputableTidilyInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) encNat + ComputableInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by - have hp := fst encNat encNat - have hstep : ComputableTidilyInSpace powStep encNat3 encNat3 fun q => (encNat3 q).length := by - obtain ⟨hp, ha, hacc⟩ := proj3 - exact budget_prod hp (budget_prod ha - (budget_comp_linear mulMod_inSpace (budget_prod hp (budget_prod hacc ha)))) - have hinit := budget_prod hp (budget_prod (budget_comp_lin natSucc linear_succ (snd _ _)) - (budget_comp_lin natMod (linear_mul _) (budget_prod (budget_const 1 (.refl _)) hp))) - have hn := budget_comp_lin natPred linear_succ (budget_comp_lin natPred linear_succ hp) - refine (snd' (snd' (budget_iterate hn hinit hstep (fun q k hk => ?_) - (.of_le_linear 4 8 fun q => le_rfl)))).of_enc_eq fun q => by rw [iterate_powStep]; rfl - rw [iterate_powStep] - have h₁ := ComputableTidilyInO.length_encNat_mono (powMod_le (p := q.1) (a := q.2 + 1) - (k := k) (by omega)) - have h₂ := length_encNat_add_le_add q.1 1 - have h₃ := length_encNat_add_le_add q.2 1 - have h₄ : (encNat 1).length = 1 := rfl - simp only [length_encPair] at h₁ h₂ h₃ ⊢ - omega + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by + have hp := fst encNat encNat + have hstep : ComputableTidilyInSpace powStep encNat3 encNat3 fun q => (encNat3 q).length := by + obtain ⟨hp, ha, hacc⟩ := proj3 + exact budget_prod hp (budget_prod ha + (budget_comp_linear mulMod_inSpace.tidy (budget_prod hp (budget_prod hacc ha)))) + have hinit := budget_prod hp (budget_prod (budget_comp_lin natSucc linear_succ (snd _ _)) + (budget_comp_lin natMod (linear_mul _) (budget_prod (budget_const 1 (.refl _)) hp))) + have hn := budget_comp_lin natPred linear_succ (budget_comp_lin natPred linear_succ hp) + refine (snd' (snd' (budget_iterate hn hinit hstep (fun q k hk => ?_) + (.of_le_linear 4 8 fun q => le_rfl)))).of_enc_eq fun q => by rw [iterate_powStep]; rfl + rw [iterate_powStep] + have h₁ := ComputableTidilyInO.length_encNat_mono (powMod_le (p := q.1) (a := q.2 + 1) + (k := k) (by omega)) + have h₂ := length_encNat_add_le_add q.1 1 + have h₃ := length_encNat_add_le_add q.2 1 + have h₄ : (encNat 1).length = 1 := rfl + simp only [length_encPair] at h₁ h₂ h₃ ⊢ + omega + simpa only [computableInSpace_iff_computableTidilyInSpace] using this end Reader diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean index 1a4d6434c..dc17c11a7 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.TreeEval.Reader.Tuple public import Complexity.Computability.TreeEval.Reader.Cert.Weight public import Complexity.Computability.TreeEval.Reader.Cert.Regs public import Complexity.Computability.TreeEval.Reader.Cert.Offset +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # The step of the Tree Evaluation read machine within its space budget @@ -101,12 +102,12 @@ private theorem hBit : ComputableTidilyInSpace (fun y : Tuple × Bool => y.2) en private theorem hParams : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.1.1) encStepInT (encPair encNat (encPair encNat encNat)) stepBudget := fst' (fst' hTup) -theorem ell_inSpace : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.ell) encStepInT encNat - stepBudget := fst' hParams +theorem ell_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.ell) encStepInT encNat + stepBudget := .of_tidy (fst' hParams) theorem height_inSpace : - ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.height) encStepInT encNat - stepBudget := fst' (snd' hParams) + ComputableInSpace (fun y : Tuple × Bool => y.1.height) encStepInT encNat + stepBudget := .of_tidy (fst' (snd' hParams)) private theorem hP : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.p) encStepInT encNat stepBudget := snd' (snd' hParams) @@ -118,8 +119,8 @@ private theorem hRegs : ComputableTidilyInSpace private theorem hStackMode : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.2.1) encStepInT (encPair (encList encFrame) encMode) stepBudget := fst' (snd' hTup) -theorem stack_inSpace : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.stack) encStepInT - (encList encFrame) stepBudget := fst' hStackMode +theorem stack_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.stack) encStepInT + (encList encFrame) stepBudget := .of_tidy (fst' hStackMode) private theorem hMode : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.mode) encStepInT encMode @@ -129,11 +130,11 @@ private theorem hCtl : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.2.2) encStepInT encCtlTuple stepBudget := snd' (snd' hTup) -theorem tag_inSpace : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.tag) encStepInT - (encFinEnum (Fin 7)) stepBudget := fst' hCtl +theorem tag_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.tag) encStepInT + (encFinEnum (Fin 7)) stepBudget := .of_tidy (fst' hCtl) -theorem n₁_inSpace : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.n₁) encStepInT encNat - stepBudget := fst' (snd' hCtl) +theorem n₁_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.n₁) encStepInT encNat + stepBudget := .of_tidy (fst' (snd' hCtl)) private theorem hN₂ : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.n₂) encStepInT encNat stepBudget := fst' (snd' (snd' hCtl)) @@ -146,24 +147,24 @@ private theorem hTop : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.stack.headD dfr) encStepInT encFrame stepBudget := budget_comp_linear (of_inO (.of_linear (ListEncoding.headD (enc := encList encFrame) dfr))) - stack_inSpace + stack_inSpace.tidy /-- The rest of the stack. -/ -theorem rest_inSpace : ComputableTidilyInSpace (fun y : Tuple × Bool => y.1.stack.tail) encStepInT +theorem rest_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.stack.tail) encStepInT (encList encFrame) stepBudget := - budget_comp_linear (of_inO (.of_linear (ListEncoding.tail encFrame))) stack_inSpace + .of_tidy (budget_comp_linear (of_inO (.of_linear (ListEncoding.tail encFrame))) stack_inSpace.tidy) /-- A function of the finite fields of the top frame. -/ private theorem hTopFinite {β : Type} {encB : β ↪ List Bool} (g : Fin 4 × Bool × Fin 3 → β) : ComputableTidilyInSpace (fun y : Tuple × Bool => g (Frame.equiv (y.1.stack.headD dfr)).2) encStepInT encB stepBudget := - budget_comp_linear (f := fun y : Tuple × Bool => y.1.stack.headD dfr) (frameFinite_inSpace g) + budget_comp_linear (f := fun y : Tuple × Bool => y.1.stack.headD dfr) (frameFinite_inSpace g).tidy hTop private theorem hRound : ComputableTidilyInSpace (fun y : Tuple × Bool => (y.1.stack.headD dfr).round) encStepInT encNat stepBudget := - budget_comp_linear round_inSpace hTop + budget_comp_linear round_inSpace.tidy hTop /-- A function of the mode. -/ private theorem hModeFinite {β : Type} {encB : β ↪ List Bool} (g : Mode → β) : @@ -245,9 +246,10 @@ private theorem hNil : stepBudget := budget_const [] len_le_stepBudget theorem succ_inSpace {n : Tuple × Bool → ℕ} - (hn : ComputableTidilyInSpace n encStepInT encNat stepBudget) : - ComputableTidilyInSpace (fun y => n y + 1) encStepInT encNat stepBudget := - budget_comp_lin natSucc linear_succ hn + (hn : ComputableInSpace n encStepInT encNat stepBudget) : + ComputableInSpace (fun y => n y + 1) encStepInT encNat stepBudget := by + have hn := hn.tidy + exact .of_tidy (budget_comp_lin natSucc linear_succ hn) /-- The header: reading the value length. -/ private theorem branch0_inSpace : @@ -257,9 +259,9 @@ private theorem branch0_inSpace : encStepInT encStepOut stepBudget := budget_ite hBit (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace) (hConstNat 0) hNil))) + (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) (out_inSpace (budget_prod - (budget_prod (budget_prod n₁_inSpace (budget_prod height_inSpace hP)) hRegs) + (budget_prod (budget_prod n₁_inSpace.tidy (budget_prod height_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 1) (hConstNat 0) (hConstNat 0) hNil)))) /-- The header: reading the height. -/ @@ -270,19 +272,19 @@ private theorem branch1_inSpace : encStepInT encStepOut stepBudget := by have h2e : ComputableTidilyInSpace (fun y : Tuple × Bool => 2 * y.1.ell + 2) encStepInT encNat stepBudget := by - have h := budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace ell_inSpace) - exact (succ_inSpace (succ_inSpace h)).of_enc_eq fun y => by congr 1; omega + have h := budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace.tidy ell_inSpace.tidy) + exact (succ_inSpace (succ_inSpace (.of_tidy h))).tidy.of_enc_eq fun y => by congr 1; omega exact budget_ite hBit (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace) (hConstNat 0) hNil))) + (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) (out_inSpace (budget_prod - (budget_prod (budget_prod ell_inSpace (budget_prod n₁_inSpace hP)) hRegs) + (budget_prod (budget_prod ell_inSpace.tidy (budget_prod n₁_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 2) h2e (hConstNat 2) hNil)))) private theorem hReplicate : ComputableTidilyInSpace (fun y : Tuple × Bool => List.replicate y.1.ell 0) encStepInT (encList encNat) stepBudget := by - refine budget_comp replicate (budget_prod ell_inSpace (hConstNat 0)) (.const_mul 64 ?_) + refine budget_comp replicate (budget_prod ell_inSpace.tidy (hConstNat 0)) (.const_mul 64 ?_) exact mul_le_stepBudget (fun y => by dsimp only; omega) fun y => by simp only [length_encPair]; have : (encNat 0).length = 0 := rfl; omega @@ -296,8 +298,8 @@ private theorem branch2_inSpace : (List.replicate y.1.ell 0, List.replicate y.1.ell 0, List.replicate y.1.ell 0)), ([], .call false 2), runCtl), [])) encStepInT encStepOut stepBudget := by - have hlt := budget_comp_lin natLt linear_succ (budget_prod hN₂ n₁_inSpace) - have hmod := budget_comp_lin natMod (linear_mul _) (budget_prod n₁_inSpace hN₂) + have hlt := budget_comp_lin natLt linear_succ (budget_prod hN₂ n₁_inSpace.tidy) + have hmod := budget_comp_lin natMod (linear_mul _) (budget_prod n₁_inSpace.tidy hN₂) have hz := budget_comp_linear natIsZero hmod have hzeros : ComputableTidilyInSpace (fun y : Tuple × Bool => ((List.replicate y.1.ell 0, List.replicate y.1.ell 0, List.replicate y.1.ell 0) : Regs)) @@ -307,15 +309,15 @@ private theorem branch2_inSpace : ((((y.1.ell, y.1.height, y.1.n₁), (List.replicate y.1.ell 0, List.replicate y.1.ell 0, List.replicate y.1.ell 0)), ([], Mode.call false 2), runCtl) : Tuple)) encStepInT encTuple stepBudget := - mkTuple_inSpace ell_inSpace height_inSpace n₁_inSpace hzeros + mkTuple_inSpace ell_inSpace.tidy height_inSpace.tidy n₁_inSpace.tidy hzeros (budget_const (encB := encList encFrame) [] len_le_stepBudget) (budget_const (encB := encMode) (.call false 2) len_le_stepBudget) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil) refine (budget_ite hlt (budget_ite hz (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace) (hConstNat 2) hNil))) + (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace).tidy (hConstNat 2) hNil))) (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 2) n₁_inSpace (succ_inSpace hN₂) hNil)))) + (mkCtl_inSpace (hConstTag 2) n₁_inSpace.tidy (succ_inSpace (.of_tidy hN₂)).tidy hNil)))) (out_inSpace hfound)).of_enc_eq fun y => ?_ simp only [decide_eq_true_eq] @@ -340,7 +342,7 @@ private theorem withRegsModeCtl_inSpace {R : Tuple × Bool → Regs} {st : Tuple (hc : ComputableTidilyInSpace c encStepInT encCtlTuple stepBudget) : ComputableTidilyInSpace (fun y => y.1.with (R y) (st y) (m y) (c y)) encStepInT encTuple stepBudget := - mkTuple_inSpace ell_inSpace height_inSpace hP hR hst hm hc + mkTuple_inSpace ell_inSpace.tidy height_inSpace.tidy hP hR hst hm hc /-- Reading a leaf. -/ private theorem branch4_inSpace : @@ -357,12 +359,12 @@ private theorem branch4_inSpace : have hneg := hModeFinite (encB := encBool) Mode.neg have hcall := hModeFinite (encB := encBool) Mode.isCall have hc := (budget_ite hBit (hSgnVal hP hneg) (hConstNat 0)) - have hmod := modifyAt_inSpace (get_inSpace hRegs ht) n₁_inSpace hP hc - have hset := set_inSpace hRegs ht hmod - refine (budget_ite hcall (budget_ite (hLt n₁_inSpace ell_inSpace) - (out_inSpace (withRegsModeCtl_inSpace hset stack_inSpace hMode - (mkCtl_inSpace (hConstTag 4) (succ_inSpace n₁_inSpace) (hConstNat 0) hNil))) - (out_inSpace (withRegsModeCtl_inSpace hRegs stack_inSpace + have hmod := (modifyAt_inSpace (get_inSpace (.of_tidy hRegs) (.of_tidy ht)) n₁_inSpace (.of_tidy hP) (.of_tidy hc)).tidy + have hset := (set_inSpace (.of_tidy hRegs) (.of_tidy ht) (.of_tidy hmod)).tidy + refine (budget_ite hcall (budget_ite (hLt n₁_inSpace.tidy ell_inSpace.tidy) + (out_inSpace (withRegsModeCtl_inSpace hset stack_inSpace.tidy hMode + (mkCtl_inSpace (hConstTag 4) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) + (out_inSpace (withRegsModeCtl_inSpace hRegs stack_inSpace.tidy (budget_const (encB := encMode) .ret len_le_stepBudget) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil)))) (out_inSpace hTup)).of_enc_eq fun y => ?_ @@ -407,31 +409,31 @@ private theorem branch5_inSpace : encStepInT encStepOut stepBudget := by have hempty := budget_comp_linear (of_inO (.of_linear (ListEncoding.isEmpty (enc₁ := encFrame) (enc := encList encFrame)))) - stack_inSpace - have hG := budget_comp tableLength_inSpace ell_inSpace (.const_mul 4096 (ell_le_stepBudget.add + stack_inSpace.tidy + have hG := budget_comp tableLength_inSpace.tidy ell_inSpace.tidy (.const_mul 4096 (ell_le_stepBudget.add (.const 1 _))) - have hdm := budget_comp_lin natDivMod (linear_mul _) (budget_prod n₁_inSpace ell_inSpace) + have hdm := budget_comp_lin natDivMod (linear_mul _) (budget_prod n₁_inSpace.tidy ell_inSpace.tidy) have hk := fst' hdm have hi := snd' hdm - have hx := get_inSpace hRegs (hRegPlus 1) - have hy := get_inSpace hRegs (hRegPlus 2) - have hw := budget_comp weight_inSpace (budget_prod (budget_prod hP (budget_prod ell_inSpace hk)) + have hx := (get_inSpace (.of_tidy hRegs) (.of_tidy (hRegPlus 1))).tidy + have hy := (get_inSpace (.of_tidy hRegs) (.of_tidy (hRegPlus 2))).tidy + have hw := budget_comp weight_inSpace.tidy (budget_prod (budget_prod hP (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy)) (.const_mul 64 (((length_le (budget_prod (budget_prod hP - (budget_prod ell_inSpace hk)) (budget_prod hx hy))).add ell_le_stepBudget).add (.const 1 _))) - have hacc' := modifyAt_inSpace hAcc hi hP hw + (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy))).add ell_le_stepBudget).add (.const 1 _))) + have hacc' := (modifyAt_inSpace (.of_tidy hAcc) (.of_tidy hi) (.of_tidy hP) (.of_tidy hw)).tidy have hB : (fun y : Tuple × Bool => (y.1.regs.get (y.1.stack.headD dfr).target).length * ((encNat y.1.p).length + 1)) ≼ stepBudget := mul_le_stepBudget (fun y => by have := length_get_le_regLen y.1 (y.1.stack.headD dfr).target omega) fun y => by omega - have hsub := subtractSums_inSpace hP (hSgnVal hP hFrNeg) hFrTarget hAcc hRegs hB - refine (budget_ite hempty (out_inSpace hTup) (budget_ite (hLt n₁_inSpace hG) + have hsub := (subtractSums_inSpace (.of_tidy hP) (.of_tidy (hSgnVal hP hFrNeg)) (.of_tidy hFrTarget) (.of_tidy hAcc) (.of_tidy hRegs) hB).tidy + refine (budget_ite hempty (out_inSpace hTup) (budget_ite (hLt n₁_inSpace.tidy hG) (budget_ite hBit (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace) (hConstNat 0) hacc'))) + (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hacc'))) (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace) (hConstNat 0) hAcc)))) - (out_inSpace (withRegsModeCtl_inSpace hsub (cons_inSpace (hFrPhase 2) rest_inSpace) + (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hAcc)))) + (out_inSpace (withRegsModeCtl_inSpace hsub (cons_inSpace (hFrPhase 2) rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call true (g.2.2 + 1)) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil))))).of_enc_eq fun y => ?_ simp only [decide_eq_true_eq] @@ -460,8 +462,8 @@ private theorem scaleT_inSpace {R : Tuple × Bool → Regs} {r : Tuple × Bool (encNat y.1.p).length + (encNat (y.1.stack.headD dfr).round).length + 3) : ComputableTidilyInSpace (fun y => (R y).scale y.1.p (r y) (a y)) encStepInT encRegs stepBudget := - scale_inSpace hP ha hR hr len_le_stepBudget (mul_le_stepBudget (fun y => by - rw [hlen]; have := length_get_le_regLen y.1 (r y); omega) fun y => by have := hasz y; omega) + (scale_inSpace (.of_tidy hP) (.of_tidy ha) (.of_tidy hR) (.of_tidy hr) len_le_stepBudget (mul_le_stepBudget (fun y => by + rw [hlen]; have := length_get_le_regLen y.1 (r y); omega) fun y => by have := hasz y; omega)).tidy private theorem hFrame0 : ComputableTidilyInSpace (fun y : Tuple × Bool => (⟨0, 0, y.1.mode.neg, y.1.mode.target⟩ : Frame)) encStepInT encFrame stepBudget := @@ -471,7 +473,7 @@ private theorem hFrame0 : ComputableTidilyInSpace (fun y : Tuple × Bool => private theorem hFrameNext : ComputableTidilyInSpace (fun y : Tuple × Bool => (⟨(y.1.stack.headD dfr).round + 1, 0, (y.1.stack.headD dfr).neg, (y.1.stack.headD dfr).target⟩ : Frame)) encStepInT encFrame stepBudget := - (mkFrame_inSpace (succ_inSpace hRound) (hTopFinite (encB := encFinEnum (Fin 4 × Bool × Fin 3)) + (mkFrame_inSpace (succ_inSpace (.of_tidy hRound)).tidy (hTopFinite (encB := encFinEnum (Fin 4 × Bool × Fin 3)) fun g => (0, g.2.1, g.2.2))).of_enc_eq fun _ => rfl private theorem hRun : ComputableTidilyInSpace @@ -484,56 +486,56 @@ private theorem branch3_inSpace : stepBudget := by have ht := hModeFinite (encB := encReg) Mode.target have hcall := hModeFinite (encB := encBool) Mode.isCall - have hlenEq := budget_comp_linear natEq (budget_prod (budget_comp length stack_inSpace - (.const_mul 8 ((length_le stack_inSpace).add (.const 1 _)))) height_inSpace) + have hlenEq := budget_comp_linear natEq (budget_prod (budget_comp length stack_inSpace.tidy + (.const_mul 8 ((length_le stack_inSpace.tidy).add (.const 1 _)))) height_inSpace.tidy) have hempty := budget_comp_linear (of_inO (.of_linear (ListEncoding.isEmpty (enc₁ := encFrame) (enc := encList encFrame)))) - stack_inSpace + stack_inSpace.tidy have hph (k : Fin 4) := hTopFinite (encB := encBool) fun g => decide (g.1 = k) have hR0 := scaleT_inSpace hRegs (hModeFinite (encB := encReg) fun m => m.target + 1) (hConstNat (unitVal 0)) (fun _ _ => rfl) fun y => by have : (encNat (unitVal 0)).length = 1 := rfl omega - have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace hRound) (fun _ _ => rfl) fun y => by + have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace (.of_tidy hRound)).tidy (fun _ _ => rfl) fun y => by have := length_encNat_add_le_add (y.1.stack.headD dfr).round 1 have : (encNat 1).length = 1 := rfl omega - have hinv := budget_comp_linear unitInv_inSpace (budget_prod hP hRound) + have hinv := budget_comp_linear unitInv_inSpace.tidy (budget_prod hP hRound) have hR2 := scaleT_inSpace hRegs (hRegPlus 1) hinv (fun _ _ => rfl) fun y => by have := length_unitInv_le y.1.p (y.1.stack.headD dfr).round; dsimp only; omega have hR3 := scaleT_inSpace hRegs (hRegPlus 2) hinv (fun _ _ => rfl) fun y => by have := length_unitInv_le y.1.p (y.1.stack.headD dfr).round; dsimp only; omega - have hR3' := scaleT_inSpace hR3 (hRegPlus 1) (succ_inSpace (succ_inSpace hRound)) + have hR3' := scaleT_inSpace hR3 (hRegPlus 1) (succ_inSpace (succ_inSpace (.of_tidy hRound))).tidy (fun y r' => length_get_scale _ _ _ _ _) fun y => by have := length_encNat_add_le_add (y.1.stack.headD dfr).round 2 have : (encNat 2).length = 2 := rfl rw [show (y.1.stack.headD dfr).round + 1 + 1 = (y.1.stack.headD dfr).round + 2 by omega] omega - have hout := budget_comp mapEqOne_inSpace (get_inSpace hRegs (budget_const 2 len_le_stepBudget)) - (.const_mul 64 ((length_le (get_inSpace hRegs (budget_const 2 len_le_stepBudget))).add + have hout := budget_comp mapEqOne_inSpace.tidy (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy + (.const_mul 64 ((length_le (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy).add (.const 1 _))) - have hnext := hLt (succ_inSpace hRound) (budget_comp_lin natPred linear_succ hP) + have hnext := hLt (succ_inSpace (.of_tidy hRound)).tidy (budget_comp_lin natPred linear_succ hP) refine (budget_ite hcall (budget_ite hlenEq (out_inSpace (withCtl_inSpace (mkCtl_inSpace (hConstTag 4) (hConstNat 0) (hConstNat 0) hNil))) - (out_inSpace (withRegsModeCtl_inSpace hR0 (cons_inSpace hFrame0 stack_inSpace) + (out_inSpace (withRegsModeCtl_inSpace hR0 (cons_inSpace hFrame0 stack_inSpace.tidy) (hModeFinite (encB := encMode) fun m => .call false (m.target + 1)) hRun))) (budget_ite hempty (budget_prod (withCtl_inSpace (mkCtl_inSpace (hConstTag 6) (hConstNat 0) (hConstNat 0) hNil)) hout) (budget_ite (hph 0) - (out_inSpace (withRegsModeCtl_inSpace hRj (cons_inSpace (hFrPhase 1) rest_inSpace) + (out_inSpace (withRegsModeCtl_inSpace hRj (cons_inSpace (hFrPhase 1) rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call false (g.2.2 + 2)) hRun)) (budget_ite (hph 1) (out_inSpace (withCtl_inSpace (mkCtl_inSpace (hConstTag 5) (hConstNat 0) (hConstNat 0) hReplicate))) (budget_ite (hph 2) - (out_inSpace (withRegsModeCtl_inSpace hR2 (cons_inSpace (hFrPhase 3) rest_inSpace) + (out_inSpace (withRegsModeCtl_inSpace hR2 (cons_inSpace (hFrPhase 3) rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call true (g.2.2 + 2)) hRun)) (budget_ite hnext - (out_inSpace (withRegsModeCtl_inSpace hR3' (cons_inSpace hFrameNext rest_inSpace) + (out_inSpace (withRegsModeCtl_inSpace hR3' (cons_inSpace hFrameNext rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call false (g.2.2 + 1)) hRun)) - (out_inSpace (withRegsModeCtl_inSpace hR3 rest_inSpace + (out_inSpace (withRegsModeCtl_inSpace hR3 rest_inSpace.tidy (budget_const (encB := encMode) .ret len_le_stepBudget) hRun)))))))).of_enc_eq fun y => ?_ simp only [runStepT, decide_eq_true_eq] @@ -542,9 +544,10 @@ private theorem branch3_inSpace : end Branches /-- **The step within its space budget.** -/ -theorem stepT_inSpace : ComputableTidilyInSpace stepT encStepInT encStepOut stepBudget := by +theorem stepT_inSpace : ComputableInSpace stepT encStepInT encStepOut stepBudget := by + refine .of_tidy ?_ have ht (k : Fin 7) := - budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = k)) tag_inSpace + budget_finite (encC := encBool) (fun t : Fin 7 => decide (t = k)) tag_inSpace.tidy refine (budget_ite (ht 0) branch0_inSpace (budget_ite (ht 1) branch1_inSpace (budget_ite (ht 2) branch2_inSpace (budget_ite (ht 3) branch3_inSpace (budget_ite (ht 4) branch4_inSpace (budget_ite (ht 5) branch5_inSpace diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean index 9e9d8c2f3..7d5e10093 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean @@ -11,6 +11,7 @@ public import Complexity.Computability.TreeEval.Reader.Cert.Residue public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Bit public import Mathlib.Data.Nat.Bitwise public import Mathlib.Data.List.GetD +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # The weights of table entries within linear work space @@ -140,8 +141,8 @@ private theorem halfStep_inSpace : have := length_encNat_add_le_add s.1.1.2.2 s.2.1 simp only [length_encPair] at this ⊢; omega) have hxj := budget_comp_lin getD (linear_mul _) (budget_prod hx hj) - have hc := budget_comp_linear chi_inSpace (budget_prod (budget_prod hp hxj) hbit) - have hm := budget_comp_linear mulMod_inSpace (budget_prod hp (budget_prod ha hc)) + have hc := budget_comp_linear chi_inSpace.tidy (budget_prod (budget_prod hp hxj) hbit) + have hm := budget_comp_linear mulMod_inSpace.tidy (budget_prod hp (budget_prod ha hc)) exact budget_prod hpar (budget_prod hsucc hm) /-- The encoding of the arguments of half of a weight. -/ @@ -184,27 +185,29 @@ abbrev encWeightIn : (ℕ × ℕ × ℕ) × List ℕ × List ℕ ↪ List Bool : /-- **The weight**, `weight p ℓ k x y` from `((p, ℓ, k), x, y)`. -/ theorem weight_inSpace : - ComputableTidilyInSpace (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => + ComputableInSpace (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => weight w.1.1 w.1.2.1 w.1.2.2 w.2.1 w.2.2) encWeightIn encNat fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := by - have hl : (fun w => (encWeightIn w).length) ≼ fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) - := .of_le fun _ => by omega - have hℓle : (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => w.1.2.1) ≼ - fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := .of_le fun _ => by omega - have hpkl := (fst encNat3 (encPair (encList encNat) (encList encNat))).weaken hl - have hxy := (snd encNat3 (encPair (encList encNat) (encList encNat))).weaken hl - have hp := fst' hpkl - have hℓ := fst' (snd' hpkl) - have hk := snd' (snd' hpkl) - have hlo₀ := budget_prod (budget_prod (budget_prod hp - (budget_prod hk (budget_const (encB := encNat) 0 hl))) (fst' hxy)) hℓ - have hhi₀ := budget_prod (budget_prod (budget_prod hp (budget_prod hk hℓ)) (snd' hxy)) hℓ - have hlo := budget_comp half_inSpace hlo₀ - (.const_mul 256 (((length_le hlo₀).add hℓle).add (.const 1 _))) - have hhi := budget_comp half_inSpace hhi₀ - (.const_mul 256 (((length_le hhi₀).add hℓle).add (.const 1 _))) - exact (budget_comp_linear mulMod_inSpace (budget_prod hp (budget_prod hlo hhi))).of_enc_eq - fun w => by rw [weight_eq] + have this : ComputableTidilyInSpace (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => weight w.1.1 w.1.2.1 w.1.2.2 w.2.1 w.2.2) encWeightIn encNat fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := by + have hl : (fun w => (encWeightIn w).length) ≼ fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) + := .of_le fun _ => by omega + have hℓle : (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => w.1.2.1) ≼ + fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := .of_le fun _ => by omega + have hpkl := (fst encNat3 (encPair (encList encNat) (encList encNat))).weaken hl + have hxy := (snd encNat3 (encPair (encList encNat) (encList encNat))).weaken hl + have hp := fst' hpkl + have hℓ := fst' (snd' hpkl) + have hk := snd' (snd' hpkl) + have hlo₀ := budget_prod (budget_prod (budget_prod hp + (budget_prod hk (budget_const (encB := encNat) 0 hl))) (fst' hxy)) hℓ + have hhi₀ := budget_prod (budget_prod (budget_prod hp (budget_prod hk hℓ)) (snd' hxy)) hℓ + have hlo := budget_comp half_inSpace hlo₀ + (.const_mul 256 (((length_le hlo₀).add hℓle).add (.const 1 _))) + have hhi := budget_comp half_inSpace hhi₀ + (.const_mul 256 (((length_le hhi₀).add hℓle).add (.const 1 _))) + exact (budget_comp_linear mulMod_inSpace.tidy (budget_prod hp (budget_prod hlo hhi))).of_enc_eq + fun w => by rw [weight_eq] + simpa only [computableInSpace_iff_computableTidilyInSpace] using this end Reader diff --git a/Complexity/Computability/USTCON/Reader/Cert.lean b/Complexity/Computability/USTCON/Reader/Cert.lean index 0b45f1568..d19212189 100644 --- a/Complexity/Computability/USTCON/Reader/Cert.lean +++ b/Complexity/Computability/USTCON/Reader/Cert.lean @@ -12,6 +12,7 @@ public import Complexity.Computability.Machines.ReadMachine.Tidy public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpaceLib public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Streaming public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.Lists +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Plain /-! # The read machine for undirected connectivity within linear work space @@ -473,31 +474,33 @@ private theorem stepBudget_bool (x : Tuple) (b : Bool) : stepBudget (x, b) = ste cases b <;> simp [stepBudget, encBool_apply] /-- The halting test of `machine` is tidily computable within the space budget of the state. -/ -theorem halt_inSpace : ComputableTidilyInSpace machine.halt encState encBool stateBudget := - (haltT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl +theorem halt_inSpace : ComputableInSpace machine.halt encState encBool stateBudget := + .of_tidy ((haltT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl) /-- The address of `machine` is tidily computable within the space budget of the state. -/ -theorem addr_inSpace : ComputableTidilyInSpace machine.addr encState (encOption encNat) +theorem addr_inSpace : ComputableInSpace machine.addr encState (encOption encNat) stateBudget := - (addrT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl + .of_tidy ((addrT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl) /-- The step of `machine`, on a state and the bit read, is tidily computable within the space budget of the state. -/ theorem step_inSpace : - ComputableTidilyInSpace (fun p : State × Bool => machine.step p.1 p.2) + ComputableInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by - have h := stepT_inSpace.of_encIn_eq (α' := State × Bool) (encIn' := encPair encState encBool) - (fun p ↦ (p.1.toTuple, p.2)) fun _ ↦ rfl - refine (h.mono_le fun p ↦ ?_).of_enc_eq fun _ ↦ rfl - rw [stateBudget, stepBudget_bool] + have this : ComputableTidilyInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by + have h := stepT_inSpace.of_encIn_eq (α' := State × Bool) (encIn' := encPair encState encBool) + (fun p ↦ (p.1.toTuple, p.2)) fun _ ↦ rfl + refine (h.mono_le fun p ↦ ?_).of_enc_eq fun _ ↦ rfl + rw [stateBudget, stepBudget_bool] + simpa only [computableInSpace_iff_computableTidilyInSpace] using this /-- **The step machine simulating the read machine is tidy**, within the space of its states together with the position of its head. -/ theorem tidy_machine : ∃ T, machine.toStepMachine.Tidy (encPair encState encNat) (ReadMachine.stateT encState T stateBudget) (ReadMachine.stateS encState stateBudget) := by - obtain ⟨T₁, h₁⟩ := halt_inSpace - obtain ⟨T₂, h₂⟩ := addr_inSpace - obtain ⟨T₃, h₃⟩ := step_inSpace + obtain ⟨T₁, h₁⟩ := halt_inSpace.tidy + obtain ⟨T₂, h₂⟩ := addr_inSpace.tidy + obtain ⟨T₃, h₃⟩ := step_inSpace.tidy let T : State → ℕ := fun s => T₁ s + T₂ s + T₃ (s, false) + T₃ (s, true) exact ⟨T, ReadMachine.tidy_toStepMachine (h₁.mono_le (fun s => by simp only [T]; omega) fun _ => le_rfl) (h₂.mono_le (fun s => by simp only [T]; omega) fun _ => le_rfl) diff --git a/Complexity/Foundations/Combinatorics/AffineDisperser/Explicit.lean b/Complexity/Foundations/Combinatorics/AffineDisperser/Explicit.lean index 1b1cfe944..03cd58a13 100644 --- a/Complexity/Foundations/Combinatorics/AffineDisperser/Explicit.lean +++ b/Complexity/Foundations/Combinatorics/AffineDisperser/Explicit.lean @@ -42,7 +42,7 @@ affine subspace of `BitString N` of dimension greater than `d(N) + 1` (`Cslib.AffineDisperser.isAffineDisperser_explicitDisperser`). Downstream, in the computability layer, the function is shown not to depend on the roots chosen for the basis (`Cslib.AffineDisperser.traceSymBits_rootBasis_eq_explicitDisperser`) and to be computable in -polynomial time (`Cslib.AffineDisperser.computableTidilyInPolyTime_explicitDisperser`). +polynomial time (`Cslib.AffineDisperser.computableInPolyTime_explicitDisperser`). Ben-Sasson and Kopparty take `n` prime and reach dimension `6 N ^ (4 / 5)` [BenSassonKopparty2012]; the field then needs an irreducible polynomial of large prime degree, diff --git a/ComplexityTests/AWPPAmplification.lean b/ComplexityTests/AWPPAmplification.lean index 09830bf42..9dc360dce 100644 --- a/ComplexityTests/AWPPAmplification.lean +++ b/ComplexityTests/AWPPAmplification.lean @@ -26,7 +26,7 @@ private def numerator (w : List Bool) : ℤ := if w.headD false then 3 else 1 private theorem numerator_gap : numerator ∈ GapP encBits := by have h : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then (3 : ℕ) else 1) encBits encNat := by fun_prop - convert SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime h) using 1 + convert SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime (.of_tidy h)) using 1 ext w simp only [numerator] split_ifs <;> rfl diff --git a/ComplexityTests/AffineDisperserRuntime.lean b/ComplexityTests/AffineDisperserRuntime.lean index 1bc078233..99807acfe 100644 --- a/ComplexityTests/AffineDisperserRuntime.lean +++ b/ComplexityTests/AffineDisperserRuntime.lean @@ -78,11 +78,11 @@ example (N : ℕ) : /-! ### Axioms -/ /-- -info: 'Cslib.AffineDisperser.computableTidilyInPolyTime_explicitDisperser' depends on axioms: +info: 'Cslib.AffineDisperser.computableInPolyTime_explicitDisperser' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms computableTidilyInPolyTime_explicitDisperser +#print axioms computableInPolyTime_explicitDisperser /-- info: 'Cslib.AffineDisperser.setOf_explicitDisperser_mem_P' depends on axioms: @@ -141,10 +141,10 @@ info: 'Cslib.AffineDisperser.polyOfCode_leastIrreducibleCode' depends on axioms: #print axioms polyOfCode_leastIrreducibleCode /-- -info: 'Cslib.AffineDisperser.computableTidilyInPolyTime_traceSymCoords' depends on axioms: +info: 'Cslib.AffineDisperser.computableInPolyTime_traceSymCoords' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms computableTidilyInPolyTime_traceSymCoords +#print axioms computableInPolyTime_traceSymCoords end ComplexityTests.AffineDisperserRuntime diff --git a/ComplexityTests/ApproximateCounting.lean b/ComplexityTests/ApproximateCounting.lean index 2f15e8402..cdab5fd37 100644 --- a/ComplexityTests/ApproximateCounting.lean +++ b/ComplexityTests/ApproximateCounting.lean @@ -25,7 +25,7 @@ private theorem head_mem_AWPP : {w : List Bool | w.headD false = true} ∈ AWPP have hf : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then (3 : ℤ) else 1) encBits encIntBin := by fun_prop - refine ⟨_, mem_GapP_of_polyTime hf, 2, fun w => ?_⟩ + refine ⟨_, mem_GapP_of_polyTime (.of_tidy hf), 2, fun w => ?_⟩ simp only [Set.mem_ofPred_eq] cases w.headD false <;> norm_num @@ -46,7 +46,7 @@ private theorem head_mem_AWPP_exp : {w : List Bool | w.headD false = true} ∈ A have hf : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then (2 : ℤ) ^ w.length else 0) encBits encIntBin := by fun_prop - refine ⟨_, mem_GapP_of_polyTime hf, Polynomial.X, fun w => ?_⟩ + refine ⟨_, mem_GapP_of_polyTime (.of_tidy hf), Polynomial.X, fun w => ?_⟩ have hp : 0 ≤ (2 : ℤ) ^ w.length := by positivity cases h : w.headD false <;> simp only [encBits_apply, Polynomial.eval_X, h, Bool.false_eq_true, ↓reduceIte, Set.mem_ofPred_eq] @@ -79,7 +79,7 @@ private theorem head_mem_SBP : {w : List Bool | w.headD false = true} ∈ SBP en have hf : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then 2 ^ w.length else 0) encBits encNat := by fun_prop - refine ⟨_, mem_SharpP_of_polyTime hf, fun w => 2 ^ w.length, + refine ⟨_, mem_SharpP_of_polyTime (.of_tidy hf), fun w => 2 ^ w.length, .of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp (.encoding_length encBits)), fun w => ?_⟩ have hp : 0 < 2 ^ w.length := by positivity @@ -109,7 +109,7 @@ private theorem head_mem_WPP_negative : {w : List Bool | w.headD false = true} have hg : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then f w else 0) encBits encIntBin := by fun_prop have hn (w : List Bool) : f w ≠ 0 := by simp [f] - refine ⟨_, mem_GapP_of_polyTime hg, f, .of_tidy hf, hn, fun w => ?_, fun w => ?_⟩ + refine ⟨_, mem_GapP_of_polyTime (.of_tidy hg), f, .of_tidy hf, hn, fun w => ?_, fun w => ?_⟩ · cases w.headD false <;> simp · simp only [Set.mem_ofPred_eq] cases w.headD false <;> simp [(hn w).symm] diff --git a/ComplexityTests/Axioms.lean b/ComplexityTests/Axioms.lean index 485cdd846..a04ca375c 100644 --- a/ComplexityTests/Axioms.lean +++ b/ComplexityTests/Axioms.lean @@ -820,10 +820,10 @@ info: 'Cslib.Complexity.SAT.isVerifier' depends on axioms: [propext, Classical.c #print axioms Cslib.Complexity.SAT.isVerifier /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SAT.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_verifier +#print axioms Cslib.Complexity.SAT.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.SAT.mem_NP' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -4082,10 +4082,10 @@ info: 'Turing.MultiTapeTM.ComputableTidilyInPolyTime.unary_to_binary' depends on #print axioms Turing.MultiTapeTM.ComputableTidilyInPolyTime.unary_to_binary /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_parameters' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_parameters' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_parameters +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_parameters /-- info: 'Turing.MultiTapeTM.Universal.computableTidilyInO_universal' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -4286,70 +4286,70 @@ info: 'Turing.computableTidilyInPolyTime_windowList' depends on axioms: [propext #print axioms Turing.computableTidilyInPolyTime_windowList /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_featureIndex' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_featureIndex' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_featureIndex +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_featureIndex /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inPos' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inPos' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inPos +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_inPos /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_head' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_head' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_head +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_head /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_cell' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cell' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_cell +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_cell /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_holds' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_holds' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_holds +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_holds /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_cert' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cert' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_cert +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_cert /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_index' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_index' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_index +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_index /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_relabel' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_relabel' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_relabel +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_relabel /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_initClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_initClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_initClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_initClauses /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_acceptClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_acceptClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_sitClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_sitClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses /-- info: 'Turing.MultiTapeTM.ComputableTidilyInPolyTime.cons'' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -4439,10 +4439,10 @@ info: 'Turing.MultiTapeTM.ComputableTidilyInPolyTime.anyConst' depends on axioms #print axioms Turing.MultiTapeTM.ComputableTidilyInPolyTime.anyConst /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_oneHotClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_oneHotClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses /-- info: 'Cslib.Crypto.GGM.computableTidilyInPolyTime_eval' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -5350,44 +5350,44 @@ info: 'Cslib.Crypto.PseudorandomGenerator.exists_pseudorandomFunction' depends o #print axioms Cslib.Crypto.PseudorandomGenerator.exists_pseudorandomFunction /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inputClauses' depends on axioms: [propext, +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_inputClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_readClauses' depends on axioms: [propext, +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_readClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_readClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_readClauses /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_stepClauses' depends on axioms: [propext, +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_stepClauses +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_tableau' depends on axioms: [propext, +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_tableau' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_tableau +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_tableau /-- -info: 'Cslib.Complexity.CookLevin.computableTidilyInPolyTime_reduce' depends on axioms: [propext, +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_reduce' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.CookLevin.computableTidilyInPolyTime_reduce +#print axioms Cslib.Complexity.CookLevin.computableInPolyTime_reduce /-- info: 'Cslib.Complexity.CookLevin.SAT_npHard' depends on axioms: diff --git a/ComplexityTests/BasicClasses.lean b/ComplexityTests/BasicClasses.lean index dc73c6832..5ca9b279b 100644 --- a/ComplexityTests/BasicClasses.lean +++ b/ComplexityTests/BasicClasses.lean @@ -45,7 +45,7 @@ example : {w : List Bool | w.headD false = true} ∆ {w | w.tail.headD false = t /-- A variable-length precomposition preserves the count `2 ^ |tail w|` without a padding factor. -/ example : (fun w : List Bool => 2 ^ w.tail.length) ∈ SharpP encBits := by simpa [Function.comp_def] using SharpP.comp_mem (SharpP.two_pow_mem (enc := encBits) Polynomial.X) - (show ComputableTidilyInPolyTime List.tail encBits encBits by fun_prop) + (.of_tidy (show ComputableTidilyInPolyTime List.tail encBits encBits by fun_prop)) /-- Requiring padding to be false gives exactly one extension, including zero padding. -/ example (n : ℕ) : acceptCount @@ -57,7 +57,7 @@ example (n : ℕ) : acceptCount example : (fun w : List Bool => (2 ^ w.tail.length : ℕ) - (1 : ℤ)) ∈ GapP encBits := by simpa [Function.comp_def] using GapP.comp_mem (GapP.natCast_sub_natCast_mem (SharpP.two_pow_mem (enc := encBits) Polynomial.X) SharpP.one_mem) - (show ComputableTidilyInPolyTime List.tail encBits encBits by fun_prop) + (.of_tidy (show ComputableTidilyInPolyTime List.tail encBits encBits by fun_prop)) example : {w : List Bool | w.headD false = true} ∈ UP encBits := P_subset_UP head_mem_P diff --git a/ComplexityTests/CircuitValueCompleteness.lean b/ComplexityTests/CircuitValueCompleteness.lean index 09fd894f6..b9248d77c 100644 --- a/ComplexityTests/CircuitValueCompleteness.lean +++ b/ComplexityTests/CircuitValueCompleteness.lean @@ -107,10 +107,10 @@ example {α : Type} {enc : α ↪ List Bool} {f : α → Bool} #guard_msgs (whitespace := lax) in #print axioms CircuitValue.exists_uniformCircuits -/-- info: 'Cslib.Complexity.CircuitValue.computableTidilyInPolyTime_tableauCode' depends on axioms: +/-- info: 'Cslib.Complexity.CircuitValue.computableInPolyTime_tableauCode' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms CircuitValue.computableTidilyInPolyTime_tableauCode +#print axioms CircuitValue.computableInPolyTime_tableauCode /-- info: 'Cslib.Complexity.CircuitValue.logSpaceComplete' depends on axioms: [propext, Classical.choice, Quot.sound] -/ diff --git a/ComplexityTests/ClassCorollaries.lean b/ComplexityTests/ClassCorollaries.lean index 1f805fc23..b76fdb43b 100644 --- a/ComplexityTests/ClassCorollaries.lean +++ b/ComplexityTests/ClassCorollaries.lean @@ -98,7 +98,7 @@ example {α : Type} (enc : α ↪ List Bool) : PPT. -/ example : IsOraclePPTOn encBits encNat (fun w => OracleComp.interpret ProbOracleComp.query (BinarySearch.search w (w.length + 1))) := - BinarySearch.isOraclePPTOn_search ComputableTidilyInPolyTime.id' (by fun_prop) + BinarySearch.isOraclePPTOn_search (.of_tidy ComputableTidilyInPolyTime.id') (.of_tidy (by fun_prop)) example {α : Type} (enc : α ↪ List Bool) : PWithSharpPOracle enc ⊆ PWithPPOracle enc := PWithSharpPOracle_subset_PWithPPOracle diff --git a/ComplexityTests/CountingAggregation.lean b/ComplexityTests/CountingAggregation.lean index b51ab5527..82f38203b 100644 --- a/ComplexityTests/CountingAggregation.lean +++ b/ComplexityTests/CountingAggregation.lean @@ -18,17 +18,17 @@ open Cslib.Complexity Turing.MultiTapeTM example : (fun w : List Bool => (-1 : ℤ) ^ w.length) ∈ GapP encBits := by have hneg : (fun _ : List Bool => (-1 : ℤ)) ∈ GapP encBits := GapP.neg_mem GapP.one_mem - exact GapP.pow_mem_polyTime hneg (ComputableTidilyInPolyTime.encoding_length encBits) + exact GapP.pow_mem_polyTime hneg (.of_tidy (ComputableTidilyInPolyTime.encoding_length encBits)) /-- The exponent-zero case includes a zero base and returns one. -/ example : (fun _ : List Bool => (0 : ℤ) ^ (0 : ℕ)) ∈ GapP encBits := - GapP.pow_mem_polyTime GapP.zero_mem (ComputableTidilyInPolyTime.const 0) + GapP.pow_mem_polyTime GapP.zero_mem (.of_tidy (ComputableTidilyInPolyTime.const 0)) /-- Summing negative weights over an input-dependent Boolean cube. -/ example : (fun w : List Bool => -(2 : ℤ) ^ w.length) ∈ GapP encBits := by have hneg : (fun _ : List Bool × List Bool => (-1 : ℤ)) ∈ GapP (encPair encBits encBits) := GapP.neg_mem GapP.one_mem - convert GapP.sum_bits_mem hneg (ComputableTidilyInPolyTime.encoding_length encBits) using 1 + convert GapP.sum_bits_mem hneg (.of_tidy (ComputableTidilyInPolyTime.encoding_length encBits)) using 1 ext w rw [Finset.sum_const, Finset.card_univ, Fintype.card_fun, Fintype.card_bool, Fintype.card_fin] diff --git a/ComplexityTests/CountingGapMachine.lean b/ComplexityTests/CountingGapMachine.lean index 8ea697d1f..4166e62fd 100644 --- a/ComplexityTests/CountingGapMachine.lean +++ b/ComplexityTests/CountingGapMachine.lean @@ -178,7 +178,7 @@ example (sign : Bool) : machine.rejectCount (clock.eval input.length) (Cfg.init machine.initial input) = 1 := by simpa only [encBits_apply, Polynomial.eval_zero, Complexity.acceptCount_false, pow_zero, Nat.sub_zero, ite_self] using exists_signed_verifier_machine encBits 0 (fun _ => false) - (ComputableTidilyInPolyTime.const false) sign + (.of_tidy (ComputableTidilyInPolyTime.const false)) sign -- Independently sized 2-bit and 0-bit successful families have odd difference 4 - 1 = 3. example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) @@ -189,7 +189,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [encBits_apply, Polynomial.eval_C, Polynomial.eval_zero, Complexity.acceptCount_true, Nat.reducePow, pow_zero, Nat.cast_ofNat, Nat.cast_one, Int.reduceSub] using exists_verifier_difference_machine encBits (Polynomial.C 2) 0 (fun _ => true) (fun _ => true) - (ComputableTidilyInPolyTime.const true) (ComputableTidilyInPolyTime.const true) + (.of_tidy (ComputableTidilyInPolyTime.const true)) (.of_tidy (ComputableTidilyInPolyTime.const true)) -- Unequal all-false families still cancel to zero, without matching their witness lengths. example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) @@ -200,7 +200,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [encBits_apply, Polynomial.eval_C, Polynomial.eval_zero, Complexity.acceptCount_false, Nat.cast_zero, sub_self] using exists_verifier_difference_machine encBits 0 (Polynomial.C 2) (fun _ => false) (fun _ => false) - (ComputableTidilyInPolyTime.const false) (ComputableTidilyInPolyTime.const false) + (.of_tidy (ComputableTidilyInPolyTime.const false)) (.of_tidy (ComputableTidilyInPolyTime.const false)) /-- info: 'Turing.MultiTapeCTM.exists_signed_verifier_machine' depends on axioms: diff --git a/ComplexityTests/CountingProducts.lean b/ComplexityTests/CountingProducts.lean index 2a791b150..ba561b8b0 100644 --- a/ComplexityTests/CountingProducts.lean +++ b/ComplexityTests/CountingProducts.lean @@ -32,7 +32,7 @@ private theorem variableCount_mem : variableCount ∈ SharpP (encPair encBits en example : (fun w : List Bool => ∏ i ∈ range w.length, variableCount (w, i)) ∈ SharpP encBits := SharpP.prod_range_mem variableCount_mem - (by simpa using ComputableTidilyInPolyTime.encoding_length encBits) + (.of_tidy (by simpa using ComputableTidilyInPolyTime.encoding_length encBits)) /-- The two factors use genuinely different certificate lengths: 10 and 17. -/ example : variableCount ([true], 0) = 2 ^ 10 ∧ variableCount ([true], 1) = 2 ^ 17 := by @@ -40,7 +40,7 @@ example : variableCount ([true], 0) = 2 ^ 10 ∧ variableCount ([true], 1) = 2 ^ /-- Empty indexed products equal one even when every possible factor is zero. -/ example : (fun _ : List Bool => ∏ _i ∈ range 0, (0 : ℕ)) ∈ SharpP encBits := - SharpP.prod_range_mem (SharpP.natCast_mem 0) (ComputableTidilyInPolyTime.const 0) + SharpP.prod_range_mem (SharpP.natCast_mem 0) (.of_tidy (ComputableTidilyInPolyTime.const 0)) example : (∏ _i ∈ range 0, (0 : ℕ)) = 1 := by simp @@ -55,11 +55,11 @@ example : acceptCount (SharpP.indexedProductVerifier (fun _ : Unit => 2) (fun _ def signedFactor (x : List Bool × ℕ) : ℤ := if x.2 = 0 then -2 else 3 private theorem signedFactor_mem : signedFactor ∈ GapP (encPair encBits encUnary) := - mem_GapP_of_polyTime (f := signedFactor) (by unfold signedFactor; fun_prop) + mem_GapP_of_polyTime (f := signedFactor) (.of_tidy (by unfold signedFactor; fun_prop)) example : (fun w : List Bool => ∏ i ∈ range w.length, signedFactor (w, i)) ∈ GapP encBits := GapP.prod_range_mem signedFactor_mem - (by simpa using ComputableTidilyInPolyTime.encoding_length encBits) + (.of_tidy (by simpa using ComputableTidilyInPolyTime.encoding_length encBits)) example : (∏ i ∈ range 2, signedFactor ([], i)) = -6 := by decide @@ -68,16 +68,16 @@ def cancelFactor (x : List Bool × ℕ) : ℤ := if x.2 = 0 then -1 else 0 private theorem cancelFactor_mem : cancelFactor ∈ GapP (encPair encBits encUnary) := by have h₁ : (fun x : List Bool × ℕ => if x.2 = 0 then (2 : ℕ) else 1) ∈ - SharpP (encPair encBits encUnary) := mem_SharpP_of_polyTime (by fun_prop) + SharpP (encPair encBits encUnary) := mem_SharpP_of_polyTime (.of_tidy (by fun_prop)) have h₂ : (fun x : List Bool × ℕ => if x.2 = 0 then (3 : ℕ) else 1) ∈ - SharpP (encPair encBits encUnary) := mem_SharpP_of_polyTime (by fun_prop) + SharpP (encPair encBits encUnary) := mem_SharpP_of_polyTime (.of_tidy (by fun_prop)) refine ⟨_, h₁, _, h₂, fun x => ?_⟩ simp only [cancelFactor] split_ifs <;> norm_num example : (fun w : List Bool => ∏ i ∈ range w.length, cancelFactor (w, i)) ∈ GapP encBits := GapP.prod_range_mem cancelFactor_mem - (by simpa using ComputableTidilyInPolyTime.encoding_length encBits) + (.of_tidy (by simpa using ComputableTidilyInPolyTime.encoding_length encBits)) example : (∏ i ∈ range 0, cancelFactor ([], i)) = 1 ∧ (∏ i ∈ range 1, cancelFactor ([], i)) = -1 ∧ diff --git a/ComplexityTests/CountingSpace.lean b/ComplexityTests/CountingSpace.lean index 493c511c5..94e8e97cd 100644 --- a/ComplexityTests/CountingSpace.lean +++ b/ComplexityTests/CountingSpace.lean @@ -10,6 +10,7 @@ module public import Complexity.Computability.Complexity.Classes.Counting.OracleSpace import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Clients for exact polynomial-space counting: zero-width certificates, a nonconstant verifier, negative integer outputs, composite and degenerate moduli, and word-oracle space bounds. -/ @@ -41,11 +42,11 @@ example : streamAcceptCount firstBit [] 4 = acceptCount firstBit [] 4 := example : ComputableTidilyInPolySpace (fun w : List Bool => acceptCount firstBit w (w.length + 1)) encBits encNat := - computableTidilyInPolySpace_acceptCount firstBit_polyTime (by fun_prop) + (computableInPolySpace_acceptCount (.of_tidy firstBit_polyTime) (.of_tidy (by fun_prop))).tidy example : ComputableTidilyInPolySpace (fun w : List Bool => acceptCount firstBit w 0) encBits encNat := - computableTidilyInPolySpace_acceptCount firstBit_polyTime (.const 0) + (computableInPolySpace_acceptCount (.of_tidy firstBit_polyTime) (.of_tidy (.const 0))).tidy theorem power_mem : (fun w : List Bool => 2 ^ w.length) ∈ SharpP encBits := by simpa using SharpP.two_pow_mem (enc := encBits) Polynomial.X @@ -92,10 +93,10 @@ example : ∃ g ∈ SharpP encBits, ∀ b : Bool, g [b] = 0 := SharpP.exists_extension (enc := encBool) SharpP.zero_mem /-- -info: 'Cslib.Complexity.computableTidilyInPolySpace_acceptCount' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.computableInPolySpace_acceptCount' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms computableTidilyInPolySpace_acceptCount +#print axioms computableInPolySpace_acceptCount /-- info: 'Cslib.Complexity.SharpP.computableTidilyInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] -/ diff --git a/ComplexityTests/Derandomization.lean b/ComplexityTests/Derandomization.lean index f03667741..c3cc6e981 100644 --- a/ComplexityTests/Derandomization.lean +++ b/ComplexityTests/Derandomization.lean @@ -126,18 +126,18 @@ info: 'Cslib.Complexity.P_eq_BPP_of_isAverageCaseHard' depends on axioms: #print axioms Cslib.Complexity.P_eq_BPP_of_isAverageCaseHard /-- -info: 'Cslib.Complexity.computableTidilyInPolyTime_nwDecider' depends on axioms: +info: 'Cslib.Complexity.computableInPolyTime_nwDecider' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInPolyTime_nwDecider +#print axioms Cslib.Complexity.computableInPolyTime_nwDecider /-- -info: 'Cslib.Complexity.exists_computableTidilyInO_of_mem_DTIME' depends on axioms: +info: 'Cslib.Complexity.exists_computableInO_of_mem_DTIME' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.exists_computableTidilyInO_of_mem_DTIME +#print axioms Cslib.Complexity.exists_computableInO_of_mem_DTIME /-- info: 'Cslib.Crypto.PRG.NisanWigderson.abs_card_div_sub_card_div_lt' depends on axioms: @@ -154,11 +154,11 @@ info: 'Cslib.Crypto.PRG.NisanWigderson.choose_le_length_greedyMasks_mul' depends #print axioms Cslib.Crypto.PRG.NisanWigderson.choose_le_length_greedyMasks_mul /-- -info: 'Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_greedyMasks' depends on axioms: +info: 'Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Crypto.PRG.NisanWigderson.computableTidilyInPolyTime_greedyMasks +#print axioms Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks /-- info: 'Cslib.Circuits.Boolean.isAverageCaseHard_xorPower' depends on axioms: diff --git a/ComplexityTests/ExponentialPadding.lean b/ComplexityTests/ExponentialPadding.lean index 4728c199e..d1c090f0d 100644 --- a/ComplexityTests/ExponentialPadding.lean +++ b/ComplexityTests/ExponentialPadding.lean @@ -13,9 +13,9 @@ open Cslib.Complexity Turing.MultiTapeTM example {Ψ : List Bool × ℕ → Bool} (hΨ : ComputableTidilyInPolyTime Ψ (encPair encBits encUnary) encBool) : {y : List Bool | Ψ (y, 2 ^ y.length) = true} ∈ E encBits := - setOf_mem_E_of_computableTidilyInPolyTime_pad hΨ + setOf_mem_E_of_computableInPolyTime_pad (.of_tidy hΨ) -- The polynomial-time premise is inhabited, including at the empty input. example : {y : List Bool | (fun _ : List Bool × ℕ => true) (y, 2 ^ y.length) = true} ∈ E encBits := - setOf_mem_E_of_computableTidilyInPolyTime_pad (ComputableTidilyInPolyTime.const true) + setOf_mem_E_of_computableInPolyTime_pad (.of_tidy (ComputableTidilyInPolyTime.const true)) diff --git a/ComplexityTests/Fagin.lean b/ComplexityTests/Fagin.lean index e5593e486..9acf4bad6 100644 --- a/ComplexityTests/Fagin.lean +++ b/ComplexityTests/Fagin.lean @@ -188,11 +188,11 @@ info: 'Cslib.Complexity.IsVerifier.strictVerifier' depends on axioms: #print axioms Cslib.Complexity.IsVerifier.strictVerifier /-- -info: 'Cslib.Complexity.computableTidilyInPolyTime_strictVerifier' depends on axioms: +info: 'Cslib.Complexity.computableInPolyTime_strictVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInPolyTime_strictVerifier +#print axioms Cslib.Complexity.computableInPolyTime_strictVerifier /-- info: 'Cslib.Complexity.CookLevin.exists_tableau_satisfiable_iff_of_strictVerifier' depends on axioms: diff --git a/ComplexityTests/FineGrained.lean b/ComplexityTests/FineGrained.lean index ff80cd26a..8b5b75ba3 100644 --- a/ComplexityTests/FineGrained.lean +++ b/ComplexityTests/FineGrained.lean @@ -108,11 +108,11 @@ example : satExponent 3 ≤ satExponent 4 := satExponent_mono (by norm_num) /-- A trivial problem is decidable within linear time, in either form. -/ example : DecidableInTimeO (∅ : Set (CNF ℕ)) encCNF fun φ => (encCNF φ).length := - .of_computableTidilyInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl + DecidableInTimeO.of_computableInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl example : (∅ : Set (CNF ℕ)) ∈ DTIME encCNF id := mem_DTIME_iff_decidableInTimeO.mpr - (.of_computableTidilyInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl) + (DecidableInTimeO.of_computableInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl) /-- The hypotheses in terms of the exponents. -/ example : ETH ↔ 0 < satExponent 3 := ETH_iff_satExponent_pos @@ -141,11 +141,11 @@ info: 'Cslib.Complexity.BruteForce.search_eq_true_iff' depends on axioms: #print axioms Cslib.Complexity.BruteForce.search_eq_true_iff /-- -info: 'Cslib.Complexity.BruteForce.exists_computableTidilyInO_search' depends on axioms: +info: 'Cslib.Complexity.BruteForce.exists_computableInO_search' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.BruteForce.exists_computableTidilyInO_search +#print axioms Cslib.Complexity.BruteForce.exists_computableInO_search /-- info: 'Cslib.Complexity.KSAT_decidableInExpTime_one' depends on axioms: @@ -187,11 +187,11 @@ info: 'Cslib.Complexity.toOV_mem_OV_iff' depends on axioms: [propext, Classical. #print axioms Cslib.Complexity.toOV_mem_OV_iff /-- -info: 'Cslib.Complexity.exists_computableTidilyInO_toOV' depends on axioms: +info: 'Cslib.Complexity.exists_computableInO_toOV' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.exists_computableTidilyInO_toOV +#print axioms Cslib.Complexity.exists_computableInO_toOV /-- info: 'Cslib.Complexity.DecidableInTimeO.decidableInExpTime_SAT' depends on axioms: diff --git a/ComplexityTests/FineGrained/GraphProblems.lean b/ComplexityTests/FineGrained/GraphProblems.lean index c3f99569a..6120b0524 100644 --- a/ComplexityTests/FineGrained/GraphProblems.lean +++ b/ComplexityTests/FineGrained/GraphProblems.lean @@ -116,7 +116,7 @@ example : (SAT.toThreeColoring φ₁).1.length + (SAT.toThreeColoring φ₁).2.l /-- The subexponential time predicate holds for a trivial problem. -/ example : DecidableInSubexpTime (∅ : Set Graph) encGraph fun G => G.1.length + G.2.length := - fun δ hδ => .of_computableTidilyInO (ComputableTidilyInO.const false) (by simp) 1 1 fun G => by + fun δ hδ => DecidableInExpTime.of_computableInO (ComputableTidilyInO.const false) (by simp) 1 1 fun G => by have h₁ : (1 : ℝ) ≤ 2 ^ (δ * ((G.1.length + G.2.length : ℕ) : ℝ)) := Real.one_le_rpow (by norm_num) (by positivity) have h₀ : (0 : ℝ) ≤ (encGraph G).length := Nat.cast_nonneg _ @@ -161,11 +161,11 @@ info: 'Cslib.Complexity.SAT.toSparseIndependentSet_mem_iff' depends on axioms: #print axioms Cslib.Complexity.SAT.toSparseIndependentSet_mem_iff /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseIndependentSet' depends on axioms: +info: 'Cslib.Complexity.SAT.computableInPolyTime_toSparseIndependentSet' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseIndependentSet +#print axioms Cslib.Complexity.SAT.computableInPolyTime_toSparseIndependentSet /-- info: 'Cslib.Complexity.SAT.length_toSparseIndependentSet_le' depends on axioms: @@ -256,11 +256,11 @@ info: 'Cslib.Complexity.SAT.toSparseHamCycle_mem_iff' depends on axioms: #print axioms Cslib.Complexity.SAT.toSparseHamCycle_mem_iff /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseHamCycle' depends on axioms: +info: 'Cslib.Complexity.SAT.computableInPolyTime_toSparseHamCycle' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_toSparseHamCycle +#print axioms Cslib.Complexity.SAT.computableInPolyTime_toSparseHamCycle /-- info: 'Cslib.Complexity.SAT.length_toSparseHamCycle_le' depends on axioms: diff --git a/ComplexityTests/HierarchyTheorems.lean b/ComplexityTests/HierarchyTheorems.lean index fb5aa4c48..1cc9ea841 100644 --- a/ComplexityTests/HierarchyTheorems.lean +++ b/ComplexityTests/HierarchyTheorems.lean @@ -142,11 +142,11 @@ info: 'Cslib.Complexity.setOf_timeDiagonal_notMem_DTIME' depends on axioms: #print axioms Cslib.Complexity.setOf_timeDiagonal_notMem_DTIME /-- -info: 'Cslib.Complexity.computableTidilyInO_timeDiagonal' depends on axioms: +info: 'Cslib.Complexity.computableInO_timeDiagonal' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInO_timeDiagonal +#print axioms Cslib.Complexity.computableInO_timeDiagonal /-- info: 'Cslib.Complexity.timeConstructible_succ_pow' depends on axioms: diff --git a/ComplexityTests/InteractiveProofs.lean b/ComplexityTests/InteractiveProofs.lean index ba1f650f9..f5bbdf5de 100644 --- a/ComplexityTests/InteractiveProofs.lean +++ b/ComplexityTests/InteractiveProofs.lean @@ -170,7 +170,7 @@ example : ComputableTidilyInPolySpace (fun w => BitString.increment (BitString.i -- A Boolean function computable within polynomial space decides a problem in `PSPACE`. example : {w : List Bool | w.headD false = true} ∈ PSPACE encBits := - mem_PSPACE_of_computableTidilyInPolySpace (f := fun w => w.headD false) + mem_PSPACE_of_computableInPolySpace (f := fun w => w.headD false) (.of_polyTime (ComputableTidilyInPolyTime.headD false)) fun _ => Iff.rfl -- The seven codes of length `3` decode to the seven words of length at most `2`, each once. @@ -333,11 +333,11 @@ example (P : Prover Unit) : #guard_msgs in #print axioms Interaction.computableTidilyInPolySpace_evaluate -/-- info: 'Cslib.Complexity.Interaction.computableTidilyInPolySpace_countAccepts' depends on axioms: [propext, +/-- info: 'Cslib.Complexity.Interaction.computableInPolySpace_countAccepts' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Interaction.computableTidilyInPolySpace_countAccepts +#print axioms Interaction.computableInPolySpace_countAccepts /-- info: 'Cslib.Complexity.GameTree.iterate_step_node' depends on axioms: [propext, Classical.choice, Quot.sound] -/ diff --git a/ComplexityTests/Isolation.lean b/ComplexityTests/Isolation.lean index b8a8597e8..7cc679b69 100644 --- a/ComplexityTests/Isolation.lean +++ b/ComplexityTests/Isolation.lean @@ -162,11 +162,11 @@ example : 1 / 2 ≤ Finset.dens (Finset.univ.filter fun w : Fin 2 → Fin 4 => /-! ### Axioms -/ /-- -info: 'Cslib.Complexity.ValiantVazirani.computableTidilyInPolyTime_reduce' depends on axioms: +info: 'Cslib.Complexity.ValiantVazirani.computableInPolyTime_reduce' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.ValiantVazirani.computableTidilyInPolyTime_reduce +#print axioms Cslib.Complexity.ValiantVazirani.computableInPolyTime_reduce /-- info: 'Cslib.Complexity.ValiantVazirani.reduce_mem_UNSAT' depends on axioms: [propext] diff --git a/ComplexityTests/Kannan.lean b/ComplexityTests/Kannan.lean index 1d78fdcd9..b79688329 100644 --- a/ComplexityTests/Kannan.lean +++ b/ComplexityTests/Kannan.lean @@ -124,10 +124,10 @@ info: 'Cslib.MCSP.exists_verifier_append' depends on axioms: [propext, Classical #print axioms Cslib.MCSP.exists_verifier_append /-- -info: 'Cslib.MCSP.computableTidilyInPolyTime_tableVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.MCSP.computableInPolyTime_tableVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.MCSP.computableTidilyInPolyTime_tableVerifier +#print axioms Cslib.MCSP.computableInPolyTime_tableVerifier /-- info: 'Cslib.MCSP.complexity_le_of_tableVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/KarpLipton2.lean b/ComplexityTests/KarpLipton2.lean index 929269073..d9d0eb5af 100644 --- a/ComplexityTests/KarpLipton2.lean +++ b/ComplexityTests/KarpLipton2.lean @@ -124,10 +124,10 @@ info: 'Cslib.Complexity.SAT.verifier_search' depends on axioms: [propext, Classi #print axioms Cslib.Complexity.SAT.verifier_search /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_search' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SAT.computableInPolyTime_search' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_search +#print axioms Cslib.Complexity.SAT.computableInPolyTime_search /-- info: 'Cslib.Complexity.SAT.exists_search' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -142,12 +142,12 @@ info: 'Cslib.Circuits.Boolean.evalAdvice_familyAdvice' depends on axioms: [prope #print axioms Cslib.Circuits.Boolean.evalAdvice_familyAdvice /-- -info: 'Cslib.Circuits.Boolean.computableTidilyInPolyTime_evalAdvice' depends on axioms: [propext, +info: 'Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms Cslib.Circuits.Boolean.computableTidilyInPolyTime_evalAdvice +#print axioms Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice /-- info: 'Cslib.Complexity.PiP_two_subset_SigmaP_two_of_SAT' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/KarpReductions.lean b/ComplexityTests/KarpReductions.lean index 7594b4f98..ff2decd8a 100644 --- a/ComplexityTests/KarpReductions.lean +++ b/ComplexityTests/KarpReductions.lean @@ -166,11 +166,11 @@ info: 'Cslib.Complexity.coNPHard.trans' depends on axioms: [propext, Classical.c #print axioms Cslib.Complexity.coNPHard.trans /-- -info: 'Cslib.Complexity.computableTidilyInPolyTime_toThreeSAT' depends on axioms: +info: 'Cslib.Complexity.computableInPolyTime_toThreeSAT' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInPolyTime_toThreeSAT +#print axioms Cslib.Complexity.computableInPolyTime_toThreeSAT /-- info: 'Cslib.Complexity.ThreeSAT.isVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -179,11 +179,11 @@ info: 'Cslib.Complexity.ThreeSAT.isVerifier' depends on axioms: [propext, Classi #print axioms Cslib.Complexity.ThreeSAT.isVerifier /-- -info: 'Cslib.Complexity.ThreeSAT.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Complexity.ThreeSAT.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.ThreeSAT.computableTidilyInPolyTime_verifier +#print axioms Cslib.Complexity.ThreeSAT.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.ThreeSAT.mem_NP' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -212,11 +212,11 @@ info: 'Cslib.Complexity.ThreeSAT_npComplete' depends on axioms: #print axioms Cslib.Complexity.ThreeSAT_npComplete /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_toIndependentSet' depends on axioms: +info: 'Cslib.Complexity.SAT.computableInPolyTime_toIndependentSet' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_toIndependentSet +#print axioms Cslib.Complexity.SAT.computableInPolyTime_toIndependentSet /-- info: 'Cslib.Complexity.IndependentSet.isVerifier' depends on axioms: @@ -226,11 +226,11 @@ info: 'Cslib.Complexity.IndependentSet.isVerifier' depends on axioms: #print axioms Cslib.Complexity.IndependentSet.isVerifier /-- -info: 'Cslib.Complexity.IndependentSet.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Complexity.IndependentSet.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.IndependentSet.computableTidilyInPolyTime_verifier +#print axioms Cslib.Complexity.IndependentSet.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.IndependentSet.mem_NP' depends on axioms: @@ -274,11 +274,11 @@ info: 'Cslib.Complexity.Clique.isVerifier' depends on axioms: [propext, Classica #print axioms Cslib.Complexity.Clique.isVerifier /-- -info: 'Cslib.Complexity.Clique.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Complexity.Clique.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.Clique.computableTidilyInPolyTime_verifier +#print axioms Cslib.Complexity.Clique.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.Clique.mem_NP' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/Ladner.lean b/ComplexityTests/Ladner.lean index 61fa07b5e..96692dcbc 100644 --- a/ComplexityTests/Ladner.lean +++ b/ComplexityTests/Ladner.lean @@ -179,11 +179,11 @@ example (h : P encBits ≠ NP encBits) : /-! ### Axioms -/ /-- -info: 'Cslib.Complexity.Ladner.computableTidilyInPolyTime_H' depends on axioms: +info: 'Cslib.Complexity.Ladner.computableInPolyTime_H' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.Ladner.computableTidilyInPolyTime_H +#print axioms Cslib.Complexity.Ladner.computableInPolyTime_H /-- info: 'Cslib.Complexity.Ladner.SATH_mem_NP' depends on axioms: diff --git a/ComplexityTests/MathlibTM2Reverse.lean b/ComplexityTests/MathlibTM2Reverse.lean index a8b327b76..4b3afe887 100644 --- a/ComplexityTests/MathlibTM2Reverse.lean +++ b/ComplexityTests/MathlibTM2Reverse.lean @@ -130,8 +130,8 @@ example : ∃ (f : List Bool → Bool) (h : TM2Computable (encList (encFinite Bo h.StacksBounded space) ∧ (∀ xs, xs ∈ {xs : List Bool | xs.isEmpty = true} ↔ f xs = true) := Cslib.Complexity.mem_PSPACE_iff_tm2.mp - (Cslib.Complexity.mem_PSPACE_of_computableTidilyInPolySpace - (.of_polyTime (.listIsEmpty' (encFinite Bool))) (fun _ => Iff.rfl)) + (Cslib.Complexity.mem_PSPACE_of_computableInPolySpace + (.of_tidy (.of_polyTime (.listIsEmpty' (encFinite Bool)))) (fun _ => Iff.rfl)) /-- info: 'Turing.MultiTapeTM.ToTM2.outputsInTime' depends on axioms: diff --git a/ComplexityTests/MonotoneCircuitValue.lean b/ComplexityTests/MonotoneCircuitValue.lean index fb1b1adc9..432dfde7a 100644 --- a/ComplexityTests/MonotoneCircuitValue.lean +++ b/ComplexityTests/MonotoneCircuitValue.lean @@ -58,10 +58,10 @@ example : ComputableInLogSpace id (encFramed encBits) encBits := by simp only [encNat_apply, List.length_cons, List.length_nil, zero_add, add_zero, Order.add_one_le_iff] omega - refine copySpec.computableInLogSpace (fun w => by - simp [CircuitValue.WriterSpec.output, copySpec]) - (ComputableTidilyInSpace.budget_const (encB := encNat) 0 hin) - (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin) + refine copySpec.computableInLogSpace (.of_tidy (fun w => by + simp [CircuitValue.WriterSpec.output, copySpec])) + (.of_tidy (ComputableTidilyInSpace.budget_const (encB := encNat) 0 hin)) + (.of_tidy (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin)) (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin) ?_ change PolynomiallyBounded fun _ : ℕ => 0 fun_prop diff --git a/ComplexityTests/NPCompleteGraphs.lean b/ComplexityTests/NPCompleteGraphs.lean index b26d44679..28eed5f5f 100644 --- a/ComplexityTests/NPCompleteGraphs.lean +++ b/ComplexityTests/NPCompleteGraphs.lean @@ -332,11 +332,11 @@ info: 'Cslib.Complexity.IndependentSet.toVertexCover_mem_iff' depends on axioms: #print axioms Cslib.Complexity.IndependentSet.toVertexCover_mem_iff /-- -info: 'Cslib.Complexity.IndependentSet.computableTidilyInPolyTime_toVertexCover' depends on axioms: +info: 'Cslib.Complexity.IndependentSet.computableInPolyTime_toVertexCover' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.IndependentSet.computableTidilyInPolyTime_toVertexCover +#print axioms Cslib.Complexity.IndependentSet.computableInPolyTime_toVertexCover /-- info: 'Cslib.Complexity.VertexCover.mem_NP' depends on axioms: @@ -373,11 +373,11 @@ info: 'Cslib.Complexity.SAT.toThreeColoring_mem_iff' depends on axioms: #print axioms Cslib.Complexity.SAT.toThreeColoring_mem_iff /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_toThreeColoring' depends on axioms: +info: 'Cslib.Complexity.SAT.computableInPolyTime_toThreeColoring' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_toThreeColoring +#print axioms Cslib.Complexity.SAT.computableInPolyTime_toThreeColoring /-- info: 'Cslib.Complexity.polyTimeReducible_ThreeSAT_ThreeColoring' depends on axioms: @@ -408,11 +408,11 @@ info: 'Cslib.Complexity.SAT.toDirHamPath_mem_iff' depends on axioms: #print axioms Cslib.Complexity.SAT.toDirHamPath_mem_iff /-- -info: 'Cslib.Complexity.SAT.computableTidilyInPolyTime_toDirHamPath' depends on axioms: +info: 'Cslib.Complexity.SAT.computableInPolyTime_toDirHamPath' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.SAT.computableTidilyInPolyTime_toDirHamPath +#print axioms Cslib.Complexity.SAT.computableInPolyTime_toDirHamPath /-- info: 'Cslib.Complexity.Graph.mem_DirHamCycle_cons_iff' depends on axioms: diff --git a/ComplexityTests/NPCompleteGraphs/TSP.lean b/ComplexityTests/NPCompleteGraphs/TSP.lean index e0b447e68..02d3ce14a 100644 --- a/ComplexityTests/NPCompleteGraphs/TSP.lean +++ b/ComplexityTests/NPCompleteGraphs/TSP.lean @@ -194,11 +194,11 @@ example : (([], []) : Graph) ∉ HamCycle := /-! ### Axiom checks for headline theorems -/ /-- -info: 'Cslib.Complexity.TSP.computableTidilyInPolyTime_tourLength' depends on axioms: +info: 'Cslib.Complexity.TSP.computableInPolyTime_tourLength' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TSP.computableTidilyInPolyTime_tourLength +#print axioms Cslib.Complexity.TSP.computableInPolyTime_tourLength /-- info: 'Cslib.Complexity.TSP.isVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -207,11 +207,11 @@ info: 'Cslib.Complexity.TSP.isVerifier' depends on axioms: [propext, Classical.c #print axioms Cslib.Complexity.TSP.isVerifier /-- -info: 'Cslib.Complexity.TSP.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Complexity.TSP.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TSP.computableTidilyInPolyTime_verifier +#print axioms Cslib.Complexity.TSP.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.TSP.mem_NP' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -227,11 +227,11 @@ info: 'Cslib.Complexity.HamCycle.toTSP_mem_iff' depends on axioms: #print axioms Cslib.Complexity.HamCycle.toTSP_mem_iff /-- -info: 'Cslib.Complexity.HamCycle.computableTidilyInPolyTime_toTSP' depends on axioms: +info: 'Cslib.Complexity.HamCycle.computableInPolyTime_toTSP' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.HamCycle.computableTidilyInPolyTime_toTSP +#print axioms Cslib.Complexity.HamCycle.computableInPolyTime_toTSP /-- info: 'Cslib.Complexity.polyTimeReducible_HamCycle_TSP' depends on axioms: diff --git a/ComplexityTests/NPExistsAppend.lean b/ComplexityTests/NPExistsAppend.lean index 7be5cbaac..b7365cd52 100644 --- a/ComplexityTests/NPExistsAppend.lean +++ b/ComplexityTests/NPExistsAppend.lean @@ -19,7 +19,7 @@ open Cslib.Complexity Turing.MultiTapeTM example : {y : List Bool × List Bool | ∃ v : List Bool, v.length = 1 ∧ (y.2 ++ v).getD 1 false = true} ∈ NP (encPair encBits encBits) := by have := mem_NP_setOf_exists_append (enc := encBits) (V := fun x => x.2.getD 1 false) - (ComputableTidilyInPolyTime.bitsGetDWithInput (.snd _ _) (.const 1) false) 1 + (.of_tidy (ComputableTidilyInPolyTime.bitsGetDWithInput (.snd _ _) (.const 1) false)) 1 simpa using this -- A zero-length suffix is also supported; the verifier can ignore both words. @@ -27,7 +27,7 @@ example : {y : List Bool × List Bool | ∃ v : List Bool, v.length = 0 ∧ (fun _ : List Bool × List Bool => true) (y.1, y.2 ++ v) = true} ∈ NP (encPair encBits encBits) := by have h := mem_NP_setOf_exists_append (enc := encBits) (V := fun _ => true) - (ComputableTidilyInPolyTime.const true) 0 + (.of_tidy (ComputableTidilyInPolyTime.const true)) 0 simpa only [Polynomial.eval_zero] using h end ComplexityTests.NPExistsAppend diff --git a/ComplexityTests/NondeterministicVerifiers.lean b/ComplexityTests/NondeterministicVerifiers.lean index c0ece5889..53d73217d 100644 --- a/ComplexityTests/NondeterministicVerifiers.lean +++ b/ComplexityTests/NondeterministicVerifiers.lean @@ -489,11 +489,11 @@ info: 'Turing.MultiTapeNTM.DecidesInTime.isVerifier' depends on axioms: #print axioms Turing.MultiTapeNTM.DecidesInTime.isVerifier /-- -info: 'Turing.MultiTapeNTM.computableTidilyInPolyTime_checkChoices' depends on axioms: +info: 'Turing.MultiTapeNTM.computableInPolyTime_checkChoices' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Turing.MultiTapeNTM.computableTidilyInPolyTime_checkChoices +#print axioms Turing.MultiTapeNTM.computableInPolyTime_checkChoices /-- info: 'Turing.MultiTapeNTM.accepts_of_runClosedCoins_choiceTable' depends on axioms: diff --git a/ComplexityTests/PCPEncoded.lean b/ComplexityTests/PCPEncoded.lean index 4b6148043..ce42cee88 100644 --- a/ComplexityTests/PCPEncoded.lean +++ b/ComplexityTests/PCPEncoded.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.PCP.Encoded.AddTrivial import Complexity.Computability.PCP.Encoded.CloudRotation import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Executable constraint graphs, boundary cases, interpretation and compositional certificates. -/ @@ -71,13 +72,19 @@ example : ((oneEdge.addLoops true).toGraph (fun c (_ _ : Bool) => c)).unsatVal = norm_num [oneEdge] at h ⊢ exact h +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (Graph.addLoops true) (Graph.encoding encBool) (Graph.encoding encBool) := by polytime +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun g : Graph Bool => Graph.mk g.vertices (g.edges ++ (List.range g.vertices).map (fun v => ⟨v, v, true⟩))) (Graph.encoding encBool) (Graph.encoding encBool) := by polytime +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Bool × Graph Bool => let g := p.2.addLoops true g.checkEdge equalityOrTrue true false [p.1, false] 0) @@ -88,6 +95,8 @@ example : ComputableTidilyInPolyTime (fun p : Bool × Graph Bool => .of_finite _ fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) (eval : C → α → α → Bool) (fallback : C) (label : α) (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) @@ -98,6 +107,8 @@ example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) (encPair (Graph.encoding enc) (encPair (encList alphabet) encUnary)) encBool := by polytime +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool × ℕ => p.1.checkEdge equalityOrTrue true false p.2.1 p.2.2) @@ -155,6 +166,8 @@ example : cloudGraph.cloudRotation false (fun p => (100, !p.2.2)) ((1, false), f example : (Graph.mk 0 ([] : List (Edge Bool))).cloudRotation false rotateReflection ((3, true), false) = ((3, true), true) := by decide +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × ((ℕ × Bool) × Bool) => p.1.cloudRotation false rotateReflection p.2) @@ -163,6 +176,8 @@ example : ComputableTidilyInPolyTime have hrotate := isPolyTime_rotateReflection fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example (rotate : ℕ × (ℕ × Bool) → ℕ × Bool) (hrotate : ComputableTidilyInPolyTime rotate (encPair encUnary (encPair encUnary encBool)) (encPair encUnary encBool)) : diff --git a/ComplexityTests/PCPEncodedAssignmentTester.lean b/ComplexityTests/PCPEncodedAssignmentTester.lean index d0387c323..0335801de 100644 --- a/ComplexityTests/PCPEncodedAssignmentTester.lean +++ b/ComplexityTests/PCPEncodedAssignmentTester.lean @@ -10,6 +10,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Pi import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Tactic.PolyTime import Mathlib.Tactic.FinCases +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Tests for executable assignment testing and its uniform finite-table certificates. -/ @@ -79,6 +80,8 @@ example {α : Type} [Fintype α] [DecidableEq α] (constraint : α → α → Bo rw [Encoded.HadamardTester.accepts_eq_true] simpa only [Encoded.HadamardTester.query_eq, LocalTest.Passes] using passes_honestProof h ω +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : (Bool → Bool → Bool) × Rand Bool × Query => Encoded.HadamardTester.query p.1 p.2.1 p.2.2) @@ -91,6 +94,8 @@ example : ComputableTidilyInPolyTime (encPair (encPi (encPi encBool)) (encPair (encFinite (Rand Bool)) (encPi encBool))) encBool := by polytime +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- The constraint is computed from an unbounded word, not fixed with the alphabet. example : ComputableTidilyInPolyTime (fun p : List Bool × Rand Bool × Query => Encoded.HadamardTester.query diff --git a/ComplexityTests/PCPEncodedComposition.lean b/ComplexityTests/PCPEncodedComposition.lean index 447755ed6..91a877019 100644 --- a/ComplexityTests/PCPEncodedComposition.lean +++ b/ComplexityTests/PCPEncodedComposition.lean @@ -8,6 +8,7 @@ Authors: Samuel Schlesinger import ComplexityTests.PCPNumbering import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Tests for exact gadget enumeration, numbering, soundness, and composition certificates. -/ @@ -89,12 +90,16 @@ example (g : Graph (Bool → Bool → Bool)) : Graph.composeEval).unsatVal := Graph.le_unsatVal_compose _ _ _ g (nodup_coins _) nodup_queries (mem_coins _) mem_queries +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (Graph.compose (numberSlots boolAlphabet).2 boolCoins queries) (Graph.encoding (encPi (encPi encBool))) (Graph.encoding (encPair (encPi (encPi encBool)) (encPair (encFinite (Rand Bool)) (encFinEnum Query)))) := by fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- The composed descriptors normalize to fixed tables over the 17-query answer alphabet. example : ComputableTidilyInPolyTime (fun g : Graph (Bool → Bool → Bool) => @@ -103,6 +108,8 @@ example : ComputableTidilyInPolyTime (Graph.encoding (encPi (encPi encBool))) := by polytime +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- A captured graph may use an arbitrary outer representation; its certificate is still required. example {Input : Type} (input : Input ↪ List Bool) (graph : Input → Graph (Bool → Bool → Bool)) (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding (encPi (encPi encBool)))) : diff --git a/ComplexityTests/PCPEncodedCompositionEnumeration.lean b/ComplexityTests/PCPEncodedCompositionEnumeration.lean index 8e6ad9f5b..ba787ade2 100644 --- a/ComplexityTests/PCPEncodedCompositionEnumeration.lean +++ b/ComplexityTests/PCPEncodedCompositionEnumeration.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.PCP.Encoded.Composition.Enumeration import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Complete constructive enumeration, exact graph semantics, and encoding inference clients. -/ @@ -59,6 +60,8 @@ example : (falseLoop.toGraph id).unsatVal / 476 ≤ -- The compact-CNF alphabet has an ordinary Pi Fintype as well as a constructive enumeration. local instance : FinEnum Bool := FinEnum.ofList [false, true] (by decide) +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun g : Graph ((Fin 3 → Bool) → (Fin 3 → Bool) → Bool) => g.composeEnumerated) (Graph.encoding (encPi (encPi encBool))) @@ -70,11 +73,15 @@ variable {α Input : Type} [FinEnum α] {input : Input ↪ List Bool} {constraints : (α → α → Bool) ↪ List Bool} (graph : Input → Graph (α → α → Bool)) (hg : ComputableTidilyInPolyTime graph input (Graph.encoding constraints)) +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun x => (graph x).composeEnumerated) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hg; fun_prop) fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun x => let g := graph x; g.composeEnumerated) input (Graph.encoding (encPi (encPi encBool))) := by polytime diff --git a/ComplexityTests/PCPEncodedConstraints.lean b/ComplexityTests/PCPEncodedConstraints.lean index f931ef34e..0a0ed432b 100644 --- a/ComplexityTests/PCPEncodedConstraints.lean +++ b/ComplexityTests/PCPEncodedConstraints.lean @@ -6,6 +6,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.PCP.Encoded.Constraints import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Fixed-alphabet tabulation of unbounded executable descriptors and exact graph interpretation. -/ @@ -56,18 +57,22 @@ example : normalized.mapConstraints (fun table => table) = normalized := example : ComputableTidilyInPolyTime (Graph.mapConstraints evalBits) (Graph.encoding encBits) (Graph.encoding (encPi (encPi encBool))) := - Graph.isPolyTime_tabulateConstraints isPolyTime_evalBits + (Graph.isPolyTime_tabulateConstraints (.of_tidy isPolyTime_evalBits)).tidy +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- Equivalent functional spelling uses constructor, projection, mapping, and finite-Pi certificates. example : ComputableTidilyInPolyTime (fun g : Graph (List Bool) => Graph.mk g.vertices (g.edges.map fun e => Edge.mk e.src e.dst (evalBits e.constraint))) (Graph.encoding encBits) (Graph.encoding (encPi (encPi encBool))) := by - have htable := Graph.isPolyTime_constraintTable isPolyTime_evalBits + have htable := (Graph.isPolyTime_constraintTable (.of_tidy isPolyTime_evalBits)).tidy fun_prop example (table : Bool → Bool → Bool) : (encPi (encPi encBool) table).length ≤ 26 := by exact Graph.length_constraintTable_le table +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- Table lookup is itself certified for runtime table and both runtime symbols. example : ComputableTidilyInPolyTime (fun p : (Bool → Bool → Bool) × Bool × Bool => p.1 p.2.1 p.2.2) diff --git a/ComplexityTests/PCPEncodedGenericComposition.lean b/ComplexityTests/PCPEncodedGenericComposition.lean index bcb46e1e0..10110c91d 100644 --- a/ComplexityTests/PCPEncodedGenericComposition.lean +++ b/ComplexityTests/PCPEncodedGenericComposition.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.PCP.Encoded.GenericComposition import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! A non-Boolean assignment tester client for the shared executable composition engine. -/ @@ -93,6 +94,8 @@ example : · intro i fin_cases i <;> simp [queries] +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun g : Graph (Fin 2 → Fin 2 → Bool) => toyImplementation.composeTabulated slotNumber [()] queries g) diff --git a/ComplexityTests/PCPEncodedIteration.lean b/ComplexityTests/PCPEncodedIteration.lean index 4743f5792..0afee1abb 100644 --- a/ComplexityTests/PCPEncodedIteration.lean +++ b/ComplexityTests/PCPEncodedIteration.lean @@ -9,6 +9,7 @@ import Complexity.Computability.PCP.Encoded.Iteration import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Iteration import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Log import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Logarithmic graph loops using the existing iteration calculus and complete encoding bounds. -/ @@ -16,6 +17,8 @@ namespace ComplexityTests.PCPEncodedIteration open Cslib.PCP.Encoded Turing.MultiTapeTM +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- The loop remains an application of the existing calculus; the graph lemmas supply its bound. example {C Input : Type} {enc : C ↪ List Bool} {input : Input ↪ List Bool} {graph : Input → Graph C} {step : Graph C → Graph C} {valid : Graph C → Prop} @@ -31,12 +34,14 @@ example {C Input : Type} {enc : C ↪ List Bool} {input : Input ↪ List Bool} ComputableTidilyInPolyTime (fun x => step^[Nat.clog 2 (graph x).edges.length] (graph x)) input (Graph.encoding enc) := by apply ComputableTidilyInPolyTime.iterate (by fun_prop) hgraph hstep - (Graph.polyBounded_iterationSize_clog hgraph factor descriptorBound) + (Graph.polyBounded_iterationSize_clog (.of_tidy hgraph) factor descriptorBound) exact fun x _ hi => Graph.iterate_length_encoding_le factor descriptorBound hvalid hwellFormed hdescriptors hgrowth (hbase x) hi private def doubleEdges (g : Graph Bool) : Graph Bool := ⟨g.vertices, g.edges ++ g.edges⟩ +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem isPolyTime_doubleEdges : ComputableTidilyInPolyTime doubleEdges (Graph.encoding encBool) (Graph.encoding encBool) := by unfold doubleEdges @@ -52,6 +57,8 @@ private theorem growth_doubleEdges (g : Graph Bool) : simp only [doubleEdges, List.length_append] lia +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- Arbitrary computed well-formed graphs can be iterated, retaining their original input encoding. example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bool} (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) @@ -60,7 +67,7 @@ example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bo (fun x => doubleEdges^[Nat.clog 2 (graph x).edges.length] (graph x)) input (Graph.encoding encBool) := by apply ComputableTidilyInPolyTime.iterate (by fun_prop) hgraph isPolyTime_doubleEdges - (Graph.polyBounded_iterationSize_clog hgraph 2 1) + (Graph.polyBounded_iterationSize_clog (.of_tidy hgraph) 2 1) exact fun x _ hi => Graph.iterate_length_encoding_le (valid := Graph.WellFormed) 2 1 (fun _ => wellFormed_doubleEdges) (fun _ h => h) (by intros; simp) (fun g _ => growth_doubleEdges g) (hwellFormed x) hi diff --git a/ComplexityTests/PCPEncodedPreprocess.lean b/ComplexityTests/PCPEncodedPreprocess.lean index 635cd3335..8ed8e1d26 100644 --- a/ComplexityTests/PCPEncodedPreprocess.lean +++ b/ComplexityTests/PCPEncodedPreprocess.lean @@ -9,6 +9,7 @@ import Complexity.Computability.PCP.Encoded.Constraints import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.RotationMap.Family import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Executable degree reduction and preprocessing, exact interpretations, arithmetic expansion, and fixed-alphabet normalization that closes the descriptor type across repeated rounds. -/ @@ -77,7 +78,7 @@ example : reduced.WellFormed := example : ComputableTidilyInPolyTime (Graph.degreeReduce false rotateReflection [()]) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := - Graph.isPolyTime_degreeReduce false [()] rotateReflection isPolyTime_rotateReflection + (Graph.isPolyTime_degreeReduce false [()] rotateReflection (.of_tidy isPolyTime_rotateReflection)).tidy example : (reduced.toGraph (Graph.degreeReduceEval constraintEval)).unsatVal = ((exampleGraph.toGraph constraintEval).degreeReduce @@ -119,8 +120,10 @@ example : preprocessed.WellFormed := example : ComputableTidilyInPolyTime (Graph.preprocess false true rotateReflection [()]) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := - Graph.isPolyTime_preprocess false true rotateReflection [()] isPolyTime_rotateReflection + (Graph.isPolyTime_preprocess false true rotateReflection [()] (.of_tidy isPolyTime_rotateReflection)).tidy +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- The same ordinary functional spelling uses the shared compositional API. example : ComputableTidilyInPolyTime (fun g : Graph Bool => let reduced := g.degreeReduce false rotateReflection [()] @@ -129,8 +132,8 @@ example : ComputableTidilyInPolyTime (fun g : Graph Bool => (some (false, true))) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := by have hrotate := isPolyTime_rotateReflection - have hdegree := Graph.isPolyTime_degreeReduce (enc := encBool) false [()] - rotateReflection hrotate + have hdegree := (Graph.isPolyTime_degreeReduce (enc := encBool) false [()] + rotateReflection (.of_tidy hrotate)).tidy fun_prop -- The exact-numbering contract is inhabited; reflection has no positive expansion claim. @@ -219,8 +222,8 @@ private theorem mem_arithmeticLabels (d : AffinePlaneFamilyLabel (ZMod 257) 257) example : ComputableTidilyInPolyTime (Graph.preprocess false true arithmeticExpanderRotate arithmeticLabels) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := - Graph.isPolyTime_preprocess false true arithmeticExpanderRotate arithmeticLabels - (polytime_arithmeticExpanderRotate (encFinite _)) + (Graph.isPolyTime_preprocess false true arithmeticExpanderRotate arithmeticLabels + (.of_tidy (polytime_arithmeticExpanderRotate (encFinite _)))).tidy noncomputable example (g : Graph Bool) (eval : Bool → Bool → Bool → Bool) : (g.toGraph eval).PreprocessExpanders (AffinePlaneFamilyLabel (ZMod 257) 257) @@ -261,12 +264,12 @@ private def tablePreprocess (g : Graph (Bool → Bool → Bool)) : Graph (Bool private theorem isPolyTime_tablePreprocess : ComputableTidilyInPolyTime tablePreprocess (Graph.encoding (encPi (encPi encBool))) (Graph.encoding (encPi (encPi encBool))) := by - have heval := Graph.isPolyTime_constraintTableEval encBool - have hdegreeEval := Graph.isPolyTime_degreeReduceEval - (eval := fun table : Bool → Bool → Bool => table) heval - have hpre := Graph.isPolyTime_preprocess (enc := encPi (encPi encBool)) - (fun (_ _ : Bool) => false) (fun _ _ => true) rotateReflection [()] isPolyTime_rotateReflection - exact (Graph.isPolyTime_tabulateConstraints hdegreeEval).comp hpre + have heval := (Graph.isPolyTime_constraintTableEval encBool).tidy + have hdegreeEval := (Graph.isPolyTime_degreeReduceEval + (eval := fun table : Bool → Bool → Bool => table) (.of_tidy heval)).tidy + have hpre := (Graph.isPolyTime_preprocess (enc := encPi (encPi encBool)) + (fun (_ _ : Bool) => false) (fun _ _ => true) rotateReflection [()] (.of_tidy isPolyTime_rotateReflection)).tidy + exact (Graph.isPolyTime_tabulateConstraints (.of_tidy hdegreeEval)).tidy.comp hpre example : ComputableTidilyInPolyTime (fun g => tablePreprocess (tablePreprocess g)) (Graph.encoding (encPi (encPi encBool))) (Graph.encoding (encPi (encPi encBool))) := by diff --git a/ComplexityTests/PCPEncodedVerifier.lean b/ComplexityTests/PCPEncodedVerifier.lean index 02564b025..1e61f3192 100644 --- a/ComplexityTests/PCPEncodedVerifier.lean +++ b/ComplexityTests/PCPEncodedVerifier.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.PCP.Encoded.Verifier.Reduction import Complexity.Computability.Complexity.Classes.SharpP.Probability import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Exact verifier behavior, padding, short words, repetition, and nonvacuous PCP contracts. -/ @@ -128,6 +129,8 @@ example : ComputableTidilyInPolyTime (encPair (Graph.encoding encBool) encBits) (encOption (Edge.encoding encBool)) := by fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => p.1.sampleEdge p.2) (encPair (Graph.encoding encBool) (encList encBool)) @@ -145,6 +148,8 @@ example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) fail_if_success solve | clear heval; fun_prop fun_prop +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example {C : Type} (enc : C ↪ List Bool) (graph : ℕ → Graph C) (hgraph : ComputableTidilyInPolyTime graph encUnary (Graph.encoding enc)) : ComputableTidilyInPolyTime @@ -158,13 +163,13 @@ example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) (heval : ComputableTidilyInPolyTime (fun p : C × α × α => evaluator p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : (Graph.repeatedEdgeVerifier 2 3 decoder evaluator).PolyTime (Graph.encoding enc) := - Graph.polyTime_repeatedEdgeVerifier 2 3 decoder heval + Graph.polyTime_repeatedEdgeVerifier 2 3 decoder (.of_tidy heval) -- Both members and nonmembers occur, and the nonmember graph has positive gap exactly one. example : ({true} : Set Bool) ∈ PCP (fun n => Nat.log 2 n + 1) (fun _ => 1) encBool := by apply Graph.mem_PCP_of_gapReduction (graph := loop) 1 encode decode (by intro x; rfl) (alphabet := encBool) (enc := encBool) (eval := eval) - (.of_finite _) (.of_finite _) loop_wellFormed + (.of_tidy (.of_finite _)) (.of_tidy (.of_finite _)) loop_wellFormed (gap := 1) ?_ (by norm_num) ?_ · intro bit hbit have hbit : bit = true := hbit diff --git a/ComplexityTests/PCPNP.lean b/ComplexityTests/PCPNP.lean index 436d87614..7da4618d2 100644 --- a/ComplexityTests/PCPNP.lean +++ b/ComplexityTests/PCPNP.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.Complexity.Classes.PCP.NP import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Sparse proof tables, duplicate addresses, malformed witnesses, and exact NP containment. -/ @@ -54,13 +55,13 @@ example : example : ComputableTidilyInPolyTime requireBit.tableVerifier (encPair (encPair encBool encNat) encBits) encBool := - PCPVerifier.isPolyTime_tableVerifier requireBit_polyTime requireBit_coins + (PCPVerifier.isPolyTime_tableVerifier requireBit_polyTime requireBit_coins).tidy example : ComputableTidilyInPolyTime (fun p : (Bool × ℕ) × List Bool => let input := p.1 requireBit.tableVerifier (input, p.2)) (encPair (encPair encBool encNat) encBits) encBool := by - have h := PCPVerifier.isPolyTime_tableVerifier requireBit_polyTime requireBit_coins + have h := (PCPVerifier.isPolyTime_tableVerifier requireBit_polyTime requireBit_coins).tidy polytime -- The table is the restriction of an actual finite PCP proof even for enormous addresses. @@ -109,6 +110,8 @@ example : noQueries.queryTable () = [] := by decide example : noQueries.tableVerifier ((), []) = true := by decide +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example (enc : Unit ↪ List Bool) : ComputableTidilyInPolyTime noQueries.tableVerifier (encPair enc encBits) encBool := by apply PCPVerifier.isPolyTime_tableVerifier (c := 0) diff --git a/ComplexityTests/PCPSelectedAssignmentTester.lean b/ComplexityTests/PCPSelectedAssignmentTester.lean index 5ef780829..3123e5869 100644 --- a/ComplexityTests/PCPSelectedAssignmentTester.lean +++ b/ComplexityTests/PCPSelectedAssignmentTester.lean @@ -9,6 +9,7 @@ import Complexity.Computability.PCP.SelectedComposition import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Pi import Complexity.Computability.Machines.Turing.MultiTape.Encodings.Finite import Complexity.Tactic.PolyTime +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! Semantic regressions and client certificates for the selected assignment tester. -/ @@ -66,6 +67,8 @@ example (constraint : Bool → Bool → Bool) (σ : Fin 2 → Bool) simpa only [LocalTest.Passes, Encoded.SelectedHadamardTester.query_eq] using passes_selected_honestProof (C := fun a b => constraint a b = true) hσ ω +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : (Bool → Bool → Bool) × (Fin 5 × Rand Bool) × Fin 6 => Encoded.SelectedHadamardTester.query p.1 p.2.1 p.2.2) diff --git a/ComplexityTests/PPTruthTable.lean b/ComplexityTests/PPTruthTable.lean index 19905fa16..06ebe0a63 100644 --- a/ComplexityTests/PPTruthTable.lean +++ b/ComplexityTests/PPTruthTable.lean @@ -86,13 +86,13 @@ theorem joint_mem_PP : query ⁻¹' headTrue ∈ PP (encPair encBits encUnary) : PolyTimeReducible.mem_PP ⟨query, .of_tidy polyTime_query, fun _ => Iff.rfl⟩ headTrue_mem_PP example : language ∈ PP encBits := - truthTable_mem_PP joint_mem_PP polyTime_count polyTime_combine + truthTable_mem_PP joint_mem_PP (.of_tidy polyTime_count) (.of_tidy polyTime_combine) example : {w : List Bool | ∀ i < count w, (w, i) ∈ query ⁻¹' headTrue} ∈ PP encBits := - forall_lt_mem_PP joint_mem_PP polyTime_count + forall_lt_mem_PP joint_mem_PP (.of_tidy polyTime_count) example : {w : List Bool | ∃ i < count w, (w, i) ∈ query ⁻¹' headTrue} ∈ PP encBits := - exists_lt_mem_PP joint_mem_PP polyTime_count + exists_lt_mem_PP joint_mem_PP (.of_tidy polyTime_count) example : headTrue ∩ secondTrue ∈ PP encBits := inter_mem_PP headTrue_mem_PP secondTrue_mem_PP diff --git a/ComplexityTests/Parameterized.lean b/ComplexityTests/Parameterized.lean index 6d1a7ecee..c32fc1c2e 100644 --- a/ComplexityTests/Parameterized.lean +++ b/ComplexityTests/Parameterized.lean @@ -47,7 +47,7 @@ example : ∃ f : ℕ → ℕ, Monotone f ∧ ∃ c : ℕ, DecidableInTimeO SAT private def Narrow : Set (CNF ℕ) := {φ | ∀ c ∈ φ, c.length ≤ 3} private theorem narrow_mem_P : Narrow ∈ P encCNF := - ⟨_, .of_tidy (computableTidilyInPolyTime_all_length_le 3), fun φ => by simp [Narrow]⟩ + ⟨_, (computableInPolyTime_all_length_le 3), fun φ => by simp [Narrow]⟩ example : Narrow ∈ FPT encCNF CNF.numVars := P_subset_FPT narrow_mem_P @@ -84,7 +84,7 @@ private def toSAT (φ : CNF ℕ) : CNF ℕ := if φ.all (fun c => decide (c.length ≤ 3)) then φ else [[]] private theorem toSAT_polyTime : ComputableTidilyInPolyTime toSAT encCNF encCNF := - ComputableTidilyInPolyTime.ite' (computableTidilyInPolyTime_all_length_le 3) + ComputableTidilyInPolyTime.ite' (computableInPolyTime_all_length_le 3).tidy ComputableTidilyInPolyTime.id' (ComputableTidilyInPolyTime.const _) private theorem numVars_toSAT_le (φ : CNF ℕ) : (toSAT φ).numVars ≤ φ.numVars := by @@ -106,7 +106,7 @@ private theorem mem_SAT_toSAT (φ : CNF ℕ) : φ ∈ ThreeSAT ↔ toSAT φ ∈ private theorem threeSAT_fptReducible_SAT : FPTReducible encCNF encCNF CNF.numVars CNF.numVars ThreeSAT SAT := - .of_computableTidilyInPolyTime toSAT_polyTime (h := id) numVars_toSAT_le mem_SAT_toSAT + FPTReducible.of_computableInPolyTime (.of_tidy toSAT_polyTime) (h := id) numVars_toSAT_le mem_SAT_toSAT /-- The reduction does not map the formula `x₀ ∧ (x₀ ∨ x₁ ∨ x₂ ∨ x₃)` to itself. -/ example : toSAT [[(0, true)], [(0, true), (1, true), (2, true), (3, true)]] = [[]] := by decide @@ -145,7 +145,7 @@ private def narrowKernel (φ : CNF ℕ) : CNF ℕ := private theorem isKernelization_narrowKernel : IsKernelization encCNF CNF.numVars Narrow narrowKernel fun _ => (encCNF ([] : CNF ℕ)).length + (encCNF narrowNo).length + 1 := by - refine ⟨.of_tidy (ComputableTidilyInPolyTime.ite' (computableTidilyInPolyTime_all_length_le 3) + refine ⟨.of_tidy (ComputableTidilyInPolyTime.ite' (computableInPolyTime_all_length_le 3).tidy (ComputableTidilyInPolyTime.const []) (ComputableTidilyInPolyTime.const narrowNo)), fun φ => ?_, fun φ => ?_, fun φ => ?_⟩ · unfold narrowKernel diff --git a/ComplexityTests/ProofComplexity.lean b/ComplexityTests/ProofComplexity.lean index 068f7be10..0e0f5dfe3 100644 --- a/ComplexityTests/ProofComplexity.lean +++ b/ComplexityTests/ProofComplexity.lean @@ -51,7 +51,7 @@ private def ψ : CNF ℕ := [[(0, true)], [(0, false)]] /-- Proofs of satisfiability: a formula followed by an assignment, in order of first occurrence, padded to the length of the encoded formula. A proof the verifier rejects proves `φ`. -/ private noncomputable def satProofSystem : ProofSystem encCNF SAT := - .ofVerifier cnfDecoder SAT.computableTidilyInPolyTime_verifier.computableInPolyTime SAT.isVerifier + .ofVerifier cnfDecoder SAT.computableInPolyTime_verifier SAT.isVerifier (a₀ := φ) ⟨fun _ => true, rfl⟩ /-- The assignment `x₀ ↦ true`, `x₁ ↦ true`, padded, proves `φ`. -/ diff --git a/ComplexityTests/QBFProtocol.lean b/ComplexityTests/QBFProtocol.lean index cce7ca782..41226f638 100644 --- a/ComplexityTests/QBFProtocol.lean +++ b/ComplexityTests/QBFProtocol.lean @@ -299,11 +299,11 @@ info: 'Cslib.Complexity.QBFProtocol.run_verifyAt_of_agreesAt' depends on axioms: #print axioms Cslib.Complexity.QBFProtocol.run_verifyAt_of_agreesAt /-- -info: 'Cslib.Complexity.TQBF.computableTidilyInPolyTime_decide_closed' depends on axioms: +info: 'Cslib.Complexity.TQBF.computableInPolyTime_decide_closed' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TQBF.computableTidilyInPolyTime_decide_closed +#print axioms Cslib.Complexity.TQBF.computableInPolyTime_decide_closed /-- info: 'Cslib.Complexity.QBFProtocol.eval_sampleMod_le' depends on axioms: diff --git a/ComplexityTests/RelativizedCounting.lean b/ComplexityTests/RelativizedCounting.lean index 293da835d..1c467b1ee 100644 --- a/ComplexityTests/RelativizedCounting.lean +++ b/ComplexityTests/RelativizedCounting.lean @@ -26,7 +26,7 @@ noncomputable def queryVerifier (A : Set (List Bool)) (x : List Bool × List Boo theorem queryVerifier_polyTime (A : Set (List Bool)) : ComputableInPolyTimeWithOracle A (queryVerifier A) (encPair encBits encBits) encBool := (computableInPolyTimeWithOracle_mem A).preprocess - (ComputableTidilyInPolyTime.fst encBits encBits) + (.of_tidy (ComputableTidilyInPolyTime.fst encBits encBits)) /-- A genuine query counts one empty witness on members and zero on nonmembers. -/ noncomputable def queryCount (A : Set (List Bool)) (w : List Bool) : ℕ := @@ -45,7 +45,7 @@ example (A : Set (List Bool)) : A ∈ PPWithOracle A encBits := by off the oracle. -/ example (A : Set (List Bool)) : Aᶜ ∈ PPWithOracle A encBits := by refine ⟨0, fun x => !queryVerifier A x, - (queryVerifier_polyTime A).map ComputableTidilyInPolyTime.bool_not, fun w => ?_⟩ + (queryVerifier_polyTime A).map (.of_tidy ComputableTidilyInPolyTime.bool_not), fun w => ?_⟩ simp only [Polynomial.eval_zero, pow_zero, acceptCount_zero, queryVerifier] by_cases hw : w ∈ A <;> simp [hw] @@ -65,7 +65,7 @@ noncomputable def tieVerifier (A : Set (List Bool)) : List Bool × List Bool → theorem tieVerifier_polyTime (A : Set (List Bool)) : ComputableInPolyTimeWithOracle A (tieVerifier A) (encPair encBits encBits) encBool := computableInPolyTimeWithOracle_selectVerifier (queryVerifier_polyTime A) - ((queryVerifier_polyTime A).map ComputableTidilyInPolyTime.bool_not) + ((queryVerifier_polyTime A).map (.of_tidy ComputableTidilyInPolyTime.bool_not)) theorem tieVerifier_count (A : Set (List Bool)) (w : List Bool) : acceptCount (tieVerifier A) w 1 = 1 := by @@ -89,7 +89,7 @@ noncomputable def queryGap (A : Set (List Bool)) (w : List Bool) : ℤ := theorem queryGap_mem (A : Set (List Bool)) : queryGap A ∈ GapPWithOracle A encBits := ⟨queryCount A, queryCount_mem A, _, ⟨0, fun x => !queryVerifier A x, - (queryVerifier_polyTime A).map ComputableTidilyInPolyTime.bool_not, fun _ => rfl⟩, + (queryVerifier_polyTime A).map (.of_tidy ComputableTidilyInPolyTime.bool_not), fun _ => rfl⟩, fun _ => by simp [queryGap]⟩ example : queryGap {w | w = [true]} [true] = 1 ∧ diff --git a/ComplexityTests/RepeatedTrials.lean b/ComplexityTests/RepeatedTrials.lean index 72f30609f..f7ed731c1 100644 --- a/ComplexityTests/RepeatedTrials.lean +++ b/ComplexityTests/RepeatedTrials.lean @@ -5,6 +5,7 @@ Authors: Samuel Schlesinger -/ import Complexity.Computability.Complexity.Classes.RepeatedTrials +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Plain /-! Clients of deterministic repetition without importing complexity-class definitions or amplification theorems. -/ @@ -54,7 +55,7 @@ example (trials width : Polynomial ℕ) : ComputableTidilyInPolyTime (fun x : List Bool × List Bool => repeatVotes (trials.eval x.1.length) (width.eval x.1.length) (fun z => z.2.headD false) x) (encPair encBits encBits) encBits := by - apply computableTidilyInPolyTime_repeatVotes <;> fun_prop + apply computableInPolyTime_repeatVotes <;> fun_prop /-- The existing aggregation certificates are available without BPP or RP. -/ example {α : Type} {enc : α ↪ List Bool} {V : α × List Bool → Bool} @@ -62,7 +63,7 @@ example {α : Type} {enc : α ↪ List Bool} {V : α × List Bool → Bool} (trials width : Polynomial ℕ) : ComputableTidilyInPolyTime (repeatAny enc trials width V) (encPair enc encBits) encBool ∧ ComputableTidilyInPolyTime (repeatMajority enc trials width V) (encPair enc encBits) encBool := - ⟨computableTidilyInPolyTime_repeatAny hV _ _, - computableTidilyInPolyTime_repeatMajority hV _ _⟩ + ⟨(computableInPolyTime_repeatAny (.of_tidy hV) _ _).tidy, + (computableInPolyTime_repeatMajority (.of_tidy hV) _ _).tidy⟩ end ComplexityTests.RepeatedTrials diff --git a/ComplexityTests/ResourceBoundsPlain.lean b/ComplexityTests/ResourceBoundsPlain.lean index 2ea2477ee..54765f902 100644 --- a/ComplexityTests/ResourceBoundsPlain.lean +++ b/ComplexityTests/ResourceBoundsPlain.lean @@ -218,7 +218,7 @@ example : single ∈ PSPACE encBits := by have hf : ComputableInPolySpace (fun w : List Bool => decide (w = [true])) encBits encBool := ⟨_, fun _ => 1, by fun_prop, h.mono (fun _ => le_rfl) fun _ => Nat.zero_le _, fun _ => by simp⟩ - exact mem_PSPACE_iff_computableTidilyInPolySpace.mpr + exact mem_PSPACE_iff_computableInPolySpace.mpr ⟨_, hf.tidy, fun w => by simp [single]⟩ /-- A plain fpt-time decider gives membership in `FPT`, for every parameter. -/ @@ -226,7 +226,7 @@ example (κ : List Bool → ℕ) : single ∈ FPT encBits κ := by obtain ⟨c, h⟩ := exists_computableInTimeAndSpace_single have hf : ComputableInFPTTime (fun w : List Bool => decide (w = [true])) encBits encBool κ := ⟨fun _ => c, 0, h.mono (fun _ => by simp) fun _ => Nat.zero_le _⟩ - exact mem_FPT_iff_computableTidilyInFPTTime.mpr + exact mem_FPT_iff_computableInFPTTime.mpr ⟨_, hf.tidy, fun w => by simp [single]⟩ /-! ### From library certificates to plain ones -/ @@ -249,21 +249,21 @@ example : ComputableInPolySpace /-- `TQBF` has a plain polynomial-space decider. -/ example : ∃ f, ComputableInPolySpace f encQBF encBool ∧ ∀ φ, φ ∈ TQBF ↔ f φ = true := by - obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableTidilyInPolySpace.mp TQBF_mem_PSPACE + obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp TQBF_mem_PSPACE exact ⟨f, .of_tidy hf, hA⟩ /-- A plain polynomial-time preprocessing of the existing TQBF decider stays in `PSPACE`. The decider's tidy certificate and the preprocessing's plain certificate compose automatically. -/ example {α : Type} {enc : α ↪ List Bool} {f : α → Logic.PL.QBF ℕ} (hf : ComputableInPolyTime f enc encQBF) : {a | f a ∈ TQBF} ∈ PSPACE enc := by - obtain ⟨dec, hdec, hA⟩ := mem_PSPACE_iff_computableTidilyInPolySpace.mp TQBF_mem_PSPACE + obtain ⟨dec, hdec, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp TQBF_mem_PSPACE have hcomp : ComputableInPolySpace (fun a => dec (f a)) enc encBool := by fun_prop - exact mem_PSPACE_iff_computableTidilyInPolySpace.mpr ⟨_, hcomp.tidy, fun a => hA (f a)⟩ + exact mem_PSPACE_iff_computableInPolySpace.mpr ⟨_, hcomp.tidy, fun a => hA (f a)⟩ /-- `SAT` has a plain fpt-time decider in the number of variables. -/ example : ∃ g, ComputableInFPTTime g encCNF encBool Logic.PL.CNF.numVars ∧ ∀ φ, φ ∈ SAT ↔ g φ = true := by - obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableTidilyInFPTTime.mp SAT_mem_FPT + obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp SAT_mem_FPT exact ⟨g, hg.computableInFPTTime, hA⟩ /-! ### Axioms -/ diff --git a/ComplexityTests/ResourceClasses.lean b/ComplexityTests/ResourceClasses.lean index b786905ef..2454a83bd 100644 --- a/ComplexityTests/ResourceClasses.lean +++ b/ComplexityTests/ResourceClasses.lean @@ -7,6 +7,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.Complexity.Classes.Inclusions import Complexity.Computability.Complexity.Classes.Ladner import Complexity.Computability.Complexity.Classes.ZPP +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! The parametric time classes and their polynomial unions, exponential time, `ZPP`, and the inclusions between the standard classes, with concrete members witnessing that the classes are @@ -61,7 +62,7 @@ example : {x | diagonal x = true} ∈ NEXP encBits ∧ {x | diagonal x = true} /-- The diagonal problem is decided within time `O(2 ^ (4 n))`, by its tidy machine. -/ theorem setOf_diagonal_mem_DTIME : {x | diagonal x = true} ∈ DTIME encBits fun n => 2 ^ (4 * n) := - setOf_mem_DTIME_of_computableTidilyInO computableTidilyInO_diagonal fun _ => le_rfl + setOf_mem_DTIME_of_computableInO computableInO_diagonal.tidy fun _ => le_rfl /-- A deterministic machine is a nondeterministic one: the diagonal problem, outside `P`, is in `NTIME (2 ^ (4 n))`. -/ @@ -138,7 +139,7 @@ example {α : Type} (enc : α ↪ List Bool) : coNP enc ⊆ PSPACE enc := fun A length in a `PSPACE` problem. -/ example {B : Set (List Bool × List Bool)} (hB : B ∈ PSPACE (encPair encBits encBits)) : {x | ∃ w : List Bool, w.length = x.length ∧ (x, w) ∈ B} ∈ PSPACE encBits := - setOf_exists_mem_PSPACE hB (ComputableTidilyInPolyTime.encoding_length encBits) + setOf_exists_mem_PSPACE hB (.of_tidy (ComputableTidilyInPolyTime.encoding_length encBits)) /-! ### Axioms -/ diff --git a/ComplexityTests/ResourceClasses3.lean b/ComplexityTests/ResourceClasses3.lean index bd81d97db..0e989b7b7 100644 --- a/ComplexityTests/ResourceClasses3.lean +++ b/ComplexityTests/ResourceClasses3.lean @@ -122,11 +122,11 @@ info: 'Cslib.Complexity.DecidesWithBoundedError.repeatMajority' depends on axiom #print axioms Cslib.Complexity.DecidesWithBoundedError.repeatMajority /-- -info: 'Cslib.Complexity.computableTidilyInPolyTime_repeatMajority' depends on axioms: +info: 'Cslib.Complexity.computableInPolyTime_repeatMajority' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInPolyTime_repeatMajority +#print axioms Cslib.Complexity.computableInPolyTime_repeatMajority /-- info: 'Cslib.Complexity.mem_BPP_iff_forall_decidesWithErrorExponent' depends on axioms: @@ -143,11 +143,11 @@ info: 'Cslib.Complexity.DecidesWithOneSidedError.repeatAny' depends on axioms: #print axioms Cslib.Complexity.DecidesWithOneSidedError.repeatAny /-- -info: 'Cslib.Complexity.computableTidilyInPolyTime_repeatAny' depends on axioms: +info: 'Cslib.Complexity.computableInPolyTime_repeatAny' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInPolyTime_repeatAny +#print axioms Cslib.Complexity.computableInPolyTime_repeatAny /-- info: 'Cslib.Complexity.mem_RP_iff_forall_decidesWithOneSidedErrorExponent' depends on axioms: diff --git a/ComplexityTests/ResourceClasses4.lean b/ComplexityTests/ResourceClasses4.lean index 6f693ccd7..568e77131 100644 --- a/ComplexityTests/ResourceClasses4.lean +++ b/ComplexityTests/ResourceClasses4.lean @@ -6,6 +6,7 @@ Authors: Samuel Schlesinger import Complexity.Computability.Complexity.Classes.Padding import Complexity.Computability.Complexity.Classes.RP +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! Padding: the padded problem of a nondeterministic machine, the translation lemma and `P = NP → EXP = NEXP`; and error reduction for deciders of a nontrivial problem. -/ @@ -28,7 +29,7 @@ theorem computableTidilyInO_two_pow_length : example (hNP : NP encBits ⊆ P encBits) : NTIME encBits (2 ^ ·) ⊆ ⋃ d, DTIME encBits fun n => (n + (n + (n + 1) * 2 ^ n) + 1) ^ d := - NTIME_subset_iUnion_DTIME_of_NP_subset_P hNP computableTidilyInO_two_pow_length + NTIME_subset_iUnion_DTIME_of_NP_subset_P hNP (.of_tidy computableTidilyInO_two_pow_length) /-- Every nondeterministic machine has a padded problem in `NP`. -/ example {k : ℕ} {State : Type} [Finite State] (ntm : MultiTapeNTM k Bool State) (c : ℕ) : diff --git a/ComplexityTests/SBPAmplification.lean b/ComplexityTests/SBPAmplification.lean index 610644abb..1a47d0e8e 100644 --- a/ComplexityTests/SBPAmplification.lean +++ b/ComplexityTests/SBPAmplification.lean @@ -25,7 +25,7 @@ def language : Set (List Bool) := {w | w.headD false = true} private def count (w : List Bool) : ℕ := if w.headD false then 3 else 1 private theorem count_mem : count ∈ SharpP encBits := - mem_SharpP_of_polyTime (f := count) (by unfold count; fun_prop) + mem_SharpP_of_polyTime (f := count) (.of_tidy (by unfold count; fun_prop)) private theorem language_mem : language ∈ SBP encBits := by refine ⟨count, count_mem, fun _ => 3, .const 3, fun w => ?_⟩ @@ -40,7 +40,7 @@ example : count [true] = 3 ∧ count [false] = 1 := by decide /-- The #P count may be exponential even though its unary exponent is polynomial-time. -/ example : (fun w : List Bool => 3 ^ w.length) ∈ SharpP encBits := SharpP.pow_mem_polyTime (SharpP.natCast_mem 3) - (by simpa using ComputableTidilyInPolyTime.encoding_length encBits) + (.of_tidy (by simpa using ComputableTidilyInPolyTime.encoding_length encBits)) /-- Zero rows accept the empty tuple, even for an always-rejecting zero-width verifier. -/ example : acceptCount (SharpP.powerVerifier (fun _ : Unit => 0) (fun _ => 0) diff --git a/ComplexityTests/SipserLautemann.lean b/ComplexityTests/SipserLautemann.lean index e0c960c66..e6f70897e 100644 --- a/ComplexityTests/SipserLautemann.lean +++ b/ComplexityTests/SipserLautemann.lean @@ -5,6 +5,7 @@ Authors: Bolton Bailey, Samuel Schlesinger -/ import Complexity.Computability.Complexity.Classes.PH.SipserLautemann +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Tests for the Sipser–Lautemann theorem @@ -118,6 +119,8 @@ theorem noisyHead_mem_PiP_two : {x : List Bool | x.headD false = true} ∈ PiP 2 theorem noisyHead_mem_PH : {x : List Bool | x.headD false = true} ∈ PH encBits := BPP_subset_PH noisyHead_mem_BPP +attribute [local fun_prop] ComputableInPolySpace.tidy in +attribute [local fun_prop] ComputableInPolyTime.tidy in -- Direct `fun_prop` synthesis on the Sipser-Lautemann matrix verifier for `noisyHeadVerifier`. example : ComputableTidilyInPolyTime (verifier encBits (Polynomial.C 2) noisyHeadVerifier) diff --git a/ComplexityTests/SpaceHierarchy.lean b/ComplexityTests/SpaceHierarchy.lean index 16b670e83..8ab4b44d4 100644 --- a/ComplexityTests/SpaceHierarchy.lean +++ b/ComplexityTests/SpaceHierarchy.lean @@ -152,11 +152,11 @@ info: 'Turing.MultiTapeTM.Universal.budgetSpace_le' depends on axioms: #print axioms Turing.MultiTapeTM.Universal.budgetSpace_le /-- -info: 'Cslib.Complexity.computableTidilyInO_spaceDiagonal' depends on axioms: +info: 'Cslib.Complexity.computableInO_spaceDiagonal' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInO_spaceDiagonal +#print axioms Cslib.Complexity.computableInO_spaceDiagonal /-- info: 'Cslib.Complexity.setOf_spaceDiagonal_notMem_DSPACE' depends on axioms: diff --git a/ComplexityTests/TFNPCompleteness.lean b/ComplexityTests/TFNPCompleteness.lean index 77fa89e45..047953dfd 100644 --- a/ComplexityTests/TFNPCompleteness.lean +++ b/ComplexityTests/TFNPCompleteness.lean @@ -41,12 +41,12 @@ private theorem cost_polytime : /-- A one-bit local-search family can have costs requiring five bits. -/ theorem wideCostFamily_mem_PLS : localOptRel (fun _ : Bool => 1) neighbor cost ∈ PLS encBool := - localOptRel_mem_PLS (const 1) neighbor_polytime cost_polytime (by simp [neighbor]) + localOptRel_mem_PLS (.of_tidy (const 1)) (.of_tidy neighbor_polytime) (.of_tidy cost_polytime) (by simp [neighbor]) /-- The reduction preserves this family without restricting costs to the vertex width. -/ theorem wideCostFamily_reduces : SearchReducible encBool encLocalOpt (localOptRel (fun _ : Bool => 1) neighbor cost) LocalOpt := - localOptRel_searchReducible_LocalOpt (const 1) neighbor_polytime cost_polytime + localOptRel_searchReducible_LocalOpt (.of_tidy (const 1)) (.of_tidy neighbor_polytime) (.of_tidy cost_polytime) (by simp [neighbor]) example : localOptRel (fun _ : Bool => 1) neighbor cost false [false] := by diff --git a/ComplexityTests/TQBF.lean b/ComplexityTests/TQBF.lean index 3dcf4a2fd..d43c4a15f 100644 --- a/ComplexityTests/TQBF.lean +++ b/ComplexityTests/TQBF.lean @@ -215,11 +215,11 @@ info: 'Cslib.Complexity.TQBF.evaluate_eq_true_iff' depends on axioms: #print axioms Cslib.Complexity.TQBF.evaluate_eq_true_iff /-- -info: 'Cslib.Complexity.TQBF.exists_computableTidilyInO_evaluate' depends on axioms: +info: 'Cslib.Complexity.TQBF.exists_computableInO_evaluate' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TQBF.exists_computableTidilyInO_evaluate +#print axioms Cslib.Complexity.TQBF.exists_computableInO_evaluate /-- info: 'Cslib.Complexity.TQBF_mem_PSPACE' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -256,18 +256,18 @@ info: 'Cslib.Complexity.TQBF.reduce_mem_TQBF_iff' depends on axioms: #print axioms Cslib.Complexity.TQBF.reduce_mem_TQBF_iff /-- -info: 'Cslib.Complexity.TQBF.computableTidilyInPolyTime_reduce' depends on axioms: +info: 'Cslib.Complexity.TQBF.computableInPolyTime_reduce' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TQBF.computableTidilyInPolyTime_reduce +#print axioms Cslib.Complexity.TQBF.computableInPolyTime_reduce /-- -info: 'Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest' depends on axioms: +info: 'Cslib.Complexity.TQBF.computableInPolyTime_edgeTest' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.TQBF.computableTidilyInPolyTime_edgeTest +#print axioms Cslib.Complexity.TQBF.computableInPolyTime_edgeTest /-- info: 'Cslib.Complexity.TQBF_pspaceHard' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/TimeHierarchy.lean b/ComplexityTests/TimeHierarchy.lean index 40a5bd1f1..e2373a9da 100644 --- a/ComplexityTests/TimeHierarchy.lean +++ b/ComplexityTests/TimeHierarchy.lean @@ -5,6 +5,7 @@ Authors: Samuel Schlesinger -/ import Complexity.Computability.Complexity.Classes.Hierarchy +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! Decoding descriptions from malformed, empty and padded words, the binary clock, the diagonal on the padded descriptions of concrete accepting and rejecting machines, and the exponential @@ -97,7 +98,7 @@ example (b : Bool) (pad : List Bool) : /-- The diagonal is computed in exponential time, up to a constant factor. -/ example : ∃ c, ComputableTidilyInTimeAndSpace diagonal encBits encBool (fun x => c * (2 ^ (4 * x.length) + 1)) fun x => c * (2 ^ (2 * x.length) + 1) := by - obtain ⟨c, h, -⟩ := computableTidilyInO_diagonal + obtain ⟨c, h, -⟩ := computableInO_diagonal.tidy exact ⟨c, h⟩ example : {x | diagonal x = true} ∉ P encBits := diagonal_notMem_P @@ -123,11 +124,11 @@ info: 'Cslib.Complexity.not_computableInTimeAndSpace_diagonal' depends on axioms #print axioms Cslib.Complexity.not_computableInTimeAndSpace_diagonal /-- -info: 'Cslib.Complexity.computableTidilyInO_diagonal' depends on axioms: +info: 'Cslib.Complexity.computableInO_diagonal' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.computableTidilyInO_diagonal +#print axioms Cslib.Complexity.computableInO_diagonal /-- info: 'Turing.MultiTapeTM.Universal.exists_computableTidilyInDegree_decodeDesc' depends on axioms: diff --git a/ComplexityTests/TimeReductions.lean b/ComplexityTests/TimeReductions.lean index 8ebe20062..810753561 100644 --- a/ComplexityTests/TimeReductions.lean +++ b/ComplexityTests/TimeReductions.lean @@ -5,6 +5,7 @@ Authors: Samuel Schlesinger -/ import Complexity.Computability.Complexity.Classes.EXP +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! Timed deterministic reductions use the time-class API without importing padding. The exponential-time client uses the diagonal language, which is outside `P`. -/ @@ -17,7 +18,7 @@ example {α : Type} {enc : α ↪ List Bool} {t : ℕ → ℕ} {A : Set α} (hA : A ∈ DTIME enc t) : ComputableTidilyInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t (enc a).length := - computableTidilyInO_indicator_of_mem_DTIME hA + (computableInO_indicator_of_mem_DTIME hA).tidy example {α : Type} {enc : α ↪ List Bool} {t : ℕ → ℕ} : DTIME enc (fun n => 2 * t n + 2) ⊆ DTIME enc t := diff --git a/ComplexityTests/VertexCoverKernel.lean b/ComplexityTests/VertexCoverKernel.lean index 8718a3b6a..1c3adacf1 100644 --- a/ComplexityTests/VertexCoverKernel.lean +++ b/ComplexityTests/VertexCoverKernel.lean @@ -148,11 +148,11 @@ info: 'Cslib.Complexity.VertexCover.length_encode_bussKernel_le' depends on axio #print axioms Cslib.Complexity.VertexCover.length_encode_bussKernel_le /-- -info: 'Cslib.Complexity.VertexCover.computableTidilyInPolyTime_bussKernel' depends on axioms: +info: 'Cslib.Complexity.VertexCover.computableInPolyTime_bussKernel' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.VertexCover.computableTidilyInPolyTime_bussKernel +#print axioms Cslib.Complexity.VertexCover.computableInPolyTime_bussKernel /-- info: 'Cslib.Complexity.VertexCover.isKernelization_bussKernel' depends on axioms: diff --git a/ComplexityTests/WPP.lean b/ComplexityTests/WPP.lean index c29efbcaf..ae30c2b2a 100644 --- a/ComplexityTests/WPP.lean +++ b/ComplexityTests/WPP.lean @@ -82,7 +82,7 @@ private theorem twoTargetGap_poly : example : {w : List Bool | w.headD false = true} ∈ LWPP encBits := by refine mem_LWPP_of_finset_targets (Finset.univ : Finset Bool) - (mem_GapP_of_polyTime twoTargetGap_poly) + (mem_GapP_of_polyTime (.of_tidy twoTargetGap_poly)) (fun b _ => twoTargets_poly b) (fun b _ => twoTargets_ne_zero b) (fun w => ?_) (fun w => ?_) @@ -102,7 +102,7 @@ example : {w : List Bool | w.headD false = true} ∈ LWPP encBits := by example : {w : List Bool | w.headD false = true} ∈ WPP encBits := by refine mem_WPP_of_finset_targets (Finset.univ : Finset Bool) - (mem_GapP_of_polyTime twoTargetGap_poly) + (mem_GapP_of_polyTime (.of_tidy twoTargetGap_poly)) (fun b _ => (twoTargets_poly b).comp (.encoding_length encBits)) (fun b _ w => twoTargets_ne_zero b w.length) (fun w => ?_) (fun w => ?_) diff --git a/ComplexityTests/WPPBounded.lean b/ComplexityTests/WPPBounded.lean index a7d800515..4cefdd7af 100644 --- a/ComplexityTests/WPPBounded.lean +++ b/ComplexityTests/WPPBounded.lean @@ -48,7 +48,7 @@ theorem joint_mem_LWPP : bitLanguage ∈ LWPP (encPair encBits encUnary) := by have hg : ComputableTidilyInPolyTime g (encPair encBits encUnary) encIntBin := by dsimp only [g] fun_prop - refine ⟨g, mem_GapP_of_polyTime hg, target, .of_tidy target_polyTime, target_ne_zero, ?_, ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy target_polyTime, target_ne_zero, ?_, ?_⟩ · intro x cases h : x.1.getD x.2 false <;> simp only [g, h] <;> simp · intro x @@ -57,16 +57,16 @@ theorem joint_mem_LWPP : bitLanguage ∈ LWPP (encPair encBits encUnary) := by simp [Ne.symm (target_ne_zero _)] example : {w | ∀ i < bound w, (w, i) ∈ bitLanguage} ∈ LWPP encBits := - forall_lt_mem_LWPP joint_mem_LWPP bound_polyTime + forall_lt_mem_LWPP joint_mem_LWPP (.of_tidy bound_polyTime) example : {w | ∃ i < bound w, (w, i) ∈ bitLanguage} ∈ LWPP encBits := - exists_lt_mem_LWPP joint_mem_LWPP bound_polyTime + exists_lt_mem_LWPP joint_mem_LWPP (.of_tidy bound_polyTime) example : {w | ∀ i < bound w, (w, i) ∈ bitLanguage} ∈ WPP encBits := - forall_lt_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) bound_polyTime + forall_lt_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) (.of_tidy bound_polyTime) example : {w | ∃ i < bound w, (w, i) ∈ bitLanguage} ∈ WPP encBits := - exists_lt_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) bound_polyTime + exists_lt_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) (.of_tidy bound_polyTime) -- Equal-length inputs have different bounds. Prefix targets also vary in sign and magnitude. example : bound [true, false] = 2 ∧ bound [false, true] = 0 := by decide @@ -98,9 +98,9 @@ example : ¬ ∃ i < bound [false, true], ([false, true], i) ∈ bitLanguage := example : ∀ i < bound [], ([], i) ∈ bitLanguage := by simp [bound] example : ¬ ∃ i < bound [], ([], i) ∈ bitLanguage := by simp [bound] example : {w : List Bool | ∀ i < 0, (w, i) ∈ bitLanguage} ∈ LWPP encBits := - forall_lt_mem_LWPP joint_mem_LWPP (.const 0) + forall_lt_mem_LWPP joint_mem_LWPP (.of_tidy (.const 0)) example : {w : List Bool | ∃ i < 0, (w, i) ∈ bitLanguage} ∈ LWPP encBits := - exists_lt_mem_LWPP joint_mem_LWPP (.const 0) + exists_lt_mem_LWPP joint_mem_LWPP (.of_tidy (.const 0)) /-- info: 'Cslib.Complexity.forall_lt_mem_WPP' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in diff --git a/ComplexityTests/WPPLowness.lean b/ComplexityTests/WPPLowness.lean index 6d42d4c2f..034ee7fdc 100644 --- a/ComplexityTests/WPPLowness.lean +++ b/ComplexityTests/WPPLowness.lean @@ -27,7 +27,7 @@ theorem univ_mem_SPP : (Set.univ : Set (List Bool)) ∈ SPP encBits := /-- A non-SPP-style `LWPP` witness for the universal language with target `-2`. -/ theorem univ_mem_LWPP : (Set.univ : Set (List Bool)) ∈ LWPP encBits := - ⟨fun _ => -2, mem_GapP_of_polyTime (.const (-2)), fun _ => -2, .const (-2), + ⟨fun _ => -2, mem_GapP_of_polyTime (.of_tidy (.const (-2))), fun _ => -2, .const (-2), fun _ => by lia, fun _ => Or.inr rfl, fun _ => by simp⟩ /-- The empty language in `LWPP` with target `-2`. -/ diff --git a/ComplexityTests/WPPRobustness.lean b/ComplexityTests/WPPRobustness.lean index 0340ffe60..ab1f51b43 100644 --- a/ComplexityTests/WPPRobustness.lean +++ b/ComplexityTests/WPPRobustness.lean @@ -18,7 +18,7 @@ private def language : Set (List Bool) := {w | w.headD false = true} private def gap (w : List Bool) : ℤ := if w.headD false then -1 else 0 -private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (by unfold gap; fun_prop) +private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (.of_tidy (by unfold gap; fun_prop)) private def targets (n : ℕ) : List ℤ := -1 :: -1 :: List.replicate n (-2) diff --git a/ComplexityTests/WPPTruthTable.lean b/ComplexityTests/WPPTruthTable.lean index 0079171d6..95012e47f 100644 --- a/ComplexityTests/WPPTruthTable.lean +++ b/ComplexityTests/WPPTruthTable.lean @@ -39,7 +39,7 @@ theorem target_ne_zero (n : ℕ) : target n ≠ 0 := by theorem oracle_mem_LWPP : oracle ∈ LWPP encBits := by let g (w : List Bool) : ℤ := if w.getD 0 false then target w.length else 0 have hg : ComputableTidilyInPolyTime g encBits encIntBin := by dsimp [g]; fun_prop - refine ⟨g, mem_GapP_of_polyTime hg, target, .of_tidy polyTime_target, target_ne_zero, ?_, ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy polyTime_target, target_ne_zero, ?_, ?_⟩ · intro w dsimp [g] split_ifs <;> simp @@ -84,10 +84,10 @@ theorem joint_mem_LWPP : query ⁻¹' oracle ∈ LWPP (encPair encBits encUnary) PolyTimeReducible.mem_LWPP ⟨query, .of_tidy polyTime_query, fun _ => Iff.rfl⟩ oracle_mem_LWPP example : language ∈ LWPP encBits := - truthTable_mem_LWPP joint_mem_LWPP polyTime_count polyTime_combine + truthTable_mem_LWPP joint_mem_LWPP (.of_tidy polyTime_count) (.of_tidy polyTime_combine) example : language ∈ WPP encBits := - truthTable_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) polyTime_count polyTime_combine + truthTable_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) (.of_tidy polyTime_count) (.of_tidy polyTime_combine) example : count [true, false] = 2 ∧ count [false, true] = 0 := by decide @@ -110,12 +110,12 @@ example : truthTableAnswers (query ⁻¹' oracle) count [] = [] := by example : {w | (fun _ : List Bool × List Bool => true) (w, truthTableAnswers (query ⁻¹' oracle) (fun _ => 0) w) = true} ∈ LWPP encBits := - truthTable_mem_LWPP joint_mem_LWPP (.const 0) (.const true) + truthTable_mem_LWPP joint_mem_LWPP (.of_tidy (.const 0)) (.of_tidy (.const true)) example : {w | (fun x : List Bool × List Bool => x.1.getD 0 false) (w, truthTableAnswers (query ⁻¹' oracle) (fun _ => 0) w) = true} ∈ LWPP encBits := truthTable_mem_LWPP (d := fun x => x.1.getD 0 false) - joint_mem_LWPP (.const 0) (by fun_prop) + joint_mem_LWPP (.of_tidy (.const 0)) (.of_tidy (by fun_prop)) end ComplexityTests.WPPTruthTable diff --git a/ComplexityTests/WPPTwoSided.lean b/ComplexityTests/WPPTwoSided.lean index 4822c0d56..9d6ac1bc0 100644 --- a/ComplexityTests/WPPTwoSided.lean +++ b/ComplexityTests/WPPTwoSided.lean @@ -18,7 +18,7 @@ private def language : Set (List Bool) := {w | w.headD false = true} private def gap (w : List Bool) : ℤ := if w.headD false then 0 else 1 -private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (by unfold gap; fun_prop) +private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (.of_tidy (by unfold gap; fun_prop)) private def yesTargets (n : ℕ) : List ℤ := 0 :: List.replicate n (-2) private def noTargets (n : ℕ) : List ℤ := 1 :: List.replicate (2 * n) 3 diff --git a/ComplexityTests/WorstCaseHardness.lean b/ComplexityTests/WorstCaseHardness.lean index bbb6e5127..c43bb40cc 100644 --- a/ComplexityTests/WorstCaseHardness.lean +++ b/ComplexityTests/WorstCaseHardness.lean @@ -263,11 +263,11 @@ info: 'Cslib.HardnessEncoding.encodedProgram_eq' depends on axioms: #print axioms Cslib.HardnessEncoding.encodedProgram_eq /-- -info: 'Cslib.HardnessEncoding.computableTidilyInPolyTime_paddedProgram' depends on axioms: +info: 'Cslib.HardnessEncoding.computableInPolyTime_paddedProgram' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.HardnessEncoding.computableTidilyInPolyTime_paddedProgram +#print axioms Cslib.HardnessEncoding.computableInPolyTime_paddedProgram /-- info: 'Cslib.HardnessEncoding.eventually_isAverageCaseHard_encodedSlice' depends on axioms: @@ -291,11 +291,11 @@ info: 'Cslib.Complexity.BPP_subset_P_of_eventually_two_pow_le_complexity' depend #print axioms Cslib.Complexity.BPP_subset_P_of_eventually_two_pow_le_complexity /-- -info: 'Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad' depends on axioms: +info: 'Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.setOf_mem_E_of_computableTidilyInPolyTime_pad +#print axioms Cslib.Complexity.setOf_mem_E_of_computableInPolyTime_pad /-- info: 'Cslib.BinaryField.card' depends on axioms: diff --git a/ComplexityTests/ZooCountingHierarchy.lean b/ComplexityTests/ZooCountingHierarchy.lean index 3e00b7902..8e36767f3 100644 --- a/ComplexityTests/ZooCountingHierarchy.lean +++ b/ComplexityTests/ZooCountingHierarchy.lean @@ -41,7 +41,7 @@ example : {w : List Bool | w.tail.headD false = true} ∈ US encBits := /-- FP counts may be exponentially large: the output encoding is binary. -/ example : (fun w : List Bool => 2 ^ w.length) ∈ SharpP encBits := - mem_SharpP_of_polyTime (ComputableTidilyInPolyTime.binary_two_pow.comp (.encoding_length encBits)) + mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp (.encoding_length encBits))) private def target (n : ℕ) : ℤ := -(2 ^ n : ℤ) @@ -59,7 +59,7 @@ private theorem head_mem_LWPP : {w : List Bool | w.headD false = true} ∈ LWPP have hgap : ComputableTidilyInPolyTime (fun w : List Bool => if w.headD false then target w.length else 0) encBits encIntBin := by fun_prop - refine ⟨_, mem_GapP_of_polyTime hgap, target, .of_tidy target_poly, target_ne_zero, + refine ⟨_, mem_GapP_of_polyTime (.of_tidy hgap), target, .of_tidy target_poly, target_ne_zero, fun w => ?_, fun w => ?_⟩ · cases w.headD false <;> simp · change (w.headD false = true) ↔ _ From 26952dbc79fd5ee0808c77c10ab4b057f149b052 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 13:26:00 -0400 Subject: [PATCH 04/11] refactor(classes): hand-complete the Classes restatement Hand fixes after the tool output: call sites that the rewrite could not convert (partial applications, non-bare conclusions, dot and field notation), translated proofs that need the tidy calculus, and tidy `fun_prop` proofs that used a restated composition rule. Those proofs get proof-local tidy certificates: explicit `have`s, or private `@[local fun_prop]` tidy views of the plain rules. The FPT family is plain (`ComputableInFPTTime.ite`/`.comp`, `ComputableInPolyTime.computableInFPTTime`, `ComputableInO.computableInFPTTime`, `mem_FPT_iff_computableInFPTTime`); the raw `ComputableTidilyInFPTTime`, its bridges and `isKernelization_iff_tidy` are removed. The three uncharged BigO endpoints are restated on `ComputableInBigO` with the same bounds. Tests state the restated API plainly. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Complexity/AffineDisperser/PolyTime.lean | 47 ++++- .../Classes/AWPP/Amplification.lean | 4 +- .../Complexity/Classes/AWPP/Lowness.lean | 3 +- .../Complexity/Classes/Alternation/NP.lean | 2 +- .../Complexity/Classes/Alternation/TQBF.lean | 10 + .../Classes/ArthurMerlin/Amplification.lean | 6 +- .../ArthurMerlin/GraphNonIsomorphism.lean | 28 ++- .../Complexity/Classes/ArthurMerlin/PH.lean | 2 + .../Classes/ArthurMerlin/SetLowerBound.lean | 7 +- .../Complexity/Classes/BPP/Amplification.lean | 2 +- .../Classes/BPP/Derandomization.lean | 19 +- .../Complexity/Classes/Constructible.lean | 17 +- .../Complexity/Classes/Counting/Space.lean | 10 +- .../Computability/Complexity/Classes/EXP.lean | 4 +- .../Complexity/Classes/Hierarchy/Space.lean | 2 +- .../Complexity/Classes/Hierarchy/Time.lean | 2 +- .../Complexity/Classes/IP/PSPACE.lean | 2 +- .../Complexity/Classes/IP/TQBF/Verifier.lean | 92 ++++++++ .../Complexity/Classes/Inclusions.lean | 3 +- .../Complexity/Classes/Ladner.lean | 42 ++++ .../Complexity/Classes/Ladner/PolyTime.lean | 132 ++++++++---- .../Complexity/Classes/MIP/NEXP.lean | 5 +- .../Complexity/Classes/NP/GuessVerify.lean | 2 +- .../Complexity/Classes/Oracle.lean | 4 +- .../Classes/Oracle/BakerGillSolovay.lean | 2 +- .../Complexity/Classes/Oracle/Space.lean | 2 +- .../Complexity/Classes/Oracle/TQBF.lean | 5 +- .../Complexity/Classes/P/Slices.lean | 22 +- .../Complexity/Classes/PP/Oracle.lean | 4 +- .../Complexity/Classes/Padding.lean | 3 +- .../Complexity/Classes/ParityP.lean | 6 +- .../Complexity/Classes/Promise/Reduction.lean | 4 +- .../Computability/Complexity/Classes/RP.lean | 2 +- .../Complexity/Classes/RepeatedTrials.lean | 12 +- .../Computability/Complexity/Classes/SBP.lean | 11 +- .../Complexity/Classes/SBP/Amplification.lean | 2 +- .../Complexity/Classes/SharpP/Oracle.lean | 2 +- .../Complexity/Classes/SharpP/Space.lean | 18 +- .../Complexity/Classes/Space/Closure.lean | 31 +-- .../GeneralizedGeography/Membership.lean | 2 +- .../Space/GeneralizedGeography/Reduction.lean | 68 ++++++ .../Complexity/Classes/Space/TQBF.lean | 2 +- .../Classes/Space/TQBF/Membership.lean | 2 +- .../Complexity/Classes/Space/TQBF/Prenex.lean | 9 +- .../Complexity/Classes/TFNP.lean | 3 +- .../Classes/TFNP/SearchToDecision.lean | 2 +- .../Complexity/Classes/TFNP/Subclasses.lean | 94 +++++++-- .../Classes/TFNP/Subclasses/Completeness.lean | 19 +- .../Complexity/Classes/Toda.lean | 1 + .../Complexity/Classes/Toda/Counting.lean | 67 ++++-- .../Complexity/Classes/Toda/Hierarchy.lean | 79 ++++++- .../Computability/Complexity/Classes/UP.lean | 14 +- .../Complexity/Classes/ValiantVazirani.lean | 3 +- .../Classes/ValiantVazirani/Collapse.lean | 2 +- .../Classes/ValiantVazirani/Reduction.lean | 36 +++- .../Complexity/Fagin/Verifier.lean | 71 ++++--- .../Computability/Complexity/FineGrained.lean | 2 +- .../Complexity/FineGrained/BruteForce.lean | 3 +- .../Complexity/FineGrained/Exponents.lean | 4 +- .../Complexity/FineGrained/GraphProblems.lean | 24 +-- .../FineGrained/OrthogonalVectors.lean | 15 +- .../Complexity/FineGrained/Reduction.lean | 3 +- .../FineGrained/Sparsification.lean | 5 +- .../Complexity/HardnessEncoding/PolyTime.lean | 198 +++++++++++++++--- .../Complexity/Parameterized.lean | 190 ++++++++--------- .../Parameterized/Kernelization.lean | 17 +- .../Complexity/Parameterized/VertexCover.lean | 2 + .../Parameterized/VertexCover/BussKernel.lean | 180 ++++++++++++---- .../Problems/CircuitValue/Compilation.lean | 4 +- .../Problems/CircuitValue/Completeness.lean | 4 +- .../Complexity/Problems/Coloring.lean | 1 + .../Complexity/Problems/Graph.lean | 3 +- .../Complexity/Problems/Hamiltonian.lean | 6 +- .../Problems/Hamiltonian/Sparse.lean | 3 + .../Problems/Hamiltonian/Undirected.lean | 1 + .../Complexity/Problems/IndependentSet.lean | 1 + .../Problems/IntegerProgramming.lean | 1 + .../Complexity/Problems/Knapsack.lean | 2 + .../MonotoneCircuitValue/Completeness.lean | 4 +- .../Complexity/Problems/SAT/PolyTime.lean | 2 +- .../Complexity/Problems/SharpSAT.lean | 4 + .../Complexity/Problems/SubsetSum.lean | 1 + .../Complexity/Problems/TQBF/Closed.lean | 1 + .../Computability/Complexity/ProofSystem.lean | 6 +- .../Machines/Turing/TM2/Reverse/Transfer.lean | 4 +- .../PCP/Approximation/MaxThreeSAT.lean | 6 + .../Computability/PCP/Completeness.lean | 4 +- .../PCP/Encoded/Amplification/Iteration.lean | 5 + .../Computability/PCP/Encoded/GapTheorem.lean | 5 +- .../Computability/PCP/Encoded/Power.lean | 24 ++- .../PCP/Encoded/Preprocess/Programs.lean | 10 +- .../Computability/PCP/Encoded/ThreeSAT.lean | 3 +- .../TreeEval/Reader/Cert/Offset.lean | 2 +- Complexity/Computability/TreeEval/Space.lean | 27 +-- Complexity/Computability/USTCON/Space.lean | 15 +- .../Crypto/Computational/GMW/PolyTime.lean | 29 +++ .../Crypto/Computational/GMW/Simulator.lean | 29 +++ .../Crypto/Computational/OneWay/BPP.lean | 2 +- ComplexityTests/AWPPLowness.lean | 4 +- ComplexityTests/Alternation.lean | 14 +- ComplexityTests/ApproximateCounting.lean | 4 +- ComplexityTests/ArthurMerlin.lean | 4 +- ComplexityTests/Axioms.lean | 20 +- ComplexityTests/CircuitValueCompleteness.lean | 4 +- ComplexityTests/CookLevinPolyTime.lean | 31 +-- ComplexityTests/CountingSpace.lean | 12 +- ComplexityTests/CountingVerifier.lean | 6 +- ComplexityTests/FaginNP.lean | 4 +- ComplexityTests/FineGrained.lean | 4 +- .../FineGrained/GraphProblems.lean | 5 +- ComplexityTests/InteractiveProofs.lean | 2 +- ComplexityTests/KarpLipton2.lean | 4 +- ComplexityTests/KarpReductions.lean | 12 +- ComplexityTests/ManyOne.lean | 11 +- ComplexityTests/MonotoneCircuitValue.lean | 6 +- ComplexityTests/NPCompleteGraphs.lean | 16 +- .../NPCompleteGraphs/Hamiltonian.lean | 5 + ComplexityTests/NPCompleteGraphs/TSP.lean | 10 +- .../NPCompleteGraphs/Undirected.lean | 6 +- ComplexityTests/NPCompleteNumbers.lean | 4 +- ComplexityTests/NPWitness.lean | 8 +- .../NondeterministicVerifiers.lean | 10 +- ComplexityTests/PCPEncoded.lean | 8 +- ComplexityTests/PCPEncodedAmplification.lean | 32 +-- .../PCPEncodedAmplificationIteration.lean | 4 +- .../PCPEncodedArithmeticAmplification.lean | 4 +- ComplexityTests/PCPEncodedConstraints.lean | 3 +- ComplexityTests/PCPEncodedEnumeration.lean | 6 +- ComplexityTests/PCPEncodedGap.lean | 12 +- ComplexityTests/PCPEncodedPreprocess.lean | 3 +- ComplexityTests/PCPEncodedThreeSAT.lean | 7 +- ComplexityTests/PCPEncodedVerifier.lean | 12 +- ComplexityTests/PCPNP.lean | 2 +- ComplexityTests/PCPPreprocessPrograms.lean | 21 +- ComplexityTests/Relativization.lean | 3 +- ComplexityTests/RepeatedTrials.lean | 2 +- ComplexityTests/ResourceBoundsPlain.lean | 21 +- ComplexityTests/ResourceClasses.lean | 2 +- ComplexityTests/ResourceClasses3.lean | 6 +- ComplexityTests/SATPolyTime.lean | 2 + ComplexityTests/SBPAmplification.lean | 6 +- ComplexityTests/SharpPLowness.lean | 3 +- ComplexityTests/SipserLautemann.lean | 3 +- ComplexityTests/TFNP.lean | 14 +- ComplexityTests/TFNPCompleteness.lean | 4 +- ComplexityTests/TimeReductions.lean | 2 +- ComplexityTests/TreeEval.lean | 16 +- ComplexityTests/UniformCircuits.lean | 24 ++- ComplexityTests/VertexCoverKernel.lean | 6 +- ComplexityTests/WPP.lean | 4 +- 150 files changed, 1630 insertions(+), 707 deletions(-) diff --git a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean index 4ac3ef05a..a1793e6d3 100644 --- a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean +++ b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean @@ -400,6 +400,19 @@ theorem computableInPolyTime_monomialBit_explicit' {α : Type} {input : α ↪ L have hv := hv.tidy exact .of_tidy (computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv)) +/-- `computableInPolyTime_monomialBit_explicit'` for tidy `fun_prop` inside proofs. -/ +private theorem computableTidilyInPolyTime_monomialBit_explicit' {α : Type} + {input : α ↪ List Bool} {N u w v : α → ℕ} (hN : ComputableTidilyInPolyTime N input encUnary) + (hu : ComputableTidilyInPolyTime u input encUnary) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hv : ComputableTidilyInPolyTime v input encUnary) : + ComputableTidilyInPolyTime + (fun a => monomialBit (degreePrimes (N a)) (explicitPowerTables (N a)) (u a) (w a) (v a)) + input encBool := + computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv) + +attribute [local fun_prop] ComputableInPolyTime.tidy + computableTidilyInPolyTime_monomialBit_explicit' in /-- The multiplication table of the explicit field on `N` bits, `N` in unary: its `n ^ 3` entries, `n ≤ N + 1`, are products over the prime factors of `n`. -/ @[fun_prop] @@ -571,7 +584,39 @@ theorem computableInPolyTime_traceBit' {α : Type} {input : α ↪ List Bool} refine .of_tidy ?_ simpa only [Function.comp_def] using computableTidilyInPolyTime_traceBit.comp (hτ.prod ha) -attribute [local fun_prop] ComputableInPolyTime.tidy in +/-- The tidy composition rules of the trace computation, for tidy `fun_prop` inside proofs. -/ +private theorem computableTidilyInPolyTime_powerPred' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {y : α → List Bool} {k : α → ℕ} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hy : ComputableTidilyInPolyTime y input encBits) + (hk : ComputableTidilyInPolyTime k input encUnary) : + ComputableTidilyInPolyTime (fun x => powerPred (tab x) (y x) (k x)) input encBits := by + simpa only [Function.comp_def] using + computableTidilyInPolyTime_powerPred.comp (htab.prod (hy.prod hk)) + +private theorem computableTidilyInPolyTime_esymmCoords' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {t : α → ℕ} {zs : α → List (List Bool)} + (htab : ComputableTidilyInPolyTime tab input encTable) + (ht : ComputableTidilyInPolyTime t input encUnary) + (hzs : ComputableTidilyInPolyTime zs input (encList encBits)) : + ComputableTidilyInPolyTime (fun x => esymmCoords (tab x) (t x) (zs x)) input encBits := by + simpa only [Function.comp_def] using + computableTidilyInPolyTime_esymmCoords.comp ((htab.prod ht).prod hzs) + +private theorem computableTidilyInPolyTime_traceVector' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} (htab : ComputableTidilyInPolyTime tab input encTable) : + ComputableTidilyInPolyTime (fun x => traceVector (tab x)) input encBits := by + simpa only [Function.comp_def] using computableTidilyInPolyTime_traceVector.comp htab + +private theorem computableTidilyInPolyTime_traceBit' {α : Type} {input : α ↪ List Bool} + {τ a : α → List Bool} (hτ : ComputableTidilyInPolyTime τ input encBits) + (ha : ComputableTidilyInPolyTime a input encBits) : + ComputableTidilyInPolyTime (fun x => traceBit (τ x) (a x)) input encBool := by + simpa only [Function.comp_def] using computableTidilyInPolyTime_traceBit.comp (hτ.prod ha) + +attribute [local fun_prop] computableTidilyInPolyTime_powerPred' + computableTidilyInPolyTime_esymmCoords' computableTidilyInPolyTime_traceVector' + computableTidilyInPolyTime_traceBit' in /-- **`traceSym 1 r t` in coordinates**, uniformly in the multiplication table, `r` and `t` in unary, and the input bits. -/ theorem computableInPolyTime_traceSymCoords : ComputableInPolyTime diff --git a/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean index a4717c96a..a364559bd 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean @@ -131,7 +131,9 @@ theorem majorityPolynomial_mem {α : Type} {enc : α ↪ List Bool} {g D : α have hd' := GapP.pow_mem_polyTime (GapP.comp_mem (GapP.sub_mem' hD hg) (.fst enc encBits)) hz have htest : ComputableInPolyTime (fun x : α × List Bool => if r x.1 < ones x then (1 : ℕ) else 0) - (encPair enc encBits) encNat := by fun_prop + (encPair enc encBits) encNat := + .of_tidy (ComputableTidilyInPolyTime.ite_decide (ComputableTidilyInPolyTime.unary_lt' hR.tidy + hones.tidy) (.const 1) (.const 0)) have hweight := GapP.mul_mem (GapP.mul_mem hg' hd') (SharpP.natCast_mem_GapP (mem_SharpP_of_polyTime htest)) have hsum := GapP.sum_bits_mem hweight diff --git a/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean b/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean index d075e0f1f..c6cd98b0b 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP/Lowness.lean @@ -165,7 +165,8 @@ theorem PPWithOracle_eq_PP_of_mem_AWPP (hA : A ∈ AWPP encBits) (enc : α ↪ L have hT : ComputableTidilyInPolyTime T enc encUnary := by dsimp [T]; fun_prop let e : α → ℕ := fun a => r a + T a + 4 have he : ComputableTidilyInPolyTime e enc encUnary := by dsimp [e]; fun_prop - obtain ⟨H, hH, R, hR, hweights⟩ := exists_AWPP_queryWeights hA hT he + obtain ⟨H, hH, R, hR, hweights⟩ := exists_AWPP_queryWeights hA (.of_tidy hT) (.of_tidy he) + have hR := hR.tidy let input : α × List Bool → List Bool := encPair enc encBits let T' : α × List Bool → ℕ := fun x => T x.1 let R' : α × List Bool → ℕ := fun x => R x.1 diff --git a/Complexity/Computability/Complexity/Classes/Alternation/NP.lean b/Complexity/Computability/Complexity/Classes/Alternation/NP.lean index 794b75432..6d877082f 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/NP.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/NP.lean @@ -44,7 +44,7 @@ variable {α : Type} {enc : α ↪ List Bool} existential, decides the problem within the same polynomial time bound. -/ theorem NP_subset_AP : NP enc ⊆ AP enc := by rintro A ⟨p, V, hV, hA⟩ - obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := hA.exists_decidesInTime hV.tidy + obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := hA.exists_decidesInTime hV refine ⟨_, .of_forall_le c d fun _ => le_rfl, k, State, hfinite, ⟨machine, fun _ => false⟩, fun a => ⟨(hdecides a).1, ?_⟩⟩ rw [(hdecides a).2] diff --git a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean index 388eebdb7..b0c9b921c 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean @@ -371,6 +371,16 @@ theorem computableInPolyTime_gameFormula {k : ℕ} {State : Type} [Fintype State (l := fun x => (List.range (w x)).flatMap (roundTokens (w x)) ++ (baseFormula (tab x) (w x)).tokens) (by fun_prop) fun _ => tokens_gameFormula .. +@[local fun_prop] +private theorem computableTidilyInPolyTime_gameFormula + {k : ℕ} {State : Type} [Fintype State] + {tab : γ → CNF (CookLevin.Var k State)} {w : γ → ℕ} + (htab : ComputableTidilyInPolyTime tab encIn + (encList (encList (encPair CookLevin.encVar encBool)))) + (hw : ComputableTidilyInPolyTime w encIn encUnary) : + ComputableTidilyInPolyTime (fun x => gameFormula (tab x) (w x)) encIn encQBF := + (ComputableInPolyTime.tidy (computableInPolyTime_gameFormula (.of_tidy htab) (.of_tidy hw))) + /-- **The reduction of a game is polynomial-time.** -/ theorem computableInPolyTime_gameReduce {kV : ℕ} {StateV : Type} [Fintype StateV] [DecidableEq StateV] (tmV : MultiTapeTM kV Bool StateV) (cV dV : ℕ) : diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean index dac82ff8f..61c896bd3 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean @@ -118,6 +118,8 @@ def merlinArthurRepeat (enc : α ↪ List Bool) (q r p : Polynomial ℕ) (V : α theorem computableInPolyTime_merlinArthurRepeat {V : α × List Bool → Bool} (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (q r p : Polynomial ℕ) : ComputableInPolyTime (merlinArthurRepeat enc q r p V) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ unfold merlinArthurRepeat repeatMajority repeatVotes fun_prop @@ -233,6 +235,8 @@ def arthurMerlinRepeat (enc : α ↪ List Bool) (r p q : Polynomial ℕ) (V : α theorem computableInPolyTime_arthurMerlinRepeat {V : α × List Bool → Bool} (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (r p q : Polynomial ℕ) : ComputableInPolyTime (arthurMerlinRepeat enc r p q V) (encPair enc encBits) encBool := by + have hV := hV.tidy + refine .of_tidy ?_ unfold arthurMerlinRepeat fun_prop @@ -534,7 +538,7 @@ theorem mem_AM_of_exists {B : Set (α × List Bool)} (hB : B ∈ AM (encPair enc x.2.take ((pB.comp L).eval (enc x.1).length) ++ x.2.drop ((pB.comp L).eval (enc x.1).length + p.eval (enc x.1).length)), ?_, fun a => ?_⟩ - · exact .of_tidy <| hVB.comp (((ComputableTidilyInPolyTime.fst _ _).prod + · exact .of_tidy <| hVB.tidy.comp (((ComputableTidilyInPolyTime.fst _ _).prod (ComputableTidilyInPolyTime.bitsTakeWithInput (ComputableTidilyInPolyTime.bitsDropWithInput (.snd _ _) hP) hp)).prod (ComputableTidilyInPolyTime.bitsAppend diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean index 200c29809..6aba367fd 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean @@ -350,10 +350,36 @@ def test (N : Polynomial ℕ) (x : (Graph × Graph) × List Bool) : Bool := (x.2.take (N.eval (encPair encGraph encGraph x.1).length)) (x.2.drop (N.eval (encPair encGraph encGraph x.1).length)) +@[local fun_prop] +private theorem computableTidilyInPolyTime_adjIndex + {γ : Type} {input : γ ↪ List Bool} {G : γ → Graph} + {i j : γ → ℕ} (hG : ComputableTidilyInPolyTime G input encGraph) + (hi : ComputableTidilyInPolyTime i input encUnary) + (hj : ComputableTidilyInPolyTime j input encUnary) : + ComputableTidilyInPolyTime (fun x => (G x).adjIndex (i x) (j x)) input encBool := + (ComputableInPolyTime.tidy (Graph.computableInPolyTime_adjIndex (.of_tidy hG) (.of_tidy hi) + (.of_tidy hj))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_image + {γ : Type} {input : γ ↪ List Bool} {n i : γ → ℕ} + {w : γ → List Bool} (hn : ComputableTidilyInPolyTime n input encUnary) + (hw : ComputableTidilyInPolyTime w input encBits) + (hi : ComputableTidilyInPolyTime i input encUnary) : + ComputableTidilyInPolyTime (fun x => GraphIsomorphism.image (n x) (w x) (i x)) input encUnary := + (ComputableInPolyTime.tidy (GraphIsomorphism.computableInPolyTime_image (.of_tidy hn) + (.of_tidy hw) (.of_tidy hi))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_distinctVertices : + ComputableTidilyInPolyTime Graph.distinctVertices encGraph (encList encNat) := + (ComputableInPolyTime.tidy (Graph.computableInPolyTime_distinctVertices)) + /-- The test is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_test (N : Polynomial ℕ) : ComputableInPolyTime (test N) (encPair (encPair encGraph encGraph) encBits) encBool := by + refine .of_tidy ?_ unfold test check dsimp only fun_prop @@ -545,7 +571,7 @@ theorem mem_AM : GraphNonIsomorphism ∈ AM (encPair encGraph encGraph) := by rw [hset, card_filter_check (by rw [hE]; omega) (by rw [hC]; omega)] rfl refine mem_AM_of_card_certifiedSet (N := N) (c := c) (R := test N) - (computableInPolyTime_test N).tidy hK (fun a => by positivity) (fun a ha => ?_) + (computableInPolyTime_test N) (.of_tidy hK) (fun a => by positivity) (fun a ha => ?_) fun a ha => ?_ · obtain ⟨G₀, G₁⟩ := a dsimp only diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean index 98d4929a4..224c3aff5 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean @@ -188,6 +188,8 @@ def piTwoVerifier (enc : α ↪ List Bool) (k p q : Polynomial ℕ) (W : α × L theorem computableInPolyTime_piTwoVerifier {W : α × List Bool → Bool} (hW : ComputableInPolyTime W (encPair enc encBits) encBool) (k p q : Polynomial ℕ) : ComputableInPolyTime (piTwoVerifier enc k p q W) (encPair enc encBits) encBool := by + have hW := hW.tidy + refine .of_tidy ?_ unfold piTwoVerifier fun_prop diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean index b82379cdf..340ce0a1a 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean @@ -165,6 +165,9 @@ theorem computableInPolyTime_verifier {N c m T : Polynomial ℕ} {ℓ : α → {R : α × List Bool → Bool} (hℓ : ComputableInPolyTime ℓ enc encUnary) (hR : ComputableInPolyTime R (encPair enc encBits) encBool) : ComputableInPolyTime (verifier enc N c m T ℓ R) (encPair enc encBits) encBool := by + have hℓ := hℓ.tidy + have hR := hR.tidy + refine .of_tidy ?_ unfold verifier dsimp only fun_prop @@ -344,10 +347,10 @@ theorem SBP_subset_AM : SBP enc ⊆ AM enc := by exact ⟨fun ⟨_, h⟩ => h, fun h => ⟨fun _ => false, h⟩⟩ refine mem_AM_of_card_certifiedSet (N := s) (c := 0) (R := fun x => W (x.1, x.2.take (s.eval (enc x.1).length))) - (hW.tidy.comp ((ComputableTidilyInPolyTime.fst enc encBits).prod + (.of_tidy (hW.tidy.comp ((ComputableTidilyInPolyTime.fst enc encBits).prod (ComputableTidilyInPolyTime.bitsTakeWithInput (.snd enc encBits) (((ComputableTidilyInPolyTime.unary_eval s).comp - (ComputableTidilyInPolyTime.encoding_length enc)).comp (.fst enc encBits))))) + (ComputableTidilyInPolyTime.encoding_length enc)).comp (.fst enc encBits)))))) hk hkpos (fun a ha => ?_) fun a ha => ?_ · rw [hcount] exact (hA a).1 ha diff --git a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean index e4c1292db..75555ef64 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean @@ -153,7 +153,7 @@ open scoped symmDiff theorem inter_mem_BPP {A B : Set α} (hA : A ∈ BPP enc) (hB : B ∈ BPP enc) : A ∩ B ∈ BPP enc := by obtain ⟨p₁, V₁, hV₁, h₁⟩ := mem_BPP_iff_forall_decidesWithErrorExponent.1 hA 3 obtain ⟨p₂, V₂, hV₂, h₂⟩ := mem_BPP_iff_forall_decidesWithErrorExponent.1 hB 3 - refine mem_BPP_iff_tidy.2 ⟨p₁ + p₂, andVerifier (fun a => p₁.eval (enc a).length) V₁ V₂, + refine mem_BPP.2 ⟨p₁ + p₂, andVerifier (fun a => p₁.eval (enc a).length) V₁ V₂, by fun_prop, fun a => ?_⟩ have hs₁ := acceptCount_add_card_filter_eq_false (V := V₁) (a := a) (n := p₁.eval (enc a).length) diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean index 9a620a50d..d0efe6667 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization.lean @@ -169,17 +169,22 @@ theorem BPP_subset_P_of_isAverageCaseHard {L : Language Bool} {c : ℕ} fun x => le_of_eq ?_ rw [← pow_add, ht] ring_nf - refine (computableInPolyTime_nwDecider hV - (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) (.of_tidy hg) (.of_tidy ?_) (.of_tidy ?_) (.of_tidy ?_) (.of_tidy ?_) - (hbudget (b + 1)) ((hbudget (k * (c * 4))).mono fun x => le_of_eq ?_)).tidy - · simp only [hseed] + have hseedO : ComputableTidilyInPolyTime seed enc encUnary := by + simp only [hseed] fun_prop - · simp only [hblock] + have hblockO : ComputableTidilyInPolyTime block enc encUnary := by + simp only [hblock] fun_prop - · simp only [hoverlap] + have hoverlapO : ComputableTidilyInPolyTime overlap enc encUnary := by + simp only [hoverlap] fun_prop - · simp only [hout] + have houtO : ComputableTidilyInPolyTime out enc encUnary := by + simp only [hout] fun_prop + refine (computableInPolyTime_nwDecider hV + (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) hg (.of_tidy hseedO) + (.of_tidy hblockO) (.of_tidy hoverlapO) (.of_tidy houtO) + (hbudget (b + 1)) ((hbudget (k * (c * 4))).mono fun x => le_of_eq ?_)).tidy · simp only [hblock] ring_nf · -- correctness on the instance `x` diff --git a/Complexity/Computability/Complexity/Classes/Constructible.lean b/Complexity/Computability/Complexity/Classes/Constructible.lean index edd3df6d5..56f81c806 100644 --- a/Complexity/Computability/Complexity/Classes/Constructible.lean +++ b/Complexity/Computability/Complexity/Classes/Constructible.lean @@ -120,7 +120,8 @@ attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `2 ^ n` is time-constructible: its binary digits are `n` zeros followed by a one. -/ theorem timeConstructible_two_pow : TimeConstructible (2 ^ ·) := - TimeConstructible.of_computableInO 1 (ComputableTidilyInDegree.two_pow_length encBits).inO_one + TimeConstructible.of_computableInO 1 + (.of_tidy (ComputableTidilyInDegree.two_pow_length encBits).inO_one) (s := fun n => n) (fun x => by simp only [encBits_apply] have := Nat.lt_two_pow_self (n := x.length) @@ -144,12 +145,13 @@ theorem TimeConstructible.succ_mul_of_computableInO {f : ℕ → ℕ} {T : List fun x => S x.length) (hT : ∀ x, T x ≤ c * ((x.length + 1) * f x.length) + c) (hn : ∀ n, n ≤ f n) : TimeConstructible fun n => (n + 1) * f n := by - have hf : ComputableTidilyInO (fun x : List Bool => f x.length) encBits encNat T fun x => S x.length := by simpa only [computableInO_iff_computableTidilyInO] using hf + have hf := hf.tidy have hlen := ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat have h := computableTidilyInDegree_mul.inO.comp (hlen.prod hf) obtain ⟨C, hC⟩ := exists_pow_length_encNat_le 3 obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 - refine Complexity.TimeConstructible.of_computableInO (150 * C + C₂ + c + 10) h (fun x => ?_) (s := fun n => + refine TimeConstructible.of_computableInO (150 * C + C₂ + c + 10) (.of_tidy h) (fun x => ?_) + (s := fun n => n + 1 + ((encNat n).length + 1) + S n + (2 * (encNat (n + 1)).length + 1 + (encNat (f n)).length + 1) ^ 3) fun x => ?_ · simp only [Function.comp_apply, length_encPair] @@ -191,7 +193,7 @@ theorem TimeConstructible.succ_mul_of_computableInO {f : ℕ → ℕ} {T : List /-- If `f` is time-constructible and `n ≤ f n`, then so is `(n + 1) * f n`. -/ theorem TimeConstructible.succ_mul {f : ℕ → ℕ} (hf : TimeConstructible f) (hn : ∀ n, n ≤ f n) : TimeConstructible fun n => (n + 1) * f n := - Complexity.TimeConstructible.succ_mul_of_computableInO 1 (.of_tidy hf.computableTidilyInO) (fun x => by + TimeConstructible.succ_mul_of_computableInO 1 (.of_tidy hf.computableTidilyInO) (fun x => by have : f x.length ≤ (x.length + 1) * f x.length := Nat.le_mul_of_pos_left _ (by omega) omega) hn @@ -202,7 +204,7 @@ theorem timeConstructible_succ_sq : TimeConstructible fun n => (n + 1) ^ 2 := by have hlen := ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat obtain ⟨C₂, hC₂⟩ := exists_pow_length_encNat_le 2 have h := TimeConstructible.succ_mul_of_computableInO (f := fun n => n + 1) - (S := fun n => n + 1 + ((encNat n).length + 1)) (C₂ + 2) hlen (fun x => by + (S := fun n => n + 1 + ((encNat n).length + 1)) (C₂ + 2) (.of_tidy hlen) (fun x => by have := hC₂ x.length have e : (C₂ + 2) * ((x.length + 1) * (x.length + 1)) = C₂ * ((x.length + 1) * (x.length + 1)) + 2 * ((x.length + 1) * (x.length + 1)) := by @@ -271,13 +273,14 @@ attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `n` is space-constructible: count the length of the word in binary. -/ theorem spaceConstructible_id : SpaceConstructible fun n => n := - SpaceConstructible.of_computableInO 1 ComputableTidilyInO.lengthNat fun x => by omega + SpaceConstructible.of_computableInO 1 (.of_tidy ComputableTidilyInO.lengthNat) fun x => by omega attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `n + 1` is space-constructible. -/ theorem spaceConstructible_succ : SpaceConstructible fun n => n + 1 := - SpaceConstructible.of_computableInO 2 (ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat) + SpaceConstructible.of_computableInO 2 + (.of_tidy (ComputableTidilyInO.natSucc.comp ComputableTidilyInO.lengthNat)) fun x => by have := Universal.length_encNat_le x.length; omega /-- Constant bounds are space-constructible, in zero space. -/ diff --git a/Complexity/Computability/Complexity/Classes/Counting/Space.lean b/Complexity/Computability/Complexity/Classes/Counting/Space.lean index 54ef2e00d..4db38aa16 100644 --- a/Complexity/Computability/Complexity/Classes/Counting/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Counting/Space.lean @@ -14,6 +14,7 @@ public import Complexity.Computability.Complexity.Classes.Space.Closure public import Complexity.Computability.Complexity.Classes.Oracle.Space import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.Plain /-! # Counting classes within polynomial space @@ -60,8 +61,8 @@ theorem PP_subset_PSPACE : PP enc ⊆ PSPACE enc := by ComputableTidilyInPolyTime.binary_lt).comp ((ComputableTidilyInPolySpace.of_polyTime hpow).prod ((ComputableTidilyInPolySpace.of_polyTime hdouble).comp - (SharpP.computableTidilyInPolySpace hf))) - exact mem_PSPACE_of_computableInPolySpace htest fun a => by simpa using hA a + (SharpP.computableInPolySpace hf).tidy)) + exact mem_PSPACE_of_computableInPolySpace (.of_tidy htest) fun a => by simpa using hA a /-- Testing whether a fixed modulus divides a #P count is in polynomial space. A quotient has at most one more bit than the verifier's certificate length, even for moduli zero and one. -/ @@ -71,7 +72,8 @@ theorem coModP_subset_PSPACE (k : ℕ) : coModP k enc ⊆ PSPACE enc := by obtain ⟨p, hp⟩ := SharpP.exists_le_two_pow hf have hleft : ComputableTidilyInPolySpace (fun x : α × List Bool => f x.1) (encPair enc encBits) encNat := - (SharpP.computableTidilyInPolySpace hf).comp (.of_polyTime (ComputableTidilyInPolyTime.fst _ _)) + (SharpP.computableInPolySpace hf).tidy.comp + (.of_polyTime (ComputableTidilyInPolyTime.fst _ _)) have hright : ComputableTidilyInPolyTime (fun x : α × List Bool => k * ofBits x.2) (encPair enc encBits) encNat := by have hread := ComputableTidilyInPolyTime.bitsToNat @@ -85,7 +87,7 @@ theorem coModP_subset_PSPACE (k : ℕ) : coModP k enc ⊆ PSPACE enc := by (hle.comp ((ComputableTidilyInPolySpace.of_polyTime hright).prod hleft))) have hB : {x : α × List Bool | f x.1 = k * ofBits x.2} ∈ PSPACE (encPair enc encBits) := - mem_PSPACE_of_computableInPolySpace htest fun x => by + mem_PSPACE_of_computableInPolySpace (.of_tidy htest) fun x => by simp only [Set.mem_ofPred_eq, Bool.and_eq_true, decide_eq_true_eq] exact le_antisymm_iff have hbound : ComputableTidilyInPolyTime (fun a => p.eval (enc a).length + 1) diff --git a/Complexity/Computability/Complexity/Classes/EXP.lean b/Complexity/Computability/Complexity/Classes/EXP.lean index 304bf7108..0a7328bb3 100644 --- a/Complexity/Computability/Complexity/Classes/EXP.lean +++ b/Complexity/Computability/Complexity/Classes/EXP.lean @@ -152,7 +152,7 @@ theorem setOf_diagonal_mem_EXP : {x | diagonal x = true} ∈ EXP encBits := mem_EXP_iff.mpr ⟨2, DTIME_mono_of_eventually_le (t₁ := fun n => 2 ^ (4 * n)) (eventually_atTop.mpr ⟨4, fun n hn => Nat.pow_le_pow_right (by norm_num) (by nlinarith)⟩) - (setOf_mem_DTIME_of_computableInO computableInO_diagonal.tidy fun _ => le_rfl)⟩ + (setOf_mem_DTIME_of_computableInO computableInO_diagonal fun _ => le_rfl)⟩ /-- **Polynomial time is strictly within exponential time**, for problems on bit words: the diagonal problem is in `EXP` and not in `P` [Arora and Barak, Theorem 3.1][AroraBarak09]. -/ @@ -196,7 +196,7 @@ theorem setOf_mem_E_of_computableInPolyTime_pad {Ψ : List Bool × ℕ → Bool} have := hbound y simp only [encBits_apply] nlinarith - refine mem_E_iff.2 ⟨d + 2, preimage_mem_DTIME (C := c * 4 ^ d + 3) hB hgO fun y => ?_⟩ + refine mem_E_iff.2 ⟨d + 2, preimage_mem_DTIME (C := c * 4 ^ d + 3) hB (.of_tidy hgO) fun y => ?_⟩ -- the time bound is `2 ^ O(n)` set n := (encBits y).length have hn : n = y.length := by simp [n, encBits_apply] diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean index a341d10c2..c06f46b33 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean @@ -178,7 +178,7 @@ theorem setOf_spaceDiagonal_mem_DSPACE {G : ℕ → ℕ} (hG : SpaceConstructibl (hn : ∀ n, n ≤ G n) : {x | spaceDiagonal G x = true} ∈ DSPACE encBits G := by obtain ⟨T, c, hc, -⟩ := computableInO_spaceDiagonal hG refine mem_DSPACE_iff.mpr ⟨2 * c, 2 * c, _, decidableInTimeAndSpace_iff.mpr - ⟨spaceDiagonal G, hc.computableInTimeAndSpace.mono (fun _ => le_rfl) fun x => ?_, + ⟨spaceDiagonal G, hc.mono (fun _ => le_rfl) fun x => ?_, fun x => Iff.rfl⟩⟩ have := hn x.length simp only [encBits_apply] diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean index 0b624b6bc..613d40f97 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean @@ -325,7 +325,7 @@ theorem setOf_timeDiagonal_notMem_DTIME {f J : ℕ → ℕ} `O((n + 1) ^ 5 * (J n + 1) ^ 3)`. -/ theorem setOf_timeDiagonal_mem_DTIME {J : ℕ → ℕ} (hJ : TimeConstructible J) : {x | timeDiagonal J x = true} ∈ DTIME encBits fun n => (n + 1) ^ 5 * (J n + 1) ^ 3 := - setOf_mem_DTIME_of_computableInO (computableInO_timeDiagonal hJ).tidy + setOf_mem_DTIME_of_computableInO (computableInO_timeDiagonal hJ) (t := fun n => (n + 1) ^ 5 * (J n + 1) ^ 3) fun _ => le_rfl /-! ### The time hierarchy theorem -/ diff --git a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean index 4ec457ad9..ecf0a43fd 100644 --- a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean +++ b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean @@ -645,7 +645,7 @@ theorem IP_subset_PSPACE (enc : α ↪ List Bool) : IP enc ⊆ PSPACE enc := by exact (ComputableTidilyInPolySpace.of_polyTime hpost).comp ((ComputableTidilyInPolySpace.of_polyTime hcap).prod (computableTidilyInPolySpace_evaluate M hfuel)) - refine mem_PSPACE_of_computableInPolySpace hdec fun a => ?_ + refine mem_PSPACE_of_computableInPolySpace (.of_tidy hdec) fun a => ?_ rw [mem_iff_two_pow_lt_value (fun a S oracle s => hreal a S oracle s) hA a, evaluate_eq, decide_eq_true_iff] diff --git a/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean b/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean index c52221d0c..db89285f9 100644 --- a/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean +++ b/Complexity/Computability/Complexity/Classes/IP/TQBF/Verifier.lean @@ -240,6 +240,94 @@ section PolyTime open ComputableTidilyInPolyTime +/-! Tidy views of the plain certificates of `Words`, for tidy `fun_prop` below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_subMod {γ : Type} {encIn : γ ↪ List Bool} + {p a b : γ → ℕ} + (hp : ComputableTidilyInPolyTime p encIn encUnary) + (ha : ComputableTidilyInPolyTime a encIn encUnary) + (hb : ComputableTidilyInPolyTime b encIn encUnary) : + ComputableTidilyInPolyTime (fun x => subMod (p x) (a x) (b x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_subMod (.of_tidy hp) (.of_tidy ha) + (.of_tidy hb))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_hornerMod {γ : Type} {encIn : γ ↪ List Bool} + {p z : γ → ℕ} {l : γ → List ℕ} + (hp : ComputableTidilyInPolyTime p encIn encUnary) + (hz : ComputableTidilyInPolyTime z encIn encUnary) + (hl : ComputableTidilyInPolyTime l encIn (encList encUnary)) : + ComputableTidilyInPolyTime (fun x => hornerMod (p x) (z x) (l x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_hornerMod (.of_tidy hp) (.of_tidy hz) + (.of_tidy hl))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_lookupPt {γ : Type} {encIn : γ ↪ List Bool} + {pt : γ → List (ℕ × ℕ)} {w : γ → ℕ} + (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) + (hw : ComputableTidilyInPolyTime w encIn encNat) : + ComputableTidilyInPolyTime (fun x => lookupPt (pt x) (w x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_lookupPt (.of_tidy hpt) (.of_tidy hw))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_normPt {γ : Type} {encIn : γ ↪ List Bool} + {p : γ → ℕ} {xs : γ → List ℕ} + {pt : γ → List (ℕ × ℕ)} (hp : ComputableTidilyInPolyTime p encIn encUnary) + (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) + (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) : + ComputableTidilyInPolyTime (fun x => normPt (p x) (xs x) (pt x)) encIn + (encList (encPair encNat encUnary)) := + (ComputableInPolyTime.tidy (computableInPolyTime_normPt (.of_tidy hp) (.of_tidy hxs) + (.of_tidy hpt))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_updatePt {γ : Type} {encIn : γ ↪ List Bool} + {p : γ → ℕ} {xs : γ → List ℕ} + {pt : γ → List (ℕ × ℕ)} {v z : γ → ℕ} (hp : ComputableTidilyInPolyTime p encIn encUnary) + (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) + (hpt : ComputableTidilyInPolyTime pt encIn (encList (encPair encNat encUnary))) + (hv : ComputableTidilyInPolyTime v encIn encNat) + (hz : ComputableTidilyInPolyTime z encIn encUnary) : + ComputableTidilyInPolyTime (fun x => updatePt (p x) (xs x) (pt x) (v x) (z x)) encIn + (encList (encPair encNat encUnary)) := + (ComputableInPolyTime.tidy (computableInPolyTime_updatePt (.of_tidy hp) (.of_tidy hxs) + (.of_tidy hpt) (.of_tidy hv) (.of_tidy hz))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_getD_zero {γ : Type} {encIn : γ ↪ List Bool} + {l : γ → List ℕ} {i : γ → ℕ} + (hl : ComputableTidilyInPolyTime l encIn (encList encUnary)) + (hi : ComputableTidilyInPolyTime i encIn encUnary) : + ComputableTidilyInPolyTime (fun x => (l x).getD (i x) 0) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_getD_zero (.of_tidy hl) (.of_tidy hi))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_width {γ : Type} {encIn : γ ↪ List Bool} + {p : γ → ℕ} + (hp : ComputableTidilyInPolyTime p encIn encUnary) : + ComputableTidilyInPolyTime (fun x => width (p x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_width (.of_tidy hp))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_replyLimit {γ : Type} {encIn : γ ↪ List Bool} + {p D : γ → ℕ} + (hp : ComputableTidilyInPolyTime p encIn encUnary) + (hD : ComputableTidilyInPolyTime D encIn encUnary) : + ComputableTidilyInPolyTime (fun x => replyLimit (p x) (D x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_replyLimit (.of_tidy hp) (.of_tidy hD))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_decodeReply {γ : Type} {encIn : γ ↪ List Bool} + {p D : γ → ℕ} {word : γ → List Bool} + (hp : ComputableTidilyInPolyTime p encIn encUnary) + (hD : ComputableTidilyInPolyTime D encIn encUnary) + (hword : ComputableTidilyInPolyTime word encIn encBits) : + ComputableTidilyInPolyTime (fun x => decodeReply (p x) (D x) (word x)) encIn + (encList encUnary) := + (ComputableInPolyTime.tidy (computableInPolyTime_decodeReply (.of_tidy hp) (.of_tidy hD) + (.of_tidy hword))) + @[local fun_prop] private lemma xs_pt : ComputableTidilyInPolyTime StepData.xs encStepData (encList encNat) := by unfold StepData.xs @@ -541,6 +629,10 @@ section VerifierPolyTime open ComputableTidilyInPolyTime TQBF +@[local fun_prop] private lemma tokens_pt : ComputableTidilyInPolyTime QBF.tokens encQBF + (encList encToken) := + computableInPolyTime_tokens.tidy + @[local fun_prop] private lemma isQuantifier_pt : ComputableTidilyInPolyTime QBF.Kind.isQuantifier encKind encBool := of_finite _ diff --git a/Complexity/Computability/Complexity/Classes/Inclusions.lean b/Complexity/Computability/Complexity/Classes/Inclusions.lean index b68d6343b..84b3214dd 100644 --- a/Complexity/Computability/Complexity/Classes/Inclusions.lean +++ b/Complexity/Computability/Complexity/Classes/Inclusions.lean @@ -15,6 +15,7 @@ public import Complexity.Computability.Complexity.Classes.Space.Closure public import Complexity.Computability.Complexity.Classes.Space.Savitch public import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace import Complexity.Computability.Machines.Turing.MultiTape.Combinators.TidyNormalForm +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat @@ -172,7 +173,7 @@ theorem PSPACE_subset_EXP : PSPACE enc ⊆ EXP enc := by (Q := fun n => (B n + 2) * (B n + 1)) (R := fun n => ((B n + 1) * (B n + B n + 1) + L + 1) ^ 2 + cE * (2 * L + 3 * B n + 3) ^ dE) (by fun_prop) (by simp only [B]; fun_prop) (by simp only [B]; fun_prop) - have hmem := setOf_mem_DTIME_of_computableInO h + have hmem := setOf_mem_DTIME_of_computableInO (.of_tidy h) (t := fun n => cT * (n + 1) ^ dT + 2 ^ ((B n + 2) * (B n + 1)) * (((B n + 1) * (B n + B n + 1) + L + 1) ^ 2 + cE * (2 * L + 3 * B n + 3) ^ dE)) fun a => by diff --git a/Complexity/Computability/Complexity/Classes/Ladner.lean b/Complexity/Computability/Complexity/Classes/Ladner.lean index 6b04611e0..dca00c092 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner.lean @@ -93,6 +93,48 @@ open Turing Turing.MultiTapeTM Turing.MultiTapeTM.Universal Cslib.Logic.PL namespace Ladner +/-! Tidy views of the plain certificates of `Ladner.PolyTime`, for tidy `fun_prop` below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_capPow + {α : Type} {input : α ↪ List Bool} + {base exp cap : α → ℕ} (hbase : ComputableTidilyInPolyTime base input encUnary) + (hexp : ComputableTidilyInPolyTime exp input encUnary) + (hcap : ComputableTidilyInPolyTime cap input encUnary) : + ComputableTidilyInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_capPow (.of_tidy hbase) (.of_tidy hexp) + (.of_tidy hcap))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_padCheck + {α : Type} {input : α ↪ List Bool} + {e : α → ℕ → ℕ} {y : α → List Bool} + (he : ComputableTidilyInPolyTime (fun p : α × ℕ => e p.1 p.2) (encPair input encUnary) + encUnary) + (hy : ComputableTidilyInPolyTime y input encBits) : + ComputableTidilyInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_padCheck (.of_tidy he) (.of_tidy hy))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_H : + ComputableTidilyInPolyTime H encUnary encUnary := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_H)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_unpad : + ComputableTidilyInPolyTime unpad encBits (encPair encBits encUnary) := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_unpad)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_decodeCNF : + ComputableTidilyInPolyTime decodeCNF encBits encCNF := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_decodeCNF)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_word : + ComputableTidilyInPolyTime word encUnary encBits := + (ComputableInPolyTime.tidy (Ladner.computableInPolyTime_word)) + /-- If `SAT` is in `P`, then `P = NP` for every encoding of instances. -/ theorem P_eq_NP_of_SAT_mem_P (h : SAT ∈ P encCNF) {α : Type} (enc : α ↪ List Bool) : P enc = NP enc := diff --git a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean index ebf20e519..66a200b13 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean @@ -82,11 +82,17 @@ def decodeCNF (w : List Bool) : CNF ℕ := Complexity.cnfDecoder.decode w theorem decodeCNF_encCNF (φ : CNF ℕ) : decodeCNF (encCNF φ) = φ := Complexity.cnfDecoder.decode_enc φ +private theorem computableTidilyInPolyTime_decodeCNF : + ComputableTidilyInPolyTime decodeCNF encBits encCNF := + let ⟨_, _, h⟩ := Complexity.cnfDecoder.computable + h.computableTidilyInPolyTime + +attribute [local fun_prop] computableTidilyInPolyTime_decodeCNF + @[fun_prop] theorem computableInPolyTime_decodeCNF : ComputableInPolyTime decodeCNF encBits encCNF := - .of_tidy (let ⟨_, _, h⟩ := Complexity.cnfDecoder.computable - h.computableTidilyInPolyTime) + .of_tidy (computableTidilyInPolyTime_decodeCNF) /-! ### Capped powers -/ @@ -126,28 +132,39 @@ private theorem computableTidilyInPolyTime_capPow_pair : omega) simpa only [iterate_min_mul, one_mul, capPow] using h +private theorem computableTidilyInPolyTime_capPow {α : Type} {input : α ↪ List Bool} + {base exp cap : α → ℕ} (hbase : ComputableTidilyInPolyTime base input encUnary) + (hexp : ComputableTidilyInPolyTime exp input encUnary) + (hcap : ComputableTidilyInPolyTime cap input encUnary) : + ComputableTidilyInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := + computableTidilyInPolyTime_capPow_pair.comp (hbase.prod (hexp.prod hcap)) + +attribute [local fun_prop] computableTidilyInPolyTime_capPow + @[fun_prop] theorem computableInPolyTime_capPow {α : Type} {input : α ↪ List Bool} {base exp cap : α → ℕ} (hbase : ComputableInPolyTime base input encUnary) (hexp : ComputableInPolyTime exp input encUnary) (hcap : ComputableInPolyTime cap input encUnary) : - ComputableInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := by - have hbase := hbase.tidy - have hexp := hexp.tidy - have hcap := hcap.tidy - exact .of_tidy (computableTidilyInPolyTime_capPow_pair.comp (hbase.prod (hexp.prod hcap))) + ComputableInPolyTime (fun x => capPow (base x) (exp x) (cap x)) input encUnary := + .of_tidy (computableTidilyInPolyTime_capPow hbase.tidy hexp.tidy hcap.tidy) /-! ### Words by index -/ -/-- The word with a given index is polynomial-time in the index in unary. -/ -@[fun_prop] -theorem computableInPolyTime_word : ComputableInPolyTime word encUnary encBits := by +private theorem computableTidilyInPolyTime_word : ComputableTidilyInPolyTime word encUnary encBits := by have h : word = fun j => (encNat (j + 1)).take ((encNat (j + 1)).length - 1) := by funext j simp [word, encNat_apply, List.dropLast_eq_take] rw [h] fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_word + +/-- The word with a given index is polynomial-time in the index in unary. -/ +@[fun_prop] +theorem computableInPolyTime_word : ComputableInPolyTime word encUnary encBits := + .of_tidy (computableTidilyInPolyTime_word) + /-! ### Reading a padded formula -/ /-- The formula `φ` such that `y` is `encCNF φ` padded with `(encCNF φ).length ^ h` ones, if there @@ -202,15 +219,20 @@ private theorem computableTidilyInPolyTime_idxOf_false_reverse : idxOfWithInput (encA := encBool) (list := fun y : List Bool => y.reverse) (value := fun _ => false) (bitsToList.comp bitsReverse) (const false) -/-- Splitting a padded word is polynomial-time. -/ -@[fun_prop] -theorem computableInPolyTime_unpad : - ComputableInPolyTime unpad encBits (encPair encBits encUnary) := by - refine .of_tidy ?_ +private theorem computableTidilyInPolyTime_unpad : + ComputableTidilyInPolyTime unpad encBits (encPair encBits encUnary) := by have hk := computableTidilyInPolyTime_idxOf_false_reverse unfold unpad fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_unpad + +/-- Splitting a padded word is polynomial-time. -/ +@[fun_prop] +theorem computableInPolyTime_unpad : + ComputableInPolyTime unpad encBits (encPair encBits encUnary) := + .of_tidy (computableTidilyInPolyTime_unpad) + /-- Reading the formula padded with a given exponent is polynomial-time. -/ private theorem computableTidilyInPolyTime_padCheckAt : ComputableTidilyInPolyTime (fun p : List Bool × ℕ => padCheckAt p.1 p.2) @@ -219,6 +241,18 @@ private theorem computableTidilyInPolyTime_padCheckAt : unfold padCheckAt fun_prop +private theorem computableTidilyInPolyTime_padCheck {α : Type} {input : α ↪ List Bool} + {e : α → ℕ → ℕ} {y : α → List Bool} + (he : ComputableTidilyInPolyTime (fun p : α × ℕ => e p.1 p.2) (encPair input encUnary) + encUnary) + (hy : ComputableTidilyInPolyTime y input encBits) : + ComputableTidilyInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := by + have h := computableTidilyInPolyTime_padCheckAt + unfold padCheck + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_padCheck + /-- Reading the formula padded along a computed exponent function is polynomial-time. The exponent function may capture the input. -/ @[fun_prop] @@ -227,13 +261,8 @@ theorem computableInPolyTime_padCheck {α : Type} {input : α ↪ List Bool} (he : ComputableInPolyTime (fun p : α × ℕ => e p.1 p.2) (encPair input encUnary) encUnary) (hy : ComputableInPolyTime y input encBits) : - ComputableInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := by - have he := he.tidy - have hy := hy.tidy - refine .of_tidy ?_ - have h := computableTidilyInPolyTime_padCheckAt - unfold padCheck - fun_prop + ComputableInPolyTime (fun x => padCheck (e x) (y x)) input (encOption encCNF) := + .of_tidy (computableTidilyInPolyTime_padCheck he.tidy hy.tidy) /-! ### Satisfiability of short formulas -/ @@ -255,13 +284,22 @@ theorem bruteSAT_iff {n : ℕ} {φ : CNF ℕ} (h : 2 ^ ((encCNF φ).length + 1) rw [hw] at hi exact List.any_eq_true.mpr ⟨index w, List.mem_range.mpr (by omega), by rwa [word_index]⟩ +private theorem computableTidilyInPolyTime_bruteSAT {α : Type} {input : α ↪ List Bool} + {n : α → ℕ} {φ : α → CNF ℕ} (hn : ComputableTidilyInPolyTime n input encUnary) + (hφ : ComputableTidilyInPolyTime φ input encCNF) : + ComputableTidilyInPolyTime (fun x => bruteSAT (n x) (φ x)) input encBool := by + have hverifier := SAT.computableInPolyTime_verifier.tidy + unfold bruteSAT + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_bruteSAT + @[fun_prop] theorem computableInPolyTime_bruteSAT {α : Type} {input : α ↪ List Bool} {n : α → ℕ} {φ : α → CNF ℕ} (hn : ComputableInPolyTime n input encUnary) (hφ : ComputableInPolyTime φ input encCNF) : - ComputableInPolyTime (fun x => bruteSAT (n x) (φ x)) input encBool := by - unfold bruteSAT - fun_prop + ComputableInPolyTime (fun x => bruteSAT (n x) (φ x)) input encBool := + .of_tidy (computableTidilyInPolyTime_bruteSAT hn.tidy hφ.tidy) /-! ### The step of the exponent function -/ @@ -340,6 +378,17 @@ theorem hstepB_eq (T : List ℕ) : hstepB T = Hstep T := by simp only [Set.mem_ofPred_eq, List.all_eq_true, List.mem_range] exact or_congr_right (forall₂_congr fun j hj => agreesB_iff hj) +private theorem computableTidilyInPolyTime_runIndexed {α : Type} {input : α ↪ List Bool} + {i : α → ℕ} {w : α → List Bool} {t : α → ℕ} + (hi : ComputableTidilyInPolyTime i input encUnary) + (hw : ComputableTidilyInPolyTime w input encBits) + (ht : ComputableTidilyInPolyTime t input encUnary) : + ComputableTidilyInPolyTime (fun x => runIndexed (i x) (w x) (t x)) input eOut := by + unfold runIndexed + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_runIndexed + /-- The run of an indexed machine, with the number of steps in unary, is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_runIndexed {α : Type} {input : α ↪ List Bool} @@ -347,9 +396,8 @@ theorem computableInPolyTime_runIndexed {α : Type} {input : α ↪ List Bool} (hi : ComputableInPolyTime i input encUnary) (hw : ComputableInPolyTime w input encBits) (ht : ComputableInPolyTime t input encUnary) : - ComputableInPolyTime (fun x => runIndexed (i x) (w x) (t x)) input eOut := by - unfold runIndexed - fun_prop + ComputableInPolyTime (fun x => runIndexed (i x) (w x) (t x)) input eOut := + .of_tidy (computableTidilyInPolyTime_runIndexed hi.tidy hw.tidy ht.tidy) private theorem computableTidilyInPolyTime_memB : ComputableTidilyInPolyTime (fun p : List ℕ × List Bool => memB p.1 p.2) @@ -382,10 +430,8 @@ theorem Htable_eq_iterate (n : ℕ) : Htable n = (fun T => T ++ [hstepB T])^[n] | zero => rfl | succ n ih => rw [Htable, Function.iterate_succ_apply', ← ih, hstepB_eq] -/-- The tables of `H` are polynomial-time in their length, in unary. -/ -theorem computableInPolyTime_Htable : - ComputableInPolyTime Htable encUnary (encList encUnary) := by - refine .of_tidy ?_ +private theorem computableTidilyInPolyTime_Htable : + ComputableTidilyInPolyTime Htable encUnary (encList encUnary) := by have hs := computableTidilyInPolyTime_hstepB have h := iterate (encIn := encUnary) (encState := encList encUnary) (count := fun n => n) (init := fun _ => []) (step := fun T => T ++ [hstepB T]) (by fun_prop) (by fun_prop) @@ -401,14 +447,25 @@ theorem computableInPolyTime_Htable : _ ≤ n * (2 * n + 1) := by rw [length_Htable]; exact Nat.mul_le_mul_right _ hi) simpa only [← Htable_eq_iterate] using h -/-- **`H` is polynomial-time** on unary numbers. -/ -@[fun_prop] -theorem computableInPolyTime_H : ComputableInPolyTime H encUnary encUnary := by - refine .of_tidy ?_ - have h := computableTidilyInPolyTime_hstepB.comp computableInPolyTime_Htable.tidy +attribute [local fun_prop] computableTidilyInPolyTime_Htable + +/-- The tables of `H` are polynomial-time in their length, in unary. -/ +theorem computableInPolyTime_Htable : + ComputableInPolyTime Htable encUnary (encList encUnary) := + .of_tidy (computableTidilyInPolyTime_Htable) + +private theorem computableTidilyInPolyTime_H : ComputableTidilyInPolyTime H encUnary encUnary := by + have h := computableTidilyInPolyTime_hstepB.comp computableTidilyInPolyTime_Htable have heq : hstepB ∘ Htable = H := funext fun n => hstepB_eq _ rwa [heq] at h +attribute [local fun_prop] computableTidilyInPolyTime_H + +/-- **`H` is polynomial-time** on unary numbers. -/ +@[fun_prop] +theorem computableInPolyTime_H : ComputableInPolyTime H encUnary encUnary := + .of_tidy (computableTidilyInPolyTime_H) + /-! ### Ladner's language is in NP -/ /-- The verifier of Ladner's language: read the padded formula and evaluate it under the @@ -421,6 +478,7 @@ private theorem computableTidilyInPolyTime_verifier : have hH : ComputableTidilyInPolyTime (fun p : (List Bool × List Bool) × ℕ => H p.2) (encPair (encPair encBits encBits) encUnary) encUnary := computableInPolyTime_H.tidy.comp (snd _ _) + have hverifier := SAT.computableInPolyTime_verifier.tidy unfold verifier fun_prop diff --git a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean index cd727cd41..c8a8a5bfa 100644 --- a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean +++ b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean @@ -600,11 +600,14 @@ def paddedMIP (c d : ℕ) : Set (List Bool) := variable [Finite Control] -/-- `checkCert` is computable tidily in polynomial time. -/ +/-- `checkCert` is computable in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_checkCert (c d : ℕ) : Turing.MultiTapeTM.ComputableInPolyTime (fun q : List Bool × Cert => checkCert M c d q.1 q.2) (encPair encBits encCert) encBool := by + have haccepts := (computableInPolyTime_accepts M).tidy + have hproj := computableInPolyTime_projHistory.tidy + have hconsistent := computableInPolyTime_consistentHist.tidy refine .of_tidy ?_ have ht : ComputableTidilyInPolyTime (fun q : List Bool × Cert => c * (q.1.length + 1) ^ d) diff --git a/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean b/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean index 38cffef4f..fb9d96308 100644 --- a/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean +++ b/Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean @@ -97,7 +97,7 @@ alphabet and finitely many states. -/ theorem decidableInPolyTime_of_mem_NP (h : A ∈ NP enc) : MultiTapeNTM.DecidableInPolyTime A enc := by obtain ⟨p, V, hV, hA⟩ := h - obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := hA.exists_decidesInTime hV.tidy + obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := hA.exists_decidesInTime hV exact ⟨_, .of_forall_le c d fun _ => le_rfl, k, State, hfinite, machine.toNTM, hdecides⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Oracle.lean b/Complexity/Computability/Complexity/Classes/Oracle.lean index c405128b9..94a052078 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle.lean @@ -271,14 +271,14 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Every problem in `P` is in `P` relative to every oracle. -/ theorem P_subset_PWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : P enc ⊆ PWithOracle A enc := fun _ ⟨f, hf, h⟩ => - ⟨f, hf.tidy.computableInPolyTimeWithOracle A, h⟩ + ⟨f, hf.computableInPolyTimeWithOracle A, h⟩ attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Every problem in `NP` is in `NP` relative to every oracle. -/ theorem NP_subset_NPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : NP enc ⊆ NPWithOracle A enc := fun _ ⟨p, V, hV, h⟩ => - ⟨p, V, hV.tidy.computableInPolyTimeWithOracle A, h⟩ + ⟨p, V, hV.computableInPolyTimeWithOracle A, h⟩ end Complexity diff --git a/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean b/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean index cb17b8328..932eb92e6 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/BakerGillSolovay.lean @@ -173,7 +173,7 @@ theorem unaryLengthLanguage_mem_NPWithOracle (B : Set (List Bool)) : ((computableInPolyTimeWithOracle_mem B).preprocess (.of_tidy (ComputableTidilyInPolyTime.snd encBits encBits))).map_with (g := fun (xu : List Bool × List Bool) b => xu.1.all id && b) - BakerGillSolovay.computableTidilyInPolyTime_all_and, fun x => ?_⟩ + (.of_tidy BakerGillSolovay.computableTidilyInPolyTime_all_and), fun x => ?_⟩ · simp only [unaryLengthLanguage, Set.mem_ofPred_eq, Polynomial.eval_X, encBits, Function.Embedding.refl_apply, Bool.and_eq_true, List.all_eq_true, id, decide_eq_true_eq] constructor diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean index b66983fad..0f1fc0b0f 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean @@ -110,7 +110,7 @@ theorem ComputableInPolyTimeWithOracle.exists_computableTidilyInO {A : Set (List subst hg' obtain ⟨program, hcert, hprogram⟩ := hf obtain ⟨k, m, machine, c, d, hrun⟩ := hcert.exists_fin_run_pure_false - obtain ⟨T, S, hS, h⟩ := machine.exists_computableTidilyInO_run (input := enc) hg + obtain ⟨T, S, hS, h⟩ := machine.exists_computableTidilyInO_run (input := enc) hg.tidy (by simpa [encBits] using hSA) c d refine ⟨T, S, hS, h.of_enc_eq fun a => ?_⟩ rw [← hprogram a, ← hrun a (languageOracle A)] diff --git a/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean b/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean index f8a9f4a12..8f83eba80 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean @@ -15,6 +15,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Fo import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.List import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat import Complexity.Foundations.Data.Nat.PolynomialBound.Closure +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # The words of `TQBF` @@ -331,8 +332,8 @@ theorem image_TQBF_mem_PSPACE : encQBF '' TQBF ∈ PSPACE encBits := by obtain ⟨e, he⟩ := exists_computableInO_evaluate obtain ⟨dc, _, hc⟩ := isCode_pt.tidy.exists_degree obtain ⟨dd, _, hd⟩ := decodeQBF_pt.tidy.exists_degree - have h := hc.inO.ite (he.comp hd.inO) (ComputableTidilyInO.const false) - refine mem_PSPACE_of_computableInO (h.mono_le (T' := _) (S' := fun w => + have h := hc.inO.ite (he.tidy.comp hd.inO) (ComputableTidilyInO.const false) + refine mem_PSPACE_of_computableInO (.of_tidy <| h.mono_le (T' := _) (S' := fun w => (w.length + 1) ^ dc + ((w.length + 1) ^ dd + (w.length + (encQBF .bot).length + 1) ^ e + w.length)) (fun _ => le_rfl) fun w => ?_) ?_ fun w => ?_ diff --git a/Complexity/Computability/Complexity/Classes/P/Slices.lean b/Complexity/Computability/Complexity/Classes/P/Slices.lean index 085c7eea4..d3d9be8b7 100644 --- a/Complexity/Computability/Complexity/Classes/P/Slices.lean +++ b/Complexity/Computability/Complexity/Classes/P/Slices.lean @@ -58,24 +58,20 @@ theorem ofSlices_mem_P {f : ∀ n, BitString n → Bool} (hf : ComputableInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool) : (Language.ofSlices f : Set (List Bool)) ∈ P encBits := by - have hf := hf.tidy - exact ⟨_, .of_tidy hf, mem_ofSlices_iff f⟩ + exact ⟨_, hf, mem_ofSlices_iff f⟩ -attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`Language.ofSlices f` is in `P`** if and only if its list evaluator -`fun x => f x.length (BitString.ofList x.length x)` is tidily computable in polynomial time. -/ +`fun x => f x.length (BitString.ofList x.length x)` is computable in polynomial time. -/ theorem ofSlices_mem_P_iff {f : ∀ N, BitString N → Bool} : (Language.ofSlices f : Set (List Bool)) ∈ P encBits ↔ ComputableInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool := by - have this : (Language.ofSlices f : Set (List Bool)) ∈ P encBits ↔ ComputableTidilyInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool := by - constructor - · rintro ⟨g, hg, hiff⟩ - have heq : (fun x : List Bool => f x.length (BitString.ofList x.length x)) = g := by - funext x - exact Bool.eq_iff_iff.mpr ((mem_ofSlices_iff f x).symm.trans (hiff x)) - exact heq ▸ hg.tidy - · exact ofSlices_mem_P - simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this + constructor + · rintro ⟨g, hg, hiff⟩ + have heq : (fun x : List Bool => f x.length (BitString.ofList x.length x)) = g := by + funext x + exact Bool.eq_iff_iff.mpr ((mem_ofSlices_iff f x).symm.trans (hiff x)) + exact heq ▸ hg + · exact ofSlices_mem_P end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean index 9885a6e6b..77de397ac 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean @@ -66,7 +66,7 @@ def PPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : Set (Set α) : /-- An ordinary PP verifier can ignore every oracle. -/ theorem PP_subset_PPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : PP enc ⊆ PPWithOracle A enc := fun _ ⟨p, V, hV, hL⟩ => - ⟨p, V, hV.tidy.computableInPolyTimeWithOracle A, hL⟩ + ⟨p, V, hV.computableInPolyTimeWithOracle A, hL⟩ /-- A polynomial-time oracle adds no PP languages. -/ theorem PPWithOracle_eq_PP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : @@ -95,7 +95,7 @@ theorem mem_PPWithOracle_iff_exists_GapPWithOracle {L : Set α} : let W₂ := andVerifier (fun a => q.eval (enc a).length) V₂ allFalseVerifier have hfalse : ComputableInPolyTimeWithOracle A (allFalseVerifier (α := α)) (encPair enc encBits) encBool := - computableInPolyTime_allFalseVerifier.tidy.computableInPolyTimeWithOracle A + computableInPolyTime_allFalseVerifier.computableInPolyTimeWithOracle A have hW₁ : ComputableInPolyTimeWithOracle A W₁ (encPair enc encBits) encBool := computableInPolyTimeWithOracle_andVerifier (.of_tidy (by fun_prop)) h₁ hfalse have hW₂ : ComputableInPolyTimeWithOracle A W₂ (encPair enc encBits) encBool := diff --git a/Complexity/Computability/Complexity/Classes/Padding.lean b/Complexity/Computability/Complexity/Classes/Padding.lean index 6d250d4af..7fac3a66f 100644 --- a/Complexity/Computability/Complexity/Classes/Padding.lean +++ b/Complexity/Computability/Complexity/Classes/Padding.lean @@ -190,7 +190,8 @@ theorem NTIME_subset_iUnion_DTIME_of_NP_subset_P (hNP : NP encBits ⊆ P encBits by nlinarith rw [Nat.mul_assoc] exact Nat.mul_le_mul_left _ this - refine Set.mem_iUnion.mpr ⟨d + 1, hpre ▸ preimage_mem_DTIME (C := (c' + 2) ^ d + 1) hd hg + refine Set.mem_iUnion.mpr ⟨d + 1, hpre ▸ preimage_mem_DTIME (C := (c' + 2) ^ d + 1) hd + (.of_tidy hg) fun a => ?_⟩ rw [encBits_apply, hlen] set n := (enc a).length diff --git a/Complexity/Computability/Complexity/Classes/ParityP.lean b/Complexity/Computability/Complexity/Classes/ParityP.lean index 7062dd290..2eab204a4 100644 --- a/Complexity/Computability/Complexity/Classes/ParityP.lean +++ b/Complexity/Computability/Complexity/Classes/ParityP.lean @@ -154,9 +154,9 @@ theorem mem_ParityP_iff_exists_SharpP : rw [mem_ParityP] constructor · rintro ⟨p, V, hV, h⟩ - exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, h⟩ + exact ⟨_, ⟨p, V, hV, fun _ => rfl⟩, h⟩ · rintro ⟨f, ⟨p, V, hV, hf⟩, h⟩ - exact ⟨p, V, hV.tidy, fun a => by rw [h a, hf a]⟩ + exact ⟨p, V, hV, fun a => by rw [h a, hf a]⟩ /-- **`⊕P` is closed under complement**: `succVerifier` accepts one more string. -/ theorem compl_mem_ParityP (hL : L ∈ ParityP enc) : Lᶜ ∈ ParityP enc := by @@ -170,7 +170,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`P ⊆ ⊕P`**: a decider accepts the empty string or nothing. -/ theorem P_subset_ParityP : P enc ⊆ ParityP enc := by rintro L ⟨f, hf, h⟩ - refine mem_ParityP.2 ⟨0, fun x => f x.1, hf.tidy.comp (.fst enc encBits), fun a => ?_⟩ + refine mem_ParityP.2 ⟨0, fun x => f x.1, .of_tidy (hf.tidy.comp (.fst enc encBits)), fun a => ?_⟩ rw [h a, Polynomial.eval_zero] cases hfa : f a <;> simp [acceptCount, hfa] diff --git a/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean b/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean index 5c3047309..9155b1839 100644 --- a/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean @@ -355,7 +355,7 @@ theorem PromiseP_subset_PromiseBPP : PromiseP enc ⊆ PromiseBPP enc := theorem PromiseRP_subset_PromiseNP : PromiseRP enc ⊆ PromiseNP enc := by rintro Q ⟨p, V, hV, h⟩ - exact mem_PromiseNP_iff.2 ⟨p, V, hV.tidy, h.exists_certificate⟩ + exact mem_PromiseNP_iff.2 ⟨p, V, hV, h.exists_certificate⟩ /-- A counted verifier's uniform rejection probability is its rejected fraction of all words. -/ private theorem uniformList_rejectCount_toReal (V : α × List Bool → Bool) (a : α) (n : ℕ) : @@ -591,7 +591,7 @@ theorem PolyTimeReducible.mem_PromiseP (h : PolyTimeReducible encA encB X Y) (hY : Y ∈ PromiseP encB) : X ∈ PromiseP encA := by obtain ⟨f, hf, hyes, hno⟩ := polyTimeReducible_iff_tidy.mp h obtain ⟨g, hg, hgyes, hgno⟩ := mem_PromiseP_iff.1 hY - exact mem_PromiseP_iff.2 ⟨g ∘ f, hg.comp hf, fun a ha => hgyes _ (hyes ha), + exact mem_PromiseP_iff.2 ⟨g ∘ f, hg.comp (.of_tidy hf), fun a ha => hgyes _ (hyes ha), fun a ha => hgno _ (hno ha)⟩ /-- A reduction of promise problems restricts to a polynomial-time reduction between the problems diff --git a/Complexity/Computability/Complexity/Classes/RP.lean b/Complexity/Computability/Complexity/Classes/RP.lean index a5e44e3e3..e09afdffe 100644 --- a/Complexity/Computability/Complexity/Classes/RP.lean +++ b/Complexity/Computability/Complexity/Classes/RP.lean @@ -224,7 +224,7 @@ theorem mem_RP_iff_forall_decidesWithOneSidedErrorExponent {A : Set α} : decider reject a member with probability at most `1 / 4`. -/ theorem RP_subset_BPP : RP enc ⊆ BPP enc := fun _ hA => by obtain ⟨p, V, hV, h⟩ := mem_RP_iff_forall_decidesWithOneSidedErrorExponent.1 hA 2 - exact ⟨p, V, .of_tidy hV, h.decidesWithErrorExponent.decidesWithBoundedError fun _ => by simp⟩ + exact ⟨p, V, hV, h.decidesWithErrorExponent.decidesWithBoundedError fun _ => by simp⟩ /-- **`coRP ⊆ BPP`**: `BPP` is closed under complement. -/ theorem coRP_subset_BPP : coRP enc ⊆ BPP enc := fun A hA => by diff --git a/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean b/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean index 53df0b00c..95c5db950 100644 --- a/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean +++ b/Complexity/Computability/Complexity/Classes/RepeatedTrials.lean @@ -106,7 +106,11 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in theorem computableInPolyTime_repeatMajority {V : α × List Bool → Bool} (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (r p : Polynomial ℕ) : ComputableInPolyTime (repeatMajority enc r p V) (encPair enc encBits) encBool := by - have hV := hV.tidy + have hV' := hV.tidy + have hvotes : ComputableTidilyInPolyTime + (fun x => repeatVotes (2 * r.eval (enc x.1).length) (p.eval (enc x.1).length) V x) + (encPair enc encBits) encBits := + (computableInPolyTime_repeatVotes hV (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop))).tidy refine .of_tidy ?_ unfold repeatMajority fun_prop @@ -136,7 +140,11 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in theorem computableInPolyTime_repeatAny {V : α × List Bool → Bool} (hV : ComputableInPolyTime V (encPair enc encBits) encBool) (q p : Polynomial ℕ) : ComputableInPolyTime (repeatAny enc q p V) (encPair enc encBits) encBool := by - have hV := hV.tidy + have hV' := hV.tidy + have hvotes : ComputableTidilyInPolyTime + (fun x => repeatVotes (q.eval (enc x.1).length) (p.eval (enc x.1).length) V x) + (encPair enc encBits) encBits := + (computableInPolyTime_repeatVotes hV (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop))).tidy refine .of_tidy ?_ unfold repeatAny fun_prop diff --git a/Complexity/Computability/Complexity/Classes/SBP.lean b/Complexity/Computability/Complexity/Classes/SBP.lean index 0302c6f29..339fae4c6 100644 --- a/Complexity/Computability/Complexity/Classes/SBP.lean +++ b/Complexity/Computability/Complexity/Classes/SBP.lean @@ -112,7 +112,7 @@ theorem BPP_subset_SBP : BPP enc ⊆ SBP enc := by intro A hA obtain ⟨p, V, hV, hA⟩ := mem_BPP_iff_forall_decidesWithErrorExponent.mp hA 2 have hf : (fun a => acceptCount V a (p.eval (enc a).length)) ∈ SharpP enc := - ⟨p, V, .of_tidy hV, fun _ => rfl⟩ + ⟨p, V, hV, fun _ => rfl⟩ refine ⟨_, SharpP.mul_mem (SharpP.natCast_mem 3) hf, fun a => 2 * 2 ^ p.eval (enc a).length, by fun_prop, fun a => ?_⟩ @@ -157,8 +157,8 @@ theorem PolyTimeReducible.mem_SBP {encB : β ↪ List Bool} {B : Set β} theorem union_mem_SBP (hA : A ∈ SBP enc) (hB : B ∈ SBP enc) : A ∪ B ∈ SBP enc := by obtain ⟨f, hf, k, hk, hkpos, hA⟩ := mem_SBP_iff_exists_pos_threshold.mp hA obtain ⟨g, hg, l, hl, hlpos, hB⟩ := mem_SBP_iff_exists_pos_threshold.mp hB - have hfl := SharpP.mul_mem hf (mem_SharpP_of_polyTime (.of_tidy hl)) - have hgk := SharpP.mul_mem hg (mem_SharpP_of_polyTime (.of_tidy hk)) + have hfl := SharpP.mul_mem hf (mem_SharpP_of_polyTime hl) + have hgk := SharpP.mul_mem hg (mem_SharpP_of_polyTime hk) refine ⟨_, SharpP.add_mem (SharpP.pow_mem hfl 2) (SharpP.pow_mem hgk 2), fun a => (k a * l a) ^ 2, by fun_prop, fun a => ?_⟩ change (a ∈ A ∪ B → (k a * l a) ^ 2 ≤ (f a * l a) ^ 2 + (g a * k a) ^ 2) ∧ @@ -193,7 +193,7 @@ theorem exists_SBP_gap_pow (hA : A ∈ SBP enc) {m : ℕ} (hm : 0 < m) : have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA refine ⟨f ^ m, SharpP.pow_mem hf m, fun a => k a ^ m, - hk.binary_pow' (.const m), fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ + hk.tidy.binary_pow' (.const m), fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ · intro ha exact Nat.pow_le_pow_left ((h a).1 ha) m · intro ha @@ -201,6 +201,7 @@ theorem exists_SBP_gap_pow (hA : A ∈ SBP enc) {m : ℕ} (hm : 0 < m) : Nat.pow_lt_pow_left ((h a).2 ha) (Nat.ne_of_gt hm) simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Intersecting an SBP language with a BPP language preserves SBP. Square the SBP gap, amplify BPP beyond the exponential bound on that count, and multiply counts. This is an elementary consequence of counting closure and @@ -211,7 +212,7 @@ theorem inter_mem_SBP_of_mem_BPP (hA : A ∈ SBP enc) (hB : B ∈ BPP enc) : obtain ⟨p, hp⟩ := SharpP.exists_le_two_pow hf obtain ⟨q, V, hV, hB⟩ := mem_BPP_iff_forall_decidesWithErrorExponent.mp hB (p + 2) let c a := acceptCount V a (q.eval (enc a).length) - have hc : c ∈ SharpP enc := ⟨q, V, .of_tidy hV, fun _ => rfl⟩ + have hc : c ∈ SharpP enc := ⟨q, V, hV, fun _ => rfl⟩ refine ⟨_, SharpP.mul_mem (SharpP.natCast_mem 4) (SharpP.mul_mem hf hc), fun a => 3 * (k a * 2 ^ q.eval (enc a).length), .of_tidy (by fun_prop), fun a => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean index dbf0150e3..38689b410 100644 --- a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean @@ -52,7 +52,7 @@ theorem exists_SBP_gap_pow_polyTime (hA : A ∈ SBP enc) {r : α → ℕ} have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA refine ⟨_, SharpP.pow_mem_polyTime hf (.of_tidy hr), fun a => k a ^ r a, - hk.binary_pow' hr, fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ + hk.tidy.binary_pow' hr, fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ · intro ha exact Nat.pow_le_pow_left ((h a).1 ha) (r a) · intro ha diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean index c3ec3d0de..062e2b43a 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean @@ -76,7 +76,7 @@ def GapPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : Set (α → /-- Ordinary counting verifiers can ignore every oracle. -/ theorem SharpP_subset_SharpPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : SharpP enc ⊆ SharpPWithOracle A enc := fun _ ⟨p, V, hV, hf⟩ => - ⟨p, V, hV.tidy.computableInPolyTimeWithOracle A, hf⟩ + ⟨p, V, hV.computableInPolyTimeWithOracle A, hf⟩ /-- Ordinary gap functions can ignore every oracle. -/ theorem GapP_subset_GapPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean index 05466485d..a50656e3f 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean @@ -39,9 +39,9 @@ its accepting coins with the same counter (`Cslib.Complexity.Interaction.countAc * `Cslib.Complexity.streamAcceptCount_eq_acceptCount`: the streaming count is `acceptCount`. * `Cslib.Complexity.computableInPolySpace_acceptCount`: count accepted certificates of a polynomial-time unary length, with binary output. -* `Cslib.Complexity.SharpP.computableTidilyInPolySpace`: every #P function is computable within +* `Cslib.Complexity.SharpP.computableInPolySpace`: every #P function is computable within polynomial space, with binary output. -* `Cslib.Complexity.GapP.computableTidilyInPolySpace`: evaluate integer gaps in binary. +* `Cslib.Complexity.GapP.computableInPolySpace`: evaluate integer gaps in binary. ## References @@ -174,18 +174,20 @@ theorem computableInPolySpace_acceptCount {V : α × List Bool → Bool} {r : α lia /-- Every #P function is computable in polynomial space when its output is written in binary. -/ -theorem SharpP.computableTidilyInPolySpace {f : α → ℕ} (hf : f ∈ SharpP enc) : - ComputableTidilyInPolySpace f enc encNat := by +theorem SharpP.computableInPolySpace {f : α → ℕ} (hf : f ∈ SharpP enc) : + Turing.MultiTapeTM.ComputableInPolySpace f enc encNat := by + refine .of_tidy ?_ obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf exact (computableInPolySpace_acceptCount (.of_tidy hV) (.of_tidy (by fun_prop))).tidy.congr fun a => (hf a).symm /-- Every GapP function is computable in polynomial space with binary sign-magnitude output. -/ -theorem GapP.computableTidilyInPolySpace {g : α → ℤ} (hg : g ∈ GapP enc) : - ComputableTidilyInPolySpace g enc encIntBin := by +theorem GapP.computableInPolySpace {g : α → ℤ} (hg : g ∈ GapP enc) : + Turing.MultiTapeTM.ComputableInPolySpace g enc encIntBin := by + refine .of_tidy ?_ obtain ⟨f₁, h₁, f₂, h₂, hg⟩ := hg have hcast := ComputableTidilyInPolySpace.of_polyTime ComputableTidilyInPolyTime.intBin_natCast exact ((ComputableTidilyInPolySpace.of_polyTime ComputableTidilyInPolyTime.intBin_sub).comp - ((hcast.comp (SharpP.computableTidilyInPolySpace h₁)).prod - (hcast.comp (SharpP.computableTidilyInPolySpace h₂)))).congr fun a => (hg a).symm + ((hcast.comp (SharpP.computableInPolySpace h₁).tidy).prod + (hcast.comp (SharpP.computableInPolySpace h₂).tidy))).congr fun a => (hg a).symm end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Space/Closure.lean b/Complexity/Computability/Complexity/Classes/Space/Closure.lean index 8a9ec3296..e547a0e3f 100644 --- a/Complexity/Computability/Complexity/Classes/Space/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Space/Closure.lean @@ -64,9 +64,11 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} function deciding it is tidily computable within some time and within space polynomial in the length of the encoded instance. -/ theorem mem_PSPACE_iff_computableInO : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), - Turing.MultiTapeTM.ComputableInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ + ComputableInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ ∀ a, a ∈ A ↔ f a = true := by - have this : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), ComputableTidilyInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ ∀ a, a ∈ A ↔ f a = true := by + have this : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), + ComputableTidilyInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ + ∀ a, a ∈ A ↔ f a = true := by constructor · rintro ⟨f, ⟨t, s, hs, hf⟩, hA⟩ obtain ⟨c, hc⟩ := ComputableInTimeAndSpace.exists_computableTidilyInTimeAndSpace hf @@ -85,9 +87,10 @@ attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in deciding it is tidily computable within space polynomial in the length of the encoded instance (`Turing.MultiTapeTM.ComputableTidilyInPolySpace`). -/ theorem mem_PSPACE_iff_computableInPolySpace : A ∈ PSPACE enc ↔ - ∃ f : α → Bool, Turing.MultiTapeTM.ComputableInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by - have this : A ∈ PSPACE enc ↔ ∃ f : α → Bool, ComputableTidilyInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by - rw [mem_PSPACE_iff_computableInO] + ∃ f : α → Bool, ComputableInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by + have this : A ∈ PSPACE enc ↔ + ∃ f : α → Bool, ComputableTidilyInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by + simp only [mem_PSPACE_iff_computableInO, computableInO_iff_computableTidilyInO] constructor · rintro ⟨f, T, S, hf, hS, hA⟩ exact ⟨f, ⟨T, S, hS, hf⟩, hA⟩ @@ -97,7 +100,7 @@ theorem mem_PSPACE_iff_computableInPolySpace : A ∈ PSPACE enc ↔ /-- A Boolean function computable within polynomial space decides a problem in `PSPACE`. -/ theorem mem_PSPACE_of_computableInPolySpace {f : α → Bool} - (hf : Turing.MultiTapeTM.ComputableInPolySpace f enc encBool) (hA : ∀ a, a ∈ A ↔ f a = true) : + (hf : ComputableInPolySpace f enc encBool) (hA : ∀ a, a ∈ A ↔ f a = true) : A ∈ PSPACE enc := mem_PSPACE_iff_computableInPolySpace.mpr ⟨f, hf, hA⟩ @@ -107,8 +110,8 @@ attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolyTime.tidy in theorem compl_mem_PSPACE (hA : A ∈ PSPACE enc) : Aᶜ ∈ PSPACE enc := by obtain ⟨f, T, S, hf, hS, hA⟩ := mem_PSPACE_iff_computableInO.mp hA have hnot := (ComputableTidilyInDegree.of_finite (encIn := encBool) (encMid := encBool) - Bool.not).inO_one.comp_linear hf - refine mem_PSPACE_iff_computableInO.mpr ⟨_, T, S, hnot, hS, fun a => ?_⟩ + Bool.not).inO_one.comp_linear hf.tidy + refine mem_PSPACE_iff_computableInO.mpr ⟨_, T, S, .of_tidy hnot, hS, fun a => ?_⟩ simp [hA a] open scoped symmDiff @@ -121,8 +124,8 @@ theorem inter_mem_PSPACE {B : Set α} (hA : A ∈ PSPACE enc) (hB : B ∈ PSPACE obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp hA obtain ⟨g, hg, hB⟩ := mem_PSPACE_iff_computableInPolySpace.mp hB exact mem_PSPACE_of_computableInPolySpace - ((ComputableTidilyInPolySpace.of_polyTime ComputableTidilyInPolyTime.bool_and).comp - (hf.prod hg)) + (.of_tidy ((ComputableTidilyInPolySpace.of_polyTime ComputableTidilyInPolyTime.bool_and).comp + (hf.tidy.prod hg.tidy))) fun a => by simp [hA a, hB a] /-- `PSPACE` as a Boolean subalgebra of `Set α`. -/ @@ -161,7 +164,7 @@ theorem PolyTimeReducible.mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : obtain ⟨g, hg, hAB⟩ := h obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableInO.mp hB obtain ⟨Tg, Sg, hSg, hgO⟩ := ComputableTidilyInPolySpace.of_polyTime hg.tidy - exact mem_PSPACE_iff_computableInO.mpr ⟨f ∘ g, _, _, hf.comp hgO, + exact mem_PSPACE_iff_computableInO.mpr ⟨f ∘ g, _, _, .of_tidy (hf.tidy.comp hgO), hSg.add (hS.comp hg.polyBounded_length), fun a => (hAB a).trans (hB (g a))⟩ /-- The edges of the graph on words of width `n + 1` whose reachability within two steps from the @@ -206,7 +209,7 @@ decides at depth `1`, reusing the space of the decider of `B` for every candidat (`Cslib.Reachability.computableTidilyInO_savitch`). -/ theorem setOf_exists_mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set (β × List Bool)} {ℓ : β → ℕ} (hB : B ∈ PSPACE (encPair encB encBits)) - (hℓ : Turing.MultiTapeTM.ComputableInPolyTime ℓ encB encUnary) : + (hℓ : ComputableInPolyTime ℓ encB encUnary) : {x | ∃ w : List Bool, w.length = ℓ x ∧ (x, w) ∈ B} ∈ PSPACE encB := by have hℓ := hℓ.tidy obtain ⟨f, T, S, hf, hS, hB⟩ := mem_PSPACE_iff_computableInO.mp hB @@ -239,7 +242,7 @@ theorem setOf_exists_mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set ( obtain ⟨Tg, Sg, hSg, hgO⟩ := ComputableTidilyInPolySpace.of_polyTime hg obtain ⟨Tc, Sc, hSc, hcO⟩ := ComputableTidilyInPolySpace.of_polyTime hc obtain ⟨Te, Se, hSe, heO⟩ := ComputableTidilyInPolySpace.of_polyTime he - have hedge := hcO.ite (hf.comp hgO) heO + have hedge := hcO.ite (hf.tidy.comp hgO) heO -- the arguments of Savitch's algorithm have hin : ComputableTidilyInPolyTime (fun x => (x, ℓ x + 1, 1, List.replicate (ℓ x + 1) false, List.replicate (ℓ x + 1) true)) @@ -268,7 +271,7 @@ theorem setOf_exists_mem_PSPACE {β : Type} {encB : β ↪ List Bool} {B : Set ( fun x => cE * (2 * (encB x).length + 3 * ℓ x + 6) ^ dE := PolyBounded.comp (size' := id) (v := fun n => cE * n ^ dE) (PolyBounded.of_polynomiallyBounded (bound := fun n => cE * n ^ dE) id (by fun_prop)) hG - refine mem_PSPACE_iff_computableInO.mpr ⟨_, _, _, h, ?_, fun x => ?_⟩ + refine mem_PSPACE_iff_computableInO.mpr ⟨_, _, _, .of_tidy h, ?_, fun x => ?_⟩ · refine (((hSi.add ((PolyBounded.const 2).mul (hℓ'.add (.const 3)))).add .self).add hpow).mono fun x => ?_ have hmax : Cslib.Reachability.edgeMax (fun q : β × List Bool × List Bool => diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean index 9f8f565f2..11bf3f252 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean @@ -607,6 +607,6 @@ open GeneralizedGeography Turing.MultiTapeTM /-- **Generalized Geography is in `PSPACE`** [Sipser, Theorem 8.14][Sipser2013]: it is a game of polynomially many moves whose winning condition is polynomial-time. -/ theorem GeneralizedGeography_mem_PSPACE : GeneralizedGeography ∈ PSPACE (encPair encGraph encNat) := - isGameVerifier_verifier.mem_PSPACE computableInPolyTime_verifier.tidy + isGameVerifier_verifier.mem_PSPACE computableInPolyTime_verifier end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean index b6ea4cb6e..9217b885c 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean @@ -607,19 +607,87 @@ theorem computableInPolyTime_literalArcs {xs : γ → List ℕ} {i : γ → ℕ} simp only [List.decide_mem_eq_any] fun_prop +@[local fun_prop] +private theorem computableTidilyInPolyTime_topNode + {j : γ → ℕ} + (hj : ComputableTidilyInPolyTime j encIn encUnary) : + ComputableTidilyInPolyTime (fun x => topNode (j x)) encIn encNat := + (ComputableInPolyTime.tidy (computableInPolyTime_topNode (.of_tidy hj))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_valueNode + {j : γ → ℕ} {b : γ → Bool} + (hj : ComputableTidilyInPolyTime j encIn encUnary) + (hb : ComputableTidilyInPolyTime b encIn encBool) : + ComputableTidilyInPolyTime (fun x => valueNode (j x) (b x)) encIn encNat := + (ComputableInPolyTime.tidy (computableInPolyTime_valueNode (.of_tidy hj) (.of_tidy hb))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_bottomNode + {j : γ → ℕ} + (hj : ComputableTidilyInPolyTime j encIn encUnary) : + ComputableTidilyInPolyTime (fun x => bottomNode (j x)) encIn encNat := + (ComputableInPolyTime.tidy (computableInPolyTime_bottomNode (.of_tidy hj))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_clauseNode + {i : γ → ℕ} + (hi : ComputableTidilyInPolyTime i encIn encUnary) : + ComputableTidilyInPolyTime (fun x => clauseNode (i x)) encIn encNat := + (ComputableInPolyTime.tidy (computableInPolyTime_clauseNode (.of_tidy hi))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_diamondArcs + {j : γ → ℕ} + (hj : ComputableTidilyInPolyTime j encIn encUnary) : + ComputableTidilyInPolyTime (fun x => diamondArcs (j x)) encIn + (encList (encPair encNat encNat)) := + (ComputableInPolyTime.tidy (computableInPolyTime_diamondArcs (.of_tidy hj))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_lastIdx + {xs : γ → List ℕ} {v : γ → ℕ} + (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) + (hv : ComputableTidilyInPolyTime v encIn encNat) : + ComputableTidilyInPolyTime (fun x => lastIdx (xs x) (v x)) encIn encUnary := + (ComputableInPolyTime.tidy (computableInPolyTime_lastIdx (.of_tidy hxs) (.of_tidy hv))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_literalArcs + {xs : γ → List ℕ} {i : γ → ℕ} + {c : γ → Clause ℕ} (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) + (hi : ComputableTidilyInPolyTime i encIn encUnary) + (hc : ComputableTidilyInPolyTime c encIn (encList (encPair encNat encBool))) : + ComputableTidilyInPolyTime (fun x => literalArcs (xs x) (i x) (c x)) encIn + (encList (encPair encNat encNat)) := + (ComputableInPolyTime.tidy (computableInPolyTime_literalArcs (.of_tidy hxs) (.of_tidy hi) + (.of_tidy hc))) + /-- The graph of a formula is polynomial-time in its quantified variables and its clauses. -/ @[fun_prop] theorem computableInPolyTime_formulaGraph {xs : γ → List ℕ} {ψ : γ → CNF ℕ} (hxs : ComputableInPolyTime xs encIn (encList encNat)) (hψ : ComputableInPolyTime ψ encIn encCNF) : ComputableInPolyTime (fun x => formulaGraph (xs x) (ψ x)) encIn encGraph := by + have hxs := hxs.tidy + have hψ := hψ.tidy + refine .of_tidy ?_ unfold formulaGraph formulaArcs encGraph unfold encCNF at hψ fun_prop +@[local fun_prop] +private theorem computableTidilyInPolyTime_formulaGraph + {xs : γ → List ℕ} {ψ : γ → CNF ℕ} + (hxs : ComputableTidilyInPolyTime xs encIn (encList encNat)) + (hψ : ComputableTidilyInPolyTime ψ encIn encCNF) : + ComputableTidilyInPolyTime (fun x => formulaGraph (xs x) (ψ x)) encIn encGraph := + (ComputableInPolyTime.tidy (computableInPolyTime_formulaGraph (.of_tidy hxs) (.of_tidy hψ))) + /-- **The reduction is polynomial-time.** -/ theorem computableInPolyTime_reduce : ComputableInPolyTime reduce encPrenexCNF (encPair encGraph encNat) := by + refine .of_tidy ?_ unfold reduce QBF.roundVars encPrenexCNF simp only [List.decide_mem_eq_any] unfold encCNF diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF.lean index b8ff5cc61..a0249f76e 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF.lean @@ -72,7 +72,7 @@ theorem TQBF_pspaceHard : PSPACEHard encQBF TQBF := by obtain ⟨k, State, hfinite, ntm, s, hs, hA⟩ := PSPACE_subset_NPSPACE hA obtain ⟨c, d, hcd⟩ := hs.exists_le obtain ⟨tV, sV, htV, -, kV, StateV, hfiniteV, tmV, htmV⟩ := - TQBF.computableInPolyTime_edgeTest.tidy (enc := enc) (ntm := ntm) (c := c) (d := d) + (TQBF.computableInPolyTime_edgeTest (enc := enc) (ntm := ntm) (c := c) (d := d)).tidy obtain ⟨cV, dV, htV⟩ := htV.exists_le have := Fintype.ofFinite StateV classical diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean index 4ae6f77bc..d6113fb36 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean @@ -413,7 +413,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in space polynomial in the length of the encoded formula. -/ theorem TQBF_mem_PSPACE : TQBF ∈ PSPACE encQBF := by obtain ⟨e, c, h, -⟩ := TQBF.exists_computableInO_evaluate - refine ⟨TQBF.evaluate, ⟨_, _, ?_, h.computableInTimeAndSpace⟩, + refine ⟨TQBF.evaluate, ⟨_, _, ?_, h⟩, fun φ => TQBF.evaluate_eq_true_iff.symm⟩ refine PolyBounded.of_forall_le (2 * c) e fun φ => ?_ have := Nat.one_le_pow e ((encQBF φ).length + 1) (by omega) diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean index b56f25bc6..dbcd7f32a 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean @@ -254,6 +254,11 @@ theorem computableInPolyTime_prenexReduce {kV : ℕ} {StateV : Type} [Fintype St (encList (encList (encPair CookLevin.encVar encBool))) (encList (encList (encPair encNat encBool))) := (CNF.computableInPolyTime_relabel computableInPolyTime_tabVar).tidy + have htabVar := (computableInPolyTime_tabVar (k := kV) (State := StateV)).tidy + have hcertVar := (CookLevin.computableInPolyTime_cert (k := kV) (State := StateV)).tidy + have hcert : ComputableTidilyInPolyTime (fun q : ℕ × ℕ => certVar q.1 q.2) + (encPair encUnary encUnary) encNat := + (computableInPolyTime_certVar (.of_tidy (.fst _ _)) (.of_tidy (.snd _ _))).tidy unfold prenexReduce gameTableau prenexPairs prenexMatrix gamePairs baseVars certLinkCNF encPrenexCNF encCNF fun_prop @@ -265,7 +270,7 @@ end TQBF /-- `TQBFCNF` is in `PSPACE`: writing the formula is polynomial-time. -/ theorem TQBFCNF_mem_PSPACE : TQBFCNF ∈ PSPACE encPrenexCNF := PolyTimeReducible.mem_PSPACE - ⟨fun x => QBF.rounds x.1 (QBF.ofCNF x.2), .of_tidy (by unfold encPrenexCNF encCNF; fun_prop), + ⟨fun x => QBF.rounds x.1 (QBF.ofCNF x.2), by unfold encPrenexCNF encCNF; fun_prop, fun _ => Iff.rfl⟩ TQBF_mem_PSPACE @@ -275,7 +280,7 @@ normal form. -/ theorem TQBFCNF_pspaceHard : PSPACEHard encPrenexCNF TQBFCNF := by intro α enc A hA obtain ⟨p, V, hV, h⟩ := exists_isGameVerifier_of_mem_PSPACE hA - obtain ⟨tV, sV, htV, -, kV, StateV, hfiniteV, tmV, htmV⟩ := hV + obtain ⟨tV, sV, htV, -, kV, StateV, hfiniteV, tmV, htmV⟩ := hV.tidy obtain ⟨cV, dV, htV⟩ := htV.exists_le have := Fintype.ofFinite StateV classical diff --git a/Complexity/Computability/Complexity/Classes/TFNP.lean b/Complexity/Computability/Complexity/Classes/TFNP.lean index 558b4a6c0..54ea5a325 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP.lean @@ -260,7 +260,8 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **Domains of `FNP` relations are in `NP`**: a solution, framed and padded, is a certificate. -/ theorem searchDomain_mem_NP (hR : R ∈ FNP enc) : searchDomain R ∈ NP enc := by obtain ⟨⟨p, hp⟩, V, hV, hR⟩ := mem_FNP_iff_tidy.mp hR - exact mem_NP_of_witness (encW := encBits) ⟨fun w => w, fun _ => rfl, id'.exists_degree⟩ hV + exact mem_NP_of_witness (encW := encBits) ⟨fun w => w, fun _ => rfl, id'.exists_degree⟩ + (.of_tidy hV) (fun a w => (hR a w).symm) fun a w h => ⟨w, h, hp a w h⟩ /-- The search problem of a verifier: the certificates of the prescribed length that it accepts. -/ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean index 0322f93e5..e63dae212 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean @@ -260,7 +260,7 @@ def searchRel (φ : Logic.PL.CNF ℕ) (w : List Bool) : Prop := /-- The search problem of `SAT` is in `FNP`. -/ theorem searchRel_mem_FNP : searchRel ∈ FNP encCNF := - mem_FNP_iff_exists_bounded.2 ⟨Polynomial.X, verifier, computableInPolyTime_verifier.tidy, + mem_FNP_iff_exists_bounded.2 ⟨Polynomial.X, verifier, computableInPolyTime_verifier, fun _ _ => by simp [searchRel]⟩ /-- The formulas with a solution in `SAT.searchRel` are the satisfiable ones. -/ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean index 9a00daa31..826278b9e 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean @@ -122,12 +122,18 @@ private theorem computableTidilyInPolyTime_zeroVertex : (bitsCons (const false) (fst encBits encBool)) (growth := 1) (fun _ _ => by simp) simpa only [heq] using h +private theorem computableTidilyInPolyTime_zeroVertex_comp {encIn : α ↪ List Bool} {n : α → ℕ} + (hn : ComputableTidilyInPolyTime n encIn encUnary) : + ComputableTidilyInPolyTime (fun a => zeroVertex (n a)) encIn encBits := + computableTidilyInPolyTime_zeroVertex.comp hn + +attribute [local fun_prop] computableTidilyInPolyTime_zeroVertex_comp + @[fun_prop] theorem computableInPolyTime_zeroVertex_comp {encIn : α ↪ List Bool} {n : α → ℕ} (hn : ComputableInPolyTime n encIn encUnary) : - ComputableInPolyTime (fun a => zeroVertex (n a)) encIn encBits := by - have hn := hn.tidy - exact .of_tidy (computableTidilyInPolyTime_zeroVertex.comp hn) + ComputableInPolyTime (fun a => zeroVertex (n a)) encIn encBits := + .of_tidy (computableTidilyInPolyTime_zeroVertex_comp hn.tidy) /-- One step of converting a most-significant-first bit string to `Nat.bits` (`encNat`): strip leading `false` bits and prepend significant bits. -/ @@ -186,6 +192,7 @@ theorem computableInPolyTime_binaryValue_le : ((computableTidilyInPolyTime_binaryValue.comp (fst encBits encBits)).prod (computableTidilyInPolyTime_binaryValue.comp (snd encBits encBits)))) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Comparing two binary natural numbers (`encNat`) is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_nat_le : @@ -202,26 +209,62 @@ theorem computableInPolyTime_nat_le' {encIn : α ↪ List Bool} {left right : α /-! ### `FNP` and `TFNP` membership of the family relations -/ +private theorem computableTidilyInPolyTime_hasOut {enc : α ↪ List Bool} {n : α → ℕ} + {P S : α × List Bool → List Bool} (hn : ComputableTidilyInPolyTime n enc encUnary) + (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) : + ComputableTidilyInPolyTime (fun x : α × List Bool => hasOut n P S x.1 x.2) + (encPair enc encBits) encBool := by + unfold hasOut + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_hasOut + @[fun_prop] theorem computableInPolyTime_hasOut {enc : α ↪ List Bool} {n : α → ℕ} {P S : α × List Bool → List Bool} (hn : ComputableInPolyTime n enc encUnary) (hP : ComputableInPolyTime P (encPair enc encBits) encBits) (hS : ComputableInPolyTime S (encPair enc encBits) encBits) : ComputableInPolyTime (fun x : α × List Bool => hasOut n P S x.1 x.2) + (encPair enc encBits) encBool := + .of_tidy (computableTidilyInPolyTime_hasOut hn.tidy hP.tidy hS.tidy) + +private theorem computableTidilyInPolyTime_hasIn {enc : α ↪ List Bool} {n : α → ℕ} + {P S : α × List Bool → List Bool} (hn : ComputableTidilyInPolyTime n enc encUnary) + (hP : ComputableTidilyInPolyTime P (encPair enc encBits) encBits) + (hS : ComputableTidilyInPolyTime S (encPair enc encBits) encBits) : + ComputableTidilyInPolyTime (fun x : α × List Bool => hasIn n P S x.1 x.2) (encPair enc encBits) encBool := by - unfold hasOut + unfold hasIn fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_hasIn + +attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] theorem computableInPolyTime_hasIn {enc : α ↪ List Bool} {n : α → ℕ} {P S : α × List Bool → List Bool} (hn : ComputableInPolyTime n enc encUnary) (hP : ComputableInPolyTime P (encPair enc encBits) encBits) (hS : ComputableInPolyTime S (encPair enc encBits) encBits) : ComputableInPolyTime (fun x : α × List Bool => hasIn n P S x.1 x.2) + (encPair enc encBits) encBool := + .of_tidy (computableTidilyInPolyTime_hasIn hn.tidy hP.tidy hS.tidy) + +private theorem computableTidilyInPolyTime_undirectedEdge {enc : α ↪ List Bool} + {N₁ N₂ : α × List Bool → List Bool} + (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) + {u v : α × List Bool → List Bool} + (hu : ComputableTidilyInPolyTime u (encPair enc encBits) encBits) + (hv : ComputableTidilyInPolyTime v (encPair enc encBits) encBits) : + ComputableTidilyInPolyTime (fun x : α × List Bool => undirectedEdge N₁ N₂ x.1 (u x) (v x)) (encPair enc encBits) encBool := by - unfold hasIn + unfold undirectedEdge fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_undirectedEdge + +attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] theorem computableInPolyTime_undirectedEdge {enc : α ↪ List Bool} {N₁ N₂ : α × List Bool → List Bool} @@ -231,9 +274,8 @@ theorem computableInPolyTime_undirectedEdge {enc : α ↪ List Bool} (hu : ComputableInPolyTime u (encPair enc encBits) encBits) (hv : ComputableInPolyTime v (encPair enc encBits) encBits) : ComputableInPolyTime (fun x : α × List Bool => undirectedEdge N₁ N₂ x.1 (u x) (v x)) - (encPair enc encBits) encBool := by - unfold undirectedEdge - fun_prop + (encPair enc encBits) encBool := + .of_tidy (computableTidilyInPolyTime_undirectedEdge hN₁.tidy hN₂.tidy hu.tidy hv.tidy) @[fun_prop] private theorem computableTidilyInPolyTime_bool_bne {encIn : α ↪ List Bool} {f g : α → Bool} @@ -242,15 +284,26 @@ private theorem computableTidilyInPolyTime_bool_bne {encIn : α ↪ List Bool} { ComputableTidilyInPolyTime (fun a => f a != g a) encIn encBool := (of_finite (fun p : Bool × Bool => p.1 != p.2)).comp (hf.prod hg) +private theorem computableTidilyInPolyTime_hasOddDegree {enc : α ↪ List Bool} + {N₁ N₂ : α × List Bool → List Bool} + (hN₁ : ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits) + (hN₂ : ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits) : + ComputableTidilyInPolyTime (fun x : α × List Bool => hasOddDegree N₁ N₂ x.1 x.2) + (encPair enc encBits) encBool := by + unfold hasOddDegree + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_hasOddDegree + +attribute [local fun_prop] ComputableInPolyTime.tidy in @[fun_prop] theorem computableInPolyTime_hasOddDegree {enc : α ↪ List Bool} {N₁ N₂ : α × List Bool → List Bool} (hN₁ : ComputableInPolyTime N₁ (encPair enc encBits) encBits) (hN₂ : ComputableInPolyTime N₂ (encPair enc encBits) encBits) : ComputableInPolyTime (fun x : α × List Bool => hasOddDegree N₁ N₂ x.1 x.2) - (encPair enc encBits) encBool := by - unfold hasOddDegree - fun_prop + (encPair enc encBits) encBool := + .of_tidy (computableTidilyInPolyTime_hasOddDegree hN₁.tidy hN₂.tidy) /-- A polynomial-time local-search family defines an `FNP` relation. -/ theorem localOptRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} @@ -278,6 +331,7 @@ theorem localOptRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} localOptRel n N C ∈ TFNP enc := ⟨localOptRel_mem_FNP hn hN hC, isTotalSearch_localOptRel hlen⟩ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A polynomial-time pigeonhole family defines an `FNP` relation. -/ theorem pigeonRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × List Bool → List Bool} (hn : ComputableInPolyTime n enc encUnary) @@ -309,6 +363,7 @@ theorem pigeonRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × pigeonRel n F ∈ TFNP enc := ⟨pigeonRel_mem_FNP hn hF, isTotalSearch_pigeonRel hlen⟩ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A polynomial-time directed end-of-line family defines an `FNP` relation. -/ theorem endOfLineRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {P S : α × List Bool → List Bool} @@ -337,6 +392,7 @@ theorem endOfLineRel_mem_TFNP {enc : α ↪ List Bool} {n : α → ℕ} endOfLineRel n P S ∈ TFNP enc := ⟨endOfLineRel_mem_FNP hn hP hS, isTotalSearch_endOfLineRel hS_len⟩ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A polynomial-time undirected parity family defines an `FNP` relation. -/ theorem leafRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} @@ -556,7 +612,7 @@ theorem SearchReducible.mem_PLS (h : SearchReducible enc encB R T) (hR : R ∈ F hC.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), fun a u hu => hlen (f a) u hu, .of_isTotalSearch (isTotalSearch_localOptRel fun a u hu => hlen (f a) u hu) - id' hg fun a w hw => hsol a w hw⟩ + (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ /-- `PPP` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPP (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) @@ -567,7 +623,7 @@ theorem SearchReducible.mem_PPP (h : SearchReducible enc encB R T) (hR : R ∈ F hn.comp hf, hF.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), fun a u hu => hlen (f a) u hu, .of_isTotalSearch (isTotalSearch_pigeonRel fun a u hu => hlen (f a) u hu) - id' hg fun a w hw => hsol a w hw⟩ + (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ /-- `PPAD` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPAD (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) @@ -579,7 +635,7 @@ theorem SearchReducible.mem_PPAD (h : SearchReducible enc encB R T) (hR : R ∈ hS.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), fun a u hu => hP_len (f a) u hu, fun a u hu => hS_len (f a) u hu, .of_isTotalSearch (isTotalSearch_endOfLineRel fun a u hu => hS_len (f a) u hu) - id' hg fun a w hw => hsol a w hw⟩ + (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ /-- `PPA` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPA (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) @@ -592,7 +648,7 @@ theorem SearchReducible.mem_PPA (h : SearchReducible enc encB R T) (hR : R ∈ F fun a u hu => hN₁_len (f a) u hu, fun a u hu => hN₂_len (f a) u hu, .of_isTotalSearch (isTotalSearch_leafRel (fun a u hu => hN₁_len (f a) u hu) (fun a u hu => hN₂_len (f a) u hu)) - id' hg fun a w hw => hsol a w hw⟩ + (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ /-! ### Inclusions in `TFNP` and between subclasses -/ @@ -624,10 +680,11 @@ private theorem endOfLineRel_searchReducible_pigeonRel {n : α → ℕ} {P S : (hS_len : ∀ a u, u.length = n a → (S (a, u)).length = n a) : SearchReducible enc enc (endOfLineRel n P S) (pigeonRel n (ppadToPppMap n P S)) := by refine .of_isTotalSearch (isTotalSearch_pigeonRel fun a u hu => length_ppadToPppMap (hS_len a) hu) - id' (g := fun p => if !hasOut n P S p.1 (p.2.take (n p.1)) then p.2.take (n p.1) + (.of_tidy id') (g := fun p => if !hasOut n P S p.1 (p.2.take (n p.1)) then p.2.take (n p.1) else p.2.drop (n p.1)) ?_ fun a w hw => endOfLineRel_of_pigeonRel hw fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`PPAD ⊆ PPP`** [Papadimitriou][Papadimitriou1994PPAD], [Beame et al.][BeameEtAl1998]: every problem in `PPAD` is in `PPP`. -/ theorem PPAD_subset_PPP : PPAD enc ⊆ PPP enc := by @@ -651,9 +708,10 @@ private theorem endOfLineRel_searchReducible_leafRel {n : α → ℕ} {P S : α (isTotalSearch_leafRel (fun a _ hw => length_ppadToPpaN₁ (hP_len a) (hS_len a) hw) (fun _ _ hw => length_ppadToPpaN₂ hw)) - id' (g := fun p => p.2.tail) (bitsTail.comp (snd enc encBits)) + (.of_tidy id') (g := fun p => p.2.tail) (.of_tidy (bitsTail.comp (snd enc encBits))) fun _ _ hw => endOfLineRel_tail_of_leafRel hw +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`PPAD ⊆ PPA`** [Papadimitriou][Papadimitriou1994PPAD]: every problem in `PPAD` is in `PPA`. -/ theorem PPAD_subset_PPA : PPAD enc ⊆ PPA enc := by intro R hR' @@ -823,11 +881,13 @@ theorem Pigeon_mem_PPP : Pigeon ∈ PPP encPigeon := pigeonRel_mem_PPP (by fun_prop) (by fun_prop) fun _ _ _ => length_evalCircuitCode _ _ _ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `EndOfLine` is in `PPAD`. -/ theorem EndOfLine_mem_PPAD : EndOfLine ∈ PPAD encEndOfLine := endOfLineRel_mem_PPAD (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (fun _ _ _ => length_evalCircuitCode _ _ _) (fun _ _ _ => length_evalCircuitCode _ _ _) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- `Leaf` is in `PPA`. -/ theorem Leaf_mem_PPA : Leaf ∈ PPA encLeaf := leafRel_mem_PPA (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean index c5532ec61..09cf1e121 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean @@ -77,8 +77,9 @@ private theorem exists_endomorphismCodes {n : α → ℕ} {F : α × List Bool (hlen : ∀ a u, u.length = n a → (F (a, u)).length = n a) : ∃ code : α → CircuitCode, ComputableTidilyInPolyTime code enc encCode ∧ ∀ a u, u.length = n a → evalCircuitCode (n a) (code a) u = F (a, u) := by - obtain ⟨code, hcode, hsem⟩ := exists_uniformCircuitCodes hn hn hF hlen - refine ⟨code, hcode, fun a u hu => ?_⟩ + obtain ⟨code, hcode, hsem⟩ := exists_uniformCircuitCodes (.of_tidy hn) (.of_tidy hn) + (.of_tidy hF) hlen + refine ⟨code, hcode.tidy, fun a u hu => ?_⟩ rw [evalCircuitCode, hsem a u hu, padBits_of_length_eq (hlen a u hu)] /-- A uniform polynomial-time pigeonhole family reduces to the canonical circuit problem. -/ @@ -90,7 +91,8 @@ theorem pigeonRel_searchReducible_Pigeon {n : α → ℕ} {F : α × List Bool have hn := hn.tidy have hF := hF.tidy obtain ⟨code, hcode, hsem⟩ := exists_endomorphismCodes hn hF hlen - apply SearchReducible.of_isTotalSearch isTotalSearch_Pigeon (hn.prod hcode) (snd enc encBits) + apply SearchReducible.of_isTotalSearch isTotalSearch_Pigeon (.of_tidy (hn.prod hcode)) + (.of_tidy (snd enc encBits)) intro a w hw change pigeonRel (fun a => n a) (fun p => evalCircuitCode (n p.1) (code p.1) p.2) a w at hw obtain ⟨hw, h⟩ := hw @@ -118,7 +120,7 @@ theorem endOfLineRel_searchReducible_EndOfLine {n : α → ℕ} obtain ⟨cP, hcP, hPs⟩ := exists_endomorphismCodes hn hP hP_len obtain ⟨cS, hcS, hSs⟩ := exists_endomorphismCodes hn hS hS_len apply SearchReducible.of_isTotalSearch isTotalSearch_EndOfLine - (hn.prod (hcP.prod hcS)) (snd enc encBits) + (.of_tidy (hn.prod (hcP.prod hcS))) (.of_tidy (snd enc encBits)) intro a u hw let P' (p : α × List Bool) := evalCircuitCode (n p.1) (cP p.1) p.2 let S' (p : α × List Bool) := evalCircuitCode (n p.1) (cS p.1) p.2 @@ -144,7 +146,7 @@ theorem leafRel_searchReducible_Leaf {n : α → ℕ} {N₁ N₂ : α × List Bo obtain ⟨c₁, hc₁, h₁⟩ := exists_endomorphismCodes hn hN₁ hN₁_len obtain ⟨c₂, hc₂, h₂⟩ := exists_endomorphismCodes hn hN₂ hN₂_len apply SearchReducible.of_isTotalSearch isTotalSearch_Leaf - (hn.prod (hc₁.prod hc₂)) (snd enc encBits) + (.of_tidy (hn.prod (hc₁.prod hc₂))) (.of_tidy (snd enc encBits)) intro a u hw let N₁' (p : α × List Bool) := evalCircuitCode (n p.1) (c₁ p.1) p.2 let N₂' (p : α × List Bool) := evalCircuitCode (n p.1) (c₂ p.1) p.2 @@ -184,8 +186,9 @@ private theorem exists_costCodes {n : α → ℕ} {C : α × List Bool → ℕ} exact hb simp only [binaryWord, List.length_append, List.length_replicate, List.length_reverse] omega - obtain ⟨code, hcode, hsem⟩ := exists_uniformCircuitCodes hn hm hword hword_len - refine ⟨code, hcode, fun a u hu => ?_⟩ + obtain ⟨code, hcode, hsem⟩ := exists_uniformCircuitCodes (.of_tidy hn) (.of_tidy hm) + (.of_tidy hword) hword_len + refine ⟨code, hcode.tidy, fun a u hu => ?_⟩ rw [hsem a u hu, binaryValue_binaryWord] /-- A uniform polynomial-time local-search family reduces to the canonical circuit problem. @@ -203,7 +206,7 @@ theorem localOptRel_searchReducible_LocalOpt {n : α → ℕ} obtain ⟨cN, hcN, hNs⟩ := exists_endomorphismCodes hn hN hlen obtain ⟨cC, hcC, hCs⟩ := exists_costCodes hn hC apply SearchReducible.of_isTotalSearch isTotalSearch_LocalOpt - (hn.prod (hcN.prod hcC)) (snd enc encBits) + (.of_tidy (hn.prod (hcN.prod hcC))) (.of_tidy (snd enc encBits)) intro a u hw change u.length = n a ∧ binaryValue (evalCircuitOutputs (cC a) u) ≤ diff --git a/Complexity/Computability/Complexity/Classes/Toda.lean b/Complexity/Computability/Complexity/Classes/Toda.lean index 576152180..7821cd99e 100644 --- a/Complexity/Computability/Complexity/Classes/Toda.lean +++ b/Complexity/Computability/Complexity/Classes/Toda.lean @@ -70,6 +70,7 @@ theorem exists_SharpP_testBit_of_mem_BPOp_ParityP {L : Set α} -- the witnesses of a pair of an instance and a random string have length `Zp` set Zp : Polynomial ℕ := ζ.comp (2 * Polynomial.X + 1 + ρ) with hZp set pF : Polynomial ℕ := (ρ + 1) + ((ρ + 1) + (ρ + (ρ + 1) * Zp)) + 1 + 1 with hpF + have hV' := hV.tidy refine ⟨fun a => acceptCount (fun x => sharpTest (fun r z => V ((x.1, r), z)) (ρ.eval (enc x.1).length) (Zp.eval (enc x.1).length) x.2) a (pF.eval (enc a).length), ⟨pF, _, .of_tidy (by fun_prop), fun _ => rfl⟩, ρ + 1, fun a => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/Toda/Counting.lean b/Complexity/Computability/Complexity/Classes/Toda/Counting.lean index c4b41e822..a99ecdc35 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Counting.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Counting.lean @@ -144,6 +144,20 @@ def subsetTest (acc : List Bool → Bool) (K Z k : ℕ) (zs : List Bool) : Bool (List.range (k - 1)).all fun i => BitString.wordLt (BitString.listRow Z i zs) (BitString.listRow Z (i + 1) zs) +private theorem computableTidilyInPolyTime_subsetTest {γ : Type} {input : γ ↪ List Bool} + {acc : γ → List Bool → Bool} + (hacc : ComputableTidilyInPolyTime (fun p : γ × List Bool => acc p.1 p.2) + (encPair input encBits) encBool) + {K Z k : γ → ℕ} {zs : γ → List Bool} + (hK : ComputableTidilyInPolyTime K input encUnary) + (hZ : ComputableTidilyInPolyTime Z input encUnary) + (hk : ComputableTidilyInPolyTime k input encUnary) + (hzs : ComputableTidilyInPolyTime zs input encBits) : + ComputableTidilyInPolyTime (fun c => subsetTest (acc c) (K c) (Z c) (k c) (zs c)) input + encBool := by + unfold subsetTest + fun_prop + @[fun_prop] theorem computableInPolyTime_subsetTest {γ : Type} {input : γ ↪ List Bool} {acc : γ → List Bool → Bool} @@ -155,9 +169,8 @@ theorem computableInPolyTime_subsetTest {γ : Type} {input : γ ↪ List Bool} (hk : ComputableInPolyTime k input encUnary) (hzs : ComputableInPolyTime zs input encBits) : ComputableInPolyTime (fun c => subsetTest (acc c) (K c) (Z c) (k c) (zs c)) input - encBool := by - unfold subsetTest - fun_prop + encBool := + .of_tidy (computableTidilyInPolyTime_subsetTest hacc.tidy hK.tidy hZ.tidy hk.tidy hzs.tidy) /-- **The `k`-subset test counts `k`-element sets of accepted words**, for `k ≤ K`. -/ private theorem card_filter_subsetTest (acc : List Bool → Bool) {K k : ℕ} (Z : ℕ) (hk : k ≤ K) : @@ -259,14 +272,21 @@ def unaryTest (K : ℕ) (kb : List Bool) : Bool := decide (0 < kb.count true) && kb == List.replicate (kb.count true) true ++ List.replicate (K - kb.count true) false +private theorem computableTidilyInPolyTime_unaryTest {γ : Type} {input : γ ↪ List Bool} + {K : γ → ℕ} {kb : γ → List Bool} + (hK : ComputableTidilyInPolyTime K input encUnary) + (hkb : ComputableTidilyInPolyTime kb input encBits) : + ComputableTidilyInPolyTime (fun c => unaryTest (K c) (kb c)) input encBool := by + unfold unaryTest + fun_prop + @[fun_prop] theorem computableInPolyTime_unaryTest {γ : Type} {input : γ ↪ List Bool} {K : γ → ℕ} {kb : γ → List Bool} (hK : ComputableInPolyTime K input encUnary) (hkb : ComputableInPolyTime kb input encBits) : - ComputableInPolyTime (fun c => unaryTest (K c) (kb c)) input encBool := by - unfold unaryTest - fun_prop + ComputableInPolyTime (fun c => unaryTest (K c) (kb c)) input encBool := + .of_tidy (computableTidilyInPolyTime_unaryTest hK.tidy hkb.tidy) /-- Summing over the words passing the unary test of length `K` sums over the sizes `1, …, K`. -/ @@ -309,15 +329,23 @@ def coeffTest (K k : ℕ) (cb : List Bool) : Bool := if k % 2 = 1 then !((cb.take (K + 1 - k)).any fun b => b) else (cb.take (K + 1 - k)).any fun b => b +private theorem computableTidilyInPolyTime_coeffTest {γ : Type} {input : γ ↪ List Bool} + {K k : γ → ℕ} {cb : γ → List Bool} + (hK : ComputableTidilyInPolyTime K input encUnary) + (hk : ComputableTidilyInPolyTime k input encUnary) + (hcb : ComputableTidilyInPolyTime cb input encBits) : + ComputableTidilyInPolyTime (fun c => coeffTest (K c) (k c) (cb c)) input encBool := by + unfold coeffTest + fun_prop + @[fun_prop] theorem computableInPolyTime_coeffTest {γ : Type} {input : γ ↪ List Bool} {K k : γ → ℕ} {cb : γ → List Bool} (hK : ComputableInPolyTime K input encUnary) (hk : ComputableInPolyTime k input encUnary) (hcb : ComputableInPolyTime cb input encBits) : - ComputableInPolyTime (fun c => coeffTest (K c) (k c) (cb c)) input encBool := by - unfold coeffTest - fun_prop + ComputableInPolyTime (fun c => coeffTest (K c) (k c) (cb c)) input encBool := + .of_tidy (computableTidilyInPolyTime_coeffTest hK.tidy hk.tidy hcb.tidy) /-- The coefficient test for size `k` accepts `parityCoeff K (k - 1)` words. -/ private theorem card_filter_coeffTest {K k : ℕ} (hk : 1 ≤ k) (hkK : k ≤ K) : @@ -521,6 +549,21 @@ theorem testBit_card_filter_sharpTest (accept : List Bool → List Bool → Bool variable {α : Type} {enc : α ↪ List Bool} {γ : Type} {input : γ ↪ List Bool} +attribute [local fun_prop] computableTidilyInPolyTime_subsetTest + computableTidilyInPolyTime_unaryTest computableTidilyInPolyTime_coeffTest in +private theorem computableTidilyInPolyTime_countingTest {V : (α × List Bool) × List Bool → Bool} + (hV : ComputableTidilyInPolyTime V (encPair (encPair enc encBits) encBits) encBool) + {a : γ → α} {K R Z : γ → ℕ} {w : γ → List Bool} + (ha : ComputableTidilyInPolyTime a input enc) + (hK : ComputableTidilyInPolyTime K input encUnary) + (hR : ComputableTidilyInPolyTime R input encUnary) + (hZ : ComputableTidilyInPolyTime Z input encUnary) + (hw : ComputableTidilyInPolyTime w input encBits) : + ComputableTidilyInPolyTime (fun c => countingTest (fun r z => V ((a c, r), z)) (K c) (R c) + (Z c) (w c)) input encBool := by + unfold countingTest + fun_prop + @[fun_prop] theorem computableInPolyTime_countingTest {V : (α × List Bool) × List Bool → Bool} (hV : ComputableInPolyTime V (encPair (encPair enc encBits) encBits) encBool) @@ -531,10 +574,10 @@ theorem computableInPolyTime_countingTest {V : (α × List Bool) × List Bool (hZ : ComputableInPolyTime Z input encUnary) (hw : ComputableInPolyTime w input encBits) : ComputableInPolyTime (fun c => countingTest (fun r z => V ((a c, r), z)) (K c) (R c) - (Z c) (w c)) input encBool := by - unfold countingTest - fun_prop + (Z c) (w c)) input encBool := + .of_tidy (computableTidilyInPolyTime_countingTest hV.tidy ha.tidy hK.tidy hR.tidy hZ.tidy hw.tidy) +attribute [local fun_prop] computableTidilyInPolyTime_countingTest in @[fun_prop] theorem computableTidilyInPolyTime_sharpTest {V : (α × List Bool) × List Bool → Bool} (hV : ComputableTidilyInPolyTime V (encPair (encPair enc encBits) encBits) encBool) diff --git a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean index 9641a2471..9e4a34c5f 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean @@ -81,6 +81,37 @@ namespace Toda variable {α : Type} {enc : α ↪ List Bool} +/-! Tidy views of the plain certificates of `ParityP` and `Toda.Isolation`, for tidy `fun_prop` +below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_hashesToZero + {γ : Type} {input : γ ↪ List Bool} {k : γ → ℕ} + {seed w : γ → List Bool} + (hk : ComputableTidilyInPolyTime k input encUnary) + (hseed : ComputableTidilyInPolyTime seed input encBits) + (hw : ComputableTidilyInPolyTime w input encBits) : + ComputableTidilyInPolyTime (fun x => hashesToZero (k x) (seed x) (w x)) input encBool := + (ComputableInPolyTime.tidy (computableInPolyTime_hashesToZero (.of_tidy hk) (.of_tidy hseed) + (.of_tidy hw))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_succTest + {γ : Type} {input : γ ↪ List Bool} + {g : γ → List Bool → Bool} {w : γ → List Bool} + (hg : ComputableTidilyInPolyTime (fun p : γ × List Bool => g p.1 p.2) (encPair input encBits) + encBool) + (hw : ComputableTidilyInPolyTime w input encBits) : + ComputableTidilyInPolyTime (fun x => succTest (g x) (w x)) input encBool := + (ComputableInPolyTime.tidy (computableInPolyTime_succTest (.of_tidy hg) (.of_tidy hw))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_succVerifier + {enc : α ↪ List Bool} + {V : α × List Bool → Bool} (hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool) : + ComputableTidilyInPolyTime (succVerifier V) (encPair enc encBits) encBool := + (ComputableInPolyTime.tidy (computableInPolyTime_succVerifier (.of_tidy hV))) + /-! ### Random parity representations -/ open Classical in @@ -205,6 +236,24 @@ def existsVerifier (enc : α ↪ List Bool) (ℓ m ρ ζ e : Polynomial ℕ) (W 4 * (e.eval (enc x.1).length + 1) * (m.eval (enc x.1).length + 3) * ((m.eval (enc x.1).length + 2) * (m.eval (enc x.1).length + 1)))) +private theorem computableTidilyInPolyTime_trialVerifier {W : α × List Bool → Bool} + (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) + {γ : Type} {input : γ ↪ List Bool} {a : γ → α} {u r seed block : γ → List Bool} + {M level : γ → ℕ} + (ha : ComputableTidilyInPolyTime a input enc) + (hu : ComputableTidilyInPolyTime u input encBits) + (hr : ComputableTidilyInPolyTime r input encBits) + (hM : ComputableTidilyInPolyTime M input encUnary) + (hlevel : ComputableTidilyInPolyTime level input encUnary) + (hseed : ComputableTidilyInPolyTime seed input encBits) + (hblock : ComputableTidilyInPolyTime block input encBits) : + ComputableTidilyInPolyTime (fun x => trialVerifier W (a x) (u x) (r x) (M x) (level x) + (seed x) (block x)) input encBool := by + unfold trialVerifier + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_trialVerifier + @[fun_prop] theorem computableInPolyTime_trialVerifier {W : α × List Bool → Bool} (hW : ComputableInPolyTime W (encPair enc encBits) encBool) @@ -218,10 +267,29 @@ theorem computableInPolyTime_trialVerifier {W : α × List Bool → Bool} (hseed : ComputableInPolyTime seed input encBits) (hblock : ComputableInPolyTime block input encBits) : ComputableInPolyTime (fun x => trialVerifier W (a x) (u x) (r x) (M x) (level x) - (seed x) (block x)) input encBool := by - unfold trialVerifier + (seed x) (block x)) input encBool := + .of_tidy (computableTidilyInPolyTime_trialVerifier hW.tidy ha.tidy hu.tidy hr.tidy hM.tidy hlevel.tidy hseed.tidy hblock.tidy) + +private theorem computableTidilyInPolyTime_trialsVerifier {W : α × List Bool → Bool} + (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) + {γ : Type} {input : γ ↪ List Bool} {a : γ → α} {u r seeds y : γ → List Bool} + {M Z T B : γ → ℕ} + (ha : ComputableTidilyInPolyTime a input enc) + (hu : ComputableTidilyInPolyTime u input encBits) + (hr : ComputableTidilyInPolyTime r input encBits) + (hseeds : ComputableTidilyInPolyTime seeds input encBits) + (hM : ComputableTidilyInPolyTime M input encUnary) + (hZ : ComputableTidilyInPolyTime Z input encUnary) + (hT : ComputableTidilyInPolyTime T input encUnary) + (hB : ComputableTidilyInPolyTime B input encUnary) + (hy : ComputableTidilyInPolyTime y input encBits) : + ComputableTidilyInPolyTime (fun x => trialsVerifier W (a x) (u x) (r x) (seeds x) (M x) (Z x) + (T x) (B x) (y x)) input encBool := by + unfold trialsVerifier fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_trialsVerifier + @[fun_prop] theorem computableInPolyTime_trialsVerifier {W : α × List Bool → Bool} (hW : ComputableInPolyTime W (encPair enc encBits) encBool) @@ -237,9 +305,8 @@ theorem computableInPolyTime_trialsVerifier {W : α × List Bool → Bool} (hB : ComputableInPolyTime B input encUnary) (hy : ComputableInPolyTime y input encBits) : ComputableInPolyTime (fun x => trialsVerifier W (a x) (u x) (r x) (seeds x) (M x) (Z x) - (T x) (B x) (y x)) input encBool := by - unfold trialsVerifier - fun_prop + (T x) (B x) (y x)) input encBool := + .of_tidy (computableTidilyInPolyTime_trialsVerifier hW.tidy ha.tidy hu.tidy hr.tidy hseeds.tidy hM.tidy hZ.tidy hT.tidy hB.tidy hy.tidy) private theorem computableTidilyInPolyTime_existsVerifier (ℓ m ρ ζ e : Polynomial ℕ) {W : α × List Bool → Bool} (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) : @@ -448,7 +515,7 @@ pairs of an instance and a random string. -/ theorem PH_subset_BPOp_ParityP : PH enc ⊆ BPOp enc (ParityP (encPair enc encBits)) := by intro L hL obtain ⟨k, ps, V, -, hV, hLV⟩ := mem_PH.1 hL - obtain ⟨ρ, ζ, W, hW, h⟩ := exists_isRandomParityRep_alternation hV.tidy ps true 0 2 + obtain ⟨ρ, ζ, W, hW, h⟩ := exists_isRandomParityRep_alternation hV ps true 0 2 set L' : Set (α × List Bool) := {x | Odd (acceptCount (fun y => W (y.1, x.2 ++ y.2)) x.1 (ζ.eval (enc x.1).length))} with hL' refine ⟨ρ, L', ?_, fun a => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/UP.lean b/Complexity/Computability/Complexity/Classes/UP.lean index 5f4471df9..d417ec59e 100644 --- a/Complexity/Computability/Complexity/Classes/UP.lean +++ b/Complexity/Computability/Complexity/Classes/UP.lean @@ -57,18 +57,16 @@ theorem mem_UP : A ∈ UP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ 1) ∧ ∀ a, a ∈ A ↔ acceptCount V a (p.eval (enc a).length) = 1 := by - have this : A ∈ UP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ 1) ∧ ∀ a, a ∈ A ↔ acceptCount V a (p.eval (enc a).length) = 1 := by - constructor - · rintro ⟨f, ⟨p, V, hV, hf⟩, hle, hA⟩ - exact ⟨p, V, hV.tidy, fun a => hf a ▸ hle a, fun a => (hA a).trans (by rw [hf a])⟩ - · rintro ⟨p, V, hV, hle, hA⟩ - exact ⟨_, ⟨p, V, .of_tidy hV, fun _ => rfl⟩, hle, hA⟩ - simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this + constructor + · rintro ⟨f, ⟨p, V, hV, hf⟩, hle, hA⟩ + exact ⟨p, V, hV, fun a => hf a ▸ hle a, fun a => (hA a).trans (by rw [hf a])⟩ + · rintro ⟨p, V, hV, hle, hA⟩ + exact ⟨_, ⟨p, V, hV, fun _ => rfl⟩, hle, hA⟩ /-- A deterministic decider uses only the empty certificate. -/ theorem P_subset_UP : P enc ⊆ UP enc := by rintro A ⟨f, hf, hA⟩ - refine mem_UP.mpr ⟨0, fun x => f x.1, hf.tidy.comp (.fst enc encBits), ?_, ?_⟩ + refine mem_UP.mpr ⟨0, fun x => f x.1, .of_tidy (hf.tidy.comp (.fst enc encBits)), ?_, ?_⟩ · intro a simp only [Polynomial.eval_zero, acceptCount_zero] split <;> omega diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean index 3d68d958c..d4d813936 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean @@ -91,7 +91,7 @@ theorem mem_RPWithOracle {A : Set (List Bool)} {enc : α ↪ List Bool} {L : Set /-- Every problem in `RP` is in `RP` relative to every oracle. -/ theorem RP_subset_RPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : RP enc ⊆ RPWithOracle A enc := fun _ ⟨p, V, hV, h⟩ => - ⟨p, V, hV.tidy.computableInPolyTimeWithOracle A, h⟩ + ⟨p, V, hV.computableInPolyTimeWithOracle A, h⟩ /-- `RP` relative to an oracle lies inside `NP` relative to the same oracle: an accepted random string is a certificate. -/ @@ -239,6 +239,7 @@ theorem NP_subset_RPWithPromiseOracle_PromiseUSAT (enc : α ↪ List Bool) : ((c * ((enc x.1).length + 1) ^ d + 2) ^ 2) x.2).map fun b => encCNF (reduce (g x.1, b)) have hqueries : ComputableTidilyInPolyTime queries (encPair enc encBits) (encList encBits) := by + have hreduce := computableInPolyTime_reduce.tidy fun_prop refine ⟨Polynomial.C 11 * (Polynomial.C c * (Polynomial.X + 1) ^ d + 3) * (Polynomial.C c * (Polynomial.X + 1) ^ d + 2) ^ 2, diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean index 7831df45b..243b2b337 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean @@ -74,7 +74,7 @@ theorem exists_mem_P_solvedBy_of_mem_PromiseP {Q : PromiseProblem β} {encQ : β ∃ A ∈ P encBits, Q.SolvedBy fun b => decide (encQ b ∈ A) := by obtain ⟨f, hf, hsolve⟩ := mem_PromiseP_iff.1 hQ obtain ⟨_, _, hD⟩ := D.computable - refine ⟨{w | f (D.decode w) = true}, ⟨_, .of_tidy (hf.comp hD.computableTidilyInPolyTime), + refine ⟨{w | f (D.decode w) = true}, ⟨_, hf.comp (.of_tidy hD.computableTidilyInPolyTime), fun _ => Iff.rfl⟩, ?_⟩ simpa [D.decode_enc] using hsolve diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean index f300ec7c6..1f7cd22a4 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean @@ -112,34 +112,60 @@ def reduce (x : CNF ℕ × List Bool) : CNF ℕ := /-! ### Polynomial time -/ +private theorem computableTidilyInPolyTime_stepClauses : + ComputableTidilyInPolyTime (fun p : Bool × Var × Var × Var => + stepClauses p.1 p.2.1 p.2.2.1 p.2.2.2) + (encPair encBool (encPair encVar (encPair encVar encVar))) + (encList (encList (encPair encVar encBool))) := by + unfold stepClauses encVar + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_stepClauses + /-- Building the clauses of one step is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_stepClauses : ComputableInPolyTime (fun p : Bool × Var × Var × Var => stepClauses p.1 p.2.1 p.2.2.1 p.2.2.2) (encPair encBool (encPair encVar (encPair encVar encVar))) + (encList (encList (encPair encVar encBool))) := + .of_tidy (computableTidilyInPolyTime_stepClauses) + +private theorem computableTidilyInPolyTime_rowClauses : + ComputableTidilyInPolyTime (fun p : List ℕ × ℕ × List Bool × Bool => + rowClauses p.1 p.2.1 p.2.2.1 p.2.2.2) + (encPair (encList encNat) (encPair encUnary (encPair encBits encBool))) (encList (encList (encPair encVar encBool))) := by - unfold stepClauses encVar + unfold rowClauses encVar fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_rowClauses + /-- Building the clauses of one equation is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_rowClauses : ComputableInPolyTime (fun p : List ℕ × ℕ × List Bool × Bool => rowClauses p.1 p.2.1 p.2.2.1 p.2.2.2) (encPair (encList encNat) (encPair encUnary (encPair encBits encBool))) + (encList (encList (encPair encVar encBool))) := + .of_tidy (computableTidilyInPolyTime_rowClauses) + +private theorem computableTidilyInPolyTime_hashCNF : + ComputableTidilyInPolyTime (fun p : List ℕ × ℕ × List Bool => hashCNF p.1 p.2.1 p.2.2) + (encPair (encList encNat) (encPair encUnary encBits)) (encList (encList (encPair encVar encBool))) := by - unfold rowClauses encVar + unfold hashCNF fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_hashCNF + /-- Building all equations is polynomial-time, with the number of equations in unary. -/ @[fun_prop] theorem computableInPolyTime_hashCNF : ComputableInPolyTime (fun p : List ℕ × ℕ × List Bool => hashCNF p.1 p.2.1 p.2.2) (encPair (encList encNat) (encPair encUnary encBits)) - (encList (encList (encPair encVar encBool))) := by - unfold hashCNF - fun_prop + (encList (encList (encPair encVar encBool))) := + .of_tidy (computableTidilyInPolyTime_hashCNF) /-- The selector ranges over the dyadic range of `φ.vars.length + 2`: the least power of two above it. -/ diff --git a/Complexity/Computability/Complexity/Fagin/Verifier.lean b/Complexity/Computability/Complexity/Fagin/Verifier.lean index fc7f2c568..c07522aaf 100644 --- a/Complexity/Computability/Complexity/Fagin/Verifier.lean +++ b/Complexity/Computability/Complexity/Fagin/Verifier.lean @@ -54,7 +54,7 @@ is not proved here. of the decoded structure by the certificate relations. * `Cslib.Logic.ESO.Sentence.Layout.realize_iff_exists_certificate`: a decoded structure satisfies the sentence exactly when some certificate is accepted. -* `Cslib.Logic.ESO.Sentence.Layout.computableTidilyInPolyTime_verifier`: the verifier is +* `Cslib.Logic.ESO.Sentence.Layout.computableInPolyTime_verifier`: the verifier is polynomial-time. * `Cslib.Logic.ESO.Sentence.queryLanguage_mem_NP`, `Cslib.Logic.ESO.Definable.queryLanguage_mem_NP`: the problem of a sentence, and the query @@ -407,15 +407,16 @@ theorem computableInPolyTime_termValue {k : ℕ} {σ : γ → List ℕ} (hσ.prod (const (encMid := encUnary) (varPos (FO.termVar t))))) @[fun_prop] -theorem computableTidilyInPolyTime_termsIndex {k : ℕ} {n : γ → ℕ} {σ : γ → List ℕ} - (hn : ComputableTidilyInPolyTime n encIn encUnary) - (hσ : ComputableTidilyInPolyTime σ encIn (encList encUnary)) : +theorem computableInPolyTime_termsIndex {k : ℕ} {n : γ → ℕ} {σ : γ → List ℕ} + (hn : ComputableInPolyTime n encIn encUnary) + (hσ : ComputableInPolyTime σ encIn (encList encUnary)) : ∀ {l : ℕ} (ts : Fin l → (L.sum (varLanguage Φ.arity)).Term (Empty ⊕ Fin k)), - ComputableTidilyInPolyTime (fun x => termsIndex (Φ := Φ) (n x) (σ x) ts) encIn encUnary - | 0, _ => const 0 + ComputableInPolyTime (fun x => termsIndex (Φ := Φ) (n x) (σ x) ts) encIn encUnary + | 0, _ => .of_tidy (const 0) | _ + 1, ts => - unary_add.comp ((computableInPolyTime_termValue (.of_tidy hσ) (ts 0)).tidy.prod - (unary_mul.comp (hn.prod (computableTidilyInPolyTime_termsIndex hn hσ fun j => ts j.succ)))) + .of_tidy (unary_add.comp ((computableInPolyTime_termValue hσ (ts 0)).tidy.prod + (unary_mul.comp (hn.tidy.prod + (computableInPolyTime_termsIndex hn hσ fun j => ts j.succ).tidy)))) omit [L.IsRelational] in attribute [local fun_prop] ComputableInPolyTime.tidy in @@ -432,45 +433,49 @@ theorem computableInPolyTime_relBit {l : ℕ} have hw := hw.tidy have hidx := hidx.tidy exact .of_tidy (match R with - | .inl r => (bitsGetD false).comp (((v.computableInPolyTime_table (.of_tidy ⟨_, r⟩)).tidy ha).prod hidx) + | .inl r => (bitsGetD false).comp + ((v.computableInPolyTime_table ⟨_, r⟩ (.of_tidy ha)).tidy.prod hidx) | .inr r => (bitsGetD false).comp (hw.prod (unary_add.comp ((unary_mul.comp ((const (encMid := encUnary) (ℓ.block r.1 : ℕ)).prod ((unary_pow _).comp hN))).prod hidx)))) /-- **The evaluator is polynomial-time** for each fixed formula, by induction on the formula. The input type is generalized, as the body of a quantifier takes the current element as well. -/ @[fun_prop] -theorem computableTidilyInPolyTime_eval {k : ℕ} +theorem computableInPolyTime_eval {k : ℕ} (φ : (L.sum (varLanguage Φ.arity)).BoundedFormula Empty k) {γ : Type} {encIn : γ ↪ List Bool} {a : γ → EncodedStructure} {N : γ → ℕ} {w : γ → List Bool} - {σ : γ → List ℕ} (ha : ComputableTidilyInPolyTime a encIn encStructure) - (hN : ComputableTidilyInPolyTime N encIn encUnary) - (hw : ComputableTidilyInPolyTime w encIn encBits) - (hσ : ComputableTidilyInPolyTime σ encIn (encList encUnary)) : - ComputableTidilyInPolyTime (fun x => ℓ.eval v (a x) (N x) (w x) φ (σ x)) encIn encBool := by + {σ : γ → List ℕ} (ha : ComputableInPolyTime a encIn encStructure) + (hN : ComputableInPolyTime N encIn encUnary) + (hw : ComputableInPolyTime w encIn encBits) + (hσ : ComputableInPolyTime σ encIn (encList encUnary)) : + ComputableInPolyTime (fun x => ℓ.eval v (a x) (N x) (w x) φ (σ x)) encIn encBool := by induction φ generalizing γ with - | falsum => exact const false + | falsum => exact .of_tidy (const false) | equal t₁ t₂ => - exact unary_beq (computableInPolyTime_termValue (.of_tidy hσ) t₁).tidy - (computableInPolyTime_termValue (.of_tidy hσ) t₂).tidy + exact .of_tidy (unary_beq (computableInPolyTime_termValue hσ t₁).tidy + (computableInPolyTime_termValue hσ t₂).tidy) | rel R ts => - exact (ℓ.computableInPolyTime_relBit R (.of_tidy ha) (.of_tidy hN) (.of_tidy hw) - (.of_tidy (computableTidilyInPolyTime_termsIndex (computableTidilyInPolyTime_card ha) hσ ts))).tidy + exact ℓ.computableInPolyTime_relBit R ha hN hw + (computableInPolyTime_termsIndex (.of_tidy (computableTidilyInPolyTime_card ha.tidy)) hσ ts) | imp φ ψ ih₁ ih₂ => - exact bool_or.comp ((bool_not.comp (ih₁ ha hN hw hσ)).prod (ih₂ ha hN hw hσ)) + exact .of_tidy + (bool_or.comp ((bool_not.comp (ih₁ ha hN hw hσ).tidy).prod (ih₂ ha hN hw hσ).tidy)) | all φ ih => - exact allWithInput (range.comp (computableTidilyInPolyTime_card ha)) - (ih (ha.comp (fst encIn encUnary)) (hN.comp (fst encIn encUnary)) - (hw.comp (fst encIn encUnary)) (listAppend' (hσ.comp (fst encIn encUnary)) - (cons' (snd encIn encUnary) (const (encMid := encList encUnary) [])))) + exact .of_tidy (allWithInput (range.comp (computableTidilyInPolyTime_card ha.tidy)) + (ih (.of_tidy (ha.tidy.comp (fst encIn encUnary))) + (.of_tidy (hN.tidy.comp (fst encIn encUnary))) + (.of_tidy (hw.tidy.comp (fst encIn encUnary))) + (.of_tidy (listAppend' (hσ.tidy.comp (fst encIn encUnary)) + (cons' (snd encIn encUnary) (const (encMid := encList encUnary) []))))).tidy) /-- **The verifier is polynomial-time.** -/ @[fun_prop] -theorem computableTidilyInPolyTime_verifier : - ComputableTidilyInPolyTime (ℓ.verifier v) (encPair encStructure encBits) encBool := - bool_and' (v.computableInPolyTime_checkShape.comp (fst encStructure encBits)) - (ℓ.computableTidilyInPolyTime_eval Φ.matrix (fst encStructure encBits) - ((encoding_length encStructure).comp (fst encStructure encBits)) - (snd encStructure encBits) (const [])) +theorem computableInPolyTime_verifier : + ComputableInPolyTime (ℓ.verifier v) (encPair encStructure encBits) encBool := + .of_tidy (bool_and' (v.computableInPolyTime_checkShape.tidy.comp (fst encStructure encBits)) + (ℓ.computableInPolyTime_eval Φ.matrix (.of_tidy (fst encStructure encBits)) + (.of_tidy ((encoding_length encStructure).comp (fst encStructure encBits))) + (.of_tidy (snd encStructure encBits)) (.of_tidy (const []))).tidy) end PolyTime @@ -485,7 +490,7 @@ the finite structures satisfying `Φ`, with respect to the encoding of structure vocabulary. -/ theorem queryLanguage_mem_NP : v.queryLanguage {M | Φ.Realize M} ∈ NP encStructure := let ℓ := Layout.ofFinite Φ - ⟨ℓ.polynomial, ℓ.verifier v, .of_tidy ℓ.computableTidilyInPolyTime_verifier, + ⟨ℓ.polynomial, ℓ.verifier v, ℓ.computableInPolyTime_verifier, ℓ.isVerifier fun _ _ => Iff.rfl⟩ end Sentence @@ -499,6 +504,6 @@ theorem Definable.queryLanguage_mem_NP {L : Language.{u, v}} [L.IsRelational] (v v.queryLanguage K ∈ NP encStructure := let ⟨Φ, hΦ⟩ := hK let ℓ := Sentence.Layout.ofFinite Φ - ⟨ℓ.polynomial, ℓ.verifier v, .of_tidy ℓ.computableTidilyInPolyTime_verifier, ℓ.isVerifier hΦ⟩ + ⟨ℓ.polynomial, ℓ.verifier v, ℓ.computableInPolyTime_verifier, ℓ.isVerifier hΦ⟩ end Cslib.Logic.ESO diff --git a/Complexity/Computability/Complexity/FineGrained.lean b/Complexity/Computability/Complexity/FineGrained.lean index 635353345..62cae906b 100644 --- a/Complexity/Computability/Complexity/FineGrained.lean +++ b/Complexity/Computability/Complexity/FineGrained.lean @@ -173,7 +173,7 @@ theorem DecidableInTimeO.inter {p : α → Bool} (hp : ComputableInPolyTime p en have h := hp.inO.ite hg (ComputableTidilyInO.const false) refine ⟨d + 1, DecidableInTimeO.mono (T := fun a => ((((enc a).length + 1) ^ d + if p a then t a else (enc a).length : ℕ) : ℝ)) - (Complexity.DecidableInTimeO.of_computableInO h (fun a => ?_) fun a => le_rfl) (c + 2) + (Complexity.DecidableInTimeO.of_computableInO (.of_tidy h) (fun a => ?_) fun a => le_rfl) (c + 2) (fun a => ?_) fun a => ?_⟩ · simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, hgB] cases p a <;> simp diff --git a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean index fac2cd5a5..089179abc 100644 --- a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean +++ b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean @@ -134,6 +134,7 @@ open ComputableTidilyInPolyTime in /-- The initial state is computed in polynomial time. -/ private theorem computableTidilyInPolyTime_init : ComputableTidilyInPolyTime init encCNF encState := by + have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy unfold init fun_prop @@ -256,6 +257,6 @@ theorem KSAT_eq_inter (k : ℕ) {B : Set (CNF ℕ)} (hB : KSAT k ⊆ B) (hBSAT : in the length of the encoded formula, on formulas with `n` variables. -/ theorem KSAT_decidableInExpTime_one (k : ℕ) : DecidableInExpTime (KSAT k) encCNF CNF.numVars 1 := by rw [KSAT_eq_inter k (KSAT_subset_SAT k) le_rfl] - exact SAT_decidableInExpTime_one.inter (computableInPolyTime_all_length_le k).tidy zero_le_one + exact SAT_decidableInExpTime_one.inter (computableInPolyTime_all_length_le k) zero_le_one end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/FineGrained/Exponents.lean b/Complexity/Computability/Complexity/FineGrained/Exponents.lean index efc031135..784e65793 100644 --- a/Complexity/Computability/Complexity/FineGrained/Exponents.lean +++ b/Complexity/Computability/Complexity/FineGrained/Exponents.lean @@ -67,7 +67,7 @@ theorem DecidableInExpTime.KSAT_of_le {k k' : ℕ} (hk : k ≤ k') {δ : ℝ} (h DecidableInExpTime (KSAT k) encCNF CNF.numVars δ := by rw [KSAT_eq_inter k (B := KSAT k') (fun φ hφ => ⟨fun c hc => (hφ.1 c hc).trans hk, hφ.2⟩) (KSAT_subset_SAT k')] - exact h.inter (computableInPolyTime_all_length_le k).tidy hδ + exact h.inter (computableInPolyTime_all_length_le k) hδ /-- The exponents of `k`-SAT. -/ private abbrev exponents (k : ℕ) : Set ℝ := @@ -159,7 +159,7 @@ theorem DecidableInExpTime.length_of_numVars {k : ℕ} {δ : ℝ} (hδ : 0 ≤ (h : DecidableInExpTime (KSAT k) encCNF CNF.numVars δ) : DecidableInExpTime (KSAT k) encCNF List.length (k * δ) := by obtain ⟨e, h⟩ := h - obtain ⟨e', h⟩ := h.inter (computableInPolyTime_all_length_le k).tidy fun φ => by positivity + obtain ⟨e', h⟩ := h.inter (computableInPolyTime_all_length_le k) fun φ => by positivity rw [← KSAT_eq_inter k le_rfl (KSAT_subset_SAT k)] at h refine ⟨e + e', h.mono 2 (fun φ => ?_) fun φ => by positivity⟩ have hL : (1 : ℝ) ≤ (encCNF φ).length + 1 := by diff --git a/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean b/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean index 8001b77cb..b0dcf27ee 100644 --- a/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean +++ b/Complexity/Computability/Complexity/FineGrained/GraphProblems.lean @@ -94,7 +94,7 @@ polynomial in the length of the encoded graph, for graphs with `|V|` declared ve edges. -/ theorem ETH.not_decidableInSubexpTime_ThreeColoring (h : ETH) : ¬DecidableInSubexpTime ThreeColoring encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring -- `(24 * 3 + 12) m + 9 ≤ 93 m + 93` (fun φ _ => SAT.toThreeColoring_mem_iff φ) (k := 93) fun φ hφ => by have := SAT.length_toThreeColoring_le hφ @@ -107,7 +107,7 @@ edges. -/ theorem ETH.not_decidableInSubexpTime_IndependentSet (h : ETH) : ¬DecidableInSubexpTime IndependentSet (encPair encGraph encNat) fun x => x.1.1.length + x.1.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet (fun φ _ => SAT.toSparseIndependentSet_mem_iff φ) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ omega @@ -117,7 +117,7 @@ some `δ > 0`, `IndependentSet` is not decidable within time `2 ^ (δ |V|)` time the length of the encoded instance, for graphs with `|V|` declared vertices. -/ theorem ETH.not_decidableInSubexpTime_IndependentSet_vertices (h : ETH) : ¬DecidableInSubexpTime IndependentSet (encPair encGraph encNat) fun x => x.1.1.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseIndependentSet (fun φ _ => SAT.toSparseIndependentSet_mem_iff φ) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ omega @@ -130,8 +130,8 @@ theorem ETH.not_decidableInSubexpTime_VertexCover (h : ETH) : ¬DecidableInSubexpTime VertexCover (encPair encGraph encNat) fun x => x.1.1.length + x.1.2.length := h.not_decidableInSubexpTime_of_reduction - (IndependentSet.computableInPolyTime_toVertexCover.tidy.comp - SAT.computableInPolyTime_toSparseIndependentSet.tidy) + (IndependentSet.computableInPolyTime_toVertexCover.comp + SAT.computableInPolyTime_toSparseIndependentSet) (fun φ _ => (IndependentSet.toVertexCover_mem_iff _).trans (SAT.toSparseIndependentSet_mem_iff φ)) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ @@ -145,9 +145,9 @@ theorem ETH.not_decidableInSubexpTime_Clique (h : ETH) : ¬DecidableInSubexpTime Clique (encPair encGraph encNat) fun x => x.1.1.length := h.not_decidableInSubexpTime_of_reduction (f := fun φ => ((SAT.toSparseIndependentSet φ).1.compl, (SAT.toSparseIndependentSet φ).2)) - ((show ComputableTidilyInPolyTime (fun x : Graph × ℕ => (x.1.compl, x.2)) + (.of_tidy ((show ComputableTidilyInPolyTime (fun x : Graph × ℕ => (x.1.compl, x.2)) (encPair encGraph encNat) (encPair encGraph encNat) by fun_prop).comp - SAT.computableInPolyTime_toSparseIndependentSet.tidy) + SAT.computableInPolyTime_toSparseIndependentSet.tidy)) (fun φ _ => (Graph.compl_mem_Clique_iff _ _).trans (SAT.toSparseIndependentSet_mem_iff φ)) (k := 24) fun φ hφ => by have := SAT.length_toSparseIndependentSet_le hφ @@ -160,7 +160,7 @@ any polynomial in the length of the encoded graph, for graphs with `|V|` declare `|E|` edges. -/ theorem ETH.not_decidableInSubexpTime_HamCycle (h : ETH) : ¬DecidableInSubexpTime HamCycle encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseHamCycle.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseHamCycle (fun φ _ => SAT.toSparseHamCycle_mem_iff φ) (k := 350) fun φ hφ => by have := SAT.length_toSparseHamCycle_le hφ omega @@ -171,7 +171,7 @@ theorem ETH.not_decidableInSubexpTime_HamCycle (h : ETH) : `|V|` declared vertices and `|E|` arcs. -/ theorem ETH.not_decidableInSubexpTime_DirHamCycle (h : ETH) : ¬DecidableInSubexpTime DirHamCycle encGraph fun G => G.1.length + G.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamCycle.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamCycle (fun φ _ => SAT.toSparseDirHamCycle_mem_iff φ) (k := 70) fun φ hφ => by have := SAT.length_toSparseDirHamCycle_le hφ omega @@ -183,7 +183,7 @@ theorem ETH.not_decidableInSubexpTime_DirHamCycle (h : ETH) : theorem ETH.not_decidableInSubexpTime_DirHamPath (h : ETH) : ¬DecidableInSubexpTime DirHamPath (encPair encGraph (encPair encNat encNat)) fun x => x.1.1.length + x.1.2.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamPath.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toSparseDirHamPath (fun φ _ => SAT.toSparseDirHamPath_mem_iff φ) (k := 70) fun φ hφ => by have := SAT.length_sparseDiamondGraph_le hφ simp only [SAT.toSparseDirHamPath] @@ -197,8 +197,8 @@ theorem ETH.not_decidableInSubexpTime_HamPath (h : ETH) : ¬DecidableInSubexpTime HamPath (encPair encGraph (encPair encNat encNat)) fun x => x.1.1.length + x.1.2.length := h.not_decidableInSubexpTime_of_reduction - (DirHamPath.computableInPolyTime_toHamPath.tidy.comp - SAT.computableInPolyTime_toSparseDirHamPath.tidy) + (DirHamPath.computableInPolyTime_toHamPath.comp + SAT.computableInPolyTime_toSparseDirHamPath) (fun φ _ => (DirHamPath.toHamPath_mem_iff _).trans (SAT.toSparseDirHamPath_mem_iff φ)) (k := 350) fun φ hφ => by have := SAT.length_sparseDiamondGraph_le hφ diff --git a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean index 309e957e9..a61e60d60 100644 --- a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean +++ b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean @@ -267,6 +267,7 @@ theorem computableInPolyTime_clauseVector : funext s simp only [clauseVector, satisfiesOn, bitsAssignment_eq_getD, List.idxOf_lt_length_iff] rw [e] + refine .of_tidy ?_ unfold encStreamState encCNF fun_prop @@ -462,6 +463,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in theorem computableInPolyTime_firstVars : ComputableInPolyTime firstVars encCNF (encList encNat) := by + have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun φ => (φ.distinctVars.reverse.drop (φ.distinctVars.length - φ.distinctVars.length / 2)).reverse) @@ -479,6 +481,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in theorem computableInPolyTime_secondVars : ComputableInPolyTime secondVars encCNF (encList encNat) := by + have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ exact (dropUnary (encA := encNat)).comp (SAT.computableInPolyTime_distinctVars.tidy.prod (show ComputableTidilyInPolyTime (fun φ => φ.distinctVars.length / 2) encCNF @@ -501,11 +504,11 @@ theorem exists_computableInO_toOV : ∃ e, ComputableInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by have this : ∃ e, ComputableTidilyInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by - obtain ⟨e₁, h₁⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_firstVars.tidy + obtain ⟨e₁, h₁⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_firstVars OV.length_firstVars_le (wrap := fun v => ((frame v).map fun b => [true, b]).flatten) (by fun_prop) [false] - obtain ⟨e₂, h₂⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_secondVars.tidy - OV.length_secondVars_le (wrap := frame) (bitsFrame encBits) [] + obtain ⟨e₂, h₂⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_secondVars + OV.length_secondVars_le (wrap := frame) (.of_tidy (bitsFrame encBits)) [] have hfm (l : List (List Bool)) (g : Bool → List Bool) : l.flatten.flatMap g = (l.map (·.flatMap g)).flatten := by induction l with @@ -515,7 +518,7 @@ theorem exists_computableInO_toOV : ∃ e, ComputableInO toOV encCNF encOV induction L with | nil => rfl | cons v L ih => rw [encList_cons, ih]; rfl - have h := h₁.append h₂ (g := toOV) (encOut := encOV) fun φ => by + have h := h₁.tidy.append h₂.tidy (g := toOV) (encOut := encOV) fun φ => by rw [encOV, encPair_apply, hencList, hencList] simp only [toOV, encBits_apply, List.append_nil] rw [frame, hfm, List.map_map] @@ -546,7 +549,7 @@ theorem DecidableInTimeO.decidableInExpTime_SAT {ε : ℝ} (hε : 0 < ε) {e : DecidableInExpTime SAT encCNF CNF.numVars (1 - min ε 1 / 2) := by obtain ⟨g, t, c, hg, hgOV, ht⟩ := h.exists_computableTidilyInO obtain ⟨E, hred⟩ := exists_computableInO_toOV - refine DecidableInExpTime.of_computableInO (hg.comp hred) (fun φ => by + refine DecidableInExpTime.of_computableInO (.of_tidy (hg.comp hred.tidy)) (fun φ => by rw [← toOV_mem_OV_iff] exact hgOV _) (3 + 9 * c) (E + e) fun φ => ?_ set ε₀ := min ε 1 @@ -635,7 +638,7 @@ theorem OVH_of_SETH (h : SETH) : OVH := by obtain ⟨k, hk⟩ := h _ hδ refine hk ?_ rw [KSAT_eq_inter k (KSAT_subset_SAT k) le_rfl] - refine hSAT.inter (computableInPolyTime_all_length_le k).tidy ?_ + refine hSAT.inter (computableInPolyTime_all_length_le k) ?_ have : min ε 1 / 2 ≤ 1 / 2 := div_le_div_of_nonneg_right (min_le_right ε 1) zero_le_two linarith diff --git a/Complexity/Computability/Complexity/FineGrained/Reduction.lean b/Complexity/Computability/Complexity/FineGrained/Reduction.lean index 57b3a8fdb..5ae50832c 100644 --- a/Complexity/Computability/Complexity/FineGrained/Reduction.lean +++ b/Complexity/Computability/Complexity/FineGrained/Reduction.lean @@ -9,6 +9,7 @@ module public import Complexity.Computability.Complexity.FineGrained.Sparsification import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Basic +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain /-! # Reductions of linear size @@ -113,7 +114,7 @@ theorem DecidableInExpTime.of_reduction {f : α → β} have hfO := hf.inO obtain ⟨l, hl⟩ := hfO.length_le_time set K : ℝ := 1 + k * 2 ^ (δ * c) * (2 * l + 1) ^ e + k - refine Complexity.DecidableInExpTime.of_computableInO (hg.comp hfO) (fun a => (hfA a).trans (hgB (f a))) + refine Complexity.DecidableInExpTime.of_computableInO (.of_tidy (hg.comp hfO)) (fun a => (hfA a).trans (hgB (f a))) ⌈K⌉₊ (d * e + d) fun a => ?_ show _ ≤ _ set P : ℝ := ((encA a).length + 1) ^ d diff --git a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean index a9c9e8734..b02cefefc 100644 --- a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean +++ b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean @@ -372,6 +372,7 @@ private theorem computableTidilyInPolyTime_root (k : ℕ) : attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem computableTidilyInPolyTime_rounds (M : ℕ) : ComputableTidilyInPolyTime (rounds M) encCNF encNat := by + have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy have h := unary_div_const M unfold rounds fun_prop @@ -553,7 +554,7 @@ theorem decidableInExpTime_search {k M : ℕ} (hkK : k ≤ K) (hM : LeafBound K set E := dn + di + 3 * d + 2 * e + 3 set C₂ : ℝ := c * 2 ^ δ * ((c₁ : ℝ) + 1) ^ e + c + 1 set C₀ : ℝ := 2 + 5 * (C₁ + C₂) - refine DecidableInExpTime.of_computableInO h (fun φ => Iff.rfl) ⌈C₀⌉₊ E fun φ => ?_ + refine DecidableInExpTime.of_computableInO (.of_tidy h) (fun φ => Iff.rfl) ⌈C₀⌉₊ E fun φ => ?_ set L := (encCNF φ).length set N := φ.numVars set P := (L + 1) ^ E @@ -759,7 +760,7 @@ theorem exists_decidableInExpTime_numVars_of_length (k : ℕ) {ε : ℝ} (hε : · rintro ⟨hw, hs⟩ exact ⟨hw, (Sparsify.search_eq_true_iff hK hα hkK hLB hgsat hw).mp hs⟩ rw [heq] - exact (hsearch.inter (computableInPolyTime_all_length_le k).tidy (by positivity)).mono + exact (hsearch.inter (computableInPolyTime_all_length_le k) (by positivity)).mono (by linarith) /-- **Subexponential time in the clauses gives subexponential time in the variables** diff --git a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean index 170a97dc3..729104af9 100644 --- a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean +++ b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean @@ -53,6 +53,78 @@ namespace Cslib.HardnessEncoding open Turing.MultiTapeTM ComputableTidilyInPolyTime Cslib.AffineDisperser +/-! Tidy views of the plain certificates of `AffineDisperser`, for tidy `fun_prop` below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_getD_list + {α γ : Type} {input : α ↪ List Bool} + {enc : List γ ↪ List Bool} {L : α → List (List γ)} {i : α → ℕ} + (hL : ComputableTidilyInPolyTime L input (encList enc)) + (hi : ComputableTidilyInPolyTime i input encUnary) (d : List γ) : + ComputableTidilyInPolyTime (fun a => (L a).getD (i a) d) input enc := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_getD_list (.of_tidy hL) + (.of_tidy hi) d)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_tableEntry + {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {u w : α → ℕ} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hu : ComputableTidilyInPolyTime u input encUnary) + (hw : ComputableTidilyInPolyTime w input encUnary) : + ComputableTidilyInPolyTime (fun a => tableEntry (tab a) (u a) (w a)) input encBits := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_tableEntry (.of_tidy htab) + (.of_tidy hu) (.of_tidy hw))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_fieldMul' + {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {a b : α → List Bool} + (htab : ComputableTidilyInPolyTime tab input encTable) + (ha : ComputableTidilyInPolyTime a input encBits) + (hb : ComputableTidilyInPolyTime b input encBits) : + ComputableTidilyInPolyTime (fun x => fieldMul (tab x) (a x) (b x)) input encBits := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_fieldMul' (.of_tidy htab) + (.of_tidy ha) (.of_tidy hb))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_powerPred' + {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {y : α → List Bool} {k : α → ℕ} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hy : ComputableTidilyInPolyTime y input encBits) + (hk : ComputableTidilyInPolyTime k input encUnary) : + ComputableTidilyInPolyTime (fun x => powerPred (tab x) (y x) (k x)) input encBits := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_powerPred' (.of_tidy htab) + (.of_tidy hy) (.of_tidy hk))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_esymmCoords' + {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {t : α → ℕ} {zs : α → List (List Bool)} + (htab : ComputableTidilyInPolyTime tab input encTable) + (ht : ComputableTidilyInPolyTime t input encUnary) + (hzs : ComputableTidilyInPolyTime zs input (encList encBits)) : + ComputableTidilyInPolyTime (fun x => esymmCoords (tab x) (t x) (zs x)) input encBits := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_esymmCoords' (.of_tidy htab) + (.of_tidy ht) (.of_tidy hzs))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_traceVector' + {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} (htab : ComputableTidilyInPolyTime tab input encTable) : + ComputableTidilyInPolyTime (fun x => traceVector (tab x)) input encBits := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_traceVector' (.of_tidy htab))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_traceBit' + {α : Type} {input : α ↪ List Bool} + {τ a : α → List Bool} (hτ : ComputableTidilyInPolyTime τ input encBits) + (ha : ComputableTidilyInPolyTime a input encBits) : + ComputableTidilyInPolyTime (fun x => traceBit (τ x) (a x)) input encBool := + (ComputableInPolyTime.tidy (AffineDisperser.computableInPolyTime_traceBit' (.of_tidy hτ) + (.of_tidy ha))) + /-! ### Field arithmetic -/ /-- The multiplication table of the power basis, from the coefficient list of the modulus. -/ @@ -62,6 +134,17 @@ private theorem computableTidilyInPolyTime_powerMulTable : have := computableInPolyTime_powerTable.tidy fun_prop +private theorem computableTidilyInPolyTime_fieldInv' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {w : α → ℕ} {y : α → List Bool} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hy : ComputableTidilyInPolyTime y input encBits) : + ComputableTidilyInPolyTime (fun x => fieldInv (tab x) (w x) (y x)) input encBits := by + unfold fieldInv + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_fieldInv' + /-- Inverses in coordinates, as a composition rule. -/ @[fun_prop] theorem computableInPolyTime_fieldInv' {α : Type} {input : α ↪ List Bool} @@ -69,9 +152,8 @@ theorem computableInPolyTime_fieldInv' {α : Type} {input : α ↪ List Bool} (htab : ComputableInPolyTime tab input encTable) (hw : ComputableInPolyTime w input encUnary) (hy : ComputableInPolyTime y input encBits) : - ComputableInPolyTime (fun x => fieldInv (tab x) (w x) (y x)) input encBits := by - unfold fieldInv - fun_prop + ComputableInPolyTime (fun x => fieldInv (tab x) (w x) (y x)) input encBits := + .of_tidy (computableTidilyInPolyTime_fieldInv' htab.tidy hw.tidy hy.tidy) /-- The parameters of a Lagrange numerator: the table, the width, the node and the point. -/ private abbrev encLagrangePar : (List (List (List Bool)) × ℕ) × (List Bool × List Bool) ↪ @@ -117,6 +199,21 @@ private theorem computableTidilyInPolyTime_lagrangeNum : ComputableTidilyInPolyT unfold lagrangeNum exact h +private theorem computableTidilyInPolyTime_lagrangeNum' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {w : α → ℕ} {E : α → List (List Bool)} + {a t : α → List Bool} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hE : ComputableTidilyInPolyTime E input (encList encBits)) + (ha : ComputableTidilyInPolyTime a input encBits) + (ht : ComputableTidilyInPolyTime t input encBits) : + ComputableTidilyInPolyTime (fun x => lagrangeNum (tab x) (w x) (E x) (a x) (t x)) input + encBits := by + simpa only [Function.comp_def] using + computableTidilyInPolyTime_lagrangeNum.comp (((htab.prod hw).prod hE).prod (ha.prod ht)) + +attribute [local fun_prop] computableTidilyInPolyTime_lagrangeNum' + /-- The Lagrange numerator, as a composition rule. -/ @[fun_prop] theorem computableInPolyTime_lagrangeNum' {α : Type} {input : α ↪ List Bool} @@ -128,15 +225,23 @@ theorem computableInPolyTime_lagrangeNum' {α : Type} {input : α ↪ List Bool} (ha : ComputableInPolyTime a input encBits) (ht : ComputableInPolyTime t input encBits) : ComputableInPolyTime (fun x => lagrangeNum (tab x) (w x) (E x) (a x) (t x)) input + encBits := + .of_tidy (computableTidilyInPolyTime_lagrangeNum' htab.tidy hw.tidy hE.tidy ha.tidy ht.tidy) + +private theorem computableTidilyInPolyTime_lagrangeVal' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {w : α → ℕ} {E : α → List (List Bool)} + {a t : α → List Bool} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hE : ComputableTidilyInPolyTime E input (encList encBits)) + (ha : ComputableTidilyInPolyTime a input encBits) + (ht : ComputableTidilyInPolyTime t input encBits) : + ComputableTidilyInPolyTime (fun x => lagrangeVal (tab x) (w x) (E x) (a x) (t x)) input encBits := by - have htab := htab.tidy - have hw := hw.tidy - have hE := hE.tidy - have ha := ha.tidy - have ht := ht.tidy - refine .of_tidy ?_ - simpa only [Function.comp_def] using - computableTidilyInPolyTime_lagrangeNum.comp (((htab.prod hw).prod hE).prod (ha.prod ht)) + unfold lagrangeVal + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_lagrangeVal' /-- A Lagrange basis polynomial at a point, as a composition rule. -/ @[fun_prop] @@ -149,9 +254,8 @@ theorem computableInPolyTime_lagrangeVal' {α : Type} {input : α ↪ List Bool} (ha : ComputableInPolyTime a input encBits) (ht : ComputableInPolyTime t input encBits) : ComputableInPolyTime (fun x => lagrangeVal (tab x) (w x) (E x) (a x) (t x)) input - encBits := by - unfold lagrangeVal - fun_prop + encBits := + .of_tidy (computableTidilyInPolyTime_lagrangeVal' htab.tidy hw.tidy hE.tidy ha.tidy ht.tidy) /-- The input of a term: the table, the width, the block length and the number of blocks; the nodes and the coordinates of the point; and the accepted input. -/ @@ -190,6 +294,23 @@ private theorem computableTidilyInPolyTime_termVal : ComputableTidilyInPolyTime unfold termVal exact h +private theorem computableTidilyInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {w b M : α → ℕ} {E xs : α → List (List Bool)} + {z : α → List Bool} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hb : ComputableTidilyInPolyTime b input encUnary) + (hM : ComputableTidilyInPolyTime M input encUnary) + (hE : ComputableTidilyInPolyTime E input (encList encBits)) + (hxs : ComputableTidilyInPolyTime xs input (encList encBits)) + (hz : ComputableTidilyInPolyTime z input encBits) : + ComputableTidilyInPolyTime (fun x => termVal (tab x) (w x) (b x) (M x) (E x) (xs x) (z x)) + input encBits := by + simpa only [Function.comp_def] using computableTidilyInPolyTime_termVal.comp + ((((htab.prod hw).prod hb).prod hM).prod ((hE.prod hxs).prod hz)) + +attribute [local fun_prop] computableTidilyInPolyTime_termVal' + /-- A term of the extension, as a composition rule. -/ @[fun_prop] theorem computableInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} @@ -203,17 +324,24 @@ theorem computableInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} (hxs : ComputableInPolyTime xs input (encList encBits)) (hz : ComputableInPolyTime z input encBits) : ComputableInPolyTime (fun x => termVal (tab x) (w x) (b x) (M x) (E x) (xs x) (z x)) + input encBits := + .of_tidy (computableTidilyInPolyTime_termVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hxs.tidy hz.tidy) + +private theorem computableTidilyInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} + {tab : α → List (List (List Bool))} {w b M : α → ℕ} {E pts xs : α → List (List Bool)} + (htab : ComputableTidilyInPolyTime tab input encTable) + (hw : ComputableTidilyInPolyTime w input encUnary) + (hb : ComputableTidilyInPolyTime b input encUnary) + (hM : ComputableTidilyInPolyTime M input encUnary) + (hE : ComputableTidilyInPolyTime E input (encList encBits)) + (hpts : ComputableTidilyInPolyTime pts input (encList encBits)) + (hxs : ComputableTidilyInPolyTime xs input (encList encBits)) : + ComputableTidilyInPolyTime (fun x => ldeVal (tab x) (w x) (b x) (M x) (E x) (pts x) (xs x)) input encBits := by - have htab := htab.tidy - have hw := hw.tidy - have hb := hb.tidy - have hM := hM.tidy - have hE := hE.tidy - have hxs := hxs.tidy - have hz := hz.tidy - refine .of_tidy ?_ - simpa only [Function.comp_def] using computableTidilyInPolyTime_termVal.comp - ((((htab.prod hw).prod hb).prod hM).prod ((hE.prod hxs).prod hz)) + unfold ldeVal + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_ldeVal' /-- **The low-degree extension at a point is polynomial-time**, as a composition rule. -/ @[fun_prop] @@ -227,9 +355,8 @@ theorem computableInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} (hpts : ComputableInPolyTime pts input (encList encBits)) (hxs : ComputableInPolyTime xs input (encList encBits)) : ComputableInPolyTime (fun x => ldeVal (tab x) (w x) (b x) (M x) (E x) (pts x) (xs x)) - input encBits := by - unfold ldeVal - fun_prop + input encBits := + .of_tidy (computableTidilyInPolyTime_ldeVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hpts.tidy hxs.tidy) /-! ### The padded program -/ @@ -261,15 +388,20 @@ private theorem polyBounded_two_pow_mul_padLength (c : ℕ) : rw [encUnary_apply, List.length_replicate] at this omega -/-- The length parameter is polynomial-time. -/ -@[fun_prop] -theorem computableInPolyTime_padLength : - ComputableInPolyTime padLength (encPair encBits encUnary) encUnary := by - refine .of_tidy ?_ +private theorem computableTidilyInPolyTime_padLength : + ComputableTidilyInPolyTime padLength (encPair encBits encUnary) encUnary := by unfold padLength have := unary_log_two fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_padLength + +/-- The length parameter is polynomial-time. -/ +@[fun_prop] +theorem computableInPolyTime_padLength : + ComputableInPolyTime padLength (encPair encBits encUnary) encUnary := + .of_tidy (computableTidilyInPolyTime_padLength) + /-- **The padded program is polynomial-time**, for any function `gL` on bit words computable in time `2 ^ O(n)`: every loop runs over at most `p ^ O(1)` elements for the padding `p`, the modulus is found among `2 ^ (w + 1) ≤ 2 p + 2` codes, and `gL` is called on words of length at most @@ -356,7 +488,7 @@ theorem encodedLanguage_mem_E {L : Language Bool} (hL : (L : Set (List Bool)) obtain ⟨k, hk⟩ := mem_E_iff.1 hL obtain ⟨gL, hgL, hgLO⟩ := exists_computableInO_of_mem_DTIME hk have h := setOf_mem_E_of_computableInPolyTime_pad - (computableInPolyTime_paddedProgram M (.of_tidy hgLO)) + (computableInPolyTime_paddedProgram M hgLO) have hset : (encodedLanguage L M : Set (List Bool)) = {y | paddedProgram M gL (y, 2 ^ y.length) = true} := by ext y diff --git a/Complexity/Computability/Complexity/Parameterized.lean b/Complexity/Computability/Complexity/Parameterized.lean index 9b94d2972..71773f0ab 100644 --- a/Complexity/Computability/Complexity/Parameterized.lean +++ b/Complexity/Computability/Complexity/Parameterized.lean @@ -39,10 +39,11 @@ monotone (`Cslib.Complexity.mem_FPT_iff_exists_monotone`). `Cslib.Complexity.FPTReducible encA encB κA κB A B`: `A` reduces to `B` by an *fpt-reduction* [FlumGrohe2006, Definition 2.1] [CyganEtAl2015, Definition 13.1]: a map `f` computable by some machine within time `F (κA a) * (L + 1) ^ c` (`Cslib.Complexity.ComputableInFPTTime`) with -`a ∈ A ↔ f a ∈ B` and `κB (f a) ≤ h (κA a)` for a function `h`. The tidy notion -`Cslib.Complexity.ComputableTidilyInFPTTime` agrees with the plain one -(`Cslib.Complexity.computableInFPTTime_iff_computableTidilyInFPTTime`), and proofs that compose -reductions use it through `Cslib.Complexity.fptReducible_iff_tidy`. Polynomial-time +`a ∈ A ↔ f a ∈ B` and `κB (f a) ≤ h (κA a)` for a function `h`. Fpt-time computability is closed +under case distinction and under composition along a function that bounds the parameter +(`Cslib.Complexity.ComputableInFPTTime.ite`, `Cslib.Complexity.ComputableInFPTTime.comp`), and +polynomial time is fpt time for every parameter +(`Turing.MultiTapeTM.ComputableInPolyTime.computableInFPTTime`). Polynomial-time reductions with a parameter bound are fpt-reductions (`Cslib.Complexity.FPTReducible.of_computableInPolyTime`). `FPT` and `XP` are closed under fpt-reductions. As for `FPT`, the functions `F` and `h` are arbitrary, where the cited @@ -52,8 +53,7 @@ definitions require them to be computable. * `Cslib.Complexity.FPT`, `Cslib.Complexity.XP`: fixed-parameter tractable and slicewise polynomial problems. -* `Cslib.Complexity.ComputableInFPTTime`, `Cslib.Complexity.ComputableTidilyInFPTTime`: functions - computable in fpt time, by any machine and by a tidy one. +* `Cslib.Complexity.ComputableInFPTTime`: functions computable in fpt time. * `Cslib.Complexity.FPTReducible`: fpt-reductions. ## Main results @@ -61,10 +61,10 @@ definitions require them to be computable. * `Cslib.Complexity.mem_FPT`, `Cslib.Complexity.mem_XP`: unfolding the classes. * `Turing.MultiTapeTM.ComputableInTimeAndSpace.computableInFPTTime`: a time bound alone gives fpt-time computability. -* `Cslib.Complexity.computableInFPTTime_iff_computableTidilyInFPTTime`: the plain and tidy notions - of fpt-time computability agree, with the shortcuts `Cslib.Complexity.ComputableInFPTTime.tidy`, - `Cslib.Complexity.ComputableInFPTTime.of_tidy` and - `Cslib.Complexity.ComputableTidilyInFPTTime.computableInFPTTime`. +* `Turing.MultiTapeTM.ComputableInPolyTime.computableInFPTTime`, + `Cslib.Complexity.ComputableInFPTTime.ite`, `Cslib.Complexity.ComputableInFPTTime.comp`: + polynomial time is fpt time, and fpt time is closed under case distinction and composition. +* `Cslib.Complexity.mem_FPT_iff_computableInFPTTime`: `FPT` in terms of fpt-time computability. * `Cslib.Complexity.P_subset_FPT`, `Cslib.Complexity.FPT_subset_XP`: `P ⊆ FPT ⊆ XP`, for every parameter. * `Cslib.Complexity.FPT_eq_P_of_le`, `Cslib.Complexity.XP_eq_P_of_le`: for a bounded parameter, @@ -77,7 +77,6 @@ definitions require them to be computable. (`Cslib.Complexity.SAT_mem_FPT`, `Cslib.Complexity.KSAT_mem_FPT`). * `Cslib.Complexity.compl_mem_FPT`, `Cslib.Complexity.inter_mem_FPT`, `Cslib.Complexity.union_mem_FPT`, `Cslib.Complexity.compl_mem_XP`: Boolean closure. -* `Cslib.Complexity.fptReducible_iff_tidy`: fpt-reductions with tidy fpt-time computability. * `Cslib.Complexity.FPTReducible.refl`, `Cslib.Complexity.FPTReducible.trans`: fpt-reducibility is a preorder; `Cslib.Complexity.FPTReducible.compl` passes to complements. * `Cslib.Complexity.FPTReducible.mem_FPT`, `Cslib.Complexity.FPTReducible.mem_XP`: `FPT` and `XP` @@ -250,39 +249,38 @@ def ComputableInFPTTime {α β : Type*} (f : α → β) (encA : α ↪ List Bool ∃ (F : ℕ → ℕ) (c : ℕ), ComputableInTimeAndSpace f encA encB (fun a => F (κ a) * ((encA a).length + 1) ^ c) fun a => F (κ a) * ((encA a).length + 1) ^ c -/-- `f` is tidily computable in fpt time with respect to the parameter `κ`: within time and space -`F (κ a) * (|encA a| + 1) ^ c` up to a constant factor, for a function `F : ℕ → ℕ` and a constant -`c`. -/ -def ComputableTidilyInFPTTime {α β : Type*} (f : α → β) (encA : α ↪ List Bool) - (encB : β ↪ List Bool) (κ : α → ℕ) : Prop := - ∃ (F : ℕ → ℕ) (c : ℕ), ComputableTidilyInO f encA encB - (fun a => F (κ a) * ((encA a).length + 1) ^ c) fun a => F (κ a) * ((encA a).length + 1) ^ c - section Plain variable {α β : Type*} {f : α → β} {encA : α ↪ List Bool} {encB : β ↪ List Bool} {κ : α → ℕ} -/-- A function computable in fpt time is tidily computable in fpt time: the output is within the -time bound, which is also the space bound. -/ -theorem ComputableInFPTTime.tidy (h : ComputableInFPTTime f encA encB κ) : - ComputableTidilyInFPTTime f encA encB κ := +/-- A function computable in fpt time is computed tidily within the same bound, up to a constant +factor: the output is within the time bound, which is also the space bound. -/ +private theorem ComputableInFPTTime.exists_computableTidilyInO + (h : ComputableInFPTTime f encA encB κ) : + ∃ (F : ℕ → ℕ) (c : ℕ), ComputableTidilyInO f encA encB + (fun a => F (κ a) * ((encA a).length + 1) ^ c) fun a => F (κ a) * ((encA a).length + 1) ^ c := let ⟨F, c, hc⟩ := h ⟨F, c, hc.computableTidilyInO hc.length_le⟩ -/-- A function tidily computable in fpt time is computable in fpt time, by the same machine. -/ -theorem ComputableInFPTTime.of_tidy (h : ComputableTidilyInFPTTime f encA encB κ) : +/-- A tidy computation within an fpt bound, up to a constant factor, is a computation in fpt time, +by the same machine. -/ +private theorem computableInFPTTime_of_computableTidilyInO {F : ℕ → ℕ} {c : ℕ} + (h : ComputableTidilyInO f encA encB (fun a => F (κ a) * ((encA a).length + 1) ^ c) + fun a => F (κ a) * ((encA a).length + 1) ^ c) : ComputableInFPTTime f encA encB κ := by - obtain ⟨F, c, d, hd, -⟩ := h + obtain ⟨d, hd, -⟩ := h have hle (a : α) : d * (F (κ a) * ((encA a).length + 1) ^ c + 1) ≤ d * (F (κ a) + 1) * ((encA a).length + 1) ^ c := by have := Nat.mul_le_mul_left d (Nat.one_le_pow c _ (Nat.succ_pos (encA a).length)) nlinarith exact ⟨fun k => d * (F k + 1), c, hd.computableInTimeAndSpace.mono hle hle⟩ -/-- `Cslib.Complexity.ComputableInFPTTime.of_tidy` for dot notation on a tidy hypothesis. -/ -theorem ComputableTidilyInFPTTime.computableInFPTTime - (h : ComputableTidilyInFPTTime f encA encB κ) : ComputableInFPTTime f encA encB κ := - .of_tidy h +/-- A computation within an fpt bound, up to a constant factor, is a computation in fpt time. -/ +theorem _root_.Turing.MultiTapeTM.ComputableInO.computableInFPTTime {F : ℕ → ℕ} {c : ℕ} + (h : ComputableInO f encA encB (fun a => F (κ a) * ((encA a).length + 1) ^ c) + fun a => F (κ a) * ((encA a).length + 1) ^ c) : + ComputableInFPTTime f encA encB κ := + computableInFPTTime_of_computableTidilyInO h.tidy /-- **A time bound alone suffices.** A function computable by some machine within time `F (κ a) * (|encA a| + 1) ^ c`, with any space bound, is computable in fpt time: a machine with `k` @@ -302,31 +300,27 @@ theorem _root_.Turing.MultiTapeTM.ComputableInTimeAndSpace.computableInFPTTime { h.mono (fun a => by dsimp only; have := hle a 1 (by omega); omega) fun a => by dsimp only; exact hle a k (by omega)⟩ -/-- **Plain and tidy computability in fpt time agree.** -/ -theorem computableInFPTTime_iff_computableTidilyInFPTTime : - ComputableInFPTTime f encA encB κ ↔ ComputableTidilyInFPTTime f encA encB κ := - ⟨ComputableInFPTTime.tidy, ComputableInFPTTime.of_tidy⟩ - end Plain variable {α β γ : Type} {encA : α ↪ List Bool} {encB : β ↪ List Bool} {encC : γ ↪ List Bool} {κ κA : α → ℕ} {κB : β → ℕ} {κC : γ → ℕ} /-- A function computable in polynomial time is computable in fpt time, for every parameter. -/ -theorem _root_.Turing.MultiTapeTM.ComputableTidilyInPolyTime.computableTidilyInFPTTime {f : α → β} - (hf : ComputableTidilyInPolyTime f encA encB) (κ : α → ℕ) : - ComputableTidilyInFPTTime f encA encB κ := - let ⟨d, _, hf⟩ := hf.exists_degree - ⟨fun _ => 1, d, hf.inO.mono_le (fun _ => (one_mul _).ge) fun _ => (one_mul _).ge⟩ +theorem _root_.Turing.MultiTapeTM.ComputableInPolyTime.computableInFPTTime {f : α → β} + (hf : ComputableInPolyTime f encA encB) (κ : α → ℕ) : + ComputableInFPTTime f encA encB κ := + let ⟨d, _, hf⟩ := hf.tidy.exists_degree + computableInFPTTime_of_computableTidilyInO (F := fun _ => 1) (c := d) + (hf.inO.mono_le (fun _ => (one_mul _).ge) fun _ => (one_mul _).ge) /-- **Case distinction in fpt time.** -/ -theorem ComputableTidilyInFPTTime.ite {p : α → Bool} {f g : α → β} - (hp : ComputableTidilyInFPTTime p encA encBool κ) - (hf : ComputableTidilyInFPTTime f encA encB κ) (hg : ComputableTidilyInFPTTime g encA encB κ) : - ComputableTidilyInFPTTime (fun a => if p a then f a else g a) encA encB κ := by - obtain ⟨F₁, c₁, hp⟩ := hp - obtain ⟨F₂, c₂, hf⟩ := hf - obtain ⟨F₃, c₃, hg⟩ := hg +theorem ComputableInFPTTime.ite {p : α → Bool} {f g : α → β} + (hp : ComputableInFPTTime p encA encBool κ) + (hf : ComputableInFPTTime f encA encB κ) (hg : ComputableInFPTTime g encA encB κ) : + ComputableInFPTTime (fun a => if p a then f a else g a) encA encB κ := by + obtain ⟨F₁, c₁, hp⟩ := ComputableInFPTTime.exists_computableTidilyInO hp + obtain ⟨F₂, c₂, hf⟩ := ComputableInFPTTime.exists_computableTidilyInO hf + obtain ⟨F₃, c₃, hg⟩ := ComputableInFPTTime.exists_computableTidilyInO hg have key : ∀ a, (F₁ (κ a) * ((encA a).length + 1) ^ c₁ + if p a then F₂ (κ a) * ((encA a).length + 1) ^ c₂ else F₃ (κ a) * ((encA a).length + 1) ^ c₃) ≤ @@ -340,7 +334,8 @@ theorem ComputableTidilyInFPTTime.ite {p : α → Bool} {f g : α → β} have h₃ := hle c₃ (by omega) (F₃ (κ a)) rw [Nat.add_mul, Nat.add_mul] split_ifs <;> omega - exact ⟨fun k => F₁ k + F₂ k + F₃ k, c₁ + c₂ + c₃, (hp.ite hf hg).mono_le key key⟩ + exact computableInFPTTime_of_computableTidilyInO (F := fun k => F₁ k + F₂ k + F₃ k) + (c := c₁ + c₂ + c₃) ((hp.ite hf hg).mono_le key key) /-- The arithmetic of composition: a bound `F₂ (n + 1) ^ e` on an output of length `n` within `l (F₁ (L + 1) ^ c₁ + 1)`, after a computation within `F₁ (L + 1) ^ c₁`. -/ @@ -386,17 +381,18 @@ private theorem computableTidilyInO_comp {f : α → β} {g : β → γ} {F₁ : exact ⟨l, (hg.comp hf).mono_le key key⟩ /-- **Composition in fpt time**, along a function that bounds the parameter. -/ -theorem ComputableTidilyInFPTTime.comp {f : α → β} {g : β → γ} - (hg : ComputableTidilyInFPTTime g encB encC κB) (hf : ComputableTidilyInFPTTime f encA encB κA) +theorem ComputableInFPTTime.comp {f : α → β} {g : β → γ} + (hg : ComputableInFPTTime g encB encC κB) (hf : ComputableInFPTTime f encA encB κA) {h : ℕ → ℕ} (hκ : ∀ a, κB (f a) ≤ h (κA a)) : - ComputableTidilyInFPTTime (g ∘ f) encA encC κA := by - obtain ⟨F₂, c₂, hg⟩ := hg - obtain ⟨F₁, c₁, hf⟩ := hf + ComputableInFPTTime (g ∘ f) encA encC κA := by + obtain ⟨F₂, c₂, hg⟩ := ComputableInFPTTime.exists_computableTidilyInO hg + obtain ⟨F₁, c₁, hf⟩ := ComputableInFPTTime.exists_computableTidilyInO hf obtain ⟨l, hgf⟩ := computableTidilyInO_comp (e₂ := fun _ => c₂) (F₂' := fun k => ∑ j ∈ Finset.range (h k + 1), F₂ j) (E := fun _ => c₂) hg hf (fun a => le_sum_range_succ (hκ a)) fun _ => le_rfl - exact ⟨fun k => F₁ k + (∑ j ∈ Finset.range (h k + 1), F₂ j) * ((l + 1) * (F₁ k + 1)) ^ c₂, - c₁ + c₁ * c₂, hgf⟩ + exact computableInFPTTime_of_computableTidilyInO + (F := fun k => F₁ k + (∑ j ∈ Finset.range (h k + 1), F₂ j) * ((l + 1) * (F₁ k + 1)) ^ c₂) + (c := c₁ + c₁ * c₂) hgf /-- Bounds of the shape `T a`, cast to the reals, are tidy bounds. -/ private theorem decidableInTimeO_natCast_iff {A : Set α} {T : α → ℕ} : @@ -412,29 +408,28 @@ private theorem decidableInTimeO_natCast_iff {A : Set α} {T : α → ℕ} : exact_mod_cast this exact ⟨g, hg.mono k ht' ht', hA⟩ · rintro ⟨g, hg, hA⟩ - exact DecidableInTimeO.of_computableInO hg hA fun _ => le_rfl + exact DecidableInTimeO.of_computableInO (.of_tidy hg) hA fun _ => le_rfl /-- **`FPT` in terms of fpt-time computability**: a problem is fixed-parameter tractable exactly when a Boolean function deciding it is tidily computable in fpt time. -/ theorem mem_FPT_iff_computableInFPTTime {A : Set α} : A ∈ FPT encA κ ↔ ∃ g : α → Bool, ComputableInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by - have this : A ∈ FPT encA κ ↔ ∃ g : α → Bool, ComputableTidilyInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by - have e : ∀ (f : ℕ → ℕ) (c : ℕ), (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ c) = - fun a => ((f (κ a) * ((encA a).length + 1) ^ c : ℕ) : ℝ) := fun f c => by - funext a - push_cast - rfl - constructor - · rintro ⟨f, c, h⟩ - rw [e, decidableInTimeO_natCast_iff] at h - obtain ⟨g, hg, hA⟩ := h - exact ⟨g, ⟨f, c, hg⟩, hA⟩ - · rintro ⟨g, ⟨f, c, hg⟩, hA⟩ - refine ⟨f, c, ?_⟩ - rw [e, decidableInTimeO_natCast_iff] - exact ⟨g, hg, hA⟩ - simpa only [computableInFPTTime_iff_computableTidilyInFPTTime] using this + have e : ∀ (f : ℕ → ℕ) (c : ℕ), (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ c) = + fun a => ((f (κ a) * ((encA a).length + 1) ^ c : ℕ) : ℝ) := fun f c => by + funext a + push_cast + rfl + constructor + · rintro ⟨f, c, h⟩ + rw [e, decidableInTimeO_natCast_iff] at h + obtain ⟨g, hg, hA⟩ := h + exact ⟨g, computableInFPTTime_of_computableTidilyInO hg, hA⟩ + · rintro ⟨g, hg, hA⟩ + obtain ⟨f, c, hg⟩ := ComputableInFPTTime.exists_computableTidilyInO hg + refine ⟨f, c, ?_⟩ + rw [e, decidableInTimeO_natCast_iff] + exact ⟨g, hg, hA⟩ /-- **`XP` in terms of tidy computability.** -/ theorem mem_XP_iff_exists_computableInO {A : Set α} : @@ -461,9 +456,10 @@ theorem mem_XP_iff_exists_computableInO {A : Set α} : /-- **Bounded parameters.** For a parameter bounded by a constant, `FPT` is `P`. -/ theorem FPT_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : FPT encA κ = P encA := by refine subset_antisymm (fun A hA => ?_) P_subset_FPT - obtain ⟨g, ⟨f, c, hg⟩, hA⟩ := + obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp (FPT_subset_FPT_of_le_comp (κ' := fun _ => 0) (h := fun _ => K) hκ hA) + obtain ⟨f, c, hg⟩ := ComputableInFPTTime.exists_computableTidilyInO hg exact ⟨g, .of_tidy <| hg.computableTidilyInPolyTime (.of_forall_le (f 0) c fun _ => le_rfl) (.of_forall_le (f 0) c fun _ => le_rfl), hA⟩ @@ -473,7 +469,7 @@ theorem XP_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : XP encA κ = P encA obtain ⟨g, f, e, hg, hA⟩ := mem_XP_iff_exists_computableInO.mp (XP_subset_XP_of_le_comp (κ' := fun _ => 0) (h := fun _ => K) hκ hA) - exact ⟨g, .of_tidy <| hg.computableTidilyInPolyTime (.of_forall_le (f 0) (e 0) fun _ => le_rfl) + exact ⟨g, .of_tidy <| hg.tidy.computableTidilyInPolyTime (.of_forall_le (f 0) (e 0) fun _ => le_rfl) (.of_forall_le (f 0) (e 0) fun _ => le_rfl), hA⟩ /-! ### Boolean closure -/ @@ -482,8 +478,8 @@ theorem XP_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : XP encA κ = P encA theorem compl_mem_FPT {A : Set α} (hA : A ∈ FPT encA κ) : Aᶜ ∈ FPT encA κ := by obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg.ite - ((ComputableTidilyInPolyTime.const false).computableTidilyInFPTTime κ) - ((ComputableTidilyInPolyTime.const true).computableTidilyInFPTTime κ), fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const false)).computableInFPTTime κ) + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ), fun a => ?_⟩ simp only [Set.mem_compl_iff, hA] cases g a <;> simp @@ -493,7 +489,7 @@ theorem inter_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT en obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite hg₂ - ((ComputableTidilyInPolyTime.const false).computableTidilyInFPTTime κ), fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const false)).computableInFPTTime κ), fun a => ?_⟩ simp only [Set.mem_inter_iff, hA, hB] cases g₁ a <;> simp @@ -503,17 +499,17 @@ theorem union_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT en obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite - ((ComputableTidilyInPolyTime.const true).computableTidilyInFPTTime κ) hg₂, fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ) hg₂, fun a => ?_⟩ simp only [Set.mem_union, hA, hB] cases g₁ a <;> simp /-- **`XP` is closed under complement.** -/ theorem compl_mem_XP {A : Set α} (hA : A ∈ XP encA κ) : Aᶜ ∈ XP encA κ := by obtain ⟨g, f, e, hg, hA⟩ := mem_XP_iff_exists_computableInO.mp hA - have h := hg.ite (ComputableTidilyInO.const (encMid := encBool) false) + have h := hg.tidy.ite (ComputableTidilyInO.const (encMid := encBool) false) (ComputableTidilyInO.const (encMid := encBool) true) refine mem_XP_iff_exists_computableInO.mpr ⟨_, fun k => f k + 1, fun k => e k + 1, - h.mono_le (fun a => ?_) (fun a => ?_), fun a => ?_⟩ + .of_tidy (h.mono_le (fun a => ?_) (fun a => ?_)), fun a => ?_⟩ rotate_left 2 · simp only [Set.mem_compl_iff, hA] cases g a <;> simp @@ -558,35 +554,18 @@ theorem fptReducible_iff_manyOneReducibleBy : ManyOneReducibleBy (ComputableInFPTWithParam encA encB κA κB) A B := Iff.rfl -/-- `Cslib.Complexity.ComputableInFPTWithParam` with the tidy notion of fpt-time computability, for -proofs that compose machines. -/ -theorem computableInFPTWithParam_iff_tidy {f : α → β} : - ComputableInFPTWithParam encA encB κA κB f ↔ - ComputableTidilyInFPTTime f encA encB κA ∧ ∃ h : ℕ → ℕ, ∀ a, κB (f a) ≤ h (κA a) := - and_congr_left' computableInFPTTime_iff_computableTidilyInFPTTime - -/-- Fpt-reducibility with the tidy notion of fpt-time computability, for proofs that compose -machines. -/ -theorem fptReducible_iff_tidy : - FPTReducible encA encB κA κB A B ↔ - ∃ f : α → β, (ComputableTidilyInFPTTime f encA encB κA ∧ - ∃ h : ℕ → ℕ, ∀ a, κB (f a) ≤ h (κA a)) ∧ ∀ a, a ∈ A ↔ f a ∈ B := by - simp only [← computableInFPTTime_iff_computableTidilyInFPTTime] - rfl - /-- **Polynomial-time reductions bounding the parameter are fpt-reductions.** -/ theorem FPTReducible.of_computableInPolyTime {f : α → β} (hf : ComputableInPolyTime f encA encB) {h : ℕ → ℕ} (hκ : ∀ a, κB (f a) ≤ h (κA a)) - (hfA : ∀ a, a ∈ A ↔ f a ∈ B) : FPTReducible encA encB κA κB A B := by - have hf := hf.tidy - exact ⟨f, ⟨(hf.computableTidilyInFPTTime κA).computableInFPTTime, h, hκ⟩, hfA⟩ + (hfA : ∀ a, a ∈ A ↔ f a ∈ B) : FPTReducible encA encB κA κB A B := + ⟨f, ⟨hf.computableInFPTTime κA, h, hκ⟩, hfA⟩ /-- Every parameterized problem reduces to itself by the identity. -/ @[refl] theorem FPTReducible.refl (encA : α ↪ List Bool) (κA : α → ℕ) (A : Set α) : FPTReducible encA encA κA κA A A := ManyOneReducibleBy.refl - ⟨(ComputableTidilyInPolyTime.id'.computableTidilyInFPTTime κA).computableInFPTTime, id, + ⟨(ComputableInPolyTime.of_tidy ComputableTidilyInPolyTime.id').computableInFPTTime κA, id, fun _ => le_rfl⟩ A /-- **Fpt-reductions compose.** -/ @@ -594,7 +573,7 @@ theorem FPTReducible.refl (encA : α ↪ List Bool) (κA : α → ℕ) (A : Set theorem FPTReducible.trans (hAB : FPTReducible encA encB κA κB A B) (hBC : FPTReducible encB encC κB κC B C) : FPTReducible encA encC κA κC A C := ManyOneReducibleBy.trans - (fun _ _ ⟨hf, h₁, hκ₁⟩ ⟨hg, h₂, hκ₂⟩ => ⟨(hg.tidy.comp hf.tidy hκ₁).computableInFPTTime, + (fun _ _ ⟨hf, h₁, hκ₁⟩ ⟨hg, h₂, hκ₂⟩ => ⟨hg.comp hf hκ₁, fun k => ∑ j ∈ Finset.range (h₁ k + 1), h₂ j, fun a => (hκ₂ _).trans (le_sum_range_succ (hκ₁ a))⟩) hAB hBC @@ -608,22 +587,23 @@ theorem FPTReducible.compl (h : FPTReducible encA encB κA κB A B) : theorem FPTReducible.mem_FPT (hAB : FPTReducible encA encB κA κB A B) (hB : B ∈ FPT encB κB) : A ∈ FPT encA κA := mem_FPT_iff_computableInFPTTime.mpr - (ManyOneReducibleBy.trans (C := {true}) (fun _ _ ⟨hf, _, hκ⟩ hg => hg.comp hf.tidy hκ) + (ManyOneReducibleBy.trans (C := {true}) (fun _ _ ⟨hf, _, hκ⟩ hg => hg.comp hf hκ) hAB (mem_FPT_iff_computableInFPTTime.mp hB)) /-- **`XP` is closed under fpt-reductions.** -/ theorem FPTReducible.mem_XP (hAB : FPTReducible encA encB κA κB A B) (hB : B ∈ XP encB κB) : A ∈ XP encA κA := by - obtain ⟨f, ⟨⟨F₁, c₁, hf⟩, h, hκ⟩, hAB⟩ := fptReducible_iff_tidy.mp hAB + obtain ⟨f, ⟨hf, h, hκ⟩, hAB⟩ := hAB + obtain ⟨F₁, c₁, hf⟩ := ComputableInFPTTime.exists_computableTidilyInO hf obtain ⟨g, F₂, e₂, hg, hB⟩ := mem_XP_iff_exists_computableInO.mp hB obtain ⟨l, hgf⟩ := computableTidilyInO_comp (F₂' := fun k => ∑ j ∈ Finset.range (h k + 1), F₂ j) - (E := fun k => ∑ j ∈ Finset.range (h k + 1), e₂ j) hg hf + (E := fun k => ∑ j ∈ Finset.range (h k + 1), e₂ j) hg.tidy hf (fun a => le_sum_range_succ (hκ a)) fun a => le_sum_range_succ (hκ a) exact mem_XP_iff_exists_computableInO.mpr ⟨g ∘ f, fun k => F₁ k + (∑ j ∈ Finset.range (h k + 1), F₂ j) * ((l + 1) * (F₁ k + 1)) ^ ∑ j ∈ Finset.range (h k + 1), e₂ j, - fun k => c₁ + c₁ * ∑ j ∈ Finset.range (h k + 1), e₂ j, hgf, + fun k => c₁ + c₁ * ∑ j ∈ Finset.range (h k + 1), e₂ j, .of_tidy hgf, fun a => (hAB a).trans (hB (f a))⟩ end Reduction diff --git a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean index 30d417cc6..937410449 100644 --- a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean +++ b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean @@ -54,7 +54,6 @@ Problems in `P` have kernels of constant size (`Cslib.Complexity.hasPolyKernel_o ## Main results -* `Cslib.Complexity.isKernelization_iff_tidy`: kernelizations with a tidy polynomial-time map. * `Cslib.Complexity.IsKernelization.fptReducible`: every kernelization is an fpt-reduction from the problem to itself. * `Cslib.Complexity.HasKernel.mem_FPT`, `Cslib.Complexity.hasKernel_of_mem_FPT`, @@ -106,15 +105,6 @@ polynomially bounded size bound. -/ def HasPolyKernel (enc : α ↪ List Bool) (κ : α → ℕ) (A : Set α) : Prop := ∃ (K : α → α) (g : ℕ → ℕ), PolynomiallyBounded g ∧ IsKernelization enc κ A K g -/-- `Cslib.Complexity.IsKernelization` with a tidy polynomial-time kernelization, for proofs that -compose machines. -/ -theorem isKernelization_iff_tidy {enc : α ↪ List Bool} {κ : α → ℕ} {A : Set α} {K : α → α} - {g : ℕ → ℕ} : IsKernelization enc κ A K g ↔ ComputableTidilyInPolyTime K enc enc ∧ - (∀ a, K a ∈ A ↔ a ∈ A) ∧ (∀ a, (enc (K a)).length ≤ g (κ a)) ∧ - ∀ a, κ (K a) ≤ g (κ a) := - ⟨fun h => ⟨h.polyTime.tidy, h.mem_iff, h.length_le, h.parameter_le⟩, - fun ⟨h₁, h₂, h₃, h₄⟩ => ⟨.of_tidy h₁, h₂, h₃, h₄⟩⟩ - theorem HasPolyKernel.hasKernel {enc : α ↪ List Bool} {κ : α → ℕ} {A : Set α} (h : HasPolyKernel enc κ A) : HasKernel enc κ A := let ⟨K, g, _, hK⟩ := h @@ -127,7 +117,7 @@ variable {α : Type} {enc : α ↪ List Bool} {κ : α → ℕ} {A : Set α} /-- Every kernelization of `(A, κ)` is an fpt-reduction from `(A, κ)` to itself. -/ theorem IsKernelization.fptReducible {K : α → α} {g : ℕ → ℕ} (hK : IsKernelization enc κ A K g) : FPTReducible enc enc κ κ A A := - FPTReducible.of_computableInPolyTime hK.polyTime.tidy hK.parameter_le fun a => (hK.mem_iff a).symm + FPTReducible.of_computableInPolyTime hK.polyTime hK.parameter_le fun a => (hK.mem_iff a).symm /-! ### Kernels give fixed-parameter tractability -/ @@ -153,8 +143,9 @@ theorem IsKernelization.mem_FPT {K : α → α} {g : ℕ → ℕ} (hK : IsKernel rw [Nat.add_mul, Nat.one_mul] omega exact mem_FPT_iff_computableInFPTTime.mpr ⟨dec ∘ K, - ⟨fun k => 1 + (c * (∑ j ∈ Finset.range (g k + 1), t j) + c), d, - (hdec.comp hKd.inO).mono_le key key⟩, + ComputableInO.computableInFPTTime + (F := fun k => 1 + (c * (∑ j ∈ Finset.range (g k + 1), t j) + c)) (c := d) + (.of_tidy ((hdec.comp hKd.inO).mono_le key key)), fun a => (hK.mem_iff a).symm.trans (hdecA (K a))⟩ /-- **A decidable problem with a kernel is fixed-parameter tractable.** -/ diff --git a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean index 84eeff974..ab2c7a121 100644 --- a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean +++ b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean @@ -389,6 +389,7 @@ open ComputableTidilyInPolyTime in /-- The initial state of the search is computed in polynomial time. -/ private theorem computableTidilyInPolyTime_init : ComputableTidilyInPolyTime init (encPair encGraph encNat) encState := by + have hcap := computableInPolyTime_cap.tidy unfold init fun_prop @@ -396,6 +397,7 @@ open ComputableTidilyInPolyTime in /-- The number `2 ^ cap x` of paths is computed in binary in polynomial time. -/ private theorem computableTidilyInPolyTime_count : ComputableTidilyInPolyTime (fun x => 2 ^ cap x) (encPair encGraph encNat) encNat := by + have hcap := computableInPolyTime_cap.tidy fun_prop open ComputableTidilyInPolyTime in diff --git a/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean b/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean index 4f5c9bafe..e49fe8547 100644 --- a/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean +++ b/Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean @@ -461,6 +461,33 @@ namespace VertexCover.Buss open ComputableTidilyInPolyTime +/-! Tidy views of the plain certificates of `Graph` and `VertexCover`, for tidy `fun_prop` in the +proofs below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_adjBool : + ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => p.1.1.adjBool p.1.2 p.2) + (encPair (encPair encGraph encNat) encNat) encBool := + Graph.computableInPolyTime_adjBool.tidy + +@[local fun_prop] +private theorem computableTidilyInPolyTime_cap : + ComputableTidilyInPolyTime cap (encPair encGraph encNat) encUnary := + computableInPolyTime_cap.tidy + +@[local fun_prop] +private theorem computableTidilyInPolyTime_distinctVertices : + ComputableTidilyInPolyTime Graph.distinctVertices encGraph (encList encNat) := + Graph.computableInPolyTime_distinctVertices.tidy + +private theorem computableTidilyInPolyTime_adjBool_comp {γ : Type} {enc : γ ↪ List Bool} + {G : γ → Graph} {u v : γ → ℕ} (hG : ComputableTidilyInPolyTime G enc encGraph) + (hu : ComputableTidilyInPolyTime u enc encNat) (hv : ComputableTidilyInPolyTime v enc encNat) : + ComputableTidilyInPolyTime (fun c => (G c).adjBool (u c) (v c)) enc encBool := + Graph.computableInPolyTime_adjBool.tidy.comp ((hG.prod hu).prod hv) + +attribute [local fun_prop] computableTidilyInPolyTime_adjBool_comp + /-- Testing adjacency between computed vertices of a computed graph is polynomial-time. This is `Cslib.Complexity.Graph.computableInPolyTime_adjBool` in the compositional form that `fun_prop` uses. -/ @@ -469,96 +496,164 @@ theorem computableInPolyTime_adjBool_comp {γ : Type} {enc : γ ↪ List Bool} {G : γ → Graph} {u v : γ → ℕ} (hG : ComputableInPolyTime G enc encGraph) (hu : ComputableInPolyTime u enc encNat) (hv : ComputableInPolyTime v enc encNat) : ComputableInPolyTime (fun c => (G c).adjBool (u c) (v c)) enc encBool := - Graph.computableInPolyTime_adjBool.comp ((hG.prod hu).prod hv) + .of_tidy (computableTidilyInPolyTime_adjBool_comp hG.tidy hu.tidy hv.tidy) + +private theorem computableTidilyInPolyTime_degree : + ComputableTidilyInPolyTime (fun p : Graph × ℕ => degree p.1 p.2) + (encPair encGraph encNat) encUnary := by + unfold degree + fun_prop + +attribute [local fun_prop] computableTidilyInPolyTime_degree /-- Computing a degree is polynomial-time, with the degree in unary. -/ @[fun_prop] theorem computableInPolyTime_degree : ComputableInPolyTime (fun p : Graph × ℕ => degree p.1 p.2) - (encPair encGraph encNat) encUnary := by - unfold degree + (encPair encGraph encNat) encUnary := + .of_tidy (computableTidilyInPolyTime_degree) + +private theorem computableTidilyInPolyTime_isHigh : + ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => isHigh p.1 p.2) + (encPair (encPair encGraph encNat) encNat) encBool := by + unfold isHigh fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_isHigh + /-- Testing for a high vertex is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_isHigh : ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => isHigh p.1 p.2) - (encPair (encPair encGraph encNat) encNat) encBool := by - unfold isHigh + (encPair (encPair encGraph encNat) encNat) encBool := + .of_tidy (computableTidilyInPolyTime_isHigh) + +private theorem computableTidilyInPolyTime_high : + ComputableTidilyInPolyTime high (encPair encGraph encNat) (encList encNat) := by + unfold high fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_high + /-- Listing the high vertices is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_high : - ComputableInPolyTime high (encPair encGraph encNat) (encList encNat) := by - unfold high + ComputableInPolyTime high (encPair encGraph encNat) (encList encNat) := + .of_tidy (computableTidilyInPolyTime_high) + +private theorem computableTidilyInPolyTime_low : + ComputableTidilyInPolyTime low (encPair encGraph encNat) (encList encNat) := by + unfold low fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_low + /-- Listing the low vertices is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_low : - ComputableInPolyTime low (encPair encGraph encNat) (encList encNat) := by - unfold low + ComputableInPolyTime low (encPair encGraph encNat) (encList encNat) := + .of_tidy (computableTidilyInPolyTime_low) + +private theorem computableTidilyInPolyTime_isActive : + ComputableTidilyInPolyTime (fun p : (Graph × ℕ) × ℕ => isActive p.1 p.2) + (encPair (encPair encGraph encNat) encNat) encBool := by + unfold isActive fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_isActive + /-- Testing for an active vertex is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_isActive : ComputableInPolyTime (fun p : (Graph × ℕ) × ℕ => isActive p.1 p.2) - (encPair (encPair encGraph encNat) encNat) encBool := by - unfold isActive + (encPair (encPair encGraph encNat) encNat) encBool := + .of_tidy (computableTidilyInPolyTime_isActive) + +private theorem computableTidilyInPolyTime_active : + ComputableTidilyInPolyTime active (encPair encGraph encNat) (encList encNat) := by + unfold active fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_active + /-- Listing the active vertices is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_active : - ComputableInPolyTime active (encPair encGraph encNat) (encList encNat) := by - unfold active + ComputableInPolyTime active (encPair encGraph encNat) (encList encNat) := + .of_tidy (computableTidilyInPolyTime_active) + +private theorem computableTidilyInPolyTime_param : + ComputableTidilyInPolyTime param (encPair encGraph encNat) encUnary := by + unfold param fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_param + /-- The kernel target is computed in unary in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_param : - ComputableInPolyTime param (encPair encGraph encNat) encUnary := by - unfold param + ComputableInPolyTime param (encPair encGraph encNat) encUnary := + .of_tidy (computableTidilyInPolyTime_param) + +private theorem computableTidilyInPolyTime_numVertices : + ComputableTidilyInPolyTime numVertices (encPair encGraph encNat) encUnary := by + unfold numVertices fun_prop +attribute [local fun_prop] computableTidilyInPolyTime_numVertices + /-- The number of kernel vertices is computed in unary in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_numVertices : - ComputableInPolyTime numVertices (encPair encGraph encNat) encUnary := by - unfold numVertices - fun_prop + ComputableInPolyTime numVertices (encPair encGraph encNat) encUnary := + .of_tidy (computableTidilyInPolyTime_numVertices) -/-- The tests of the kernel are polynomial-time. The capped target `cap x` is computed in unary -and converted to binary to compare it with the binary target. -/ -@[fun_prop] -theorem computableInPolyTime_accept : - ComputableInPolyTime accept (encPair encGraph encNat) encBool := by - refine .of_tidy ?_ +private theorem computableTidilyInPolyTime_accept : + ComputableTidilyInPolyTime accept (encPair encGraph encNat) encBool := by unfold accept exact bool_and' (bool_and' ((unary_to_binary.comp computableInPolyTime_cap.tidy).decide_eq' (snd _ _)) (by fun_prop)) (by fun_prop) -/-- Listing the kernel edges is polynomial-time. -/ +attribute [local fun_prop] computableTidilyInPolyTime_accept + +/-- The tests of the kernel are polynomial-time. The capped target `cap x` is computed in unary +and converted to binary to compare it with the binary target. -/ @[fun_prop] -theorem computableInPolyTime_edges : - ComputableInPolyTime edges (encPair encGraph encNat) +theorem computableInPolyTime_accept : + ComputableInPolyTime accept (encPair encGraph encNat) encBool := + .of_tidy (computableTidilyInPolyTime_accept) + +private theorem computableTidilyInPolyTime_edges : + ComputableTidilyInPolyTime edges (encPair encGraph encNat) (encList (encPair encNat encNat)) := by unfold edges polytime -/-- Building the kernel graph is polynomial-time. -/ +attribute [local fun_prop] computableTidilyInPolyTime_edges + +/-- Listing the kernel edges is polynomial-time. -/ @[fun_prop] -theorem computableInPolyTime_graph : - ComputableInPolyTime graph (encPair encGraph encNat) encGraph := by - refine .of_tidy ?_ +theorem computableInPolyTime_edges : + ComputableInPolyTime edges (encPair encGraph encNat) + (encList (encPair encNat encNat)) := + .of_tidy (computableTidilyInPolyTime_edges) + +private theorem computableTidilyInPolyTime_graph : + ComputableTidilyInPolyTime graph (encPair encGraph encNat) encGraph := by have hV : ComputableTidilyInPolyTime (fun x : Graph × ℕ => List.range (numVertices x)) (encPair encGraph encNat) (encList encNat) := by simpa only [Function.comp_def, List.map_id'] using - (map unary_to_binary).comp (range.comp computableInPolyTime_numVertices.tidy) - exact (hV.prod computableInPolyTime_edges.tidy).of_enc_eq fun _ => rfl + (map unary_to_binary).comp (range.comp computableTidilyInPolyTime_numVertices) + exact (hV.prod computableTidilyInPolyTime_edges).of_enc_eq fun _ => rfl + +attribute [local fun_prop] computableTidilyInPolyTime_graph + +/-- Building the kernel graph is polynomial-time. -/ +@[fun_prop] +theorem computableInPolyTime_graph : + ComputableInPolyTime graph (encPair encGraph encNat) encGraph := + .of_tidy (computableTidilyInPolyTime_graph) end VertexCover.Buss @@ -605,16 +700,21 @@ theorem length_encode_bussKernel_le (x : Graph × ℕ) : have : 1 ≤ (x.2 + 1) ^ 6 := Nat.one_le_pow _ _ (Nat.succ_pos _) omega +private theorem computableTidilyInPolyTime_bussKernel : + ComputableTidilyInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := by + unfold bussKernel + exact computableTidilyInPolyTime_accept.cond + (computableTidilyInPolyTime_graph.prod + (ComputableTidilyInPolyTime.unary_to_binary.comp computableTidilyInPolyTime_param)) + (ComputableTidilyInPolyTime.const _) + +attribute [local fun_prop] computableTidilyInPolyTime_bussKernel + /-- **Buss's kernel is polynomial-time.** -/ @[fun_prop] theorem computableInPolyTime_bussKernel : - ComputableInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := by - refine .of_tidy ?_ - unfold bussKernel - exact computableInPolyTime_accept.tidy.cond - (computableInPolyTime_graph.tidy.prod - (ComputableTidilyInPolyTime.unary_to_binary.comp computableInPolyTime_param.tidy)) - (ComputableTidilyInPolyTime.const _) + ComputableInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := + .of_tidy (computableTidilyInPolyTime_bussKernel) /-- Buss's kernel has target at most `k`, or `1`. -/ private theorem bussKernel_snd_le (x : Graph × ℕ) : (bussKernel x).2 ≤ max x.2 1 := by diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean index 6667d23c1..99e276fc0 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean @@ -90,7 +90,7 @@ private theorem exists_uniformOutputBits {α : Type} {enc : α ↪ List Bool} (∀ a j, j ≤ m a → (cs a j).size = (cs a 0).size) ∧ ∀ a j (x : Fin (n a) → Bool), (cs a j).eval interpretation x 0 = (F (a, List.ofFn x)).getD j false := by - obtain ⟨circuits, hcode, hcorrect⟩ := exists_uniformCircuits (polytime_outputBit hF) + obtain ⟨circuits, hcode, hcorrect⟩ := exists_uniformCircuits (.of_tidy (polytime_outputBit hF)) let cs (a : α) (j : ℕ) : Circuit signature (n a) 1 := prefixCircuit (bitPrefix enc m a j) (circuits ((bitPrefix enc m a j).length + n a)) @@ -102,7 +102,7 @@ private theorem exists_uniformOutputBits {α : Type} {enc : α ↪ List Bool} refine ⟨cs, ?_, ?_, ?_⟩ · have h := (computableInPolyTime_prefixCode (.of_tidy hprefix) (.of_tidy (ComputableTidilyInPolyTime.unary_to_binary.comp (hn.comp - (ComputableTidilyInPolyTime.fst enc encUnary)))) (.of_tidy (hcode.comp hlength))).tidy + (ComputableTidilyInPolyTime.fst enc encUnary)))) (hcode.comp (.of_tidy hlength))).tidy exact h.of_enc_eq fun p => by rw [show (cs p.1 p.2).code = _ from code_prefixCircuit _ _] rfl diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean index dc0b598db..f63c1ee34 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean @@ -242,10 +242,10 @@ theorem computableInLogSpace_tableauInstance : have hs := (ComputableTidilyInSpace.fst encWState encBool).weaken hin have hn := fst' (snd' hs) have hi := snd' (snd' hs) - refine (tableauSpec tm C d).computableInLogSpace (.of_tidy (tableauSpec_output tm C d)) + refine (tableauSpec tm C d).computableInLogSpace (tableauSpec_output tm C d) (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin (.of_tidy hn))) (.of_tidy (gateChunk_inSpace tm C d hin hn hi)) - (trailer_inSpace (k := k) (State := State) C d hin hn) ?_ + (.of_tidy (trailer_inSpace (k := k) (State := State) C d hin hn)) ?_ change PolynomiallyBounded fun n => numGates k State (timeBound C d n) simp only [numGates, blockSize, colStart, gfStart, globStart, numCols, timeBound] fun_prop diff --git a/Complexity/Computability/Complexity/Problems/Coloring.lean b/Complexity/Computability/Complexity/Problems/Coloring.lean index b7595e22b..d67b0210a 100644 --- a/Complexity/Computability/Complexity/Problems/Coloring.lean +++ b/Complexity/Computability/Complexity/Problems/Coloring.lean @@ -505,6 +505,7 @@ theorem toThreeColoring_mem_iff (φ : CNF ℕ) : toThreeColoring φ ∈ ThreeCol /-! ### Polynomial-time reduction -/ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The reduction `toThreeColoring` is computable in polynomial time: vertex labels are computed in unary from clause, position and first-occurrence indices, then converted to binary. -/ @[fun_prop] diff --git a/Complexity/Computability/Complexity/Problems/Graph.lean b/Complexity/Computability/Complexity/Problems/Graph.lean index cc687ed03..cb92dd343 100644 --- a/Complexity/Computability/Complexity/Problems/Graph.lean +++ b/Complexity/Computability/Complexity/Problems/Graph.lean @@ -256,13 +256,14 @@ theorem isVerifier_verifySubset {rel : Graph → ℕ → ℕ → Bool} {P : Grap · exact Or.inl huv · exact Or.inr ((hrel x.1 u v huv).2 (h hu hv huv)) -@[fun_prop] private theorem bool_or' {α : Type} {encA : α ↪ List Bool} {left right : α → Bool} (hleft : ComputableTidilyInPolyTime left encA encBool) (hright : ComputableTidilyInPolyTime right encA encBool) : ComputableTidilyInPolyTime (fun a => left a || right a) encA encBool := bool_or.comp (hleft.prod hright) +attribute [local fun_prop] bool_or' + /-- `verifySubset` is computable in polynomial time whenever the pairwise test `rel` is. -/ @[fun_prop] theorem computableInPolyTime_verifySubset {rel : Graph → ℕ → ℕ → Bool} diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian.lean index 2ed5e15f4..65a1ee954 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian.lean @@ -489,7 +489,8 @@ private theorem computableTidilyInPolyTime_pathCheck {r : Graph → ℕ → ℕ simp only [← List.head?_reverse] exact bool_and' (bool_and' (((head? encNat).comp hp).decide_eq' hs) (((head? encNat).comp ((listReverse encNat).comp hp)).decide_eq' ht)) - (Graph.computableInPolyTime_chainBool (.of_tidy (hr.comp hproj)) (.of_tidy hp)).tidy + (ComputableInPolyTime.tidy + (Graph.computableInPolyTime_chainBool (.of_tidy (hr.comp hproj)) (.of_tidy hp))) attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in @@ -505,7 +506,8 @@ private theorem computableTidilyInPolyTime_cycleCheck {r : Graph → ℕ → ℕ (encPair (encPair (encPair encGraph (encList encNat)) encNat) encNat) (encPair (encPair encGraph encNat) encNat) := by fun_prop - exact (Graph.computableInPolyTime_cycleChainBool (.of_tidy (hr.comp hproj)) (.of_tidy (snd _ _))).tidy + exact ComputableInPolyTime.tidy + (Graph.computableInPolyTime_cycleChainBool (.of_tidy (hr.comp hproj)) (.of_tidy (snd _ _))) namespace DirHamPath diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean index 4e868edf0..d4a0035b5 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean @@ -346,6 +346,9 @@ theorem computableInPolyTime_sparseDiamondGraph : theorem computableInPolyTime_toSparseDirHamPath : ComputableInPolyTime toSparseDirHamPath encCNF (encPair encGraph (encPair encNat encNat)) := by + have hgraph := computableInPolyTime_sparseDiamondGraph.tidy + have htop := Diamond.computableInPolyTime_topNode.tidy + have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ have hn := computableTidilyInPolyTime_numDiamonds unfold toSparseDirHamPath diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean index 764be71ec..d070809f1 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean @@ -561,6 +561,7 @@ def toHamPath (x : Graph × ℕ × ℕ) : Graph × ℕ × ℕ := theorem toHamPath_mem_iff (x : Graph × ℕ × ℕ) : toHamPath x ∈ HamPath ↔ x ∈ DirHamPath := Graph.split_mem_HamPath_iff x.1 x.2.1 x.2.2 +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The reduction `DirHamPath.toHamPath` is polynomial-time. -/ @[fun_prop] theorem computableInPolyTime_toHamPath : diff --git a/Complexity/Computability/Complexity/Problems/IndependentSet.lean b/Complexity/Computability/Complexity/Problems/IndependentSet.lean index db12ec938..20db729d5 100644 --- a/Complexity/Computability/Complexity/Problems/IndependentSet.lean +++ b/Complexity/Computability/Complexity/Problems/IndependentSet.lean @@ -288,6 +288,7 @@ theorem _root_.Cslib.Logic.PL.Occurrence.computableInPolyTime_conflict : unfold Occurrence.Conflict encOccurrence Cslib.Logic.PL.encOccurrence fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Karp's reduction `toIndependentSet` is computable in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_toIndependentSet : diff --git a/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean b/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean index c7ec340eb..bd86236b2 100644 --- a/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean +++ b/Complexity/Computability/Complexity/Problems/IntegerProgramming.lean @@ -97,6 +97,7 @@ theorem isVerifier : theorem computableInPolyTime_verifier : ComputableInPolyTime verifier (encPair (encList (encPair (encList encNat) encNat)) encBits) encBool := by + have hmask := (computableInPolyTime_maskSelect encNat).tidy refine .of_tidy ?_ unfold verifier apply allWithInput (by fun_prop) diff --git a/Complexity/Computability/Complexity/Problems/Knapsack.lean b/Complexity/Computability/Complexity/Problems/Knapsack.lean index 00c174b42..98597023f 100644 --- a/Complexity/Computability/Complexity/Problems/Knapsack.lean +++ b/Complexity/Computability/Complexity/Problems/Knapsack.lean @@ -91,6 +91,8 @@ theorem isVerifier : IsVerifier encKnapsack Polynomial.X verifier Knapsack := by @[fun_prop] theorem computableInPolyTime_verifier : ComputableInPolyTime verifier (encPair encKnapsack encBits) encBool := by + have hmask := (computableInPolyTime_maskSelect (encPair encNat encNat)).tidy + refine .of_tidy ?_ unfold verifier fun_prop diff --git a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean index f2753de39..166e3fa0f 100644 --- a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean @@ -277,9 +277,9 @@ theorem computableInLogSpace_dualTableauInstance : have hn := fst' (snd' hs) have hi := snd' (snd' hs) refine (dualSpec tm C d).computableInLogSpace - (.of_tidy (encMonotoneCircuitValue_dualTableauInstance tm C d)) + (encMonotoneCircuitValue_dualTableauInstance tm C d) (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin (.of_tidy hn))) - (.of_tidy (dualChunk_inSpace tm C d hin hn hi)) (dualTrailer_inSpace tm C d hin hn) ?_ + (.of_tidy (dualChunk_inSpace tm C d hin hn hi)) (.of_tidy (dualTrailer_inSpace tm C d hin hn)) ?_ change PolynomiallyBounded fun n => Tableau.numGates k State (timeBound C d n) simp only [Tableau.numGates, Tableau.blockSize, Tableau.colStart, Tableau.gfStart, Tableau.globStart, Tableau.numCols, timeBound] diff --git a/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean b/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean index 2af054674..f14846658 100644 --- a/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean +++ b/Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean @@ -142,11 +142,11 @@ theorem computableInPolyTime_clause : (encPair (encPair encCNF encBits) (encList (encPair encNat encBool))) encBool := by fun_prop [Clause.eval, Literal.eval, assignment] -attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The SAT verifier is polynomial-time, including on certificates of arbitrary length. -/ @[fun_prop] theorem computableInPolyTime_verifier : ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by + have hclause := computableInPolyTime_clause.tidy refine .of_tidy ?_ fun_prop [verifier, CNF.eval] diff --git a/Complexity/Computability/Complexity/Problems/SharpSAT.lean b/Complexity/Computability/Complexity/Problems/SharpSAT.lean index 3d53b91cb..5f8cb0d69 100644 --- a/Complexity/Computability/Complexity/Problems/SharpSAT.lean +++ b/Complexity/Computability/Complexity/Problems/SharpSAT.lean @@ -158,11 +158,13 @@ theorem acceptCount_verifier (φ : CNF ℕ) : /-! ### Polynomial time -/ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Testing for a first occurrence is polynomial-time, with the position in unary. -/ @[fun_prop] theorem computableInPolyTime_isFirst : ComputableInPolyTime (fun p : CNF ℕ × ℕ => isFirst p.1 p.2) (encPair encCNF encUnary) encBool := by + refine .of_tidy ?_ fun_prop [isFirst] /-- The number of distinct variables occurring in `φ` is computable in polynomial time in unary. -/ @@ -171,10 +173,12 @@ theorem computableInPolyTime_card_vars : ComputableInPolyTime (fun φ : CNF ℕ => φ.vars.toFinset.card) encCNF encUnary := (CNF.computableInPolyTime_numVars encNat) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The counting verifier is polynomial-time, including on certificates of arbitrary length. -/ @[fun_prop] theorem computableInPolyTime_verifier : ComputableInPolyTime verifier (encPair encCNF encBits) encBool := by + refine .of_tidy ?_ fun_prop [verifier, canonical] /-- **`#SAT` belongs to `#P`**, with certificates as long as the encoded formula. -/ diff --git a/Complexity/Computability/Complexity/Problems/SubsetSum.lean b/Complexity/Computability/Complexity/Problems/SubsetSum.lean index 7fb5c78cf..58d52d1dd 100644 --- a/Complexity/Computability/Complexity/Problems/SubsetSum.lean +++ b/Complexity/Computability/Complexity/Problems/SubsetSum.lean @@ -610,6 +610,7 @@ theorem computableInPolyTime_octal : unfold octal fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- The numbers of the digit construction are computed in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_digitNumbers : diff --git a/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean b/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean index 7bb71de48..fbed2fd07 100644 --- a/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean +++ b/Complexity/Computability/Complexity/Problems/TQBF/Closed.lean @@ -203,6 +203,7 @@ private theorem length_freeVarStep_le (stack : List (List ℕ)) (t : QBF.Kind × /-- **Closedness is decided in polynomial time.** -/ theorem computableInPolyTime_decide_closed : Turing.MultiTapeTM.ComputableInPolyTime (fun φ : QBF ℕ => decide φ.Closed) encQBF encBool := by + have htokens := computableInPolyTime_tokens.tidy refine .of_tidy ?_ simp only [← QBF.isClosed_tokens] unfold QBF.isClosed diff --git a/Complexity/Computability/Complexity/ProofSystem.lean b/Complexity/Computability/Complexity/ProofSystem.lean index 6f1628eab..f4250ba24 100644 --- a/Complexity/Computability/Complexity/ProofSystem.lean +++ b/Complexity/Computability/Complexity/ProofSystem.lean @@ -194,10 +194,10 @@ theorem PolynomiallyBounded.mem_NP {P : ProofSystem enc L} (hP : P.PolynomiallyB L ∈ NP enc := by classical obtain ⟨p, hp⟩ := hP - have hcheck : ComputableTidilyInPolyTime (fun x : α × List Bool => decide (P x.2 = x.1)) + have hcheck : ComputableInPolyTime (fun x : α × List Bool => decide (P x.2 = x.1)) (encPair enc encBits) encBool := - ComputableTidilyInPolyTime.decide_eq' (P.computable.tidy.comp (.snd enc encBits)) - (.fst enc encBits) + .of_tidy (ComputableTidilyInPolyTime.decide_eq' (P.computable.tidy.comp (.snd enc encBits)) + (.fst enc encBits)) have h := mem_NP_of_witness (p := p) Decoder.bits hcheck (R := fun a π => P π = a) (fun _ _ => decide_eq_true_iff) fun a π hπ => hp a (hπ ▸ P.mem π) have hL : {a | ∃ π, P π = a} = L := P.range_eq diff --git a/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean b/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean index 5b3437cab..2cae8f0c1 100644 --- a/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean +++ b/Complexity/Computability/Machines/Turing/TM2/Reverse/Transfer.lean @@ -175,10 +175,10 @@ theorem mem_PSPACE_iff_tm2 {α : Type} {encIn : α ↪ List Bool} {A : Set α} : rw [mem_PSPACE_iff_computableInPolySpace] constructor · rintro ⟨f, hf, hA⟩ - obtain ⟨h, hfinite, hspace⟩ := (ComputableInPolySpace.of_tidy hf).exists_tm2Computable + obtain ⟨h, hfinite, hspace⟩ := hf.exists_tm2Computable exact ⟨f, h, hfinite, hspace, hA⟩ · rintro ⟨f, h, hfinite, ⟨space, hspace, hstacks⟩, hA⟩ let := hfinite - exact ⟨f, (h.computableInPolySpace hspace hstacks).tidy, hA⟩ + exact ⟨f, h.computableInPolySpace hspace hstacks, hA⟩ end Cslib.Complexity diff --git a/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean b/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean index f76d93847..05156e441 100644 --- a/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean +++ b/Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean @@ -255,6 +255,10 @@ fixed list `pairs` is tested against its constraint table. -/ theorem isPolyTime_toCNF : ComputableInPolyTime (toCNF e pairs) (encoding (encPi (encPi encBool))) encCNF := by refine .of_tidy ?_ + have hsrc := (Edge.isPolyTime_src (enc := encPi (encPi encBool)) + (edge := fun d : Edge (α → α → Bool) => d) (.of_tidy .id')).tidy + have hdst := (Edge.isPolyTime_dst (enc := encPi (encPi encBool)) + (edge := fun d : Edge (α → α → Bool) => d) (.of_tidy .id')).tidy have hclause (p : α × α) : ComputableTidilyInPolyTime (fun d : Edge (α → α → Bool) => excludeClause e d.src d.dst p) (Edge.encoding (encPi (encPi encBool))) (encList (encPair encNat encBool)) := by @@ -263,6 +267,8 @@ theorem isPolyTime_toCNF : have htest (p : α × α) : ComputableTidilyInPolyTime (fun d : Edge (α → α → Bool) => !d.constraint p.1 p.2) (Edge.encoding (encPi (encPi encBool))) encBool := by + have hconstraint := (Edge.isPolyTime_constraint (enc := encPi (encPi encBool)) + (edge := fun d : Edge (α → α → Bool) => d) (.of_tidy .id')).tidy fun_prop have hedge : ComputableTidilyInPolyTime (edgeCNF e pairs) (Edge.encoding (encPi (encPi encBool))) encCNF := diff --git a/Complexity/Computability/PCP/Completeness.lean b/Complexity/Computability/PCP/Completeness.lean index 9fce4a820..ef46894b8 100644 --- a/Complexity/Computability/PCP/Completeness.lean +++ b/Complexity/Computability/PCP/Completeness.lean @@ -65,8 +65,8 @@ theorem NP_subset_PCP_log {Input : Type} (input : Input ↪ List Bool) : have heval : ComputableTidilyInPolyTime (fun p : (GapAlphabet → GapAlphabet → Bool) × GapAlphabet × GapAlphabet => p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) - (encPair (encPair encBool (encPi encBool)) (encPair encBool (encPi encBool)))) encBool := by - fun_prop + (encPair (encPair encBool (encPi encBool)) (encPair encBool (encPi encBool)))) encBool := + (Graph.isPolyTime_constraintTableEval (encPair encBool (encPi encBool))).tidy exact Graph.mem_PCP_of_gapReduction (FinEnum.card (Fin 6) + 1) encodeLabel decodeLabel decode_encodeLabel (isPolyTime_gapGraph hreduce) (.of_tidy heval) (fun x => wellFormed_gapGraph (reduce x)) diff --git a/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean b/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean index f7650a456..8ab37a61e 100644 --- a/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean +++ b/Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean @@ -97,6 +97,11 @@ theorem isPolyTime_amplifyIter_clog {Input : Type} {input : Input ↪ List Bool} _ ≤ _ := Nat.mul_le_mul_left _ (Nat.le_add_left _ _) have heval := (isPolyTime_constraintTableEval (α := SelectedAlphabet) (encPair encBool (encPi encBool))).tidy + have hedges := (isPolyTime_edges (graph := fun g : Graph Constraint => g) + (enc := encPi (encPi encBool)) (.of_tidy .id')).tidy + have hamplify := ComputableInPolyTime.tidy (isPolyTime_amplify (graph := id) (eval := id) + (alphabet := encPair encBool (encPi encBool)) (.of_tidy .id') (.of_tidy hcost) + (.of_tidy heval) fallback T q walks number coins queries) unfold amplifyIter apply ComputableTidilyInPolyTime.iterate (by fun_prop) hgraph (by fun_prop) (polyBounded_iterationSize_clog (.of_tidy hgraph) factor descriptorBound) diff --git a/Complexity/Computability/PCP/Encoded/GapTheorem.lean b/Complexity/Computability/PCP/Encoded/GapTheorem.lean index dcb20b867..09d92fc71 100644 --- a/Complexity/Computability/PCP/Encoded/GapTheorem.lean +++ b/Complexity/Computability/PCP/Encoded/GapTheorem.lean @@ -70,11 +70,10 @@ theorem isPolyTime_gapGraph {V Input : Type} [DecidableEq V] ComputableInPolyTime (fun x => gapGraph (formula x)) input (Graph.encoding (encPi (encPi encBool))) := by have hformula := hformula.tidy - refine .of_tidy ?_ unfold gapGraph apply Graph.isPolyTime_arithmeticAmplify - · exact (Graph.isPolyTime_composeSelectedEnumerated - (Graph.isPolyTime_ofCompactCNF (.of_tidy ((CNF.isPolyTime_to3CNF enc).tidy.comp hformula)))).tidy + · exact Graph.isPolyTime_composeSelectedEnumerated + (Graph.isPolyTime_ofCompactCNF (.of_tidy ((CNF.isPolyTime_to3CNF enc).tidy.comp hformula))) · exact fun x => (Graph.wellFormed_ofCompactCNF (formula x).to3CNF).composeSelectedEnumerated /-- Every output edge has endpoints in the declared finite vertex range. -/ diff --git a/Complexity/Computability/PCP/Encoded/Power.lean b/Complexity/Computability/PCP/Encoded/Power.lean index cd8dd9886..97ab10d40 100644 --- a/Complexity/Computability/PCP/Encoded/Power.lean +++ b/Complexity/Computability/PCP/Encoded/Power.lean @@ -197,6 +197,7 @@ section Complexity variable [Fintype D] [DecidableEq D] [Fintype α] [DecidableEq α] {enc : C ↪ List Bool} {alphabet : α ↪ List Bool} {labelEncoding : D ↪ List Bool} +attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem polytime_powerPreprocessEdge (eval : C → α → α → Bool) (fallback : C) (rotate : ℕ × (ℕ × D) → ℕ × D) (hrotate : ComputableTidilyInPolyTime rotate @@ -215,21 +216,26 @@ private theorem polytime_powerPreprocessEdge (eval : C → α → α → Bool) ( p.1.preprocessRotation fallback rotate p.2) (encPair (encoding enc) (encPair (encPair encUnary encBool) (encFinite (PreprocessLabel D)))) - (encPair (encPair encUnary encBool) (encFinite (PreprocessLabel D))) := by - fun_prop + (encPair (encPair encUnary encBool) (encFinite (PreprocessLabel D))) := + ComputableInPolyTime.tidy (isPolyTime_preprocessRotation (.of_tidy (.fst _ _)) + (.of_tidy (.snd _ _)) (.of_tidy hrotate) fallback) have he : ComputableTidilyInPolyTime (fun p : Graph C × (((ℕ × Bool) × PreprocessLabel D) × (α × α)) => p.1.preprocessRelation eval fallback p.2.1 p.2.2.1 p.2.2.2) (encPair (encoding enc) (encPair (encPair (encPair encUnary encBool) (encFinite (PreprocessLabel D))) - (encPair alphabet alphabet))) encBool := by - fun_prop + (encPair alphabet alphabet))) encBool := + ComputableInPolyTime.tidy (isPolyTime_preprocessRelation (.of_tidy (.fst _ _)) + (.of_tidy ((ComputableTidilyInPolyTime.snd _ _).fst')) (.of_tidy heval) + (.of_tidy ((ComputableTidilyInPolyTime.snd _ _).snd'.fst')) + (.of_tidy ((ComputableTidilyInPolyTime.snd _ _).snd'.snd')) fallback) have hwalk := rotationMap_killedPowRotWithInput hr T q (encFinEnum (Fin q)) have hrel := (RegularConstraintGraph.isPolyTime_powerRelationWithInput (.of_tidy hr) (.of_tidy he) T q (encFinEnum (Fin q))).tidy unfold powerPreprocessEdge - apply Edge.isPolyTime_mk - · fun_prop + refine ComputableInPolyTime.tidy (Edge.isPolyTime_mk (.of_tidy ?_) (.of_tidy ?_) (.of_tidy ?_)) + · have := isPolyTime_halfEdgeNumber.tidy + fun_prop · exact isPolyTime_halfEdgeNumber.tidy.comp hwalk.fst' · apply pi intro a @@ -238,6 +244,7 @@ private theorem polytime_powerPreprocessEdge (eval : C → α → α → Bool) ( simpa only [RegularConstraintGraph.powerInputEncoding, Function.comp_def] using hrel.comp ((fst _ _).prod ((snd _ _).prod (const (a, b)))) +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Construct the entire output truth tables, charging every rotation, constraint lookup, opinion table, copied graph, edge record and list delimiter. All finite parameters are fixed. -/ private theorem polytime_powerPreprocess (eval : C → α → α → Bool) (fallback : C) @@ -254,10 +261,13 @@ private theorem polytime_powerPreprocess (eval : C → α → α → Bool) (fall (fun g : Graph C => g.halfEdges.product walks) (encoding enc) (encList (encPair (encPair encUnary encBool) (encPair (encPi (encFinite (PreprocessLabel D))) (encPi (encFinEnum (Fin q)))))) := by + have := (isPolyTime_halfEdges (enc := enc) (.of_tidy .id')).tidy unfold List.product fun_prop unfold powerPreprocess - apply isPolyTime_mk (by fun_prop) + refine ComputableInPolyTime.tidy (isPolyTime_mk (.of_tidy ?_) (.of_tidy ?_)) + · have := (isPolyTime_edges (enc := enc) (.of_tidy .id')).tidy + fun_prop exact mapWithInput hdarts hedge omit [Fintype D] [Fintype α] [DecidableEq D] in diff --git a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean index 8c0b987eb..2088085d6 100644 --- a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean +++ b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean @@ -146,8 +146,6 @@ theorem preprocessRelation_eq_true [DecidableEq α] (g : Graph C) variable {enc : C ↪ List Bool} {labelEncoding : D ↪ List Bool} {dartEncoding : PreprocessLabel D ↪ List Bool} -attribute [local fun_prop] ComputableInPolySpace.tidy in -attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A fixed finite dart label selects a branch; each branch charges the runtime graph and vertex. The numerical rotation certificate is joint in size, vertex and edge label. -/ private theorem polytime_preprocessRotation [Finite D] (fallback : C) @@ -171,8 +169,10 @@ private theorem polytime_preprocessRotation [Finite D] (fallback : C) (fun p : Graph C × ((ℕ × Bool) × PreprocessLabel D) => p.1.cloudRotation fallback rotate (p.2.1, d)) (encPair (encoding enc) (encPair (encPair encUnary encBool) dartEncoding)) - (encPair (encPair encUnary encBool) labelEncoding) := by - fun_prop + (encPair (encPair encUnary encBool) labelEncoding) := + ComputableInPolyTime.tidy (isPolyTime_cloudRotation (.of_tidy (.fst _ _)) + (.of_tidy ((ComputableTidilyInPolyTime.snd _ _).fst'.prod (.const d))) + (.of_tidy hrotate) fallback) have hlabel : ComputableTidilyInPolyTime (fun d : D => (Sum.inl (Sum.inl (Sum.inr d)) : PreprocessLabel D)) labelEncoding dartEncoding := .of_finite _ @@ -182,6 +182,8 @@ private theorem polytime_preprocessRotation [Finite D] (fallback : C) rotate (2 * p.1.edges.length, halfEdgeNumber p.2.1, d)) (encPair (encoding enc) (encPair (encPair encUnary encBool) dartEncoding)) (encPair encUnary labelEncoding) := by + have hedges := (isPolyTime_edges (enc := enc) (.of_tidy .id')).tidy + have hnumber := isPolyTime_halfEdgeNumber.tidy fun_prop have hlabel : ComputableTidilyInPolyTime (fun d : D => (Sum.inl (Sum.inr d) : PreprocessLabel D)) diff --git a/Complexity/Computability/PCP/Encoded/ThreeSAT.lean b/Complexity/Computability/PCP/Encoded/ThreeSAT.lean index 08434e849..eed80b6e5 100644 --- a/Complexity/Computability/PCP/Encoded/ThreeSAT.lean +++ b/Complexity/Computability/PCP/Encoded/ThreeSAT.lean @@ -110,7 +110,8 @@ theorem isPolyTime_cnfEdge : have hliteral := ComputableTidilyInPolyTime.getElem? (encA := encPair encUnary encBool) hclause (hindex.comp ((snd _ _).snd')) unfold cnfEdge - apply Edge.isPolyTime_mk (by fun_prop) (by fun_prop) + refine ComputableInPolyTime.tidy + (Edge.isPolyTime_mk (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy ?_)) refine pi fun a => pi fun b => ?_ have ha : ComputableTidilyInPolyTime a (encFinEnum (Fin 3)) encBool := .of_finite _ fun_prop diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean index 094ed441d..1e4bdbe6d 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean @@ -244,7 +244,7 @@ theorem dirs_inSpace : have hl₀ : (fun q => (encPair (encList encBool) encFrame q).length) ≼ fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := .of_le fun _ => by omega have hd := budget_comp (frameFinite_inSpace (encB := encBool) - fun y : Fin 4 × Bool × Fin 3 => y.1.val % 2 == 1) + fun y : Fin 4 × Bool × Fin 3 => y.1.val % 2 == 1).tidy ((snd (encList encBool) encFrame).weaken hl₀) (.of_le fun x => by simp only [length_encPair]; omega) have hc : ComputableTidilyInSpace (fun p : Bool × List Bool => p.1 :: p.2) diff --git a/Complexity/Computability/TreeEval/Space.lean b/Complexity/Computability/TreeEval/Space.lean index 87efac476..623ac965e 100644 --- a/Complexity/Computability/TreeEval/Space.lean +++ b/Complexity/Computability/TreeEval/Space.lean @@ -30,11 +30,12 @@ of the read machine together with the position of the head, stay within the spac ## Main results -* `Cslib.TreeEval.computableTidilyInSpace_eval`: Tree Evaluation in space - `O(spaceBound ℓ H + log (n + 2))`. +* `Cslib.TreeEval.computableInSpace_eval`: Tree Evaluation in space + `O(spaceBound ℓ H + log (n + 2))`, with the value not charged to the space bound + (`Turing.MultiTapeTM.ComputableInBigO`). * `Cslib.TreeEval.spaceBound_add_length_le_log_mul_log_log`: on nontrivial instances, `spaceBound ℓ H + |n + 1| ≤ 6 · |n| · ||n||`. -* `Cslib.TreeEval.computableTidilyInSpace_eval_log_mul_log_log`: Tree Evaluation on nontrivial +* `Cslib.TreeEval.computableInSpace_eval_log_mul_log_log`: Tree Evaluation on nontrivial instances in space `O(|n| · ||n||) = O(log n · log log n)`. ## References @@ -61,9 +62,9 @@ def encNontrivialInstance : NontrivialInstance ↪ List Bool := encNontrivialInstance I = encInstance I.1 := rfl /-- **Tree Evaluation in small space** (Cook–Mertz): the value of the tree of an instance of value -length `ℓ` and height `H` is tidily computable from its encoding in space -`O((ℓ + H + 1) · log (ℓ + 2) + log (n + 2))`. -/ -theorem computableTidilyInSpace_eval : ∃ t, ComputableTidilyInBigO +length `ℓ` and height `H` is computable from its encoding in space +`O((ℓ + H + 1) · log (ℓ + 2) + log (n + 2))`; the value is not charged to the space bound. -/ +theorem computableInSpace_eval : ∃ t, ComputableInBigO (fun I : Instance => List.ofFn I.tree.eval) encInstance encBits t fun I => spaceBound I.ell I.height + (encNat ((encInstance I).length + 1)).length := by obtain ⟨T, hT⟩ := tidy_machine @@ -77,7 +78,8 @@ theorem computableTidilyInSpace_eval : ∃ t, ComputableTidilyInBigO let tS := ReadMachine.stateT encState T stateBudget let tMax (I : Instance) : ℕ := ∑ i ∈ Finset.range (rounds I + 1), tS (machine.toStepMachine.run (encInstance I) i).state - refine ⟨_, (hT.computableTidilyInTimeAndSpace (fun I : Instance => List.ofFn I.tree.eval) + refine ⟨_, ComputableTidilyInBigO.computableInBigO <| + (hT.computableTidilyInTimeAndSpace (fun I : Instance => List.ofFn I.tree.eval) rounds hr (fun I => by rw [encBits_apply, ho]) (tMax := tMax) (sMax := fun I => 5 * 2 ^ 12 * spaceBound I.ell I.height + 2 * (encNat ((encInstance I).length + 1)).length + 6) fun I i hi => ⟨?_, ?_⟩).weaken @@ -133,14 +135,15 @@ theorem spaceBound_add_length_le_log_mul_log_log {I : Instance} nlinarith /-- **Tree Evaluation in space `O(log n · log log n)`** (Cook–Mertz): on nontrivial instances -(`1 ≤ ℓ` and `1 ≤ H`), the value of the tree is tidily computable from its encoding in space -`O(|n| · ||n||)`, where `n` is the length of the encoded instance and `|m| = (encNat m).length`. -/ -theorem computableTidilyInSpace_eval_log_mul_log_log : ∃ t, ComputableTidilyInBigO +(`1 ≤ ℓ` and `1 ≤ H`), the value of the tree is computable from its encoding in space +`O(|n| · ||n||)`, where `n` is the length of the encoded instance and `|m| = (encNat m).length`; +the value is not charged to the space bound. -/ +theorem computableInSpace_eval_log_mul_log_log : ∃ t, ComputableInBigO (fun I : NontrivialInstance => List.ofFn I.1.tree.eval) encNontrivialInstance encBits t fun I => (encNat (encNontrivialInstance I).length).length * (encNat (encNat (encNontrivialInstance I).length).length).length := by - obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableTidilyInSpace_eval - have hN : ComputableTidilyInBigO (fun I : NontrivialInstance => List.ofFn I.1.tree.eval) + obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableInSpace_eval + have hN : ComputableInBigO (fun I : NontrivialInstance => List.ofFn I.1.tree.eval) encNontrivialInstance encBits (fun I => t I.1) (fun I => spaceBound I.1.ell I.1.height + (encNat ((encInstance I.1).length + 1)).length) := ⟨c, k, State, hfinite, tm, fun I => htm I.1⟩ diff --git a/Complexity/Computability/USTCON/Space.lean b/Complexity/Computability/USTCON/Space.lean index cd44ee355..70b74a486 100644 --- a/Complexity/Computability/USTCON/Space.lean +++ b/Complexity/Computability/USTCON/Space.lean @@ -31,7 +31,8 @@ instances; recognising which bit strings are encodings is not formalised. ## Main results -* `Cslib.USTCON.computableTidilyInBigO_decide`: the decision in space `O(log n)`. +* `Cslib.USTCON.computableInBigO_decide`: the decision in space `O(log n)`, with the output not + charged to the space bound (`Turing.MultiTapeTM.ComputableInBigO`). * `Cslib.USTCON.computableInLogSpace_decide`: the decision is computable in logarithmic space. ## References @@ -48,9 +49,9 @@ open Turing MultiTapeTM Reader Cslib.Complexity open scoped Classical in /-- **Undirected connectivity in space `O(log n)`**: the decision of undirected `s`–`t` -connectivity is tidily computable from the encoded instance in space linear in the logarithm of -its length. -/ -theorem computableTidilyInBigO_decide : ∃ t, ComputableTidilyInBigO +connectivity is computable from the encoded instance in space linear in the logarithm of its +length. -/ +theorem computableInBigO_decide : ∃ t, ComputableInBigO (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) encUSTCON encBool t fun I ↦ Nat.log2 (encUSTCON I).length + 1 := by obtain ⟨T, hT⟩ := tidy_machine @@ -63,7 +64,7 @@ theorem computableTidilyInBigO_decide : ∃ t, ComputableTidilyInBigO let tS := ReadMachine.stateT encState T stateBudget let tMax (I : USTCONInstance) : ℕ := ∑ i ∈ Finset.range (rounds I + 1), tS (machine.toStepMachine.run (encUSTCON I) i).state - refine ⟨_, (hT.computableTidilyInTimeAndSpace (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) + refine ⟨_, ComputableTidilyInBigO.computableInBigO <| (hT.computableTidilyInTimeAndSpace (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) rounds hr (fun I ↦ by rw [encBool_apply, ho]) (tMax := tMax) (sMax := fun I ↦ 6 * stateConst * (Nat.log2 (encUSTCON I).length + 2) + 2 * (Nat.log2 (encUSTCON I).length + 2) + 12) fun I i hi ↦ ⟨?_, ?_⟩).weaken @@ -94,7 +95,7 @@ open scoped Classical in space, on encodings of instances by their adjacency matrices. -/ theorem computableInLogSpace_decide : ComputableInLogSpace (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) encUSTCON encBool := by - obtain ⟨t, c, hc⟩ := computableTidilyInBigO_decide - exact ⟨_, 2 * c, hc.computableInTimeAndSpace.mono (fun _ ↦ le_rfl) fun I ↦ by nlinarith⟩ + obtain ⟨t, c, hc⟩ := computableInBigO_decide + exact ⟨_, 2 * c, hc.mono (fun _ ↦ le_rfl) fun I ↦ by nlinarith⟩ end Cslib.USTCON diff --git a/Complexity/Crypto/Computational/GMW/PolyTime.lean b/Complexity/Crypto/Computational/GMW/PolyTime.lean index e80c0ee8a..de3a7bb56 100644 --- a/Complexity/Crypto/Computational/GMW/PolyTime.lean +++ b/Complexity/Crypto/Computational/GMW/PolyTime.lean @@ -58,6 +58,35 @@ namespace Cslib.Crypto.GMW open Probability Complexity Logic.PL Turing.MultiTapeTM ComputableTidilyInPolyTime +/-! Tidy views of the plain `SAT` certificates, for tidy `fun_prop` below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_vars : + ComputableTidilyInPolyTime (CNF.vars (V := ℕ)) encCNF (encList encNat) := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_vars)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_clause_length + {α : Type} {input : α ↪ List Bool} + {c : α → Clause ℕ} + (hc : ComputableTidilyInPolyTime c input (encList (encPair encNat encBool))) : + ComputableTidilyInPolyTime (fun a => (c a).length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_clause_length (.of_tidy hc))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_length + {α : Type} {input : α ↪ List Bool} {φ : α → CNF ℕ} + (hφ : ComputableTidilyInPolyTime φ input encCNF) : + ComputableTidilyInPolyTime (fun a => (φ a).length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_length (.of_tidy hφ))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_vars_length + {α : Type} {input : α ↪ List Bool} + {φ : α → CNF ℕ} (hφ : ComputableTidilyInPolyTime φ input encCNF) : + ComputableTidilyInPolyTime (fun a => (φ a).vars.length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_vars_length (.of_tidy hφ))) + /-! ### Polynomial-time certificates for protocol gadgets -/ private theorem computableTidilyInPolyTime_clauseLitVar (i : ℕ) {α : Type} {input : α ↪ List Bool} diff --git a/Complexity/Crypto/Computational/GMW/Simulator.lean b/Complexity/Crypto/Computational/GMW/Simulator.lean index b804789c5..c751f2ba3 100644 --- a/Complexity/Crypto/Computational/GMW/Simulator.lean +++ b/Complexity/Crypto/Computational/GMW/Simulator.lean @@ -79,6 +79,35 @@ namespace Cslib.Crypto.GMW open Probability Complexity Logic.PL Turing.MultiTapeTM ComputableTidilyInPolyTime open scoped NNReal ENNReal +/-! Tidy views of the plain `SAT` certificates, for tidy `fun_prop` below. -/ + +@[local fun_prop] +private theorem computableTidilyInPolyTime_vars : + ComputableTidilyInPolyTime (CNF.vars (V := ℕ)) encCNF (encList encNat) := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_vars)) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_clause_length + {α : Type} {input : α ↪ List Bool} + {c : α → Clause ℕ} + (hc : ComputableTidilyInPolyTime c input (encList (encPair encNat encBool))) : + ComputableTidilyInPolyTime (fun a => (c a).length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_clause_length (.of_tidy hc))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_length + {α : Type} {input : α ↪ List Bool} {φ : α → CNF ℕ} + (hφ : ComputableTidilyInPolyTime φ input encCNF) : + ComputableTidilyInPolyTime (fun a => (φ a).length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_length (.of_tidy hφ))) + +@[local fun_prop] +private theorem computableTidilyInPolyTime_vars_length + {α : Type} {input : α ↪ List Bool} + {φ : α → CNF ℕ} (hφ : ComputableTidilyInPolyTime φ input encCNF) : + ComputableTidilyInPolyTime (fun a => (φ a).vars.length) input encUnary := + (ComputableInPolyTime.tidy (SAT.computableInPolyTime_vars_length (.of_tidy hφ))) + /-! ### Step 1: Replacing the verifier's challenge in `runTwoRound` by a random guess -/ private theorem runTwoRound_query_inl {α β : Type} (reply1 reply2 : List Bool → List Bool) diff --git a/Complexity/Crypto/Computational/OneWay/BPP.lean b/Complexity/Crypto/Computational/OneWay/BPP.lean index fee068c99..596c21ef6 100644 --- a/Complexity/Crypto/Computational/OneWay/BPP.lean +++ b/Complexity/Crypto/Computational/OneWay/BPP.lean @@ -224,7 +224,7 @@ theorem exists_inverter_of_preimagePrefix_mem_BPP ∃ inverter : Inverter, IsPPT encBits inverter ∧ ∀ n, 1 / 2 ≤ Game.succProbability (ProbComp.eval (inversionGame f inverter n)) := by obtain ⟨p, V, hV, herr⟩ := mem_BPP_iff_forall_decidesWithErrorExponent.1 h (Polynomial.X + 1) - exact ⟨randomizedPreimageSearch p V, isPPT_randomizedPreimageSearch hV, + exact ⟨randomizedPreimageSearch p V, isPPT_randomizedPreimageSearch hV.tidy, half_le_succProbability_inversionGame herr⟩ /-- **One-way functions have preimage-prefix problems outside `BPP`.** -/ diff --git a/ComplexityTests/AWPPLowness.lean b/ComplexityTests/AWPPLowness.lean index 243c3b165..6ff744daa 100644 --- a/ComplexityTests/AWPPLowness.lean +++ b/ComplexityTests/AWPPLowness.lean @@ -50,8 +50,8 @@ example : ∃ H ∈ GapP (encPair encBits encBits), ∃ R : List Bool → ℕ, (0 ≤ H (a, w) ∧ H (a, w) ≤ D) ∧ D - H (a, w) ≤ D := by obtain ⟨H, hH, R, hR, hb⟩ := exists_AWPP_queryWeights univ_mem (T := fun _ : List Bool => 0) (e := fun _ : List Bool => 0) - (ComputableTidilyInPolyTime.const 0) (ComputableTidilyInPolyTime.const 0) - refine ⟨H, hH, R, hR, fun a w => ⟨(hb a w).1, ?_⟩⟩ + (.of_tidy (ComputableTidilyInPolyTime.const 0)) (.of_tidy (ComputableTidilyInPolyTime.const 0)) + refine ⟨H, hH, R, hR.tidy, fun a w => ⟨(hb a w).1, ?_⟩⟩ simpa only [pow_zero, one_mul] using (hb a w).2.1 (Set.mem_univ _) /-- info: 'Cslib.Complexity.exists_AWPP_queryWeights' depends on axioms: diff --git a/ComplexityTests/Alternation.lean b/ComplexityTests/Alternation.lean index 936111018..96d9ab0e1 100644 --- a/ComplexityTests/Alternation.lean +++ b/ComplexityTests/Alternation.lean @@ -104,7 +104,7 @@ example : (Set.univ : Set (List Bool)) ∈ PSPACE encBits := /-- A problem in `AP` has a game verifier. -/ example : ∃ (p : Polynomial ℕ) (V : List Bool × List Bool → Bool), - MultiTapeTM.ComputableTidilyInPolyTime V (MultiTapeTM.encPair encBits encBits) + MultiTapeTM.ComputableInPolyTime V (MultiTapeTM.encPair encBits encBits) MultiTapeTM.encBool ∧ IsGameVerifier encBits p V (∅ : Set (List Bool)) := exists_isGameVerifier_of_mem_AP ⟨_, PolyBounded.const 1, 0, Unit, inferInstance, emitMove true, decidesInTime_empty⟩ @@ -175,27 +175,27 @@ private theorem isGameVerifier_secondMove : /-- `Set.univ ∈ AP` through the guess-then-verify machine. -/ example : (Set.univ : Set (List Bool)) ∈ AP encBits := - isGameVerifier_firstMove.mem_AP computableTidilyInPolyTime_firstMove + isGameVerifier_firstMove.mem_AP (.of_tidy computableTidilyInPolyTime_firstMove) /-- `∅ ∈ AP` through the guess-then-verify machine. -/ example : (∅ : Set (List Bool)) ∈ AP encBits := - isGameVerifier_secondMove.mem_AP computableTidilyInPolyTime_secondMove + isGameVerifier_secondMove.mem_AP (.of_tidy computableTidilyInPolyTime_secondMove) /-- A game verifier gives a problem in `PSPACE`, and conversely. -/ example : (∅ : Set (List Bool)) ∈ PSPACE encBits := mem_PSPACE_iff_exists_isGameVerifier.mpr - ⟨1, secondMove, computableTidilyInPolyTime_secondMove, isGameVerifier_secondMove⟩ + ⟨1, secondMove, (.of_tidy computableTidilyInPolyTime_secondMove), isGameVerifier_secondMove⟩ /-- `AP = PSPACE`, used to move a problem from one class to the other. -/ example : (Set.univ : Set (List Bool)) ∈ PSPACE encBits := - AP_eq_PSPACE ▸ isGameVerifier_firstMove.mem_AP computableTidilyInPolyTime_firstMove + AP_eq_PSPACE ▸ isGameVerifier_firstMove.mem_AP (.of_tidy computableTidilyInPolyTime_firstMove) /-- A problem in `PSPACE` has a polynomial-time game verifier. -/ example : ∃ (p : Polynomial ℕ) (V : List Bool × List Bool → Bool), - MultiTapeTM.ComputableTidilyInPolyTime V (MultiTapeTM.encPair encBits encBits) + MultiTapeTM.ComputableInPolyTime V (MultiTapeTM.encPair encBits encBits) MultiTapeTM.encBool ∧ IsGameVerifier encBits p V (Set.univ : Set (List Bool)) := exists_isGameVerifier_of_mem_PSPACE - (AP_eq_PSPACE ▸ isGameVerifier_firstMove.mem_AP computableTidilyInPolyTime_firstMove) + (AP_eq_PSPACE ▸ isGameVerifier_firstMove.mem_AP (.of_tidy computableTidilyInPolyTime_firstMove)) /-! ### Single-bit moves -/ diff --git a/ComplexityTests/ApproximateCounting.lean b/ComplexityTests/ApproximateCounting.lean index cdab5fd37..324226c39 100644 --- a/ComplexityTests/ApproximateCounting.lean +++ b/ComplexityTests/ApproximateCounting.lean @@ -66,7 +66,7 @@ private theorem univ_mem_SBP_zero : (Set.univ : Set (List Bool)) ∈ SBP encBits example : (Set.univ : Set (List Bool)) ∈ PP encBits := SBP_subset_PP univ_mem_SBP_zero example : ∃ f ∈ SharpP encBits, ∃ k : List Bool → ℕ, - ComputableTidilyInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ + ComputableInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, (w ∈ (Set.univ : Set (List Bool)) → k w ≤ f w) ∧ (w ∉ (Set.univ : Set (List Bool)) → 2 * f w < k w) := mem_SBP_iff_exists_pos_threshold.mp univ_mem_SBP_zero @@ -141,7 +141,7 @@ example : {w : List Bool | w.headD false = true} ∆ {w | w.tail.headD false = t /-- The repetition count is a theorem parameter, independent of the input. -/ example (m : ℕ) (hm : 0 < m) : ∃ f ∈ SharpP encBits, ∃ k : List Bool → ℕ, - ComputableTidilyInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, + ComputableInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, (w.headD false = true → k w ≤ f w) ∧ (w.headD false ≠ true → 2 ^ m * f w < k w) := exists_SBP_gap_pow head_mem_SBP hm diff --git a/ComplexityTests/ArthurMerlin.lean b/ComplexityTests/ArthurMerlin.lean index 2402bbec4..099939978 100644 --- a/ComplexityTests/ArthurMerlin.lean +++ b/ComplexityTests/ArthurMerlin.lean @@ -71,13 +71,13 @@ example : {w : List Bool | w.tail.headD false = true} ∈ AM encBits := /-- The error-exponent conditions are satisfiable, for every error exponent. -/ example : ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : List Bool × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair encBits encBits) encBool ∧ + ComputableInPolyTime V (encPair encBits encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent encBits e q p V {w : List Bool | w.headD false = true} := mem_MA_iff_exists_forall_errorExponent.mp head_mem_MA_direct example (e : Polynomial ℕ) : ∃ (p q : Polynomial ℕ) (V : _ × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair encCNF encBits) encBool ∧ + ComputableInPolyTime V (encPair encCNF encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent encCNF e p q V SAT := mem_AM_iff_forall_errorExponent.mp (NP_subset_AM SAT.mem_NP) e diff --git a/ComplexityTests/Axioms.lean b/ComplexityTests/Axioms.lean index a04ca375c..1d33d8ae5 100644 --- a/ComplexityTests/Axioms.lean +++ b/ComplexityTests/Axioms.lean @@ -807,11 +807,11 @@ info: 'Cslib.Logic.ESO.Definable.queryLanguage_mem_NP' depends on axioms: #print axioms Cslib.Logic.ESO.Definable.queryLanguage_mem_NP /-- -info: 'Cslib.Logic.ESO.Sentence.Layout.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Logic.ESO.Sentence.Layout.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Logic.ESO.Sentence.Layout.computableTidilyInPolyTime_verifier +#print axioms Cslib.Logic.ESO.Sentence.Layout.computableInPolyTime_verifier /-- info: 'Cslib.Complexity.SAT.isVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] @@ -5358,33 +5358,25 @@ info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses' depends on #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_readClauses' depends on axioms: [propext, - Classical.choice, - Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_readClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_readClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses' depends on axioms: [propext, - Classical.choice, - Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_tableau' depends on axioms: [propext, - Classical.choice, - Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_tableau' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_tableau /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_reduce' depends on axioms: [propext, - Classical.choice, - Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_reduce' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_reduce diff --git a/ComplexityTests/CircuitValueCompleteness.lean b/ComplexityTests/CircuitValueCompleteness.lean index b9248d77c..1c658be18 100644 --- a/ComplexityTests/CircuitValueCompleteness.lean +++ b/ComplexityTests/CircuitValueCompleteness.lean @@ -96,9 +96,9 @@ example (h : CircuitValue ∈ L encCircuitValue) : P encBits ⊆ L encBits := /-- A single certified constructor provides circuits for every encoded input length. -/ example {α : Type} {enc : α ↪ List Bool} {f : α → Bool} - (hf : ComputableTidilyInPolyTime f enc encBool) : + (hf : ComputableInPolyTime f enc encBool) : ∃ circuits : (n : ℕ) → Circuit signature n 1, - ComputableTidilyInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ + ComputableInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval interpretation (fun i => (enc a)[i]) 0 = f a := CircuitValue.exists_uniformCircuits hf diff --git a/ComplexityTests/CookLevinPolyTime.lean b/ComplexityTests/CookLevinPolyTime.lean index 771e60021..f2cee4ee5 100644 --- a/ComplexityTests/CookLevinPolyTime.lean +++ b/ComplexityTests/CookLevinPolyTime.lean @@ -23,21 +23,25 @@ namespace ComplexityTests.CookLevinPolyTime open Turing.MultiTapeTM Cslib.Complexity Cslib.Complexity.CookLevin example {k : ℕ} {State : Type} [Fintype State] (tm : Turing.MultiTapeTM k Bool State) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun T => (initClauses tm T ++ sitClauses T ++ acceptClauses T).relabel Var.index) - encUnary encCNF := by - fun_prop + encUnary encCNF := + computableInPolyTime_relabel.comp <| .of_tidy <| by + have hinit := (computableInPolyTime_initClauses tm).tidy + have hsit := (computableInPolyTime_sitClauses (k := k) (State := State)).tidy + have haccept := (computableInPolyTime_acceptClauses (k := k) (State := State)).tidy + fun_prop -- Fixed tape/symbol traversals combine with input-dependent windows and nested lists. example {k : ℕ} {State : Type} [Fintype State] : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : ℕ × ℕ => Feature.groups (k := k) (State := State) p.1 p.2) (encPair encUnary encUnary) (encList (encList encFeature)) := by fun_prop -- Exactly-one constraints compose with the existing binary variable numbering. example {k : ℕ} {State : Type} [Fintype State] [DecidableEq State] : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : ((List Bool × ℕ) × ℕ) × ℕ => (oneHotClauses (k := k) (State := State) p.1.1.1 p.1.1.2 p.1.2 p.2).relabel Var.index) (encPair (encPair (encPair encBits encUnary) encUnary) encUnary) encCNF := by @@ -47,7 +51,7 @@ example {k : ℕ} {State : Type} [Fintype State] [DecidableEq State] : example {k : ℕ} {State α : Type} [Fintype State] (tm : Turing.MultiTapeTM k Bool State) (enc : α ↪ List Bool) (p : Polynomial ℕ) (c d : ℕ) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun a => (initClauses tm (parameters p c d enc a).2.2).relabel Var.index) enc encCNF := by fun_prop @@ -55,35 +59,34 @@ example {k : ℕ} {State α : Type} [Fintype State] private def finish : Turing.MultiTapeTM 0 Bool Unit := ofTr () fun _ _ _ => ⟨0, Fin.elim0, some true, none⟩ -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun T => (initClauses finish T).relabel Var.index) encUnary encCNF := by fun_prop -attribute [local fun_prop] ComputableInPolyTime.tidy in -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun n => (oneHotClauses (k := 0) (State := Unit) [] n n n).relabel Var.index) encUnary encCNF := by fun_prop [oneHotClauses] -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun j => (Var.cert (k := 0) (State := Empty) j).index) encUnary encNat := by fun_prop -- The complete reduction has a concrete machine witness, not a supplied efficiency hypothesis. -example : ComputableTidilyInPolyTime (reduce finish (Polynomial.X + 1) 3 2 encBits) +example : ComputableInPolyTime (reduce finish (Polynomial.X + 1) 3 2 encBits) encBits encCNF := by fun_prop -- A computed tableau and the same computation through a tuple both emit binary SAT instances. -example : ComputableTidilyInPolyTime (fun word : List Bool => +example : ComputableInPolyTime (fun word : List Bool => (tableau finish word (word.length + 1) (word.length ^ 2 + 2)).relabel Var.index) encBits encCNF := by polytime -- The same functional computation also accepts the generic list encoding of its input. -example : ComputableTidilyInPolyTime (fun word : List Bool => +example : ComputableInPolyTime (fun word : List Bool => (tableau finish word (word.length + 1) (word.length ^ 2 + 2)).relabel Var.index) (encList encBool) encCNF := by polytime -example : ComputableTidilyInPolyTime (fun q : List Bool × ℕ × ℕ => +example : ComputableInPolyTime (fun q : List Bool × ℕ × ℕ => (tableau finish q.1 q.2.1 q.2.2).relabel Var.index) (encPair encBits (encPair encUnary encUnary)) encCNF := by fun_prop diff --git a/ComplexityTests/CountingSpace.lean b/ComplexityTests/CountingSpace.lean index 94e8e97cd..eee6cfcd1 100644 --- a/ComplexityTests/CountingSpace.lean +++ b/ComplexityTests/CountingSpace.lean @@ -51,9 +51,9 @@ example : ComputableTidilyInPolySpace theorem power_mem : (fun w : List Bool => 2 ^ w.length) ∈ SharpP encBits := by simpa using SharpP.two_pow_mem (enc := encBits) Polynomial.X -example : ComputableTidilyInPolySpace (fun w : List Bool => -((2 ^ w.length : ℕ) : ℤ)) +example : ComputableInPolySpace (fun w : List Bool => -((2 ^ w.length : ℕ) : ℤ)) encBits encIntBin := - GapP.computableTidilyInPolySpace (GapP.neg_mem (SharpP.natCast_mem_GapP power_mem)) + GapP.computableInPolySpace (GapP.neg_mem (SharpP.natCast_mem_GapP power_mem)) example (k : ℕ) : {w : List Bool | 2 ^ w.length % k ≠ 0} ∈ PSPACE encBits := ModP_subset_PSPACE k ⟨_, power_mem, fun _ => Iff.rfl⟩ @@ -98,15 +98,15 @@ info: 'Cslib.Complexity.computableInPolySpace_acceptCount' depends on axioms: [p #guard_msgs in #print axioms computableInPolySpace_acceptCount /-- -info: 'Cslib.Complexity.SharpP.computableTidilyInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SharpP.computableInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms SharpP.computableTidilyInPolySpace +#print axioms SharpP.computableInPolySpace /-- -info: 'Cslib.Complexity.GapP.computableTidilyInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.GapP.computableInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms GapP.computableTidilyInPolySpace +#print axioms GapP.computableInPolySpace /-- info: 'Cslib.Complexity.PP_subset_PSPACE' depends on axioms: [propext, Classical.choice, Quot.sound] -/ diff --git a/ComplexityTests/CountingVerifier.lean b/ComplexityTests/CountingVerifier.lean index 110a04cae..2cc115a9a 100644 --- a/ComplexityTests/CountingVerifier.lean +++ b/ComplexityTests/CountingVerifier.lean @@ -132,7 +132,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [MultiTapeTM.encBits_apply, Polynomial.eval_zero, Complexity.acceptCount_true, pow_zero, Nat.sub_self] using exists_verifier_counting_machine MultiTapeTM.encBits 0 (fun _ => true) - (MultiTapeTM.ComputableTidilyInPolyTime.const true) + (.of_tidy (MultiTapeTM.ComputableTidilyInPolyTime.const true)) -- Four distinct witnesses may have the identical Boolean output; all four occurrences count. example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) @@ -143,7 +143,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [MultiTapeTM.encBits_apply, Polynomial.eval_C, Complexity.acceptCount_true, Nat.reducePow, Nat.sub_self] using exists_verifier_counting_machine MultiTapeTM.encBits (Polynomial.C 2) (fun _ => true) - (MultiTapeTM.ComputableTidilyInPolyTime.const true) + (.of_tidy (MultiTapeTM.ComputableTidilyInPolyTime.const true)) -- The all-rejecting empty witness is still a terminal branch, and supplies the zero #P function. example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) @@ -154,7 +154,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [MultiTapeTM.encBits_apply, Polynomial.eval_zero, Complexity.acceptCount_false, pow_zero, Nat.sub_zero] using exists_verifier_counting_machine MultiTapeTM.encBits 0 (fun _ => false) - (MultiTapeTM.ComputableTidilyInPolyTime.const false) + (.of_tidy (MultiTapeTM.ComputableTidilyInPolyTime.const false)) /-- info: 'Turing.MultiTapeCTM.exists_verifier_machine' depends on axioms: diff --git a/ComplexityTests/FaginNP.lean b/ComplexityTests/FaginNP.lean index 86a24c5bb..b2fbcb823 100644 --- a/ComplexityTests/FaginNP.lean +++ b/ComplexityTests/FaginNP.lean @@ -113,11 +113,11 @@ info: 'Cslib.Logic.ESO.Sentence.queryLanguage_mem_NP' depends on axioms: #print axioms Cslib.Logic.ESO.Sentence.queryLanguage_mem_NP /-- -info: 'Cslib.Logic.ESO.Sentence.Layout.computableTidilyInPolyTime_verifier' depends on axioms: +info: 'Cslib.Logic.ESO.Sentence.Layout.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Logic.ESO.Sentence.Layout.computableTidilyInPolyTime_verifier +#print axioms Cslib.Logic.ESO.Sentence.Layout.computableInPolyTime_verifier /-- info: 'Cslib.Logic.Vocabulary.mem_queryLanguage_encode' depends on axioms: diff --git a/ComplexityTests/FineGrained.lean b/ComplexityTests/FineGrained.lean index 8b5b75ba3..870197f54 100644 --- a/ComplexityTests/FineGrained.lean +++ b/ComplexityTests/FineGrained.lean @@ -108,11 +108,11 @@ example : satExponent 3 ≤ satExponent 4 := satExponent_mono (by norm_num) /-- A trivial problem is decidable within linear time, in either form. -/ example : DecidableInTimeO (∅ : Set (CNF ℕ)) encCNF fun φ => (encCNF φ).length := - DecidableInTimeO.of_computableInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl + DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) fun _ => le_rfl example : (∅ : Set (CNF ℕ)) ∈ DTIME encCNF id := mem_DTIME_iff_decidableInTimeO.mpr - (DecidableInTimeO.of_computableInO (ComputableTidilyInO.const false) (by simp) fun _ => le_rfl) + (DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) fun _ => le_rfl) /-- The hypotheses in terms of the exponents. -/ example : ETH ↔ 0 < satExponent 3 := ETH_iff_satExponent_pos diff --git a/ComplexityTests/FineGrained/GraphProblems.lean b/ComplexityTests/FineGrained/GraphProblems.lean index 6120b0524..a78ddb8a1 100644 --- a/ComplexityTests/FineGrained/GraphProblems.lean +++ b/ComplexityTests/FineGrained/GraphProblems.lean @@ -116,7 +116,8 @@ example : (SAT.toThreeColoring φ₁).1.length + (SAT.toThreeColoring φ₁).2.l /-- The subexponential time predicate holds for a trivial problem. -/ example : DecidableInSubexpTime (∅ : Set Graph) encGraph fun G => G.1.length + G.2.length := - fun δ hδ => DecidableInExpTime.of_computableInO (ComputableTidilyInO.const false) (by simp) 1 1 fun G => by + fun δ hδ => DecidableInExpTime.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) + (by simp) 1 1 fun G => by have h₁ : (1 : ℝ) ≤ 2 ^ (δ * ((G.1.length + G.2.length : ℕ) : ℝ)) := Real.one_le_rpow (by norm_num) (by positivity) have h₀ : (0 : ℝ) ≤ (encGraph G).length := Nat.cast_nonneg _ @@ -134,7 +135,7 @@ example (h : ETH) : /-- Under `ETH`, 3SAT is not decidable in subexponential time in the number of clauses: the identity is a reduction of linear size. -/ example (h : ETH) : ¬DecidableInSubexpTime ThreeSAT encCNF List.length := - h.not_decidableInSubexpTime_of_reduction (f := id) ComputableTidilyInPolyTime.id' + h.not_decidableInSubexpTime_of_reduction (f := id) (.of_tidy ComputableTidilyInPolyTime.id') (fun φ hφ => ⟨fun h => h.2, fun h' => ⟨hφ, h'⟩⟩) (k := 1) fun φ _ => by simp /-! ### Axioms -/ diff --git a/ComplexityTests/InteractiveProofs.lean b/ComplexityTests/InteractiveProofs.lean index f5bbdf5de..af2143b03 100644 --- a/ComplexityTests/InteractiveProofs.lean +++ b/ComplexityTests/InteractiveProofs.lean @@ -171,7 +171,7 @@ example : ComputableTidilyInPolySpace (fun w => BitString.increment (BitString.i -- A Boolean function computable within polynomial space decides a problem in `PSPACE`. example : {w : List Bool | w.headD false = true} ∈ PSPACE encBits := mem_PSPACE_of_computableInPolySpace (f := fun w => w.headD false) - (.of_polyTime (ComputableTidilyInPolyTime.headD false)) fun _ => Iff.rfl + (.of_polyTime (.of_tidy (ComputableTidilyInPolyTime.headD false))) fun _ => Iff.rfl -- The seven codes of length `3` decode to the seven words of length at most `2`, each once. example : (List.range (Interaction.codeCount 2)).map (fun i => diff --git a/ComplexityTests/KarpLipton2.lean b/ComplexityTests/KarpLipton2.lean index d9d0eb5af..40ae8de7e 100644 --- a/ComplexityTests/KarpLipton2.lean +++ b/ComplexityTests/KarpLipton2.lean @@ -142,9 +142,7 @@ info: 'Cslib.Circuits.Boolean.evalAdvice_familyAdvice' depends on axioms: [prope #print axioms Cslib.Circuits.Boolean.evalAdvice_familyAdvice /-- -info: 'Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice' depends on axioms: [propext, - Classical.choice, - Quot.sound] +info: 'Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice diff --git a/ComplexityTests/KarpReductions.lean b/ComplexityTests/KarpReductions.lean index ff2decd8a..c65ab10d0 100644 --- a/ComplexityTests/KarpReductions.lean +++ b/ComplexityTests/KarpReductions.lean @@ -44,25 +44,25 @@ example : NPHard (encPair encGraph encNat) Clique := /-! ### Compositional `fun_prop` synthesis -/ -example : ComputableTidilyInPolyTime toThreeSAT encCNF encCNF := by fun_prop +example : ComputableInPolyTime toThreeSAT encCNF encCNF := by fun_prop -example : ComputableTidilyInPolyTime ThreeSAT.verifier (encPair encCNF encBits) encBool := by +example : ComputableInPolyTime ThreeSAT.verifier (encPair encCNF encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime SAT.toIndependentSet encCNF (encPair encGraph encNat) := by +example : ComputableInPolyTime SAT.toIndependentSet encCNF (encPair encGraph encNat) := by fun_prop example : ComputableTidilyInPolyTime Graph.compl encGraph encGraph := by fun_prop -example : ComputableTidilyInPolyTime IndependentSet.verifier +example : ComputableInPolyTime IndependentSet.verifier (encPair (encPair encGraph encNat) encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime Clique.verifier +example : ComputableInPolyTime Clique.verifier (encPair (encPair encGraph encNat) encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun φ : CNF ℕ => let x := SAT.toIndependentSet φ; (x.1.compl, x.2)) encCNF (encPair encGraph encNat) := by fun_prop diff --git a/ComplexityTests/ManyOne.lean b/ComplexityTests/ManyOne.lean index fd646b776..d62c437d8 100644 --- a/ComplexityTests/ManyOne.lean +++ b/ComplexityTests/ManyOne.lean @@ -147,19 +147,14 @@ example {κA : α → ℕ} {κB : β → ℕ} : FPTReducible encA encB κA κB A ∃ h : ℕ → ℕ, ∀ a, κB (f a) ≤ h (κA a)) ∧ ∀ a, a ∈ A ↔ f a ∈ B := Iff.rfl -example {κA : α → ℕ} {κB : β → ℕ} : FPTReducible encA encB κA κB A B ↔ - ∃ f : α → β, (ComputableTidilyInFPTTime f encA encB κA ∧ - ∃ h : ℕ → ℕ, ∀ a, κB (f a) ≤ h (κA a)) ∧ ∀ a, a ∈ A ↔ f a ∈ B := - fptReducible_iff_tidy - example {κA : α → ℕ} {κB : β → ℕ} : FPTReducible encA encB κA κB A B ↔ ManyOneReducibleBy (ComputableInFPTWithParam encA encB κA κB) A B := fptReducible_iff_manyOneReducibleBy -/-- The identity, with its tidy fpt-time certificate, bounds the parameter by itself. -/ +/-- The identity, computable in polynomial time, bounds the parameter by itself. -/ example {κA : α → ℕ} : ComputableInFPTWithParam encA encA κA κA id := - computableInFPTWithParam_iff_tidy.mpr - ⟨ComputableTidilyInPolyTime.id'.computableTidilyInFPTTime κA, id, fun _ => le_rfl⟩ + ⟨(ComputableInPolyTime.of_tidy ComputableTidilyInPolyTime.id').computableInFPTTime κA, id, + fun _ => le_rfl⟩ /-! ### Non-`Set` hardness and completeness instances -/ diff --git a/ComplexityTests/MonotoneCircuitValue.lean b/ComplexityTests/MonotoneCircuitValue.lean index 432dfde7a..86bf12ce2 100644 --- a/ComplexityTests/MonotoneCircuitValue.lean +++ b/ComplexityTests/MonotoneCircuitValue.lean @@ -58,11 +58,11 @@ example : ComputableInLogSpace id (encFramed encBits) encBits := by simp only [encNat_apply, List.length_cons, List.length_nil, zero_add, add_zero, Order.add_one_le_iff] omega - refine copySpec.computableInLogSpace (.of_tidy (fun w => by - simp [CircuitValue.WriterSpec.output, copySpec])) + refine copySpec.computableInLogSpace (fun w => by + simp [CircuitValue.WriterSpec.output, copySpec]) (.of_tidy (ComputableTidilyInSpace.budget_const (encB := encNat) 0 hin)) (.of_tidy (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin)) - (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin) ?_ + (.of_tidy (ComputableTidilyInSpace.budget_const (encB := encBits) [] hin)) ?_ change PolynomiallyBounded fun _ : ℕ => 0 fun_prop diff --git a/ComplexityTests/NPCompleteGraphs.lean b/ComplexityTests/NPCompleteGraphs.lean index 28eed5f5f..13dd1d306 100644 --- a/ComplexityTests/NPCompleteGraphs.lean +++ b/ComplexityTests/NPCompleteGraphs.lean @@ -54,28 +54,28 @@ example : PolyTimeReducible encCNF (encPair encGraph (encPair encNat encNat)) Th /-! ### Compositional `fun_prop` synthesis -/ -example : ComputableTidilyInPolyTime IndependentSet.toVertexCover (encPair encGraph encNat) +example : ComputableInPolyTime IndependentSet.toVertexCover (encPair encGraph encNat) (encPair encGraph encNat) := by fun_prop -example : ComputableTidilyInPolyTime VertexCover.verifier +example : ComputableInPolyTime VertexCover.verifier (encPair (encPair encGraph encNat) encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime (KColoring.verifier 3) (encPair encGraph encBits) encBool := by +example : ComputableInPolyTime (KColoring.verifier 3) (encPair encGraph encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime SAT.toThreeColoring encCNF encGraph := by fun_prop +example : ComputableInPolyTime SAT.toThreeColoring encCNF encGraph := by fun_prop -example : ComputableTidilyInPolyTime (SAT.toKColoring 2) encCNF encGraph := by fun_prop +example : ComputableInPolyTime (SAT.toKColoring 2) encCNF encGraph := by fun_prop -example : ComputableTidilyInPolyTime SAT.toDirHamPath encCNF +example : ComputableInPolyTime SAT.toDirHamPath encCNF (encPair encGraph (encPair encNat encNat)) := by fun_prop -example : ComputableTidilyInPolyTime SAT.toDirHamCycle encCNF encGraph := by fun_prop +example : ComputableInPolyTime SAT.toDirHamCycle encCNF encGraph := by fun_prop -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun φ => IndependentSet.toVertexCover (SAT.toIndependentSet φ)) encCNF (encPair encGraph encNat) := by fun_prop diff --git a/ComplexityTests/NPCompleteGraphs/Hamiltonian.lean b/ComplexityTests/NPCompleteGraphs/Hamiltonian.lean index bbd71f6fc..b5dfcf36a 100644 --- a/ComplexityTests/NPCompleteGraphs/Hamiltonian.lean +++ b/ComplexityTests/NPCompleteGraphs/Hamiltonian.lean @@ -32,20 +32,25 @@ example : IsVerifier encGraph (Polynomial.X ^ 2) HamCycle.verifier HamCycle := H /-! ### Compositional `fun_prop` synthesis -/ +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime DirHamPath.verifier (encPair (encPair encGraph (encPair encNat encNat)) encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime DirHamCycle.verifier (encPair encGraph encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime HamPath.verifier (encPair (encPair encGraph (encPair encNat encNat)) encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime HamCycle.verifier (encPair encGraph encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun x : List ℕ × List Bool => Graph.decodeVertexList x.1 x.2) (encPair (encList encNat) encBits) (encList encNat) := by fun_prop diff --git a/ComplexityTests/NPCompleteGraphs/TSP.lean b/ComplexityTests/NPCompleteGraphs/TSP.lean index 02d3ce14a..9427fdd7e 100644 --- a/ComplexityTests/NPCompleteGraphs/TSP.lean +++ b/ComplexityTests/NPCompleteGraphs/TSP.lean @@ -29,18 +29,20 @@ example : IsVerifier encTSP (Polynomial.X ^ 2) TSP.verifier TSP := TSP.isVerifie /-! ### Compositional `fun_prop` synthesis -/ -example : ComputableTidilyInPolyTime HamCycle.toTSP encGraph encTSP := by fun_prop +example : ComputableInPolyTime HamCycle.toTSP encGraph encTSP := by fun_prop -example : ComputableTidilyInPolyTime TSP.verifier (encPair encTSP encBits) encBool := by fun_prop +example : ComputableInPolyTime TSP.verifier (encPair encTSP encBits) encBool := by fun_prop -example : ComputableTidilyInPolyTime (fun x : List (List ℕ) × List ℕ => TSP.tourLength x.1 x.2) +example : ComputableInPolyTime (fun x : List (List ℕ) × List ℕ => TSP.tourLength x.1 x.2) (encPair (encList (encList encNat)) (encList encNat)) encNat := by fun_prop -- Tour lengths compose with the binary comparison and sum certificates. -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun x : (List (List ℕ) × List ℕ) × ℕ => decide (TSP.tourLength x.1.1 x.1.2 + x.2 ≤ x.2 * 2)) (encPair (encPair (encList (encList encNat)) (encList encNat)) encNat) encBool := by + have htour := TSP.computableInPolyTime_tourLength.tidy + refine .of_tidy ?_ fun_prop /-- Non-membership in `TSP`, checked over the permutations of the cities. -/ diff --git a/ComplexityTests/NPCompleteGraphs/Undirected.lean b/ComplexityTests/NPCompleteGraphs/Undirected.lean index 576f1f3f6..36b38aaa2 100644 --- a/ComplexityTests/NPCompleteGraphs/Undirected.lean +++ b/ComplexityTests/NPCompleteGraphs/Undirected.lean @@ -27,14 +27,14 @@ example : PolyTimeReducible (encPair encGraph (encPair encNat encNat)) example : PolyTimeReducible encGraph encGraph DirHamCycle HamCycle := polyTimeReducible_DirHamCycle_HamCycle -example : ComputableTidilyInPolyTime Graph.split encGraph encGraph := by fun_prop +example : ComputableInPolyTime Graph.split encGraph encGraph := by fun_prop -example : ComputableTidilyInPolyTime DirHamPath.toHamPath +example : ComputableInPolyTime DirHamPath.toHamPath (encPair encGraph (encPair encNat encNat)) (encPair encGraph (encPair encNat encNat)) := by fun_prop -- Certificates compose: splitting twice is polynomial-time. -example : ComputableTidilyInPolyTime (fun G : Graph => G.split.split) encGraph encGraph := by +example : ComputableInPolyTime (fun G : Graph => G.split.split) encGraph encGraph := by fun_prop /-! ### The split graph -/ diff --git a/ComplexityTests/NPCompleteNumbers.lean b/ComplexityTests/NPCompleteNumbers.lean index 32610490c..91f422593 100644 --- a/ComplexityTests/NPCompleteNumbers.lean +++ b/ComplexityTests/NPCompleteNumbers.lean @@ -58,11 +58,11 @@ example : PolyTimeReducible encCNF encKnapsack ThreeSAT Knapsack := /-! ### Compositional `fun_prop` synthesis -/ -example : ComputableTidilyInPolyTime ThreeSAT.toSubsetSum encCNF +example : ComputableInPolyTime ThreeSAT.toSubsetSum encCNF (encPair (encList encNat) encNat) := by fun_prop -example : ComputableTidilyInPolyTime (fun x => SubsetSum.toPartition x) +example : ComputableInPolyTime (fun x => SubsetSum.toPartition x) (encPair (encList encNat) encNat) (encList encNat) := by fun_prop diff --git a/ComplexityTests/NPWitness.lean b/ComplexityTests/NPWitness.lean index e96c5b353..b14d4258c 100644 --- a/ComplexityTests/NPWitness.lean +++ b/ComplexityTests/NPWitness.lean @@ -43,7 +43,7 @@ theorem isVerifier_even : IsVerifier encUnary (2 * Polynomial.X + 1) isVerifier_witnessVerifier Decoder.unary isHalf_iff fun _ m h => ⟨m, h, by simp; omega⟩ example : {n | ∃ m, m + m = n} ∈ NP encUnary := - mem_NP_of_witness Decoder.unary (p := Polynomial.X) computableTidilyInPolyTime_isHalf isHalf_iff + mem_NP_of_witness Decoder.unary (p := Polynomial.X) (.of_tidy computableTidilyInPolyTime_isHalf) isHalf_iff fun _ m h => ⟨m, h, by simp; omega⟩ -- In: the framed witness `2` for `4`, padded to the certificate length `2 * 4 + 1`. @@ -106,10 +106,10 @@ theorem isVerifier_distinctEntries : IsVerifier (encPair (encList encNat) encNat · simp [hasCount, List.toFinset_card_of_nodup hl] example : DistinctEntries ∈ NP (encPair (encList encNat) encNat) := - mem_NP_of_subsetWitness (check := hasCount) (ComputableTidilyInPolyTime.fst _ _) - ((ComputableTidilyInPolyTime.unary_to_binary.comp + mem_NP_of_subsetWitness (check := hasCount) (.of_tidy (ComputableTidilyInPolyTime.fst _ _)) + (.of_tidy ((ComputableTidilyInPolyTime.unary_to_binary.comp ((ComputableTidilyInPolyTime.length_list encNat).comp (ComputableTidilyInPolyTime.snd _ _)) - ).decide_eq' (by fun_prop)) + ).decide_eq' (by fun_prop))) fun x l hl _ => by simp [hasCount, List.toFinset_card_of_nodup hl] -- In: the mask selects `1` and `2`. diff --git a/ComplexityTests/NondeterministicVerifiers.lean b/ComplexityTests/NondeterministicVerifiers.lean index 53d73217d..d498d088b 100644 --- a/ComplexityTests/NondeterministicVerifiers.lean +++ b/ComplexityTests/NondeterministicVerifiers.lean @@ -235,7 +235,7 @@ guessing `[true]`. -/ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePTM k Bool State), machine.toNTM.Accepts [] := by obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := - IsVerifier.exists_decidesInTime (enc := encBits) (p := 1) (A := Set.univ) polyTime_headD + IsVerifier.exists_decidesInTime (enc := encBits) (p := 1) (A := Set.univ) (.of_tidy polyTime_headD) fun _ => ⟨fun _ => ⟨[true], by simp, rfl⟩, fun _ => trivial⟩ exact ⟨k, State, hfinite, machine, ((hdecides []).2).mp trivial⟩ @@ -244,7 +244,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePT example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePTM k Bool State), ¬machine.toNTM.Accepts [] := by obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := - IsVerifier.exists_decidesInTime (enc := encBits) (p := 0) (A := ∅) polyTime_headD + IsVerifier.exists_decidesInTime (enc := encBits) (p := 0) (A := ∅) (.of_tidy polyTime_headD) fun _ => by simp exact ⟨k, State, hfinite, machine, fun h => ((hdecides []).2).mpr h⟩ @@ -253,7 +253,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePT machine.toNTM.Accepts [] := by obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := IsVerifier.exists_decidesInTime (enc := encBits) (p := 0) (A := Set.univ) - (ComputableTidilyInPolyTime.const true) fun _ => by simp + (.of_tidy (ComputableTidilyInPolyTime.const true)) fun _ => by simp exact ⟨k, State, hfinite, machine, ((hdecides []).2).mp trivial⟩ /-- The guessing decider of the rejecting verifier rejects the empty instance, although every @@ -263,7 +263,7 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePT ∀ input (cfg : Cfg k Bool State input), ∃ cfg', machine.toNTM.Step cfg cfg' := by obtain ⟨k, State, hfinite, machine, c, d, hdecides, htotal⟩ := IsVerifier.exists_decidesInTime (enc := encBits) (p := 0) (A := ∅) - (ComputableTidilyInPolyTime.const false) fun _ => by simp + (.of_tidy (ComputableTidilyInPolyTime.const false)) fun _ => by simp exact ⟨k, State, hfinite, machine, _, fun h => ((hdecides []).2).mpr h, (hdecides []).1, htotal⟩ @@ -276,12 +276,14 @@ example : MultiTapeNTM.DecidableInPolyTime {a : Bool × ℕ | a.1 = true} /-! ### Checking encoded accepting computations -/ +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- A fixed machine's checker is inferred under any encoding of instances. -/ example {k : ℕ} {State α : Type} [Finite State] (ntm : MultiTapeNTM k Bool State) (enc : α ↪ List Bool) : ComputableTidilyInPolyTime (ntm.checkChoices enc) (encPair enc encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in /-- Checker inference composes with ordinary projections and a runtime guard. -/ example {k : ℕ} {State α : Type} [Finite State] (ntm : MultiTapeNTM k Bool State) (enc : α ↪ List Bool) : diff --git a/ComplexityTests/PCPEncoded.lean b/ComplexityTests/PCPEncoded.lean index ce42cee88..e3ccf8538 100644 --- a/ComplexityTests/PCPEncoded.lean +++ b/ComplexityTests/PCPEncoded.lean @@ -85,7 +85,7 @@ example : ComputableTidilyInPolyTime (fun g : Graph Bool => attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -example : ComputableTidilyInPolyTime (fun p : Bool × Graph Bool => +example : ComputableInPolyTime (fun p : Bool × Graph Bool => let g := p.2.addLoops true g.checkEdge equalityOrTrue true false [p.1, false] 0) (encPair encBool (Graph.encoding encBool)) encBool := by @@ -99,9 +99,9 @@ attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) (eval : C → α → α → Bool) (fallback : C) (label : α) - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : Graph C × List α × ℕ => p.1.checkEdge eval fallback label p.2.1 (p.2.2 + 1)) (encPair (Graph.encoding enc) (encPair (encList alphabet) encUnary)) encBool := by @@ -168,7 +168,7 @@ example : (Graph.mk 0 ([] : List (Edge Bool))).cloudRotation false rotateReflect attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun p : Graph Bool × ((ℕ × Bool) × Bool) => p.1.cloudRotation false rotateReflection p.2) (encPair (Graph.encoding encBool) (encPair (encPair encUnary encBool) encBool)) diff --git a/ComplexityTests/PCPEncodedAmplification.lean b/ComplexityTests/PCPEncodedAmplification.lean index 56ebd355f..7eee6aab4 100644 --- a/ComplexityTests/PCPEncodedAmplification.lean +++ b/ComplexityTests/PCPEncodedAmplification.lean @@ -126,7 +126,7 @@ example (g : Graph Bool) : g.satisfiable_powerPreprocess_iff evalConstraint false reflection rotateReflection rotateReflection_eq 1 2 walks nodup_walks mem_walks -example : ComputableTidilyInPolyTime powered (Graph.encoding encBool) +example : ComputableInPolyTime powered (Graph.encoding encBool) (Graph.encoding (encPi (encPi encBool))) := by have hr := isPolyTime_rotateReflection have he : ComputableTidilyInPolyTime @@ -138,8 +138,8 @@ example : ComputableTidilyInPolyTime powered (Graph.encoding encBool) fun_prop example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bool} - (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) : - ComputableTidilyInPolyTime + (hgraph : ComputableInPolyTime graph input (Graph.encoding encBool)) : + ComputableInPolyTime (fun x => (graph x).powerPreprocess evalConstraint false rotateReflection 1 2 walks) input (Graph.encoding (encPi (encPi encBool))) := by have hr := isPolyTime_rotateReflection @@ -152,12 +152,12 @@ example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bo -- Both ordinary let-bound spelling and missing-certificate rejection use the shared tactic. example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bool} - (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) + (hgraph : ComputableInPolyTime graph input (Graph.encoding encBool)) (rotate : ℕ × (ℕ × Unit) → ℕ × Unit) - (hr : ComputableTidilyInPolyTime rotate + (hr : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary (encFinEnum Unit))) (encPair encUnary (encFinEnum Unit))) : - ComputableTidilyInPolyTime (fun x => + ComputableInPolyTime (fun x => let g := graph x g.powerPreprocess evalConstraint false rotate 1 2 walks) input (Graph.encoding (encPi (encPi encBool))) := by @@ -181,12 +181,12 @@ private def unitOpinions (D : Type) (T : ℕ) : Numbering (Graph.PowerAlphabet D -- The concrete opinion type has Unique.fintype, while the generic power proof used -- Pi.instFintype. Their enumeration must not be unified to infer the output encoding. example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bool} - (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) + (hgraph : ComputableInPolyTime graph input (Graph.encoding encBool)) (rotate : ℕ × (ℕ × Fin 16) → ℕ × Fin 16) - (hr : ComputableTidilyInPolyTime rotate + (hr : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary (encFinEnum (Fin 16)))) (encPair encUnary (encFinEnum (Fin 16)))) : - ComputableTidilyInPolyTime (fun x => + ComputableInPolyTime (fun x => let powered := (graph x).powerPreprocess unitEval false rotate 4 2 [(fun _ => .inr (), fun _ => 0)] powered.composeTabulated (numberSlots (unitOpinions (Fin 16) 4)).2 [default] queries) @@ -201,14 +201,14 @@ example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bo -- Clients may choose any fixed encoding of the finite constraint table, independently of its -- internal enumeration. The graph itself still ranges over arbitrarily large input data. example {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph Bool} - (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) + (hgraph : ComputableInPolyTime graph input (Graph.encoding encBool)) (rotate : ℕ × (ℕ × Fin 16) → ℕ × Fin 16) - (hr : ComputableTidilyInPolyTime rotate + (hr : ComputableInPolyTime rotate (encPair encUnary (encPair encUnary (encFinEnum (Fin 16)))) (encPair encUnary (encFinEnum (Fin 16)))) (output : (Graph.PowerAlphabet (Fin 16) Unit 4 → Graph.PowerAlphabet (Fin 16) Unit 4 → Bool) ↪ List Bool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun x => (graph x).powerPreprocess unitEval false rotate 4 2 [(fun _ => .inr (), fun _ => 0)]) input (Graph.encoding output) := by @@ -243,7 +243,7 @@ example : (selectedPartialRound exampleGraph).WellFormed := exampleGraph.wellFormed_amplify unitEval false reflection rotateReflection rotateReflection_eq 1 2 walks (numberSelectedSlots (unitOpinions Unit 1)).2 [(0, oneCoin)] selectedQueries -example : ComputableTidilyInPolyTime selectedPartialRound (Graph.encoding encBool) +example : ComputableInPolyTime selectedPartialRound (Graph.encoding encBool) (Graph.encoding (encPi (encPi encBool))) := by have hr := isPolyTime_rotateReflection have he : ComputableTidilyInPolyTime @@ -296,7 +296,7 @@ private def completeRound (g : Graph Bool) := g.amplify unitEval false RotationMap.arithmeticExpanderRotate 4 2 fullWalks (numberSelectedSlots (unitOpinions ArithmeticLabel 4)).2 fullSelectedCoins selectedQueries -example : ComputableTidilyInPolyTime completeRound (Graph.encoding encBool) +example : ComputableInPolyTime completeRound (Graph.encoding encBool) (Graph.encoding (encPi (encPi encBool))) := by have hr := RotationMap.polytime_arithmeticExpanderRotate (encFinite ArithmeticLabel) have he : ComputableTidilyInPolyTime @@ -308,8 +308,8 @@ example : ComputableTidilyInPolyTime completeRound (Graph.encoding encBool) polytime example {Input : Type} (input : Input ↪ List Bool) (graph : Input → Graph Bool) - (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding encBool)) : - ComputableTidilyInPolyTime (fun x => + (hgraph : ComputableInPolyTime graph input (Graph.encoding encBool)) : + ComputableInPolyTime (fun x => let powered := (graph x).powerPreprocess unitEval false RotationMap.arithmeticExpanderRotate 4 2 fullWalks powered.composeTabulated (numberSlots (unitOpinions ArithmeticLabel 4)).2 fullCoins queries) diff --git a/ComplexityTests/PCPEncodedAmplificationIteration.lean b/ComplexityTests/PCPEncodedAmplificationIteration.lean index 09c7d8096..ebfb25f13 100644 --- a/ComplexityTests/PCPEncodedAmplificationIteration.lean +++ b/ComplexityTests/PCPEncodedAmplificationIteration.lean @@ -29,7 +29,7 @@ variable {D Input : Type} [Fintype D] [DecidableEq D] {width : ℕ} (number : Graph.SelectedComposeSlot (Graph.PowerAlphabet D Alphabet T) ≃ Fin width) (coins : List (Fin 5 × Rand (Graph.PowerAlphabet D Alphabet T))) (queries : List (Fin 6)) -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun x => Graph.amplifyIter fallback rotate T q walks number coins queries (Nat.clog 2 (graph x).edges.length) (graph x)) input (Graph.encoding (encPi (encPi encBool))) := by @@ -37,7 +37,7 @@ example : ComputableTidilyInPolyTime fail_if_success (clear hgraph; fun_prop) fun_prop -example : ComputableTidilyInPolyTime (fun x => +example : ComputableInPolyTime (fun x => let g := graph x Graph.amplifyIter fallback rotate T q walks number coins queries (Nat.clog 2 g.edges.length) g) input (Graph.encoding (encPi (encPi encBool))) := by diff --git a/ComplexityTests/PCPEncodedArithmeticAmplification.lean b/ComplexityTests/PCPEncodedArithmeticAmplification.lean index fb7ed68f5..ef150c6f7 100644 --- a/ComplexityTests/PCPEncodedArithmeticAmplification.lean +++ b/ComplexityTests/PCPEncodedArithmeticAmplification.lean @@ -24,13 +24,13 @@ variable {Input : Type} {input : Input ↪ List Bool} {graph : Input → Graph C (hgraph : ComputableTidilyInPolyTime graph input (Graph.encoding (encPi (encPi encBool)))) (hwellFormed : ∀ x, (graph x).WellFormed) -example : ComputableTidilyInPolyTime (fun x => (graph x).arithmeticAmplify) +example : ComputableInPolyTime (fun x => (graph x).arithmeticAmplify) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hgraph; fun_prop) fail_if_success (clear hwellFormed; fun_prop) fun_prop -example : ComputableTidilyInPolyTime (fun x => +example : ComputableInPolyTime (fun x => let initial := graph x initial.arithmeticAmplify) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hgraph; polytime) diff --git a/ComplexityTests/PCPEncodedConstraints.lean b/ComplexityTests/PCPEncodedConstraints.lean index 0a0ed432b..445d67b48 100644 --- a/ComplexityTests/PCPEncodedConstraints.lean +++ b/ComplexityTests/PCPEncodedConstraints.lean @@ -74,7 +74,8 @@ example (table : Bool → Bool → Bool) : (encPi (encPi encBool) table).length attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -- Table lookup is itself certified for runtime table and both runtime symbols. -example : ComputableTidilyInPolyTime +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (fun p : (Bool → Bool → Bool) × Bool × Bool => p.1 p.2.1 p.2.2) (encPair (encPi (encPi encBool)) (encPair encBool encBool)) encBool := by fun_prop diff --git a/ComplexityTests/PCPEncodedEnumeration.lean b/ComplexityTests/PCPEncodedEnumeration.lean index b5d8db92f..1b02c7960 100644 --- a/ComplexityTests/PCPEncodedEnumeration.lean +++ b/ComplexityTests/PCPEncodedEnumeration.lean @@ -58,7 +58,7 @@ private theorem polytime_unitEval : ComputableTidilyInPolyTime fun_prop -- The full complete round has a uniform certificate, including for arbitrary runtime graphs. -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun g : Graph Bool => g.amplifyEnumerated unitEval false rotateLoops 1 2) (Graph.encoding encBool) (Graph.encoding (encPi (encPi encBool))) := by have hr := polytime_rotateLoops @@ -93,7 +93,7 @@ variable {C α D Input : Type} [FinEnum α] [FinEnum D] (he : ComputableTidilyInPolyTime (fun p : C × (α × α) => eval p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun x => (graph x).amplifyEnumerated eval fallback rotate T q) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hg; fun_prop) @@ -101,7 +101,7 @@ example : ComputableTidilyInPolyTime fail_if_success (clear he; fun_prop) fun_prop -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun x => let g := graph x; g.amplifyEnumerated eval fallback rotate T q) input (Graph.encoding (encPi (encPi encBool))) := by polytime diff --git a/ComplexityTests/PCPEncodedGap.lean b/ComplexityTests/PCPEncodedGap.lean index 072a34e8d..27ce384ec 100644 --- a/ComplexityTests/PCPEncodedGap.lean +++ b/ComplexityTests/PCPEncodedGap.lean @@ -16,19 +16,19 @@ namespace ComplexityTests.PCPEncodedGap open Cslib.Logic.PL Cslib.PCP.Encoded Turing.MultiTapeTM open Cslib.PCP.ConstraintGraph.Amplification.Arithmetic -example : ComputableTidilyInPolyTime (gapGraph (V := ℕ)) +example : ComputableInPolyTime (gapGraph (V := ℕ)) (encList (encList (encPair encNat encBool))) (Graph.encoding (encPi (encPi encBool))) := by polytime -example : ComputableTidilyInPolyTime (gapGraph (V := List Bool)) +example : ComputableInPolyTime (gapGraph (V := List Bool)) (encList (encList (encPair encBits encBool))) (Graph.encoding (encPi (encPi encBool))) := by polytime -example : ComputableTidilyInPolyTime (gapGraph (V := List Bool)) +example : ComputableInPolyTime (gapGraph (V := List Bool)) (encList (encList (encPair (encList encBool) encBool))) (Graph.encoding (encPi (encPi encBool))) := by fun_prop -example (empty : Empty ↪ List Bool) : ComputableTidilyInPolyTime (gapGraph (V := Empty)) +example (empty : Empty ↪ List Bool) : ComputableInPolyTime (gapGraph (V := Empty)) (encList (encList (encPair empty encBool))) (Graph.encoding (encPi (encPi encBool))) := by polytime @@ -39,12 +39,12 @@ variable {V Input : Type} [DecidableEq V] {enc : V ↪ List Bool} (hformula : ComputableTidilyInPolyTime formula input (encList (encList (encPair enc encBool)))) -example : ComputableTidilyInPolyTime (fun x => gapGraph (formula x)) input +example : ComputableInPolyTime (fun x => gapGraph (formula x)) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hformula; fun_prop) fun_prop -example : ComputableTidilyInPolyTime +example : ComputableInPolyTime (fun x => let φ := formula x; gapGraph (φ ++ φ)) input (Graph.encoding (encPi (encPi encBool))) := by fail_if_success (clear hformula; polytime) diff --git a/ComplexityTests/PCPEncodedPreprocess.lean b/ComplexityTests/PCPEncodedPreprocess.lean index 8ed8e1d26..af6fe7897 100644 --- a/ComplexityTests/PCPEncodedPreprocess.lean +++ b/ComplexityTests/PCPEncodedPreprocess.lean @@ -125,7 +125,8 @@ example : ComputableTidilyInPolyTime (Graph.preprocess false true rotateReflecti attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -- The same ordinary functional spelling uses the shared compositional API. -example : ComputableTidilyInPolyTime (fun g : Graph Bool => +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (fun g : Graph Bool => let reduced := g.degreeReduce false rotateReflection [()] (reduced.addTrivial (some (false, true)) (Graph.rotationEdges rotateReflection [()] reduced.vertices)).addLoops diff --git a/ComplexityTests/PCPEncodedThreeSAT.lean b/ComplexityTests/PCPEncodedThreeSAT.lean index 9c254b80f..d2abf5cdd 100644 --- a/ComplexityTests/PCPEncodedThreeSAT.lean +++ b/ComplexityTests/PCPEncodedThreeSAT.lean @@ -71,23 +71,28 @@ example : (3 : ℝ)⁻¹ ≤ ((Graph.ofCompactCNF ([[]] : CNF ℕ)).toGraph id). simpa using Graph.inv_edges_le_unsatVal_ofCompactCNF ([[]] : CNF ℕ) (by simp) (by simp [CNF.Satisfiable]) +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (Graph.ofCompactCNF (V := ℕ)) (encList (encList (encPair encNat encBool))) (Graph.encoding (encPi (encPi encBool))) := by polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (Graph.ofCompactCNF (V := List Bool)) (encList (encList (encPair encBits encBool))) (Graph.encoding (encPi (encPi encBool))) := by polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (Graph.ofCompactCNF (V := List Bool)) (encList (encList (encPair (encList encBool) encBool))) (Graph.encoding (encPi (encPi encBool))) := by fun_prop -example : ComputableTidilyInPolyTime (fun names : List ℕ => +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (fun names : List ℕ => let formula := names.map fun n => [(n, true)] Graph.ofCompactCNF formula) (encList encNat) (Graph.encoding (encPi (encPi encBool))) := by polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in example (algorithm : List Bool → CNF ℕ) (h : ComputableTidilyInPolyTime algorithm encBits (encList (encList (encPair encNat encBool)))) : diff --git a/ComplexityTests/PCPEncodedVerifier.lean b/ComplexityTests/PCPEncodedVerifier.lean index 1e61f3192..6116f0892 100644 --- a/ComplexityTests/PCPEncodedVerifier.lean +++ b/ComplexityTests/PCPEncodedVerifier.lean @@ -109,21 +109,25 @@ example (proof : List Bool) : Graph.unsatVal_div_two_le_rejectProb 1 decode eval (loop false) proof -- Ordinary expressions preserve the raw and framed random-word encodings. +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => p.1.sampleEdge p.2) (encPair (Graph.encoding encBool) encBits) (encOption (Edge.encoding encBool)) := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => let graph := p.1; graph.sampleEdge p.2) (encPair (Graph.encoding encBool) encBits) (encOption (Edge.encoding encBool)) := by polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => p.1.sampleEdge p.2) (encPair (Graph.encoding encBool) encBits) (encOption (Edge.encoding encBool)) := by polytime +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => let graph := p.1; graph.sampleEdge p.2) (encPair (Graph.encoding encBool) encBits) (encOption (Edge.encoding encBool)) := by @@ -135,14 +139,16 @@ example : ComputableTidilyInPolyTime (fun p : Graph Bool × List Bool => p.1.sampleEdge p.2) (encPair (Graph.encoding encBool) (encList encBool)) (encOption (Edge.encoding encBool)) := by - apply Graph.isPolyTime_sampleEdge (by fun_prop) + refine ComputableInPolyTime.tidy (Graph.isPolyTime_sampleEdge (.of_tidy (by fun_prop)) + (.of_tidy ?_)) exact ComputableTidilyInPolyTime.listToBits.comp (by fun_prop) +attribute [local fun_prop] ComputableInPolyTime.tidy in example {C α : Type} (enc : C ↪ List Bool) (alphabet : α ↪ List Bool) (decoder : (Fin 2 → Bool) → α) (evaluator : C → α → α → Bool) - (heval : ComputableTidilyInPolyTime (fun p : C × α × α => evaluator p.1 p.2.1 p.2.2) + (heval : ComputableInPolyTime (fun p : C × α × α => evaluator p.1 p.2.1 p.2.2) (encPair enc (encPair alphabet alphabet)) encBool) : - ComputableTidilyInPolyTime + ComputableInPolyTime (fun p : Edge C × List Bool => p.1.proofVerdict 2 decoder evaluator p.2) (encPair (Edge.encoding enc) encBits) encBool := by fail_if_success solve | clear heval; fun_prop diff --git a/ComplexityTests/PCPNP.lean b/ComplexityTests/PCPNP.lean index 7da4618d2..f136532ce 100644 --- a/ComplexityTests/PCPNP.lean +++ b/ComplexityTests/PCPNP.lean @@ -112,7 +112,7 @@ example : noQueries.tableVerifier ((), []) = true := by decide attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -example (enc : Unit ↪ List Bool) : ComputableTidilyInPolyTime noQueries.tableVerifier +example (enc : Unit ↪ List Bool) : ComputableInPolyTime noQueries.tableVerifier (encPair enc encBits) encBool := by apply PCPVerifier.isPolyTime_tableVerifier (c := 0) · refine ⟨?_, ?_, ?_⟩ <;> unfold noQueries <;> fun_prop diff --git a/ComplexityTests/PCPPreprocessPrograms.lean b/ComplexityTests/PCPPreprocessPrograms.lean index 389419ca0..27ddcec8c 100644 --- a/ComplexityTests/PCPPreprocessPrograms.lean +++ b/ComplexityTests/PCPPreprocessPrograms.lean @@ -81,7 +81,8 @@ example : exampleGraph.preprocessRelation constraintEval false example : exampleGraph.preprocessRelation constraintEval false ((0, false), whole false) true false = true := by decide -example : ComputableTidilyInPolyTime +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (fun p : Graph Bool × ((ℕ × Bool) × Graph.PreprocessLabel Bool) => p.1.preprocessRotation false rotateReflection p.2) (encPair (Graph.encoding encBool) @@ -90,7 +91,8 @@ example : ComputableTidilyInPolyTime have h := isPolyTime_rotateReflection fun_prop -example : ComputableTidilyInPolyTime +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (fun g : Graph Bool => g.preprocessRotation false rotateReflection ((g.edges.length, false), cloud false)) (Graph.encoding encBool) @@ -98,14 +100,25 @@ example : ComputableTidilyInPolyTime have h := isPolyTime_rotateReflection fun_prop -example (T : ℕ) : ComputableTidilyInPolyTime +attribute [local fun_prop] ComputableInPolyTime.tidy in +private theorem isPolyTime_preprocessRotation_finEnum : ComputableInPolyTime + (fun p : Graph Bool × ((ℕ × Bool) × Graph.PreprocessLabel Bool) => + p.1.preprocessRotation false rotateReflection p.2) + (encPair (Graph.encoding encBool) + (encPair (encPair encUnary encBool) (encFinEnum (Graph.PreprocessLabel Bool)))) + (encPair (encPair encUnary encBool) (encFinEnum (Graph.PreprocessLabel Bool))) := by + have h := isPolyTime_rotateReflection + fun_prop + +example (T : ℕ) : ComputableInPolyTime (RotationMap.powRotWithInput (fun p : Graph Bool × ((ℕ × Bool) × Graph.PreprocessLabel Bool) => p.1.preprocessRotation false rotateReflection p.2) T) (encPair (Graph.encoding encBool) (encPair (encPair encUnary encBool) (encPi (encFinEnum (Graph.PreprocessLabel Bool))))) (encPair (encPair encUnary encBool) (encPi (encFinEnum (Graph.PreprocessLabel Bool)))) := by - have h := isPolyTime_rotateReflection + have hrot := isPolyTime_preprocessRotation_finEnum.tidy + refine .of_tidy ?_ fun_prop end ComplexityTests.PreprocessPrograms diff --git a/ComplexityTests/Relativization.lean b/ComplexityTests/Relativization.lean index c372941b2..c6d91d646 100644 --- a/ComplexityTests/Relativization.lean +++ b/ComplexityTests/Relativization.lean @@ -72,7 +72,8 @@ example (A : Set (List Bool)) : (Set.univ : Set (List Bool)) ∈ PWithOracle A e /-- A deterministic computation is polynomial time relative to an oracle, with a certificate. -/ example (A : Set (List Bool)) : ComputableInPolyTimeWithOracle A (fun _ : List Bool => false) encBits encBool := - (ComputableTidilyInPolyTime.const false).computableInPolyTimeWithOracle A + (ComputableInPolyTime.of_tidy + (ComputableTidilyInPolyTime.const false)).computableInPolyTimeWithOracle A /-- `fun_prop` lifts polynomial-time certificates to every oracle. -/ example (A : Set (List Bool)) : diff --git a/ComplexityTests/RepeatedTrials.lean b/ComplexityTests/RepeatedTrials.lean index f7ed731c1..1dadba293 100644 --- a/ComplexityTests/RepeatedTrials.lean +++ b/ComplexityTests/RepeatedTrials.lean @@ -52,7 +52,7 @@ example {α : Type} (trials width : ℕ) (V : α × List Bool → Bool) (a : α) /-- Polynomial-time certification composes through input-dependent dimensions. -/ example (trials width : Polynomial ℕ) : - ComputableTidilyInPolyTime (fun x : List Bool × List Bool => + ComputableInPolyTime (fun x : List Bool × List Bool => repeatVotes (trials.eval x.1.length) (width.eval x.1.length) (fun z => z.2.headD false) x) (encPair encBits encBits) encBits := by apply computableInPolyTime_repeatVotes <;> fun_prop diff --git a/ComplexityTests/ResourceBoundsPlain.lean b/ComplexityTests/ResourceBoundsPlain.lean index 54765f902..f3c3d1da9 100644 --- a/ComplexityTests/ResourceBoundsPlain.lean +++ b/ComplexityTests/ResourceBoundsPlain.lean @@ -189,10 +189,6 @@ theorem id_computableInFPTTime (κ : List Bool → ℕ) : ⟨fun _ => 1, 1, computableInTimeAndSpace_id.mono (fun w => by simp [encBits]) fun _ => Nat.zero_le _⟩ -example (κ : List Bool → ℕ) : - ComputableTidilyInFPTTime (id : List Bool → List Bool) encBits encBits κ := - (id_computableInFPTTime κ).tidy - /-- A time bound alone suffices for fpt time: the space bound may be exponential. -/ example (κ : List Bool → ℕ) : ComputableInFPTTime (id : List Bool → List Bool) encBits encBits κ := @@ -219,7 +215,7 @@ example : single ∈ PSPACE encBits := by ⟨_, fun _ => 1, by fun_prop, h.mono (fun _ => le_rfl) fun _ => Nat.zero_le _, fun _ => by simp⟩ exact mem_PSPACE_iff_computableInPolySpace.mpr - ⟨_, hf.tidy, fun w => by simp [single]⟩ + ⟨_, hf, fun w => by simp [single]⟩ /-- A plain fpt-time decider gives membership in `FPT`, for every parameter. -/ example (κ : List Bool → ℕ) : single ∈ FPT encBits κ := by @@ -227,7 +223,7 @@ example (κ : List Bool → ℕ) : single ∈ FPT encBits κ := by have hf : ComputableInFPTTime (fun w : List Bool => decide (w = [true])) encBits encBool κ := ⟨fun _ => c, 0, h.mono (fun _ => by simp) fun _ => Nat.zero_le _⟩ exact mem_FPT_iff_computableInFPTTime.mpr - ⟨_, hf.tidy, fun w => by simp [single]⟩ + ⟨_, hf, fun w => by simp [single]⟩ /-! ### From library certificates to plain ones -/ @@ -250,7 +246,7 @@ example : ComputableInPolySpace /-- `TQBF` has a plain polynomial-space decider. -/ example : ∃ f, ComputableInPolySpace f encQBF encBool ∧ ∀ φ, φ ∈ TQBF ↔ f φ = true := by obtain ⟨f, hf, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp TQBF_mem_PSPACE - exact ⟨f, .of_tidy hf, hA⟩ + exact ⟨f, .of_tidy hf.tidy, hA⟩ /-- A plain polynomial-time preprocessing of the existing TQBF decider stays in `PSPACE`. The decider's tidy certificate and the preprocessing's plain certificate compose automatically. -/ @@ -258,13 +254,13 @@ example {α : Type} {enc : α ↪ List Bool} {f : α → Logic.PL.QBF ℕ} (hf : ComputableInPolyTime f enc encQBF) : {a | f a ∈ TQBF} ∈ PSPACE enc := by obtain ⟨dec, hdec, hA⟩ := mem_PSPACE_iff_computableInPolySpace.mp TQBF_mem_PSPACE have hcomp : ComputableInPolySpace (fun a => dec (f a)) enc encBool := by fun_prop - exact mem_PSPACE_iff_computableInPolySpace.mpr ⟨_, hcomp.tidy, fun a => hA (f a)⟩ + exact mem_PSPACE_iff_computableInPolySpace.mpr ⟨_, hcomp, fun a => hA (f a)⟩ /-- `SAT` has a plain fpt-time decider in the number of variables. -/ example : ∃ g, ComputableInFPTTime g encCNF encBool Logic.PL.CNF.numVars ∧ ∀ φ, φ ∈ SAT ↔ g φ = true := by obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp SAT_mem_FPT - exact ⟨g, hg.computableInFPTTime, hA⟩ + exact ⟨g, hg, hA⟩ /-! ### Axioms -/ @@ -303,11 +299,4 @@ info: 'Turing.MultiTapeTM.ComputableInTimeAndSpace.computableInFPTTime' depends #guard_msgs (whitespace := lax) in #print axioms ComputableInTimeAndSpace.computableInFPTTime -/-- -info: 'Cslib.Complexity.computableInFPTTime_iff_computableTidilyInFPTTime' depends on axioms: -[propext, Classical.choice, Quot.sound] --/ -#guard_msgs (whitespace := lax) in -#print axioms computableInFPTTime_iff_computableTidilyInFPTTime - end ComplexityTests.ResourceBoundsPlain diff --git a/ComplexityTests/ResourceClasses.lean b/ComplexityTests/ResourceClasses.lean index 2454a83bd..4e831ba4d 100644 --- a/ComplexityTests/ResourceClasses.lean +++ b/ComplexityTests/ResourceClasses.lean @@ -62,7 +62,7 @@ example : {x | diagonal x = true} ∈ NEXP encBits ∧ {x | diagonal x = true} /-- The diagonal problem is decided within time `O(2 ^ (4 n))`, by its tidy machine. -/ theorem setOf_diagonal_mem_DTIME : {x | diagonal x = true} ∈ DTIME encBits fun n => 2 ^ (4 * n) := - setOf_mem_DTIME_of_computableInO computableInO_diagonal.tidy fun _ => le_rfl + setOf_mem_DTIME_of_computableInO computableInO_diagonal fun _ => le_rfl /-- A deterministic machine is a nondeterministic one: the diagonal problem, outside `P`, is in `NTIME (2 ^ (4 n))`. -/ diff --git a/ComplexityTests/ResourceClasses3.lean b/ComplexityTests/ResourceClasses3.lean index 0e989b7b7..ddfb29259 100644 --- a/ComplexityTests/ResourceClasses3.lean +++ b/ComplexityTests/ResourceClasses3.lean @@ -91,13 +91,13 @@ example {α : Type} {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × Lis example {α : Type} (enc : α ↪ List Bool) (A : Set α) : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := mem_BPP_iff_forall_decidesWithErrorExponent example {α : Type} (enc : α ↪ List Bool) (A : Set α) : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent enc q p V A := mem_RP_iff_forall_decidesWithOneSidedErrorExponent @@ -105,7 +105,7 @@ example {α : Type} (enc : α ↪ List Bool) (A : Set α) : needed for Adleman's theorem. -/ example {α : Type} (enc : α ↪ List Bool) (A : Set α) (hA : A ∈ BPP enc) : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc (.X + 1) p V A := mem_BPP_iff_forall_decidesWithErrorExponent.1 hA _ diff --git a/ComplexityTests/SATPolyTime.lean b/ComplexityTests/SATPolyTime.lean index d28390a88..14f4be58b 100644 --- a/ComplexityTests/SATPolyTime.lean +++ b/ComplexityTests/SATPolyTime.lean @@ -27,9 +27,11 @@ example : Turing.MultiTapeNTM.DecidableInPolyTime SAT encCNF := example : UNSAT ∈ coNP encCNF := UNSAT_mem_coNP +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime SAT.verifier (encPair encCNF encBits) encBool := by fun_prop +attribute [local fun_prop] ComputableInPolyTime.tidy in example : ComputableTidilyInPolyTime (fun p => (SAT.verifier p, !SAT.verifier p)) (encPair encCNF encBits) (encPair encBool encBool) := by fun_prop diff --git a/ComplexityTests/SBPAmplification.lean b/ComplexityTests/SBPAmplification.lean index 1a47d0e8e..144e78efa 100644 --- a/ComplexityTests/SBPAmplification.lean +++ b/ComplexityTests/SBPAmplification.lean @@ -57,20 +57,20 @@ example (r : ℕ) : acceptCount (SharpP.powerVerifier (fun _ : Unit => r + 1) (f /-- One pair of witnesses achieves a gap growing with the input length. -/ example : ∃ f ∈ SharpP encBits, ∃ k : List Bool → ℕ, - ComputableTidilyInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, + ComputableInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, (w ∈ language → k w ≤ f w) ∧ (w ∉ language → 2 ^ (w.length + 1) * f w < k w) := exists_SBP_gap_pow_polyBounded language_mem (fun w => w.length + 1) (PolyBounded.self.add (.const 1)) /-- A zero requested exponent still has a strict nonmember inequality and positive threshold. -/ example : ∃ f ∈ SharpP encBits, ∃ k : List Bool → ℕ, - ComputableTidilyInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, + ComputableInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, (w ∈ language → k w ≤ f w) ∧ (w ∉ language → 2 ^ (0 : ℕ) * f w < k w) := exists_SBP_gap_pow_polyBounded language_mem (fun _ => 0) (.const 0) /-- A noncomputable requested rate can be handled by fixed dominating polynomial repetition. -/ example (S : Set (List Bool)) : ∃ f ∈ SharpP encBits, ∃ k : List Bool → ℕ, - ComputableTidilyInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, + ComputableInPolyTime k encBits encNat ∧ (∀ w, 0 < k w) ∧ ∀ w, let r := @ite ℕ (w ∈ S) (Classical.propDecidable _) w.length 0 (w ∈ language → k w ≤ f w) ∧ (w ∉ language → 2 ^ r * f w < k w) := by classical diff --git a/ComplexityTests/SharpPLowness.lean b/ComplexityTests/SharpPLowness.lean index c711ebe57..d161421be 100644 --- a/ComplexityTests/SharpPLowness.lean +++ b/ComplexityTests/SharpPLowness.lean @@ -43,7 +43,8 @@ theorem headTrue_mem_SPP : headTrue ∈ SPP encBits := theorem oracleId_computableInPolyTimeWithOracle : ComputableInPolyTimeWithOracle headTrue (fun w : List Bool => w) encBits encBits := - (ComputableTidilyInPolyTime.id').computableInPolyTimeWithOracle headTrue + (ComputableInPolyTime.of_tidy ComputableTidilyInPolyTime.id').computableInPolyTimeWithOracle + headTrue example : ((fun _ : List Bool => (1 : ℕ)) ∘ fun w : List Bool => w) ∈ SharpP encBits := SharpP.comp_mem_of_computableInPolyTimeWithOracle headTrue_mem_UP headTrue_mem_coUP diff --git a/ComplexityTests/SipserLautemann.lean b/ComplexityTests/SipserLautemann.lean index e6f70897e..113e8d36f 100644 --- a/ComplexityTests/SipserLautemann.lean +++ b/ComplexityTests/SipserLautemann.lean @@ -122,7 +122,8 @@ theorem noisyHead_mem_PH : {x : List Bool | x.headD false = true} ∈ PH encBits attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in -- Direct `fun_prop` synthesis on the Sipser-Lautemann matrix verifier for `noisyHeadVerifier`. -example : ComputableTidilyInPolyTime +attribute [local fun_prop] ComputableInPolyTime.tidy in +example : ComputableInPolyTime (verifier encBits (Polynomial.C 2) noisyHeadVerifier) (encPair encBits encBits) encBool := by fun_prop diff --git a/ComplexityTests/TFNP.lean b/ComplexityTests/TFNP.lean index 7ec9f6848..f55139c4b 100644 --- a/ComplexityTests/TFNP.lean +++ b/ComplexityTests/TFNP.lean @@ -29,7 +29,7 @@ private theorem emptyRel_mem_TFNP : emptyRel ∈ TFNP encBits := ⟨emptyRel_mem_FNP, fun _ => ⟨[], rfl⟩⟩ private theorem emptyRel_mem_FPSearch : emptyRel ∈ FPSearch encBits := - mem_FPSearch_of_total emptyRel_mem_FNP (ComputableTidilyInPolyTime.const []) fun _ => rfl + mem_FPSearch_of_total emptyRel_mem_FNP (.of_tidy (ComputableTidilyInPolyTime.const [])) fun _ => rfl example : searchDomain emptyRel = Set.univ := isTotalSearch_iff_searchDomain_eq_univ.1 emptyRel_mem_TFNP.2 @@ -122,8 +122,8 @@ example : PolyTimeReducible encBits encBits (searchDomain emptyRel) (searchDomai /-- A reduction to the total `emptyRel` needs only the one-way condition on solutions. -/ example : SearchReducible encBits encBits emptyRel emptyRel := - .of_isTotalSearch emptyRel_mem_TFNP.2 ComputableTidilyInPolyTime.id' - (ComputableTidilyInPolyTime.const []) fun _ _ _ => rfl + .of_isTotalSearch emptyRel_mem_TFNP.2 (.of_tidy ComputableTidilyInPolyTime.id') + (.of_tidy (ComputableTidilyInPolyTime.const [])) fun _ _ _ => rfl /-- **A complete problem.** `emptyRel` is complete for the total problems solvable in polynomial time: such a problem reduces to it by solving the instance in the map back. -/ @@ -131,8 +131,8 @@ example : SearchComplete (fun {α : Type} (enc : α ↪ List Bool) => TFNP enc encBits emptyRel := by refine ⟨⟨emptyRel_mem_TFNP, emptyRel_mem_FPSearch⟩, fun _ enc R ⟨hR, hR'⟩ => ?_⟩ obtain ⟨g, hg, hgR⟩ := exists_total_of_mem_FPSearch hR' hR.2 - exact .of_isTotalSearch emptyRel_mem_TFNP.2 (ComputableTidilyInPolyTime.const []) - (hg.comp (ComputableTidilyInPolyTime.fst enc encBits)) fun a _ _ => hgR a + exact .of_isTotalSearch emptyRel_mem_TFNP.2 (.of_tidy (ComputableTidilyInPolyTime.const [])) + (hg.comp (.of_tidy (ComputableTidilyInPolyTime.fst enc encBits))) fun a _ _ => hgR a /-! ### `SAT` -/ @@ -193,8 +193,8 @@ example : Leaf (1, notCode1, idCode1) [true] := private theorem emptyRel_searchReducible_EndOfLine : SearchReducible encBits encEndOfLine emptyRel EndOfLine := .of_isTotalSearch isTotalSearch_EndOfLine - (ComputableTidilyInPolyTime.const (0, ([], []), ([], []))) - (ComputableTidilyInPolyTime.const []) fun _ _ _ => rfl + (.of_tidy (ComputableTidilyInPolyTime.const (0, ([], []), ([], [])))) + (.of_tidy (ComputableTidilyInPolyTime.const [])) fun _ _ _ => rfl example : emptyRel ∈ PPAD encBits := emptyRel_searchReducible_EndOfLine.mem_PPAD emptyRel_mem_FNP EndOfLine_mem_PPAD diff --git a/ComplexityTests/TFNPCompleteness.lean b/ComplexityTests/TFNPCompleteness.lean index 047953dfd..c690a1074 100644 --- a/ComplexityTests/TFNPCompleteness.lean +++ b/ComplexityTests/TFNPCompleteness.lean @@ -17,9 +17,9 @@ open Turing.MultiTapeTM ComputableTidilyInPolyTime -- One uniform constructor handles every identity cube, including the zero-dimensional cube. example : ∃ code : ℕ → CircuitCode, - ComputableTidilyInPolyTime code encUnary encCode ∧ + ComputableInPolyTime code encUnary encCode ∧ ∀ n u, u.length = n → evalCircuitOutputs (code n) u = u := - exists_uniformCircuitCodes id' id' (snd encUnary encBits) (fun _ _ h => h) + exists_uniformCircuitCodes (.of_tidy id') (.of_tidy id') (.of_tidy (snd encUnary encBits)) (fun _ _ h => h) -- Each canonical search problem has the advertised class and reduction quantifiers. example : SearchComplete @PPP encPigeon Pigeon := Pigeon_searchComplete diff --git a/ComplexityTests/TimeReductions.lean b/ComplexityTests/TimeReductions.lean index 810753561..e17ed7fab 100644 --- a/ComplexityTests/TimeReductions.lean +++ b/ComplexityTests/TimeReductions.lean @@ -29,7 +29,7 @@ along the linear-time map from unary numbers to words of ones stays in exponenti example : (fun n : ℕ => List.replicate n true) ⁻¹' {x | diagonal x = true} ∈ EXP encUnary := by obtain ⟨k, hk⟩ := mem_EXP_iff.mp setOf_diagonal_mem_EXP refine mem_EXP_iff.mpr ⟨k + 1, preimage_mem_DTIME (C := 2) hk - (ComputableTidilyInO.of_linear (.of_eq fun _ => rfl)) fun n => ?_⟩ + (.of_tidy (ComputableTidilyInO.of_linear (.of_eq fun _ => rfl))) fun n => ?_⟩ simp only [encUnary_apply, encBits_apply, List.length_replicate] have h₁ : n < 2 ^ n ^ (k + 1) := Nat.lt_two_pow_self.trans_le (Nat.pow_le_pow_right (by norm_num) (Nat.le_self_pow (by omega) n)) diff --git a/ComplexityTests/TreeEval.lean b/ComplexityTests/TreeEval.lean index fc8efd767..996899a8b 100644 --- a/ComplexityTests/TreeEval.lean +++ b/ComplexityTests/TreeEval.lean @@ -75,9 +75,9 @@ example : encInstance ⟨2, 2, sample⟩ ≠ encInstance ⟨2, 0, .leaf ![false, open Turing MultiTapeTM Reader in /-- **Tree Evaluation in small space**: `O((ℓ + H + 1) · log (ℓ + 2) + log (n + 2))`. -/ -example : ∃ t, ComputableTidilyInBigO (fun I : Instance => List.ofFn I.tree.eval) encInstance +example : ∃ t, ComputableInBigO (fun I : Instance => List.ofFn I.tree.eval) encInstance encBits t fun I => spaceBound I.ell I.height + (encNat ((encInstance I).length + 1)).length := - computableTidilyInSpace_eval + computableInSpace_eval open Turing MultiTapeTM Reader in /-- Instantiating `computableTidilyInSpace_eval` on `sample` (`spaceBound 2 2 + 7 = 22`) yields a @@ -130,11 +130,11 @@ example : spaceBound sampleNontrivial.1.ell sampleNontrivial.1.height + open Turing MultiTapeTM in /-- **Tree Evaluation in space `O(log n · log log n)`** on nontrivial instances. -/ -example : ∃ t, ComputableTidilyInBigO +example : ∃ t, ComputableInBigO (fun I : NontrivialInstance => List.ofFn I.1.tree.eval) encNontrivialInstance encBits t fun I => (encNat (encNontrivialInstance I).length).length * (encNat (encNat (encNontrivialInstance I).length).length).length := - computableTidilyInSpace_eval_log_mul_log_log + computableInSpace_eval_log_mul_log_log open Turing MultiTapeTM in /-- Instantiating `computableTidilyInSpace_eval_log_mul_log_log` on `sampleNontrivial` @@ -220,11 +220,11 @@ info: 'Cslib.TreeEval.encode_injective' depends on axioms: #print axioms Cslib.TreeEval.encode_injective /-- -info: 'Cslib.TreeEval.computableTidilyInSpace_eval' depends on axioms: +info: 'Cslib.TreeEval.computableInSpace_eval' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.TreeEval.computableTidilyInSpace_eval +#print axioms Cslib.TreeEval.computableInSpace_eval /-- info: 'Cslib.TreeEval.ell_lt_length_encNat_length_encInstance' depends on axioms: @@ -248,8 +248,8 @@ info: 'Cslib.TreeEval.spaceBound_add_length_le_log_mul_log_log' depends on axiom #print axioms Cslib.TreeEval.spaceBound_add_length_le_log_mul_log_log /-- -info: 'Cslib.TreeEval.computableTidilyInSpace_eval_log_mul_log_log' depends on axioms: +info: 'Cslib.TreeEval.computableInSpace_eval_log_mul_log_log' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.TreeEval.computableTidilyInSpace_eval_log_mul_log_log +#print axioms Cslib.TreeEval.computableInSpace_eval_log_mul_log_log diff --git a/ComplexityTests/UniformCircuits.lean b/ComplexityTests/UniformCircuits.lean index d1bdc79a3..2a62ce061 100644 --- a/ComplexityTests/UniformCircuits.lean +++ b/ComplexityTests/UniformCircuits.lean @@ -16,33 +16,35 @@ open Cslib Cslib.Complexity Cslib.Circuits Cslib.Circuits.Boolean Turing.MultiTa /-- One constructor builds reversal circuits at every instance-dependent input length. -/ theorem reverseFamily : ∃ circuits : (a : List Bool) → Circuit signature a.length a.length, - ComputableTidilyInPolyTime (fun a => (circuits a).code) encBits encCode ∧ + ComputableInPolyTime (fun a => (circuits a).code) encBits encCode ∧ ∀ a (x : Fin a.length → Bool) (j : Fin a.length), (circuits a).eval interpretation x j = (List.ofFn x).reverse.getD j.val false := CircuitValue.exists_uniformCircuitFamily (F := fun p : List Bool × List Bool => p.2.reverse) - ComputableTidilyInPolyTime.length_bits ComputableTidilyInPolyTime.length_bits - (by fun_prop) + (.of_tidy ComputableTidilyInPolyTime.length_bits) + (.of_tidy ComputableTidilyInPolyTime.length_bits) (by fun_prop) /-- Fixed output width is independent of input width. An empty function output is padded with false, including at input length zero. -/ theorem paddedFamily : ∃ circuits : (a : List Bool) → Circuit signature a.length 3, - ComputableTidilyInPolyTime (fun a => (circuits a).code) encBits encCode ∧ + ComputableInPolyTime (fun a => (circuits a).code) encBits encCode ∧ ∀ a (x : Fin a.length → Bool) (j : Fin 3), (circuits a).eval interpretation x j = false := by obtain ⟨circuits, hc, he⟩ := CircuitValue.exists_uniformCircuitFamily - ComputableTidilyInPolyTime.length_bits (ComputableTidilyInPolyTime.const 3) - (ComputableTidilyInPolyTime.const ([] : List Bool) - (encIn := encPair encBits encBits) (encMid := encBits)) + (.of_tidy ComputableTidilyInPolyTime.length_bits) + (.of_tidy (ComputableTidilyInPolyTime.const 3)) + (.of_tidy (ComputableTidilyInPolyTime.const ([] : List Bool) + (encIn := encPair encBits encBits) (encMid := encBits))) exact ⟨circuits, hc, fun a x j => by simpa using he a x j⟩ /-- An empty output family is admitted, even for an input type with arbitrarily long encodings. -/ example : ∃ circuits : (a : List Bool) → Circuit signature a.length 0, - ComputableTidilyInPolyTime (fun a => (circuits a).code) encBits encCode := by + ComputableInPolyTime (fun a => (circuits a).code) encBits encCode := by obtain ⟨circuits, hc, _⟩ := CircuitValue.exists_uniformCircuitFamily - ComputableTidilyInPolyTime.length_bits (ComputableTidilyInPolyTime.const 0) - (ComputableTidilyInPolyTime.const ([] : List Bool) - (encIn := encPair encBits encBits) (encMid := encBits)) + (.of_tidy ComputableTidilyInPolyTime.length_bits) + (.of_tidy (ComputableTidilyInPolyTime.const 0)) + (.of_tidy (ComputableTidilyInPolyTime.const ([] : List Bool) + (encIn := encPair encBits encBits) (encMid := encBits))) exact ⟨circuits, hc⟩ /-- info: 'Cslib.Complexity.CircuitValue.exists_uniformCircuitFamily' depends on axioms: diff --git a/ComplexityTests/VertexCoverKernel.lean b/ComplexityTests/VertexCoverKernel.lean index 1c3adacf1..a644185ef 100644 --- a/ComplexityTests/VertexCoverKernel.lean +++ b/ComplexityTests/VertexCoverKernel.lean @@ -105,10 +105,10 @@ example : IsKernelization (encPair encGraph encNat) Prod.snd VertexCover bussKer example : HasPolyKernel (encPair encGraph encNat) Prod.snd VertexCover := VertexCover_hasPolyKernel -/-- The kernelization is tidily computable in polynomial time, for proofs that compose it. -/ +/-- The kernelization is computable in polynomial time. -/ example : - ComputableTidilyInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := - (isKernelization_iff_tidy.mp isKernelization_bussKernel).1 + ComputableInPolyTime bussKernel (encPair encGraph encNat) (encPair encGraph encNat) := + isKernelization_bussKernel.polyTime /-! ### Axioms -/ diff --git a/ComplexityTests/WPP.lean b/ComplexityTests/WPP.lean index ae30c2b2a..6d02e52c5 100644 --- a/ComplexityTests/WPP.lean +++ b/ComplexityTests/WPP.lean @@ -83,7 +83,7 @@ private theorem twoTargetGap_poly : example : {w : List Bool | w.headD false = true} ∈ LWPP encBits := by refine mem_LWPP_of_finset_targets (Finset.univ : Finset Bool) (mem_GapP_of_polyTime (.of_tidy twoTargetGap_poly)) - (fun b _ => twoTargets_poly b) + (fun b _ => .of_tidy (twoTargets_poly b)) (fun b _ => twoTargets_ne_zero b) (fun w => ?_) (fun w => ?_) · unfold twoTargetGap twoTargets @@ -103,7 +103,7 @@ example : {w : List Bool | w.headD false = true} ∈ LWPP encBits := by example : {w : List Bool | w.headD false = true} ∈ WPP encBits := by refine mem_WPP_of_finset_targets (Finset.univ : Finset Bool) (mem_GapP_of_polyTime (.of_tidy twoTargetGap_poly)) - (fun b _ => (twoTargets_poly b).comp (.encoding_length encBits)) + (fun b _ => .of_tidy ((twoTargets_poly b).comp (.encoding_length encBits))) (fun b _ w => twoTargets_ne_zero b w.length) (fun w => ?_) (fun w => ?_) · unfold twoTargetGap twoTargets From 5415b868e7a11a5cb039e023b7e663074e502e9f Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 13:30:44 -0400 Subject: [PATCH 05/11] refactor(classes): restate the remaining deferred Classes certificates TimeConstructible/SpaceConstructible.computableInO, DecidableInTimeO.exists_computableInO, ComputableInPolyTimeWithOracle.computableInPolyTime and .exists_computableInO, Interaction.computableInPolySpace_evaluate, SharpP/GapP.computableInPolySpace, ComputableInO.computableInPolyTime_take and ComputableInPolyTime.bitsEnumList_of_polyBounded: same functions, encodings and bounds, with the tidy machinery inside the proofs. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../BPP/Derandomization/Generator.lean | 51 +++++++++++-------- .../Complexity/Classes/Constructible.lean | 17 ++++--- .../Complexity/Classes/Hierarchy/Space.lean | 3 +- .../Complexity/Classes/Hierarchy/Time.lean | 2 +- .../Complexity/Classes/IP/PSPACE.lean | 14 +++-- .../Complexity/Classes/Oracle/PolyTime.lean | 13 ++--- .../Complexity/Classes/Oracle/Space.lean | 26 +++++----- .../Complexity/Classes/PP/Oracle.lean | 2 +- .../Complexity/Classes/SharpP/Oracle.lean | 2 +- .../Classes/ValiantVazirani/Collapse.lean | 4 +- .../Computability/Complexity/FineGrained.lean | 17 ++++--- .../FineGrained/OrthogonalVectors.lean | 3 +- .../Complexity/FineGrained/Reduction.lean | 3 +- .../FineGrained/Sparsification.lean | 3 +- .../Complexity/HardnessEncoding/PolyTime.lean | 22 ++++---- .../Complexity/Parameterized.lean | 3 +- .../Parameterized/Kernelization.lean | 3 +- ComplexityTests/ClassCorollaries.lean | 4 +- ComplexityTests/InteractiveProofs.lean | 11 ++-- ComplexityTests/Relativization.lean | 4 +- 20 files changed, 115 insertions(+), 92 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean index 2902029d5..3f4290b09 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean @@ -39,7 +39,7 @@ bounds on `2 ^ ℓ` and on `T n` as functions of the instance: time and space `O(t n)` (`Cslib.Complexity.exists_computableInO_of_mem_DTIME`); * such a decider, applied to words cut to a computed length `n`, runs in polynomial time when `T n` is polynomially bounded - (`Turing.MultiTapeTM.ComputableTidilyInO.computableTidilyInPolyTime_take`); + (`Turing.MultiTapeTM.ComputableInO.computableInPolyTime_take`); * the greedy design of `Cslib.Crypto.PRG.NisanWigderson.greedyMasks` is a loop over the `2 ^ ℓ` masks of length `ℓ` that keeps at most one more mask per step (`Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks`); @@ -61,9 +61,9 @@ generator for each of the `2 ^ ℓ` seeds and takes the strict majority of the a * `Cslib.Complexity.exists_computableInO_of_mem_DTIME`: deterministic time classes have tidy deciders within the same time bound, up to constant factors. -* `Turing.MultiTapeTM.ComputableTidilyInO.computableTidilyInPolyTime_take`: evaluation of a +* `Turing.MultiTapeTM.ComputableInO.computableInPolyTime_take`: evaluation of a function computable in time `T n` on words of polynomially bounded `T n`. -* `Turing.MultiTapeTM.ComputableTidilyInPolyTime.bitsEnumList_of_polyBounded`: enumeration of the +* `Turing.MultiTapeTM.ComputableInPolyTime.bitsEnumList_of_polyBounded`: enumeration of the words of a computed length `ℓ` when `2 ^ ℓ` is polynomially bounded. * `Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_greedyMasks`, `Cslib.Crypto.PRG.NisanWigderson.computableInPolyTime_listGenerator`: the greedy design @@ -124,17 +124,20 @@ end Cslib.Complexity namespace Turing.MultiTapeTM -/-- **Evaluation on short words.** Let `g` be tidily computable within time and space `O(T n)` on -words of length `n`, for a monotone `T`. Then cutting a word to a computed length `cut x` and -applying `g` is polynomial-time in the pair of `x` and the word, provided `T (cut x)` is -polynomially bounded in the length of `x`. -/ -theorem ComputableTidilyInO.computableTidilyInPolyTime_take {γ : Type} {encIn : γ ↪ List Bool} +/-- **Evaluation on short words.** Let `g` be computable within time and space `O(T n)` on words +of length `n`, for a monotone `T`. Then cutting a word to a computed length `cut x` and applying +`g` is polynomial-time in the pair of `x` and the word, provided `T (cut x)` is polynomially +bounded in the length of `x`. -/ +theorem ComputableInO.computableInPolyTime_take {γ : Type} {encIn : γ ↪ List Bool} {g : List Bool → Bool} {T : ℕ → ℕ} (hT : Monotone T) - (hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length) - {cut : γ → ℕ} (hcut : ComputableTidilyInPolyTime cut encIn encUnary) + (hg : ComputableInO g encBits encBool (fun y => T y.length) fun y => T y.length) + {cut : γ → ℕ} (hcut : ComputableInPolyTime cut encIn encUnary) (hbound : PolyBounded (fun x => (encIn x).length) fun x => T (cut x)) : - ComputableTidilyInPolyTime (fun p : γ × List Bool => g (p.2.take (cut p.1))) + ComputableInPolyTime (fun p : γ × List Bool => g (p.2.take (cut p.1))) (encPair encIn encBits) encBool := by + have hg := hg.tidy + have hcut := hcut.tidy + refine .of_tidy ?_ have h₁ : ComputableTidilyInPolyTime (fun p : γ × List Bool => p.2.take (cut p.1)) (encPair encIn encBits) encBits := by have := hcut.comp (ComputableTidilyInPolyTime.fst encIn encBits) @@ -152,20 +155,23 @@ theorem ComputableTidilyInO.computableTidilyInPolyTime_take {γ : Type} {encIn : (ht.add hs).add (hfst.mono fun p => hT (List.length_take_le _ _)) exact (hg.comp h₁).computableTidilyInPolyTime hpoly hpoly -namespace ComputableTidilyInPolyTime +namespace ComputableInPolyTime variable {γ : Type} {encIn : γ ↪ List Bool} +open ComputableTidilyInPolyTime in /-- Enumerate the words of a computed length `count x` when `2 ^ count x` is polynomially bounded. -/ theorem bitsEnumList_of_polyBounded {count : γ → ℕ} - (hcount : ComputableTidilyInPolyTime count encIn encUnary) + (hcount : ComputableInPolyTime count encIn encUnary) (hbudget : PolyBounded (fun x => (encIn x).length) fun x => 2 ^ count x) : - ComputableTidilyInPolyTime (fun x => Cslib.BitString.enumList (count x)) encIn + ComputableInPolyTime (fun x => Cslib.BitString.enumList (count x)) encIn (encList encBits) := by + have hcount := hcount.tidy + refine .of_tidy ?_ obtain ⟨c, d, h⟩ := hbudget.exists_le - refine bitsEnumList hcount (size := fun n => 3 * (c * (n + 1) ^ d) ^ 2) (by fun_prop) - fun x => ?_ + refine ComputableTidilyInPolyTime.bitsEnumList hcount + (size := fun n => 3 * (c * (n + 1) ^ d) ^ 2) (by fun_prop) fun x => ?_ have h₁ : 2 * count x + 1 ≤ 3 * 2 ^ count x := by have := Nat.lt_two_pow_self (n := count x) omega @@ -175,7 +181,7 @@ theorem bitsEnumList_of_polyBounded {count : γ → ℕ} _ ≤ 3 * (c * ((encIn x).length + 1) ^ d) ^ 2 := Nat.mul_le_mul_left _ (Nat.pow_le_pow_left (h x) 2) -end ComputableTidilyInPolyTime +end ComputableInPolyTime end Turing.MultiTapeTM @@ -231,7 +237,8 @@ theorem computableInPolyTime_greedyMasks {seed block overlap : γ → ℕ} unfold greedyMasks refine foldlWith_of_bounded_growth (encA := encBits) (par := fun x => (block x, overlap x)) (step := fun p kept w => greedyStep p.1 p.2 kept w) (growth := fun x => 2 * seed x + 1) - (hblock.prod hoverlap) (bitsEnumList_of_polyBounded hseed hbudget) (.const []) + (hblock.prod hoverlap) + (ComputableInPolyTime.bitsEnumList_of_polyBounded (.of_tidy hseed) hbudget).tidy (.const []) computableTidilyInPolyTime_greedyStep ((hseed.polyBounded.mul (.const 2)).add (.const 1) |>.mono fun x => by simp [Nat.mul_comm]) fun x kept w hw => ?_ @@ -260,9 +267,9 @@ theorem computableInPolyTime_listGenerator {g : List Bool → Bool} {T : ℕ → have hmasks := hmasks.tidy have hseed := hseed.tidy refine .of_tidy ?_ - have heval := hg.computableTidilyInPolyTime_take hT - (hblock.comp (fst encIn encBits)) (hbudget.comp (PolyBounded.self.mono fun p => by - simp [length_frame]; omega)) + have heval := (ComputableInO.computableInPolyTime_take hT (.of_tidy hg) + (.of_tidy (hblock.comp (fst encIn encBits))) (hbudget.comp (PolyBounded.self.mono fun p => by + simp [length_frame]; omega))).tidy have hread : ComputableTidilyInPolyTime (fun p : γ × List Bool => restrictMask p.2 (seed p.1)) (encPair encIn encBits) encBits := computableTidilyInPolyTime_restrictMask.comp @@ -332,6 +339,6 @@ theorem computableInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List exact bitsStrictMajorityWithInput (mapToBitsWithInput (f := fun x z => V (x, listGenerator g (block x) ((greedyMasks (seed x) (block x) (overlap x)).take (out x)) z)) - (bitsEnumList_of_polyBounded hseed hseedBudget) hvote) + (ComputableInPolyTime.bitsEnumList_of_polyBounded (.of_tidy hseed) hseedBudget).tidy hvote) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Constructible.lean b/Complexity/Computability/Complexity/Classes/Constructible.lean index 56f81c806..21fda57f3 100644 --- a/Complexity/Computability/Complexity/Classes/Constructible.lean +++ b/Complexity/Computability/Complexity/Classes/Constructible.lean @@ -70,10 +70,11 @@ def TimeConstructible (t : ℕ → ℕ) : Prop := ∃ c : ℕ, ∃ s : ℕ → ℕ, ComputableInTimeAndSpaceOfLength (fun x : List Bool => t x.length) encBits encNat (fun n => c * t n + c) s -/-- A time-constructible bound is computed tidily within time and space `O(t n)`. -/ -theorem TimeConstructible.computableTidilyInO {t : ℕ → ℕ} (ht : TimeConstructible t) : - ComputableTidilyInO (fun x : List Bool => t x.length) encBits encNat (fun x => t x.length) +/-- A time-constructible bound is computed within time and space `O(t n)`. -/ +theorem TimeConstructible.computableInO {t : ℕ → ℕ} (ht : TimeConstructible t) : + ComputableInO (fun x : List Bool => t x.length) encBits encNat (fun x => t x.length) fun x => t x.length := by + refine .of_tidy ?_ obtain ⟨c, s, h⟩ := ht obtain ⟨k, h⟩ := ComputableInTimeAndSpace.exists_space_linear h obtain ⟨d, h⟩ := h.exists_computableTidilyInTimeAndSpace @@ -193,7 +194,7 @@ theorem TimeConstructible.succ_mul_of_computableInO {f : ℕ → ℕ} {T : List /-- If `f` is time-constructible and `n ≤ f n`, then so is `(n + 1) * f n`. -/ theorem TimeConstructible.succ_mul {f : ℕ → ℕ} (hf : TimeConstructible f) (hn : ∀ n, n ≤ f n) : TimeConstructible fun n => (n + 1) * f n := - TimeConstructible.succ_mul_of_computableInO 1 (.of_tidy hf.computableTidilyInO) (fun x => by + TimeConstructible.succ_mul_of_computableInO 1 hf.computableInO (fun x => by have : f x.length ≤ (x.length + 1) * f x.length := Nat.le_mul_of_pos_left _ (by omega) omega) hn @@ -234,13 +235,13 @@ def SpaceConstructible (s : ℕ → ℕ) : Prop := ∃ c : ℕ, ∃ t : ℕ → ℕ, ComputableInTimeAndSpaceOfLength (fun x : List Bool => s x.length) encBits encNat t fun n => c * s n + c -/-- A space-constructible bound is computed tidily within space `O(s n)`, within some time. -/ -theorem SpaceConstructible.computableTidilyInO {s : ℕ → ℕ} (hs : SpaceConstructible s) : - ∃ T, ComputableTidilyInO (fun x : List Bool => s x.length) encBits encNat T +/-- A space-constructible bound is computed within space `O(s n)`, within some time. -/ +theorem SpaceConstructible.computableInO {s : ℕ → ℕ} (hs : SpaceConstructible s) : + ∃ T, ComputableInO (fun x : List Bool => s x.length) encBits encNat T fun x => s x.length := by obtain ⟨c, t, h⟩ := hs obtain ⟨d, h⟩ := ComputableInTimeAndSpace.exists_computableTidilyInTimeAndSpace h - refine ⟨_, .of_bounds h (d * (c + 1) + 1) (T := fun x => 2 * t x.length + + refine ⟨_, .of_tidy <| .of_bounds h (d * (c + 1) + 1) (T := fun x => 2 * t x.length + 3 * (c * s x.length + c) + d) (fun x => ?_) (fun x => ?_) fun x => ?_⟩ · exact (Nat.le_succ _).trans (Nat.le_mul_of_pos_left _ (by omega)) · dsimp only [encBits_apply] diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean index c06f46b33..930e85bc3 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean @@ -127,7 +127,8 @@ theorem computableInO_spaceDiagonal {G : ℕ → ℕ} (hG : SpaceConstructible G ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) have hdesc := hdec.inO.comp hu have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one - obtain ⟨TG, hGb⟩ := hG.computableTidilyInO + obtain ⟨TG, hGb⟩ := hG.computableInO + have hGb := hGb.tidy have hGu := ComputableTidilyInO.natToUnary.comp hGb have hclock := ((ComputableTidilyInDegree.two_pow_length encUnary).inO_one.comp_linear hGu).of_enc_eq (encOut := encNat) (g := fun x : List Bool => 2 ^ G x.length) fun x => by diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean index 613d40f97..0edc554ad 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean @@ -232,7 +232,7 @@ theorem computableInO_timeDiagonal {J : ℕ → ℕ} (hJ : TimeConstructible J) ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) have hdesc := hdec.inO.comp hu have hsym := Universal.computableTidilyInDegree_map_eBit.inO_one - have hclock := hJ.computableTidilyInO + have hclock := hJ.computableInO.tidy have hU := computableTidilyInO_universal.comp (hdesc.prod (hsym.prod hclock)) have h := computableInO_shortDesc.tidy.ite (computableInO_verdict.tidy.comp hU) (ComputableTidilyInO.const (encMid := encBool) false) diff --git a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean index ecf0a43fd..beb8f5edb 100644 --- a/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean +++ b/Complexity/Computability/Complexity/Classes/IP/PSPACE.lean @@ -54,7 +54,7 @@ values: `2 ^ ((t + 1) * (2 * t + 1))` steps, with at most `t` frames of `O(t)` bits each (`Cslib.Complexity.Interaction.length_encEvalState_iterate_le`), so it computes `W` within polynomial space (`Cslib.Complexity.Interaction.evaluate_eq`, - `Cslib.Complexity.Interaction.computableTidilyInPolySpace_evaluate`), in exponential time. + `Cslib.Complexity.Interaction.computableInPolySpace_evaluate`), in exponential time. The converse inclusion `PSPACE ⊆ IP`, and so `IP = PSPACE`, is not formalized here. @@ -71,7 +71,7 @@ The converse inclusion `PSPACE ⊆ IP`, and so `IP = PSPACE`, is not formalized words. * `Cslib.Complexity.Interaction.gameTree_value_eq`: the value is the value of the game tree. * `Cslib.Complexity.Interaction.evaluate_eq`: the evaluation computes the value. -* `Cslib.Complexity.Interaction.computableTidilyInPolySpace_evaluate`: within polynomial space. +* `Cslib.Complexity.Interaction.computableInPolySpace_evaluate`: within polynomial space. * `Cslib.Complexity.mem_iff_two_pow_lt_value`: the value decides the problem. * `Cslib.Complexity.IP_subset_PSPACE`: `IP ⊆ PSPACE`. @@ -526,9 +526,13 @@ theorem length_encEvalState_iterate_le (a : α) (j : ℕ) : simp only [encEvalState, length_encPair] nlinarith +omit hfuel in /-- **The evaluation within polynomial space.** -/ -theorem computableTidilyInPolySpace_evaluate [Finite Control] [Inhabited α] : - ComputableTidilyInPolySpace (evaluate enc M fuel) enc encNat := by +theorem computableInPolySpace_evaluate [Finite Control] [Inhabited α] + (hfuel : ComputableInPolyTime fuel enc encUnary) : + ComputableInPolySpace (evaluate enc M fuel) enc encNat := by + have hfuel := hfuel.tidy + refine .of_tidy ?_ have hn : ComputableTidilyInPolyTime (evalTime fuel) enc encNat := by have hexp : ComputableTidilyInPolyTime (fun a => (fuel a + 1) * (2 * fuel a + 1)) enc encUnary := by @@ -644,7 +648,7 @@ theorem IP_subset_PSPACE (enc : α ↪ List Bool) : IP enc ⊆ PSPACE enc := by (ComputableTidilyInPolyTime.snd _ _)) exact (ComputableTidilyInPolySpace.of_polyTime hpost).comp ((ComputableTidilyInPolySpace.of_polyTime hcap).prod - (computableTidilyInPolySpace_evaluate M hfuel)) + (computableInPolySpace_evaluate M (.of_tidy hfuel)).tidy) refine mem_PSPACE_of_computableInPolySpace (.of_tidy hdec) fun a => ?_ rw [mem_iff_two_pow_lt_value (fun a S oracle s => hreal a S oracle s) hA a, evaluate_eq, decide_eq_true_iff] diff --git a/Complexity/Computability/Complexity/Classes/Oracle/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Oracle/PolyTime.lean index 788cc0c5c..a3332a2b5 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/PolyTime.lean @@ -24,11 +24,11 @@ polynomial time the instruction is polynomial-time (`Turing.MultiTapePTM.computableTidilyInPolyTime_answerStep`), the storage grows by a bounded amount per instruction, and the clock is polynomial, so the run is polynomial-time (`Turing.MultiTapePTM.computableTidilyInPolyTime_run`, -`Cslib.Complexity.ComputableInPolyTimeWithOracle.computableTidilyInPolyTime`). +`Cslib.Complexity.ComputableInPolyTimeWithOracle.computableInPolyTime`). ## Main results -* `Cslib.Complexity.ComputableInPolyTimeWithOracle.computableTidilyInPolyTime`: polynomial time +* `Cslib.Complexity.ComputableInPolyTimeWithOracle.computableInPolyTime`: polynomial time relative to an oracle in `P` is polynomial time. * `Cslib.Complexity.PWithOracle_eq_P`, `Cslib.Complexity.NPWithOracle_eq_NP`: `P^A = P` and `NP^A = NP` for `A ∈ P`. @@ -50,10 +50,11 @@ open Classical in /-- **Polynomial time relative to an oracle in `P` is polynomial time.** Relative to an oracle language decided in polynomial time, a function computable in polynomial time relative to it is computable in polynomial time: every query is answered by running the decider. -/ -theorem ComputableInPolyTimeWithOracle.computableTidilyInPolyTime {f : α → β} +theorem ComputableInPolyTimeWithOracle.computableInPolyTime {f : α → β} {output : β ↪ List Bool} (hA : A ∈ P encBits) (hf : ComputableInPolyTimeWithOracle A f enc output) : - ComputableTidilyInPolyTime f enc output := by + ComputableInPolyTime f enc output := by + refine .of_tidy ?_ obtain ⟨g, hg, hgA⟩ := hA have hg' : g = fun w => decide (w ∈ A) := funext fun w => Bool.eq_iff_iff.mpr ⟨fun h => decide_eq_true ((hgA w).mpr h), @@ -68,14 +69,14 @@ theorem ComputableInPolyTimeWithOracle.computableTidilyInPolyTime {f : α → β /-- **`P` relative to an oracle in `P` is `P`.** -/ theorem PWithOracle_eq_P (hA : A ∈ P encBits) (enc : α ↪ List Bool) : PWithOracle A enc = P enc := - Set.Subset.antisymm (fun _ ⟨f, hf, hL⟩ => ⟨f, .of_tidy (hf.computableTidilyInPolyTime hA), hL⟩) + Set.Subset.antisymm (fun _ ⟨f, hf, hL⟩ => ⟨f, hf.computableInPolyTime hA, hL⟩) (P_subset_PWithOracle A enc) /-- **`NP` relative to an oracle in `P` is `NP`.** -/ theorem NPWithOracle_eq_NP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : NPWithOracle A enc = NP enc := Set.Subset.antisymm - (fun _ ⟨p, V, hV, hL⟩ => ⟨p, V, .of_tidy (hV.computableTidilyInPolyTime hA), hL⟩) + (fun _ ⟨p, V, hV, hL⟩ => ⟨p, V, hV.computableInPolyTime hA, hL⟩) (NP_subset_NPWithOracle A enc) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean index 0f1fc0b0f..02e1a2fc3 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean @@ -29,7 +29,7 @@ The run is simulated instruction by instruction, answering each query with the d the request, which is no longer than the clock (`Turing.MultiTapePTM.exists_computableTidilyInO_run`). So the space is polynomial, while the time charges the decider of `A` once per instruction -(`Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableTidilyInO`, +(`Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableInO`, `Cslib.Complexity.PWithOracle_subset_PSPACE`). For `NP` relative to `A`, `Cslib.Complexity.mem_PSPACE_of_isVerifier` and @@ -39,10 +39,10 @@ bounded existential quantification (`Cslib.Complexity.setOf_exists_mem_PSPACE`). ## Main results * `Cslib.Complexity.exists_computableInO_of_mem_PSPACE`, - `Cslib.Complexity.mem_PSPACE_of_computableInO`: `PSPACE` in terms of tidy computability - within explicit bounds. + `Cslib.Complexity.mem_PSPACE_of_computableInO`: `PSPACE` in terms of computability within + explicit bounds. * `Cslib.Complexity.mem_PSPACE_of_isVerifier`: certificate search within polynomial space. -* `Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableTidilyInO`: polynomial time +* `Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableInO`: polynomial time relative to an oracle in `PSPACE` is within polynomial space. * `Cslib.Complexity.PWithOracle_subset_PSPACE`, `Cslib.Complexity.NPWithOracle_subset_PSPACE`. @@ -97,12 +97,12 @@ theorem mem_PSPACE_of_isVerifier {p : Polynomial ℕ} {V : α × List Bool → B open Classical in /-- **Oracle polynomial time within polynomial space.** Relative to an oracle language in -`PSPACE`, a function computable in polynomial time relative to it is tidily computable within -space polynomial in the length of the encoded input. -/ -theorem ComputableInPolyTimeWithOracle.exists_computableTidilyInO {A : Set (List Bool)} +`PSPACE`, a function computable in polynomial time relative to it is computable within space +polynomial in the length of the encoded input. -/ +theorem ComputableInPolyTimeWithOracle.exists_computableInO {A : Set (List Bool)} {f : α → β} {output : β ↪ List Bool} (hA : A ∈ PSPACE encBits) (hf : ComputableInPolyTimeWithOracle A f enc output) : - ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ ComputableTidilyInO f enc output T S := by + ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ ComputableInO f enc output T S := by obtain ⟨TA, SA, hSA, g, hg, hgA⟩ := exists_computableInO_of_mem_PSPACE hA have hg' : g = fun w => decide (w ∈ A) := funext fun w => Bool.eq_iff_iff.mpr ⟨fun h => decide_eq_true ((hgA w).mpr h), @@ -112,22 +112,22 @@ theorem ComputableInPolyTimeWithOracle.exists_computableTidilyInO {A : Set (List obtain ⟨k, m, machine, c, d, hrun⟩ := hcert.exists_fin_run_pure_false obtain ⟨T, S, hS, h⟩ := machine.exists_computableTidilyInO_run (input := enc) hg.tidy (by simpa [encBits] using hSA) c d - refine ⟨T, S, hS, h.of_enc_eq fun a => ?_⟩ + refine ⟨T, S, hS, .of_tidy <| h.of_enc_eq fun a => ?_⟩ rw [← hprogram a, ← hrun a (languageOracle A)] rfl /-- **`P` relative to an oracle in `PSPACE` is within `PSPACE`.** -/ theorem PWithOracle_subset_PSPACE {A : Set (List Bool)} (hA : A ∈ PSPACE encBits) : PWithOracle A enc ⊆ PSPACE enc := fun _ ⟨_, hf, hL⟩ => - let ⟨_, _, hS, h⟩ := hf.exists_computableTidilyInO hA - mem_PSPACE_of_computableInO (.of_tidy h) hS hL + let ⟨_, _, hS, h⟩ := hf.exists_computableInO hA + mem_PSPACE_of_computableInO h hS hL /-- **`NP` relative to an oracle in `PSPACE` is within `PSPACE`** [Arora and Barak, Theorem 3.7][AroraBarak09]: the verifier runs within polynomial space, and its certificates are searched within polynomial space. -/ theorem NPWithOracle_subset_PSPACE {A : Set (List Bool)} (hA : A ∈ PSPACE encBits) : NPWithOracle A enc ⊆ PSPACE enc := fun _ ⟨_, _, hV, hL⟩ => - let ⟨_, _, hS, h⟩ := hV.exists_computableTidilyInO hA - mem_PSPACE_of_isVerifier (.of_tidy h) hS hL + let ⟨_, _, hS, h⟩ := hV.exists_computableInO hA + mem_PSPACE_of_isVerifier h hS hL end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean index 77de397ac..ae7be2c2f 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Oracle.lean @@ -72,7 +72,7 @@ theorem PP_subset_PPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : theorem PPWithOracle_eq_PP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : PPWithOracle A enc = PP enc := Set.Subset.antisymm (fun _ ⟨p, V, hV, hL⟩ => - ⟨p, V, .of_tidy (hV.computableTidilyInPolyTime hA), hL⟩) (PP_subset_PPWithOracle A enc) + ⟨p, V, hV.computableInPolyTime hA, hL⟩) (PP_subset_PPWithOracle A enc) /-- Relativized PP is exactly positivity of a relativized gap function. For the reverse direction, two counts are padded to a common certificate length and selected with one extra bit. -/ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean index 062e2b43a..1702c90af 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean @@ -88,7 +88,7 @@ theorem GapP_subset_GapPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool theorem SharpPWithOracle_eq_SharpP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : SharpPWithOracle A enc = SharpP enc := Set.Subset.antisymm (fun _ ⟨p, V, hV, hf⟩ => - ⟨p, V, .of_tidy (hV.computableTidilyInPolyTime hA), hf⟩) (SharpP_subset_SharpPWithOracle A enc) + ⟨p, V, hV.computableInPolyTime hA, hf⟩) (SharpP_subset_SharpPWithOracle A enc) /-- A polynomial-time oracle adds no gap functions. -/ theorem GapPWithOracle_eq_GapP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean index 243b2b337..2fffd0bf6 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani/Collapse.lean @@ -19,7 +19,7 @@ By the Valiant–Vazirani theorem [Valiant and Vazirani][ValiantVazirani1986], [ Section 17.4][AroraBarak09], every problem in `NP` is in `RP` relative to every language solving `PromiseUSAT` (`Cslib.Complexity.NP_subset_RPWithPromiseOracle_PromiseUSAT`). An oracle decided in polynomial time adds nothing to randomized polynomial time: its queries are answered by -running its decider (`Cslib.Complexity.ComputableInPolyTimeWithOracle.computableTidilyInPolyTime`), +running its decider (`Cslib.Complexity.ComputableInPolyTimeWithOracle.computableInPolyTime`), so `RP^A = RP` for `A ∈ P` (`Cslib.Complexity.RPWithOracle_eq_RP`). Hence, if `PromiseUSAT` has a polynomial-time solver, then `NP = RP`, for every encoding of instances (`Cslib.Complexity.NP_eq_RP_of_PromiseUSAT_mem_PromiseP`). In particular `USAT ∈ P` implies @@ -62,7 +62,7 @@ variable {α β : Type} {A : Set (List Bool)} theorem RPWithOracle_eq_RP (hA : A ∈ P encBits) (enc : α ↪ List Bool) : RPWithOracle A enc = RP enc := Set.Subset.antisymm - (fun _ ⟨p, V, hV, hL⟩ => ⟨p, V, .of_tidy (hV.computableTidilyInPolyTime hA), hL⟩) + (fun _ ⟨p, V, hV, hL⟩ => ⟨p, V, hV.computableInPolyTime hA, hL⟩) (RP_subset_RPWithOracle A enc) open Classical in diff --git a/Complexity/Computability/Complexity/FineGrained.lean b/Complexity/Computability/Complexity/FineGrained.lean index 62cae906b..8934593c1 100644 --- a/Complexity/Computability/Complexity/FineGrained.lean +++ b/Complexity/Computability/Complexity/FineGrained.lean @@ -61,7 +61,7 @@ The negation of `ETH` is `Cslib.Complexity.DecidableInSubexpTime`: decidability * `Cslib.Complexity.mem_DTIME_iff_decidableInTimeO`: `DTIME` is `DecidableInTimeO` for bounds in the length of the encoded instance. -* `Cslib.Complexity.DecidableInTimeO.exists_computableTidilyInO`, +* `Cslib.Complexity.DecidableInTimeO.exists_computableInO`, `Cslib.Complexity.DecidableInTimeO.of_computableInO`: deciders within time `O(T)` are tidy deciders within time `O(T)`, which compose. * `Cslib.Complexity.DecidableInTimeO.inter`: restricting to a set decided in polynomial time. @@ -131,17 +131,17 @@ section Machines variable {α : Type} {enc : α ↪ List Bool} {A B : Set α} {T : α → ℝ} -/-- A decider within time `O(T)` is a tidy decider within time and space `O(t)`, for a bound `t` +/-- A decider within time `O(T)` is a decider within time and space `O(t)`, for a bound `t` within `O(T)`. -/ -theorem DecidableInTimeO.exists_computableTidilyInO (h : DecidableInTimeO A enc T) : - ∃ (g : α → Bool) (t : α → ℕ) (c : ℕ), ComputableTidilyInO g enc encBool t t ∧ +theorem DecidableInTimeO.exists_computableInO (h : DecidableInTimeO A enc T) : + ∃ (g : α → Bool) (t : α → ℕ) (c : ℕ), ComputableInO g enc encBool t t ∧ (∀ a, a ∈ A ↔ g a = true) ∧ ∀ a, (t a : ℝ) ≤ c * T a + c := by obtain ⟨c, t, s, ht, h⟩ := h obtain ⟨g, hg, hA⟩ := decidableInTimeAndSpace_iff.mp h obtain ⟨k, hg⟩ := ComputableInTimeAndSpace.exists_space_linear hg obtain ⟨d, hg⟩ := ComputableInTimeAndSpace.exists_computableTidilyInTimeAndSpace hg - refine ⟨g, t, c, ComputableTidilyInO.of_bounds hg (2 + 3 * k + d + d * k + d) (fun a => ?_) - (fun a => ?_) (fun a => ?_), hA, ht⟩ + refine ⟨g, t, c, .of_tidy <| ComputableTidilyInO.of_bounds hg (2 + 3 * k + d + d * k + d) + (fun a => ?_) (fun a => ?_) (fun a => ?_), hA, ht⟩ all_goals have e : (2 + 3 * k + d + d * k + d) * (t a + 1) = 2 * t a + 3 * (k * t a + k) + d + (2 + d * t a + d * (k * t a + k + 1) + d * t a) := by ring @@ -168,12 +168,13 @@ theorem DecidableInTimeO.inter {p : α → Bool} (hp : ComputableInPolyTime p en ∃ e : ℕ, DecidableInTimeO ({a | p a = true} ∩ B) enc fun a => (if p a = true then T a else 0) + ((enc a).length + 1) ^ e := by have hp := hp.tidy - obtain ⟨g, t, c, hg, hgB, ht⟩ := hB.exists_computableTidilyInO + obtain ⟨g, t, c, hg, hgB, ht⟩ := hB.exists_computableInO + have hg := hg.tidy obtain ⟨d, _, hp⟩ := hp.exists_degree have h := hp.inO.ite hg (ComputableTidilyInO.const false) refine ⟨d + 1, DecidableInTimeO.mono (T := fun a => ((((enc a).length + 1) ^ d + if p a then t a else (enc a).length : ℕ) : ℝ)) - (Complexity.DecidableInTimeO.of_computableInO (.of_tidy h) (fun a => ?_) fun a => le_rfl) (c + 2) + (DecidableInTimeO.of_computableInO (.of_tidy h) (fun a => ?_) fun a => le_rfl) (c + 2) (fun a => ?_) fun a => ?_⟩ · simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, hgB] cases p a <;> simp diff --git a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean index a61e60d60..08818ee69 100644 --- a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean +++ b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean @@ -547,7 +547,8 @@ theorem DecidableInTimeO.decidableInExpTime_SAT {ε : ℝ} (hε : 0 < ε) {e : (h : DecidableInTimeO OV encOV fun p => ((p.1.length + p.2.length : ℕ) : ℝ) ^ (2 - ε) * (OV.dim p + 1) ^ e) : DecidableInExpTime SAT encCNF CNF.numVars (1 - min ε 1 / 2) := by - obtain ⟨g, t, c, hg, hgOV, ht⟩ := h.exists_computableTidilyInO + obtain ⟨g, t, c, hg, hgOV, ht⟩ := h.exists_computableInO + have hg := hg.tidy obtain ⟨E, hred⟩ := exists_computableInO_toOV refine DecidableInExpTime.of_computableInO (.of_tidy (hg.comp hred.tidy)) (fun φ => by rw [← toOV_mem_OV_iff] diff --git a/Complexity/Computability/Complexity/FineGrained/Reduction.lean b/Complexity/Computability/Complexity/FineGrained/Reduction.lean index 5ae50832c..eb41ef06b 100644 --- a/Complexity/Computability/Complexity/FineGrained/Reduction.lean +++ b/Complexity/Computability/Complexity/FineGrained/Reduction.lean @@ -109,7 +109,8 @@ theorem DecidableInExpTime.of_reduction {f : α → β} (h : DecidableInExpTime B encB μB δ) : DecidableInExpTime A encA μA (c * δ) := by have hf := hf.tidy obtain ⟨e, h⟩ := h - obtain ⟨g, t, k, hg, hgB, ht⟩ := h.exists_computableTidilyInO + obtain ⟨g, t, k, hg, hgB, ht⟩ := h.exists_computableInO + have hg := hg.tidy obtain ⟨d, _, hf⟩ := hf.exists_degree have hfO := hf.inO obtain ⟨l, hl⟩ := hfO.length_le_time diff --git a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean index b02cefefc..b35b14980 100644 --- a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean +++ b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean @@ -744,7 +744,8 @@ theorem exists_decidableInExpTime_numVars_of_length (k : ℕ) {ε : ℝ} (hε : exact_mod_cast h₁.trans h₃ refine ⟨Sparsify.occBound K α, fun δ hδ h => ?_⟩ obtain ⟨e, h⟩ := h - obtain ⟨g, t, c, hg, hgA, ht⟩ := h.exists_computableTidilyInO + obtain ⟨g, t, c, hg, hgA, ht⟩ := h.exists_computableInO + have hg := hg.tidy have hgsat : ∀ ψ : CNF ℕ, (∀ c ∈ ψ, c.length ≤ k) → (g ψ = true ↔ ψ.Satisfiable) := fun ψ hψ => by rw [← hgA] diff --git a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean index 729104af9..3557fa805 100644 --- a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean +++ b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean @@ -429,23 +429,25 @@ theorem computableInPolyTime_paddedProgram (M : ℕ) {gL : List Bool → Bool} { -- the enumerations have hE : ComputableTidilyInPolyTime (fun x => BitString.enumList (blockLength M (padLength x))) (encPair encBits encUnary) (encList encBits) := - bitsEnumList_of_polyBounded hb ((polyBounded_two_pow_mul_padLength 1).mono fun x => by - rw [one_mul] - exact Nat.pow_le_pow_right (by norm_num) (hbℓ x)) + (ComputableInPolyTime.bitsEnumList_of_polyBounded (.of_tidy hb) + ((polyBounded_two_pow_mul_padLength 1).mono fun x => by + rw [one_mul] + exact Nat.pow_le_pow_right (by norm_num) (hbℓ x))).tidy have hMb : ComputableTidilyInPolyTime (fun x => M * blockLength M (padLength x)) (encPair encBits encUnary) encUnary := by fun_prop have hEn : ComputableTidilyInPolyTime (fun x => BitString.enumList (M * blockLength M (padLength x))) (encPair encBits encUnary) (encList encBits) := - bitsEnumList_of_polyBounded hMb ((polyBounded_two_pow_mul_padLength 1).mono fun x => by - rw [one_mul] - exact Nat.pow_le_pow_right (by norm_num) (hMbℓ x)) + (ComputableInPolyTime.bitsEnumList_of_polyBounded (.of_tidy hMb) + ((polyBounded_two_pow_mul_padLength 1).mono fun x => by + rw [one_mul] + exact Nat.pow_le_pow_right (by norm_num) (hMbℓ x))).tidy -- the queries to the decider - have htest := hgL.computableTidilyInPolyTime_take - (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) hMb - ((polyBounded_two_pow_mul_padLength k).mono fun x => - Nat.pow_le_pow_right (by norm_num) (Nat.mul_le_mul_left k (hMbℓ x))) + have htest := (ComputableInO.computableInPolyTime_take + (fun _ _ h => Nat.pow_le_pow_right two_pos (Nat.mul_le_mul_left k h)) (.of_tidy hgL) + (.of_tidy hMb) ((polyBounded_two_pow_mul_padLength k).mono fun x => + Nat.pow_le_pow_right (by norm_num) (Nat.mul_le_mul_left k (hMbℓ x)))).tidy have hpts : ComputableTidilyInPolyTime (fun x => (BitString.enumList (M * blockLength M (padLength x))).filter fun z => gL (z.take (M * blockLength M (padLength x)))) diff --git a/Complexity/Computability/Complexity/Parameterized.lean b/Complexity/Computability/Complexity/Parameterized.lean index 71773f0ab..9237f1718 100644 --- a/Complexity/Computability/Complexity/Parameterized.lean +++ b/Complexity/Computability/Complexity/Parameterized.lean @@ -400,7 +400,8 @@ private theorem decidableInTimeO_natCast_iff {A : Set α} {T : α → ℕ} : ∃ g : α → Bool, ComputableTidilyInO g encA encBool T T ∧ ∀ a, a ∈ A ↔ g a = true := by constructor · intro h - obtain ⟨g, t, k, hg, hA, ht⟩ := h.exists_computableTidilyInO + obtain ⟨g, t, k, hg, hA, ht⟩ := h.exists_computableInO + have hg := hg.tidy have ht' : ∀ a, t a ≤ k * (T a + 1) := fun a => by have : (t a : ℝ) ≤ ((k * (T a + 1) : ℕ) : ℝ) := by push_cast diff --git a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean index 937410449..d1623c434 100644 --- a/Complexity/Computability/Complexity/Parameterized/Kernelization.lean +++ b/Complexity/Computability/Complexity/Parameterized/Kernelization.lean @@ -126,7 +126,8 @@ then a decider on its output. -/ theorem IsKernelization.mem_FPT {K : α → α} {g : ℕ → ℕ} (hK : IsKernelization enc κ A K g) {t : ℕ → ℕ} (hA : A ∈ DTIME enc t) : A ∈ FPT enc κ := by obtain ⟨dec, tt, c, hdec, hdecA, htt⟩ := - (mem_DTIME_iff_decidableInTimeO.mp hA).exists_computableTidilyInO + (mem_DTIME_iff_decidableInTimeO.mp hA).exists_computableInO + have hdec := hdec.tidy obtain ⟨d, _, hKd⟩ := hK.polyTime.tidy.exists_degree have htt' : ∀ a, tt (K a) ≤ c * (∑ j ∈ Finset.range (g (κ a) + 1), t j) + c := fun a => by have h₁ : tt (K a) ≤ c * t (enc (K a)).length + c := by exact_mod_cast htt (K a) diff --git a/ComplexityTests/ClassCorollaries.lean b/ComplexityTests/ClassCorollaries.lean index b76fdb43b..5b61714d4 100644 --- a/ComplexityTests/ClassCorollaries.lean +++ b/ComplexityTests/ClassCorollaries.lean @@ -138,11 +138,11 @@ info: 'Cslib.Complexity.PH_eq_SigmaP_two_of_NP_subset_BPP' depends on axioms: #print axioms Cslib.Complexity.PH_eq_SigmaP_two_of_NP_subset_BPP /-- -info: 'Cslib.Complexity.ComputableInPolyTimeWithOracle.computableTidilyInPolyTime' depends on +info: 'Cslib.Complexity.ComputableInPolyTimeWithOracle.computableInPolyTime' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.ComputableInPolyTimeWithOracle.computableTidilyInPolyTime +#print axioms Cslib.Complexity.ComputableInPolyTimeWithOracle.computableInPolyTime /-- info: 'Cslib.Complexity.PWithOracle_eq_P' depends on axioms: diff --git a/ComplexityTests/InteractiveProofs.lean b/ComplexityTests/InteractiveProofs.lean index af2143b03..74c0db1df 100644 --- a/ComplexityTests/InteractiveProofs.lean +++ b/ComplexityTests/InteractiveProofs.lean @@ -327,11 +327,12 @@ example (P : Prover Unit) : #guard_msgs in #print axioms Interaction.evaluate_eq -/-- info: 'Cslib.Complexity.Interaction.computableTidilyInPolySpace_evaluate' depends on axioms: [propext, - Classical.choice, - Quot.sound] -/ -#guard_msgs in -#print axioms Interaction.computableTidilyInPolySpace_evaluate +/-- +info: 'Cslib.Complexity.Interaction.computableInPolySpace_evaluate' depends on axioms: + [propext, Classical.choice, Quot.sound] +-/ +#guard_msgs (whitespace := lax) in +#print axioms Interaction.computableInPolySpace_evaluate /-- info: 'Cslib.Complexity.Interaction.computableInPolySpace_countAccepts' depends on axioms: [propext, Classical.choice, diff --git a/ComplexityTests/Relativization.lean b/ComplexityTests/Relativization.lean index c6d91d646..b3653ed7f 100644 --- a/ComplexityTests/Relativization.lean +++ b/ComplexityTests/Relativization.lean @@ -381,11 +381,11 @@ info: 'Cslib.Complexity.NPWithOracle_subset_PSPACE' depends on axioms: #print axioms Cslib.Complexity.NPWithOracle_subset_PSPACE /-- -info: 'Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableTidilyInO' depends on axioms: +info: 'Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableInO' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableTidilyInO +#print axioms Cslib.Complexity.ComputableInPolyTimeWithOracle.exists_computableInO /-- info: 'Cslib.Complexity.mem_PSPACE_of_isVerifier' depends on axioms: From 3420502b21180c12db240554fb000cba2a2ecfd6 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 13:44:43 -0400 Subject: [PATCH 06/11] refactor(classes): retire the class and reduction tidy bridges The 24 public bridges between plain and tidy class membership and reductions (`mem_X_iff_tidy` for twenty classes, `polyTimeReducible_iff_tidy`, `parsimoniousReducible_iff_tidy`, `polyTimeTruthTableReducible_iff_tidy`, `searchReducible_iff_tidy`) are removed: the classes and reductions are stated plainly and their `mem_X` lemmas are plain, so proofs that build tidy certificates convert them with `.of_tidy`, and proofs that destructure plain memberships take `.tidy` locally. Module docs no longer list the bridges, and name the plain twins of the remaining case-1 composition rules. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Complexity/Classes/AWPP.lean | 7 +- .../Complexity/Classes/ArthurMerlin.lean | 14 -- .../Classes/ArthurMerlin/Amplification.lean | 12 +- .../Computability/Complexity/Classes/BPP.lean | 8 -- .../Complexity/Classes/BPP/Amplification.lean | 6 +- .../BPP/Derandomization/Generator.lean | 9 +- .../Complexity/Classes/BPP/Reduction.lean | 10 +- .../Classes/BooleanHierarchy/Kadin.lean | 4 +- .../Complexity/Classes/Hierarchy.lean | 4 +- .../Complexity/Classes/Ladner.lean | 6 +- .../Computability/Complexity/Classes/NP.lean | 11 +- .../Complexity/Classes/NP/SelfReduction.lean | 4 +- .../Complexity/Classes/NP/Witness.lean | 25 ++-- .../Complexity/Classes/Oracle/Closure.lean | 3 +- .../Complexity/Classes/Oracle/Space.lean | 6 +- .../Computability/Complexity/Classes/P.lean | 20 +-- .../Classes/PCP/ZeroRandomness.lean | 4 +- .../Computability/Complexity/Classes/PH.lean | 14 -- .../Complexity/Classes/PH/Kannan.lean | 7 +- .../Computability/Complexity/Classes/PP.lean | 6 - .../Classes/PP/Characterization.lean | 14 +- .../Complexity/Classes/PP/Closure.lean | 6 +- .../Complexity/Classes/Promise/Basic.lean | 6 +- .../Complexity/Classes/Promise/Reduction.lean | 31 ++-- .../Computability/Complexity/Classes/RP.lean | 7 - .../Complexity/Classes/RP/Closure.lean | 4 +- .../Computability/Complexity/Classes/SBP.lean | 13 +- .../Complexity/Classes/SharpP.lean | 8 -- .../Classes/SharpP/Aggregation.lean | 3 +- .../Complexity/Classes/SharpP/Closure.lean | 11 +- .../Classes/SharpP/Combinators.lean | 8 +- .../Classes/SharpP/Completeness.lean | 14 +- .../Complexity/Classes/SharpP/Power.lean | 4 +- .../Complexity/Classes/SharpP/Products.lean | 2 +- .../Complexity/Classes/SharpP/Space.lean | 4 +- .../Complexity/Classes/Space.lean | 3 +- .../Complexity/Classes/TFNP.lean | 65 +++------ .../Classes/TFNP/SearchToDecision.lean | 31 ++-- .../Complexity/Classes/TFNP/Subclasses.lean | 136 ++++++------------ .../Classes/TFNP/Subclasses/Completeness.lean | 16 +-- .../Complexity/Classes/Time.lean | 10 +- .../Complexity/Classes/ValiantVazirani.lean | 3 +- .../Computability/Complexity/Classes/WPP.lean | 37 ++--- .../Complexity/Classes/WPP/Bounded.lean | 7 +- .../Complexity/Classes/WPP/Lowness.lean | 6 +- .../Complexity/Classes/WPP/Robustness.lean | 4 +- .../Complexity/Classes/WPP/TruthTable.lean | 11 +- .../Complexity/Classes/WPP/TwoSided.lean | 4 +- .../Computability/Complexity/Classes/ZPP.lean | 23 ++- .../Complexity/CookLevin/Completeness.lean | 3 +- .../Computability/Complexity/FineGrained.lean | 4 +- .../Problems/CircuitValue/Completeness.lean | 3 +- .../Complexity/Problems/Clique.lean | 2 +- .../MonotoneCircuitValue/Completeness.lean | 3 +- .../Computability/Complexity/Reduction.lean | 10 +- .../Complexity/Reduction/TruthTable.lean | 28 ++-- ComplexityTests/KarpReductions.lean | 4 +- ComplexityTests/PolyTimePlain.lean | 8 +- ComplexityTests/TFNP.lean | 5 - 59 files changed, 269 insertions(+), 472 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/AWPP.lean b/Complexity/Computability/Complexity/Classes/AWPP.lean index cf63cf453..25b4a5c4f 100644 --- a/Complexity/Computability/Complexity/Classes/AWPP.lean +++ b/Complexity/Computability/Complexity/Classes/AWPP.lean @@ -141,10 +141,11 @@ theorem mem_AWPP_of_polyTime_exponent {g : α → ℤ} {r : α → ℕ} /-- Polynomial-time many-one reductions preserve AWPP after dyadic denominator padding. -/ theorem PolyTimeReducible.mem_AWPP {β : Type} {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ AWPP encB) : A ∈ AWPP enc := by - obtain ⟨r, hr, hAB⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨r, hr, hAB⟩ := h obtain ⟨g, hg, p, hB⟩ := hB - refine mem_AWPP_of_polyTime_exponent (GapP.comp_mem hg (.of_tidy hr)) - (r := fun a => p.eval (encB (r a)).length) (.of_tidy (by fun_prop)) (fun a => ?_) + refine mem_AWPP_of_polyTime_exponent (GapP.comp_mem hg hr) + (r := fun a => p.eval (encB (r a)).length) (.of_tidy (by have hr := hr.tidy; fun_prop)) + (fun a => ?_) simpa only [Function.comp_apply, ← hAB a] using hB (r a) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin.lean index 3665354a8..2ca0957f3 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin.lean @@ -57,8 +57,6 @@ the second level of the polynomial hierarchy in ## Main results -* `Cslib.Complexity.mem_MA_iff_tidy`, `Cslib.Complexity.mem_AM_iff_tidy`: membership through a - tidy verifier. * `Cslib.Complexity.NP_subset_MA`, `Cslib.Complexity.BPP_subset_MA`. * `Cslib.Complexity.PolyTimeReducible.mem_MA`, `Cslib.Complexity.PolyTimeReducible.mem_AM`: closure under polynomial-time many-one reductions. @@ -105,12 +103,6 @@ theorem mem_MA : A ∈ MA enc ↔ ∃ (q p : Polynomial ℕ) (V : α × List Boo IsMerlinArthurVerifier enc q p V A := Iff.rfl -/-- `Cslib.Complexity.mem_MA` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_MA_iff_tidy : A ∈ MA enc ↔ ∃ (q p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - IsMerlinArthurVerifier enc q p V A := by - simp only [mem_MA, computableInPolyTime_iff_computableTidilyInPolyTime] - /-! ### Arthur–Merlin -/ /-- `V` is an Arthur–Merlin verifier for `A`, with random strings of length `p` and replies of @@ -138,12 +130,6 @@ theorem mem_AM : A ∈ AM enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Boo IsArthurMerlinVerifier enc p q V A := Iff.rfl -/-- `Cslib.Complexity.mem_AM` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_AM_iff_tidy : A ∈ AM enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - IsArthurMerlinVerifier enc p q V A := by - simp only [mem_AM, computableInPolyTime_iff_computableTidilyInPolyTime] - /-! ### `NP` and `BPP` -/ /-- With no random bits, the single random string is accepted or rejected. -/ diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean index 61c896bd3..9dd62e170 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean @@ -194,12 +194,12 @@ theorem mem_MA_iff_exists_forall_errorExponent : (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by have this : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by - rw [mem_MA_iff_tidy] + rw [mem_MA] refine ⟨fun ⟨q, p, V, hV, h⟩ => ⟨q, fun e => ⟨12 * e * p, _, - (computableInPolyTime_merlinArthurRepeat (.of_tidy hV) _ _ _).tidy, h.repeatMajority e⟩⟩, + (computableInPolyTime_merlinArthurRepeat hV _ _ _).tidy, h.repeatMajority e⟩⟩, fun ⟨q, h⟩ => ?_⟩ obtain ⟨p, V, hV, h⟩ := h 2 - exact ⟨q, p, V, hV, h.isMerlinArthurVerifier fun _ => by simp⟩ + exact ⟨q, p, V, (.of_tidy hV), h.isMerlinArthurVerifier fun _ => by simp⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Error reduction for `AM` -/ @@ -353,11 +353,11 @@ theorem mem_AM_iff_forall_errorExponent : ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by have this : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by - rw [mem_AM_iff_tidy] + rw [mem_AM] refine ⟨fun ⟨p, q, V, hV, h⟩ e => ⟨12 * e * p, 12 * e * q, _, - (computableInPolyTime_arthurMerlinRepeat (.of_tidy hV) _ _ _).tidy, h.repeatMajority e⟩, fun h => ?_⟩ + (computableInPolyTime_arthurMerlinRepeat hV _ _ _).tidy, h.repeatMajority e⟩, fun h => ?_⟩ obtain ⟨p, q, V, hV, h⟩ := h 2 - exact ⟨p, q, V, hV, h.isArthurMerlinVerifier fun _ => by simp⟩ + exact ⟨p, q, V, (.of_tidy hV), h.isArthurMerlinVerifier fun _ => by simp⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### `MA ⊆ AM` -/ diff --git a/Complexity/Computability/Complexity/Classes/BPP.lean b/Complexity/Computability/Complexity/Classes/BPP.lean index 7324cbdf6..9b25a9b7b 100644 --- a/Complexity/Computability/Complexity/Classes/BPP.lean +++ b/Complexity/Computability/Complexity/Classes/BPP.lean @@ -40,7 +40,6 @@ The probability is written as a count over the random strings, which are functio ## Main results -* `Cslib.Complexity.mem_BPP_iff_tidy`: membership through a tidy verifier. * `Cslib.Complexity.DecidesWithBoundedError.compl`: negating the verifier decides the complement with bounded error. * `Cslib.Complexity.compl_mem_BPP`, `Cslib.Complexity.BPP_eq_preimage_compl_BPP`: `BPP` is closed @@ -87,13 +86,6 @@ theorem mem_BPP {enc : α ↪ List Bool} {A : Set α} : DecidesWithBoundedError enc p V A := Iff.rfl -/-- `Cslib.Complexity.mem_BPP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_BPP_iff_tidy {enc : α ↪ List Bool} {A : Set α} : - A ∈ BPP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - DecidesWithBoundedError enc p V A := by - simp only [mem_BPP, computableInPolyTime_iff_computableTidilyInPolyTime] - namespace DecidesWithBoundedError /-- Negating the verifier decides the complement with bounded error. -/ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean index 75555ef64..9f87a7613 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean @@ -137,11 +137,11 @@ theorem mem_BPP_iff_forall_decidesWithErrorExponent {A : Set α} : ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by have this : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by - rw [mem_BPP_iff_tidy] + rw [mem_BPP] refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨12 * q * p, _, - (computableInPolyTime_repeatMajority (.of_tidy hV) _ _).tidy, h.repeatMajority q⟩, fun h => ?_⟩ + (computableInPolyTime_repeatMajority hV _ _).tidy, h.repeatMajority q⟩, fun h => ?_⟩ obtain ⟨p, V, hV, h⟩ := h 2 - exact ⟨p, V, hV, h.decidesWithBoundedError fun _ => by simp⟩ + exact ⟨p, V, (.of_tidy hV), h.decidesWithBoundedError fun _ => by simp⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-! ### Boolean closure of `BPP` -/ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean index 3f4290b09..a4ac2f0b1 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean @@ -60,7 +60,7 @@ generator for each of the `2 ^ ℓ` seeds and takes the strict majority of the a ## Main results * `Cslib.Complexity.exists_computableInO_of_mem_DTIME`: deterministic time classes have - tidy deciders within the same time bound, up to constant factors. + deciders within the same time and space bound, up to constant factors. * `Turing.MultiTapeTM.ComputableInO.computableInPolyTime_take`: evaluation of a function computable in time `T n` on words of polynomially bounded `T n`. * `Turing.MultiTapeTM.ComputableInPolyTime.bitsEnumList_of_polyBounded`: enumeration of the @@ -83,9 +83,10 @@ open Turing Turing.MultiTapeTM namespace Cslib.Complexity -/-- **Deterministic time classes have tidy deciders.** A problem decided within time `O(t n)`, by -a machine with any space bound, has a Boolean decider tidily computable within time and space -`O(t n)`: time bounds space, and the tidy normal form costs a linear overhead. -/ +/-- **Deterministic time classes have deciders within time and space `O(t n)`.** A problem +decided within time `O(t n)`, by a machine with any space bound, has a Boolean decider computable +within time and space `O(t n)`: time bounds space, and the tidy normal form of the proof costs a +linear overhead. -/ theorem exists_computableInO_of_mem_DTIME {A : Set (List Bool)} {t : ℕ → ℕ} (h : A ∈ DTIME encBits t) : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Reduction.lean b/Complexity/Computability/Complexity/Classes/BPP/Reduction.lean index 2752d5f77..4a1dd8156 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Reduction.lean @@ -47,17 +47,19 @@ variable {α β : Type} {enc : α ↪ List Bool} {encB : β ↪ List Bool} {A : `B` on the reduced instance and on the prefix of the random string that this decider expects. -/ theorem PolyTimeReducible.mem_BPP (h : PolyTimeReducible enc encB A B) (hB : B ∈ BPP encB) : A ∈ BPP enc := by - rw [mem_BPP_iff_tidy] at hB ⊢ - obtain ⟨g, hg, hAB⟩ := polyTimeReducible_iff_tidy.mp h + rw [Complexity.mem_BPP] at hB ⊢ + obtain ⟨g, hg, hAB⟩ := h obtain ⟨q, W, hW, hWB⟩ := hB + have hg := hg.tidy + have hW := hW.tidy have hlen : ComputableTidilyInPolyTime (fun a => q.eval (encB (g a)).length) enc encUnary := (ComputableTidilyInPolyTime.unary_eval q).comp ((ComputableTidilyInPolyTime.encoding_length encB).comp hg) obtain ⟨p, hle⟩ := hlen.polyBounded.exists_polynomial refine ⟨p, andVerifier (fun a => q.eval (encB (g a)).length) (fun x => W (g x.1, x.2)) fun _ => true, - computableTidilyInPolyTime_andVerifier hlen - (hW.comp ((hg.comp (.fst enc encBits)).prod (.snd enc encBits))) (.const true), + .of_tidy (computableTidilyInPolyTime_andVerifier hlen + (hW.comp ((hg.comp (.fst enc encBits)).prod (.snd enc encBits))) (.const true)), fun a => ?_⟩ obtain ⟨j, hj⟩ := Nat.exists_eq_add_of_le (hle a) rw [hj] diff --git a/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean b/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean index 05404a1a1..0d294ad35 100644 --- a/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean +++ b/Complexity/Computability/Complexity/Classes/BooleanHierarchy/Kadin.lean @@ -152,8 +152,8 @@ private theorem congr_poly (h : OnSliceAlt enc b k q R) {q' : Polynomial ℕ} `α`. -/ private theorem mem_SigmaP (h : OnSliceAlt enc true k 0 R) : {a | R a []} ∈ SigmaP k enc := by obtain ⟨ps, V, hk, hV, hR⟩ := h - refine mem_SigmaP_iff_tidy.mpr ⟨ps, fun x => V ((x.1, []), x.2), hk, ?_, fun a => ?_⟩ - · exact hV.tidy.comp (((fst enc encBits).prod (.const [])).prod (snd enc encBits)) + refine Complexity.mem_SigmaP.mpr ⟨ps, fun x => V ((x.1, []), x.2), hk, ?_, fun a => ?_⟩ + · exact .of_tidy (hV.tidy.comp (((fst enc encBits).prod (.const [])).prod (snd enc encBits))) · exact hR a [] (by simp) /-- Negating the verifier swaps quantifier polarities. -/ diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Hierarchy.lean index 7a218209c..c6dc97e8e 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy.lean @@ -148,8 +148,8 @@ theorem not_forall_halted_diagonal {k : ℕ} {State : Type} [Finite State] /-- **The diagonal problem is not in `P`**, by the diagonal argument of the time hierarchy theorem [Arora and Barak, Theorem 3.1][AroraBarak09]. -/ theorem diagonal_notMem_P : {x | diagonal x = true} ∉ P encBits := by - rw [mem_P_iff_tidy] - rintro ⟨f, ⟨t, s, ht, -, k, State, hfinite, tm, htm⟩, hf⟩ + rintro ⟨f, hfpoly, hf⟩ + obtain ⟨t, s, ht, -, k, State, hfinite, tm, htm⟩ := hfpoly.tidy have hfx (x : List Bool) : f x = diagonal x := by cases h : diagonal x · cases hfx : f x diff --git a/Complexity/Computability/Complexity/Classes/Ladner.lean b/Complexity/Computability/Complexity/Classes/Ladner.lean index dca00c092..bc9f60445 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner.lean @@ -189,7 +189,8 @@ private theorem eventually_clock_le (i : ℕ) : /-- **If `SATH` is in `P`, then `H` is bounded**: some index of a machine deciding `SATH` has a clock exceeding its polynomial time bound, and from some point on `H` is at most that index. -/ theorem exists_H_le_of_mem_P (h : SATH ∈ P encBits) : ∃ C, ∀ n, H n ≤ C := by - obtain ⟨f, ⟨t, s, ht, -, k, State, hfinite, tm, htm⟩, hf⟩ := mem_P_iff_tidy.mp h + obtain ⟨f, hfpoly, hf⟩ := mem_P.mp h + obtain ⟨t, s, ht, -, k, State, hfinite, tm, htm⟩ := hfpoly.tidy have := Fintype.ofFinite State let eS : State ↪ ℕ := (Fintype.equivFin State).toEmbedding.trans Fin.valEmbedding have hrun (x : List Bool) : (tm.runFrom (tm.initCfg x) (t x)).Halted ∧ @@ -369,7 +370,8 @@ then `SAT` is in `P`: the self-reduction leaves a formula of bounded length, dec table. -/ theorem SAT_mem_P_of_reducible_of_tendsto (hR : PolyTimeReducible encCNF encBits SAT SATH) (hH : Filter.Tendsto H Filter.atTop Filter.atTop) : SAT ∈ P encCNF := by - obtain ⟨R, hRpoly, hR⟩ := polyTimeReducible_iff_tidy.mp hR + obtain ⟨R, hRpoly, hR⟩ := hR + have hRpoly := hRpoly.tidy obtain ⟨c, d, hRlen⟩ := hRpoly.polyBounded_length.exists_le simp only [encBits_apply] at hRlen obtain ⟨M, hM⟩ := Filter.eventually_atTop.mp (Filter.tendsto_atTop.mp hH (d + 1)) diff --git a/Complexity/Computability/Complexity/Classes/NP.lean b/Complexity/Computability/Complexity/Classes/NP.lean index 65da52454..c45a0d718 100644 --- a/Complexity/Computability/Complexity/Classes/NP.lean +++ b/Complexity/Computability/Complexity/Classes/NP.lean @@ -38,9 +38,7 @@ builds them from polynomial-time witness relations. The verifier's efficiency can equally be stated in upstream terms: some machine computes it, in the sense of `Turing.MultiTapeTM.ComputableInTimeAndSpaceOfLength`, within time and space bounded by polynomially bounded functions of the length of its encoded input, which pairs the instance with -the certificate (`Cslib.Complexity.mem_NP_iff_exists_computableInTimeAndSpaceOfLength`). Proofs -usually build verifiers with the tidy calculus; `Cslib.Complexity.mem_NP_iff_tidy` states -membership with a tidy verifier (`Turing.MultiTapeTM.ComputableTidilyInPolyTime`). +the certificate (`Cslib.Complexity.mem_NP_iff_exists_computableInTimeAndSpaceOfLength`). ## Main definitions @@ -49,7 +47,6 @@ membership with a tidy verifier (`Turing.MultiTapeTM.ComputableTidilyInPolyTime` ## Main results -* `Cslib.Complexity.mem_NP_iff_tidy`: `NP` with tidy verifiers. * `Cslib.Complexity.mem_NP_iff_exists_computableInTimeAndSpaceOfLength`: `NP` with verifiers computed in the sense of upstream `Turing.MultiTapeTM.ComputableInTimeAndSpaceOfLength`. * `Cslib.Complexity.IsVerifier.of_padding`: a verifier that accepts certificates of exactly the @@ -89,12 +86,6 @@ theorem mem_NP {enc : α ↪ List Bool} {A : Set α} : ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsVerifier enc p V A := Iff.rfl -/-- `NP` with tidy verifiers, the form in which proofs build them. -/ -theorem mem_NP_iff_tidy {enc : α ↪ List Bool} {A : Set α} : - A ∈ NP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsVerifier enc p V A := by - simp only [mem_NP, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- **`NP` in upstream terms:** `A ∈ NP enc` exactly when, for a polynomial `p`, some verifier for `A` with certificates of length `p` is computed by a machine with a binary alphabet and finitely many states within time and space bounded by polynomially bounded functions of the length of the diff --git a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean index a7f815c14..15ddf80e8 100644 --- a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean +++ b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean @@ -276,8 +276,8 @@ theorem exists_search (h : SAT ∈ P encCNF) : ∃ g : CNF ℕ → List Bool, ComputableInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by have this : ∃ g : CNF ℕ → List Bool, ComputableTidilyInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by - obtain ⟨D, hD, hSAT⟩ := mem_P_iff_tidy.mp h - exact ⟨search D, (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (snd _ _))) (.of_tidy id')).tidy, + obtain ⟨D, hD, hSAT⟩ := mem_P.mp h + exact ⟨search D, (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (.of_tidy (snd _ _))).tidy) (.of_tidy id')).tidy, fun φ => verifier_search_iff fun ψ _ => (hSAT ψ).symm⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this diff --git a/Complexity/Computability/Complexity/Classes/NP/Witness.lean b/Complexity/Computability/Complexity/Classes/NP/Witness.lean index 1b9ecc0f5..0b1920a8d 100644 --- a/Complexity/Computability/Complexity/Classes/NP/Witness.lean +++ b/Complexity/Computability/Complexity/Classes/NP/Witness.lean @@ -166,8 +166,9 @@ theorem mem_NP_of_witness (D : Decoder encW) {check : α × β → Bool} {R : α (hp : ∀ a b, R a b → ∃ b', R a b' ∧ (encW b').length ≤ p.eval (enc a).length) : {a | ∃ b, R a b} ∈ NP enc := by have hcheck := hcheck.tidy - exact mem_NP_iff_tidy.mpr - ⟨_, _, (computableInPolyTime_witnessVerifier D (.of_tidy hcheck)).tidy, isVerifier_witnessVerifier D hR hp⟩ + exact mem_NP.mpr + ⟨_, _, computableInPolyTime_witnessVerifier D (.of_tidy hcheck), + isVerifier_witnessVerifier D hR hp⟩ end Witness @@ -245,8 +246,8 @@ theorem mem_NP_of_subsetWitness {encγ : γ ↪ List Bool} {vs : α → List γ} have hvs := hvs.tidy have hcheck := hcheck.tidy obtain ⟨p, hle⟩ := hvs.polyBounded_length.exists_polynomial - refine mem_NP_iff_tidy.mpr ⟨p, _, - (computableInPolyTime_subsetVerifier (.of_tidy hvs) (.of_tidy hcheck)).tidy, + refine mem_NP.mpr ⟨p, _, + computableInPolyTime_subsetVerifier (.of_tidy hvs) (.of_tidy hcheck), isVerifier_subsetVerifier (fun a => ?_) hP⟩ exact (length_le_length_encList encγ (vs a)).trans (hle a) @@ -259,15 +260,16 @@ end Subset expects. For the oracle classes, see `Cslib.Complexity.PolyTimeReducible.mem_NPWithOracle`. -/ theorem PolyTimeReducible.mem_NP {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ NP encB) : A ∈ NP enc := by - obtain ⟨f, hf, hAB⟩ := polyTimeReducible_iff_tidy.mp h - obtain ⟨q, W, hW, hWB⟩ := mem_NP_iff_tidy.mp hB + obtain ⟨f, hf, hAB⟩ := h + obtain ⟨q, W, hW, hWB⟩ := Complexity.mem_NP.mp hB + have hf := hf.tidy have hlen : ComputableTidilyInPolyTime (fun a => q.eval (encB (f a)).length) enc encUnary := (unary_eval q).comp ((encoding_length encB).comp hf) obtain ⟨p, hle⟩ := hlen.polyBounded.exists_polynomial - refine mem_NP_iff_tidy.mpr ⟨p, + refine Complexity.mem_NP.mpr ⟨p, fun x => W (f x.1, x.2.take (q.eval (encB (f x.1)).length)), ?_, IsVerifier.of_padding (fun a w hw h => ?_) fun a ha => ?_⟩ - · exact hW.comp ((hf.comp (fst enc encBits)).prod + · exact .of_tidy <| hW.tidy.comp ((hf.comp (fst enc encBits)).prod (bitsTakeWithInput (snd enc encBits) (hlen.comp (fst enc encBits)))) · refine (hAB a).2 ((hWB (f a)).2 ⟨_, List.length_take_of_le ?_, h⟩) rw [hw] @@ -291,10 +293,11 @@ theorem mem_NP_setOf_exists_append {V : α × List Bool → Bool} {y : α × List Bool | ∃ v : List Bool, v.length = q.eval (enc y.1).length ∧ V (y.1, y.2 ++ v) = true} ∈ NP (encPair enc encBits) := by have hV := hV.tidy - refine mem_NP_iff_tidy.mpr + refine mem_NP.mpr ⟨q, fun z => V (z.1.1, z.1.2 ++ z.2.take (q.eval (enc z.1.1).length)), ?_, fun y => ?_⟩ - · exact hV.comp ((fst _ _).fst'.prod (bitsAppend (fst _ _).snd' (bitsTakeWithInput (snd _ _) - ((unary_eval q).comp ((encoding_length enc).comp (fst _ _).fst'))))) + · exact .of_tidy <| hV.comp ((fst _ _).fst'.prod (bitsAppend (fst _ _).snd' + (bitsTakeWithInput (snd _ _) ((unary_eval q).comp ((encoding_length enc).comp + (fst _ _).fst'))))) · have hle : q.eval (enc y.1).length ≤ q.eval (encPair enc encBits y).length := q.eval_mono (length_le_encPair_left _ _ _) constructor diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean index 88b3d149e..fb7657de4 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean @@ -165,7 +165,7 @@ the length required by the reduced instance. -/ theorem PolyTimeReducible.mem_NPWithOracle {encA : α ↪ List Bool} {encB : β ↪ List Bool} {L : Set α} {L' : Set β} (h : PolyTimeReducible encA encB L L') (hL' : L' ∈ NPWithOracle A encB) : L ∈ NPWithOracle A encA := by - obtain ⟨g, hg, hL⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨g, hg, hL⟩ := h obtain ⟨p, V, hV, hL'⟩ := hL' obtain ⟨r, hlen⟩ := hg.polyBounded_length.exists_polynomial -- the certificate length of the reduced instance, as a polynomial of the instance length @@ -173,6 +173,7 @@ theorem PolyTimeReducible.mem_NPWithOracle {encA : α ↪ List Bool} {encB : β have hpq (a : α) : p.eval (encB (g a)).length ≤ q.eval (encA a).length := by rw [hq, Polynomial.eval_comp] exact p.eval_mono (hlen a) + have hg := hg.tidy refine ⟨q, fun aw => V (g aw.1, aw.2.take (p.eval (encB (g aw.1)).length)), hV.preprocess (f := V) (g := fun aw : α × List Bool => (g aw.1, aw.2.take (p.eval (encB (g aw.1)).length))) (.of_tidy (by fun_prop)), fun a => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean index 02e1a2fc3..2f6c96e75 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean @@ -59,9 +59,9 @@ open _root_.Turing _root_.Turing.MultiTapeTM variable {α β : Type} {enc : α ↪ List Bool} -/-! ### `PSPACE` through tidy computability -/ +/-! ### `PSPACE` through explicit time and space bounds -/ -/-- A problem in `PSPACE` has a tidy decider within explicit bounds, the space polynomial in the +/-- A problem in `PSPACE` has a decider within explicit bounds, the space polynomial in the length of the encoded instance. -/ theorem exists_computableInO_of_mem_PSPACE {L : Set α} (hL : L ∈ PSPACE enc) : ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ @@ -69,7 +69,7 @@ theorem exists_computableInO_of_mem_PSPACE {L : Set α} (hL : L ∈ PSPACE enc) let ⟨f, T, S, hf, hS, hL⟩ := mem_PSPACE_iff_computableInO.mp hL ⟨T, S, hS, f, hf, hL⟩ -/-- A tidy decider within polynomial space puts a problem in `PSPACE`. -/ +/-- A decider within polynomial space puts a problem in `PSPACE`. -/ theorem mem_PSPACE_of_computableInO {L : Set α} {f : α → Bool} {T S : α → ℕ} (hf : Turing.MultiTapeTM.ComputableInO f enc encBool T S) (hS : PolyBounded (fun a => (enc a).length) S) (hL : ∀ a, a ∈ L ↔ f a = true) : L ∈ PSPACE enc := diff --git a/Complexity/Computability/Complexity/Classes/P.lean b/Complexity/Computability/Complexity/Classes/P.lean index 31d95fb2d..488f72f98 100644 --- a/Complexity/Computability/Complexity/Classes/P.lean +++ b/Complexity/Computability/Complexity/Classes/P.lean @@ -26,17 +26,12 @@ bounded functions of the length of the encoded instance definition, a polynomial time bound alone suffices (`Cslib.Complexity.mem_P_of_decidableInTimeAndSpace`). -Proofs usually build deciders with the tidy calculus, in which polynomial-time computability is -closed under composition. `Cslib.Complexity.mem_P_iff_tidy` states membership with a tidy decider -(`Turing.MultiTapeTM.ComputableTidilyInPolyTime`); the two notions agree -(`Turing.MultiTapeTM.computableInPolyTime_iff_computableTidilyInPolyTime`). - Mathlib's `Turing.TM2ComputableInPolyTime` is stated for Mathlib's stack machines; this file uses cslib's multi-tape machines, which carry the time and space measures the rest of the -development is built on. For finite working alphabets and injective word encoders, -`Turing.TM2ComputableInPolyTime.computableTidilyInPolyTime` in -`Complexity.Computability.Machines.Turing.TM2.PolyTime` transfers Mathlib certificates to tidy -polynomial time, and so to this notion, under the standard binary encodings of their words. +development is built on. For machines with finite stack alphabets, +`Turing.TM2ComputableInPolyTime.computableInPolyTime` in +`Complexity.Computability.Machines.Turing.TM2.Recoding` transfers Mathlib certificates over binary +encodings to this notion. ## Main definitions @@ -44,7 +39,6 @@ polynomial time, and so to this notion, under the standard binary encodings of t ## Main results -* `Cslib.Complexity.mem_P_iff_tidy`: `P` with tidy deciders. * `Cslib.Complexity.mem_P_iff_exists_decidableInTimeAndSpace`: `P` in terms of upstream `Turing.MultiTapeTM.DecidableInTimeAndSpace` with polynomially bounded time and space. * `Cslib.Complexity.mem_P_of_decidableInTimeAndSpace`: a polynomial time bound alone suffices. @@ -76,12 +70,6 @@ theorem mem_P {enc : α ↪ List Bool} {A : Set α} : A ∈ P enc ↔ ∃ f : α → Bool, ComputableInPolyTime f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := Iff.rfl -/-- `P` with tidy deciders, the form in which proofs build them. -/ -theorem mem_P_iff_tidy {enc : α ↪ List Bool} {A : Set α} : - A ∈ P enc ↔ - ∃ f : α → Bool, ComputableTidilyInPolyTime f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by - simp only [mem_P, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- **`P` in upstream terms:** `A ∈ P enc` exactly when some machine with a binary alphabet and finitely many states decides `A` within time and space bounded by polynomially bounded functions of the length of the encoded instance. -/ diff --git a/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean b/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean index 99fa26d67..0e95b5c30 100644 --- a/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean +++ b/Complexity/Computability/Complexity/Classes/PCP/ZeroRandomness.lean @@ -107,7 +107,7 @@ of the proof, where `n` is the length of the encoded instance and `p(n)` the len certificates, and runs the `NP` verifier on the bits read. -/ theorem exists_mem_PCP_zero_of_mem_NP {A : Set α} (hA : A ∈ NP enc) : ∃ k : ℕ, A ∈ PCP (fun _ => 0) (fun n => (n + 1) ^ k) enc := by - obtain ⟨p, V, hV, hver⟩ := mem_NP_iff_tidy.mp hA + obtain ⟨p, V, hV, hver⟩ := mem_NP.mp hA obtain ⟨c, k, hle⟩ := polynomiallyBounded_iff_le.mp (PolynomiallyBounded.polynomial_eval p) refine ⟨k, ⟨fun _ => 0, fun x => List.range (p.eval (enc x.1).length), fun y => V (y.1.1, y.2)⟩, 0, c, ⟨?_, ?_, ?_⟩, ?_, ?_, ?_, ?_⟩ @@ -123,7 +123,7 @@ theorem exists_mem_PCP_zero_of_mem_NP {A : Set α} (hA : A ∈ NP enc) : (ComputableTidilyInPolyTime.map ComputableTidilyInPolyTime.unary_to_binary).comp (ComputableTidilyInPolyTime.range.comp h1) · apply ComputableInPolyTime.of_tidy - exact hV.comp (((ComputableTidilyInPolyTime.fst enc encBits).comp + exact hV.tidy.comp (((ComputableTidilyInPolyTime.fst enc encBits).comp (ComputableTidilyInPolyTime.fst (encPair enc encBits) encBits)).pair (ComputableTidilyInPolyTime.snd (encPair enc encBits) encBits)) · intro a diff --git a/Complexity/Computability/Complexity/Classes/PH.lean b/Complexity/Computability/Complexity/Classes/PH.lean index d51ac907d..b4cb2a2c0 100644 --- a/Complexity/Computability/Complexity/Classes/PH.lean +++ b/Complexity/Computability/Complexity/Classes/PH.lean @@ -218,26 +218,12 @@ theorem mem_SigmaP : A ∈ SigmaP k enc ↔ IsAlternatingVerifier enc true ps V A := Iff.rfl -/-- `Cslib.Complexity.mem_SigmaP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_SigmaP_iff_tidy : A ∈ SigmaP k enc ↔ - ∃ (ps : List (Polynomial ℕ)) (V : α × List Bool → Bool), ps.length = k ∧ - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - IsAlternatingVerifier enc true ps V A := by - simp only [mem_SigmaP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_PiP : A ∈ PiP k enc ↔ ∃ (ps : List (Polynomial ℕ)) (V : α × List Bool → Bool), ps.length = k ∧ ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsAlternatingVerifier enc false ps V A := Iff.rfl -/-- `Cslib.Complexity.mem_PiP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_PiP_iff_tidy : A ∈ PiP k enc ↔ - ∃ (ps : List (Polynomial ℕ)) (V : α × List Bool → Bool), ps.length = k ∧ - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - IsAlternatingVerifier enc false ps V A := by - simp only [mem_PiP, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- A problem is in the polynomial hierarchy exactly when it is in some level `Σₖ`. -/ theorem mem_PH : A ∈ PH enc ↔ ∃ k, A ∈ SigmaP k enc := Set.mem_iUnion diff --git a/Complexity/Computability/Complexity/Classes/PH/Kannan.lean b/Complexity/Computability/Complexity/Classes/PH/Kannan.lean index 468d8ee0a..05c6a5f92 100644 --- a/Complexity/Computability/Complexity/Classes/PH/Kannan.lean +++ b/Complexity/Computability/Complexity/Classes/PH/Kannan.lean @@ -88,14 +88,15 @@ problem in `NP` on words, when the encoding has a decoder: the verifier decodes that it encodes what was decoded, and runs the verifier of the problem. -/ theorem mem_NP_image {β : Type} {encB : β ↪ List Bool} (D : Decoder encB) {B : Set β} (hB : B ∈ NP encB) : encB '' B ∈ NP encBits := by - obtain ⟨p, V, hV, hBV⟩ := mem_NP_iff_tidy.mp hB + obtain ⟨p, V, hV, hBV⟩ := mem_NP.mp hB obtain ⟨d, e, hD⟩ := D.computable have hdec : ComputableTidilyInPolyTime (fun x : List Bool × List Bool => D.decode x.1) (encPair encBits encBits) encB := hD.computableTidilyInPolyTime.comp (fst _ _) - refine mem_NP_iff_tidy.mpr + refine mem_NP.mpr ⟨p, fun x => decide (encB (D.decode x.1) = x.1) && V (D.decode x.1, x.2), - bool_and' (decide_eq' ((encode encB).comp hdec) (fst _ _)) (hV.comp (hdec.prod (snd _ _))), + .of_tidy (bool_and' (decide_eq' ((encode encB).comp hdec) (fst _ _)) + (hV.tidy.comp (hdec.prod (snd _ _)))), fun w => ?_⟩ simp only [encBits_apply, Bool.and_eq_true, decide_eq_true_eq] constructor diff --git a/Complexity/Computability/Complexity/Classes/PP.lean b/Complexity/Computability/Complexity/Classes/PP.lean index a958210cc..c1b06ae0d 100644 --- a/Complexity/Computability/Complexity/Classes/PP.lean +++ b/Complexity/Computability/Complexity/Classes/PP.lean @@ -36,7 +36,6 @@ characterisation by probabilistic machines is not proved here. ## Main results -* `Cslib.Complexity.mem_PP_iff_tidy`: membership through a tidy verifier. * `Cslib.Complexity.DecidesWithBoundedError.decidesByMajority`: bounded error gives a majority. * `Cslib.Complexity.BPP_subset_PP`. @@ -73,11 +72,6 @@ theorem mem_PP {A : Set α} : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesByMajority enc p V A := Iff.rfl -/-- `Cslib.Complexity.mem_PP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_PP_iff_tidy {A : Set α} : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesByMajority enc p V A := by - simp only [mem_PP, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- Bounded error gives a majority: a decider that is right on at least two thirds of the random strings accepts the members of its problem, and only them, on more than half. -/ theorem DecidesWithBoundedError.decidesByMajority {p : Polynomial ℕ} {V : α × List Bool → Bool} diff --git a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean index 126c1b8d6..5a856af13 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean @@ -103,8 +103,8 @@ theorem mem_PP_iff_decidesByNonstrictMajority {A : Set α} : have this : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p V A := by constructor · intro hA - obtain ⟨p, V, hV, h⟩ := mem_PP_iff_tidy.mp (compl_mem_PP hA) - refine ⟨p, fun x => !V x, ComputableTidilyInPolyTime.bool_not.comp hV, ?_⟩ + obtain ⟨p, V, hV, h⟩ := mem_PP.mp (compl_mem_PP hA) + refine ⟨p, fun x => !V x, ComputableTidilyInPolyTime.bool_not.comp hV.tidy, ?_⟩ simpa using decidesByMajority_iff_decidesByNonstrictMajority_compl.1 h · rintro ⟨p, V, hV, h⟩ have h' : DecidesByMajority enc p (fun x => !V x) Aᶜ := by @@ -121,17 +121,19 @@ of the encoded instance, and the ignored bits multiply both sides of the majorit the same power of two. -/ theorem PolyTimeReducible.mem_PP {β : Type} {encB : β ↪ List Bool} {A : Set α} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ PP encB) : A ∈ PP enc := by - rw [mem_PP_iff_tidy] at hB ⊢ - obtain ⟨f, hf, hAB⟩ := polyTimeReducible_iff_tidy.mp h + rw [Complexity.mem_PP] at hB ⊢ + obtain ⟨f, hf, hAB⟩ := h obtain ⟨q, W, hW, hWB⟩ := hB + have hf := hf.tidy + have hW := hW.tidy have hlen : ComputableTidilyInPolyTime (fun a => q.eval (encB (f a)).length) enc encUnary := (ComputableTidilyInPolyTime.unary_eval q).comp ((ComputableTidilyInPolyTime.encoding_length encB).comp hf) obtain ⟨p, hle⟩ := hlen.polyBounded.exists_polynomial refine ⟨p, andVerifier (fun a => q.eval (encB (f a)).length) (fun x => W (f x.1, x.2)) fun _ => true, - computableTidilyInPolyTime_andVerifier hlen - (hW.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits))) (.const true), + .of_tidy (computableTidilyInPolyTime_andVerifier hlen + (hW.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits))) (.const true)), fun a => ?_⟩ obtain ⟨j, hj⟩ := Nat.exists_eq_add_of_le (hle a) rw [hAB a, hWB (f a), hj, acceptCount_andVerifier_true, pow_add, ← mul_assoc] diff --git a/Complexity/Computability/Complexity/Classes/PP/Closure.lean b/Complexity/Computability/Complexity/Classes/PP/Closure.lean index 224924754..c45e278c8 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Closure.lean @@ -78,7 +78,7 @@ what the verifier accepts on `w` when `b₁ = true`. With `acc` accepted and `re of length `m`, this accepts `2 ^ m + 1 + 2 * rej` of the `4 * 2 ^ m` strings, more than half exactly when `2 * acc ≤ 2 ^ m`. -/ theorem compl_mem_PP (hA : A ∈ PP enc) : Aᶜ ∈ PP enc := by - rw [mem_PP_iff_tidy] at hA ⊢ + rw [mem_PP] at hA ⊢ obtain ⟨p, V, hV, hA⟩ := hA let V' (x : α × List Bool) : Bool := if x.2.headD false then !V (x.1, x.2.tail.tail) @@ -91,7 +91,7 @@ theorem compl_mem_PP (hA : A ∈ PP enc) : Aᶜ ∈ PP enc := by exact ComputableTidilyInPolyTime.cond ((ComputableTidilyInPolyTime.headD (encA := encBool) false).comp (.snd _ _)) (ComputableTidilyInPolyTime.bool_not.comp - (hV.comp ((ComputableTidilyInPolyTime.fst _ _).prod hw))) + (hV.comp (.of_tidy ((ComputableTidilyInPolyTime.fst _ _).prod hw))).tidy) (ComputableTidilyInPolyTime.bool_or.comp ((ComputableTidilyInPolyTime.bool_not.comp ((ComputableTidilyInPolyTime.headD (encA := encBool) false).comp @@ -99,7 +99,7 @@ theorem compl_mem_PP (hA : A ∈ PP enc) : Aᶜ ∈ PP enc := by (ComputableTidilyInPolyTime.bool_not.comp (ComputableTidilyInPolyTime.bitsAnyWithInput (test := fun _ b => b) hw (.snd _ _))))) - refine ⟨p + 2, V', hV', fun a => ?_⟩ + refine ⟨p + 2, V', (.of_tidy hV'), fun a => ?_⟩ -- exactly one word of length `m` is all zeros have hzero (m : ℕ) : (Finset.univ.filter fun w : Fin m → Bool => ((List.ofFn w).any fun b => b) = false).card = 1 := by diff --git a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean index d7122b471..a24b25de9 100644 --- a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean +++ b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean @@ -191,10 +191,8 @@ def PromiseP (enc : α ↪ List Bool) : Set (PromiseProblem α) := promiseClass /-- **Goldreich's definition of promise-P**: a promise problem is in `PromiseP` when a polynomial-time function solves it. -/ theorem mem_PromiseP_iff : - Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableInPolyTime f enc encBool ∧ Q.SolvedBy f := by - have this : Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableTidilyInPolyTime f enc encBool ∧ Q.SolvedBy f := - mem_promiseClass_iff_solvedBy fun _ => mem_P_iff_tidy - simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this + Q ∈ PromiseP enc ↔ ∃ f : α → Bool, ComputableInPolyTime f enc encBool ∧ Q.SolvedBy f := + mem_promiseClass_iff_solvedBy fun _ => mem_P @[simp] theorem ofSet_mem_PromiseP {A : Set α} : ofSet A ∈ PromiseP enc ↔ A ∈ P enc := ofSet_mem_promiseClass diff --git a/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean b/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean index 9155b1839..bd20091bc 100644 --- a/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Promise/Reduction.lean @@ -552,13 +552,6 @@ def PolyTimeReducible (encA : α ↪ List Bool) (encB : β ↪ List Bool) (X : P ∃ f : α → β, ComputableInPolyTime f encA encB ∧ Set.MapsTo f X.yes Y.yes ∧ Set.MapsTo f X.no Y.no -/-- Reductions of promise problems with a reduction computable tidily in polynomial time, the form -in which proofs build reductions. -/ -private theorem polyTimeReducible_iff_tidy : PolyTimeReducible encA encB X Y ↔ - ∃ f : α → β, ComputableTidilyInPolyTime f encA encB ∧ Set.MapsTo f X.yes Y.yes ∧ - Set.MapsTo f X.no Y.no := by - simp only [PolyTimeReducible, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- On decision problems, reductions of promise problems are polynomial-time reductions. -/ theorem polyTimeReducible_ofSet_iff {A : Set α} {B : Set β} : PolyTimeReducible encA encB (ofSet A) (ofSet B) ↔ Complexity.PolyTimeReducible encA encB A B := @@ -589,9 +582,9 @@ theorem PolyTimeReducible.of_subset (hyes : Y.yes ⊆ Y'.yes) (hno : Y.no ⊆ Y' /-- **`PromiseP` is closed under reductions.** -/ theorem PolyTimeReducible.mem_PromiseP (h : PolyTimeReducible encA encB X Y) (hY : Y ∈ PromiseP encB) : X ∈ PromiseP encA := by - obtain ⟨f, hf, hyes, hno⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨f, hf, hyes, hno⟩ := h obtain ⟨g, hg, hgyes, hgno⟩ := mem_PromiseP_iff.1 hY - exact mem_PromiseP_iff.2 ⟨g ∘ f, hg.comp (.of_tidy hf), fun a ha => hgyes _ (hyes ha), + exact mem_PromiseP_iff.2 ⟨g ∘ f, hg.comp hf, fun a ha => hgyes _ (hyes ha), fun a ha => hgno _ (hno ha)⟩ /-- A reduction of promise problems restricts to a polynomial-time reduction between the problems @@ -619,28 +612,28 @@ theorem PolyTimeReducible.mem_PromiseNP (h : PolyTimeReducible encA encB X Y) /-- **`PromiseBPP` is closed under polynomial-time reductions.** -/ theorem PolyTimeReducible.mem_PromiseBPP (h : PolyTimeReducible encA encB X Y) (hY : Y ∈ PromiseBPP encB) : X ∈ PromiseBPP encA := by - obtain ⟨f, hf, hfyes, hfno⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨f, hf, hfyes, hfno⟩ := h obtain ⟨M, hM, hyes, hno⟩ := mem_PromiseBPP_iff_exists_isPPTOn.mp hY exact mem_PromiseBPP_iff_exists_isPPTOn.mpr - ⟨fun a => M (f a), hM.preprocess hf, fun a ha => hyes (f a) (hfyes ha), + ⟨fun a => M (f a), hM.preprocess hf.tidy, fun a ha => hyes (f a) (hfyes ha), fun a ha => hno (f a) (hfno ha)⟩ /-- **`PromiseRP` is closed under polynomial-time reductions.** -/ theorem PolyTimeReducible.mem_PromiseRP (h : PolyTimeReducible encA encB X Y) (hY : Y ∈ PromiseRP encB) : X ∈ PromiseRP encA := by - obtain ⟨f, hf, hfyes, hfno⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨f, hf, hfyes, hfno⟩ := h obtain ⟨M, hM, hyes, hno⟩ := mem_PromiseRP_iff_exists_isPPTOn.mp hY exact mem_PromiseRP_iff_exists_isPPTOn.mpr - ⟨fun a => M (f a), hM.preprocess hf, fun a ha => hyes (f a) (hfyes ha), + ⟨fun a => M (f a), hM.preprocess hf.tidy, fun a ha => hyes (f a) (hfyes ha), fun a ha => hno (f a) (hfno ha)⟩ /-- **`PromiseCoRP` is closed under polynomial-time reductions.** -/ theorem PolyTimeReducible.mem_PromiseCoRP (h : PolyTimeReducible encA encB X Y) (hY : Y ∈ PromiseCoRP encB) : X ∈ PromiseCoRP encA := by - obtain ⟨f, hf, hfyes, hfno⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨f, hf, hfyes, hfno⟩ := h obtain ⟨M, hM, hyes, hno⟩ := mem_PromiseCoRP_iff_exists_isPPTOn.mp hY exact mem_PromiseCoRP_iff_exists_isPPTOn.mpr - ⟨fun a => M (f a), hM.preprocess hf, fun a ha => hyes (f a) (hfyes ha), + ⟨fun a => M (f a), hM.preprocess hf.tidy, fun a ha => hyes (f a) (hfyes ha), fun a ha => hno (f a) (hfno ha)⟩ /-! ### Randomized reductions with one-sided error -/ @@ -826,8 +819,8 @@ theorem rpReducible_iff_exists_seeded : reduction with soundness `1` (zero error). -/ theorem PolyTimeReducible.rpReducibleWithError (h : PolyTimeReducible encA encB X Y) : RPReducibleWithError encA encB (fun _ => 1) X Y := by - obtain ⟨f, hf, hyes, hno⟩ := polyTimeReducible_iff_tidy.mp h - refine ⟨fun a => pure (f a), hf.isPPTOn, fun a ha b hb => ?_, fun a ha => ?_⟩ + obtain ⟨f, hf, hyes, hno⟩ := h + refine ⟨fun a => pure (f a), hf.tidy.isPPTOn, fun a ha b hb => ?_, fun a ha => ?_⟩ · simp only [ProbComp.eval_pure, PMF.support_pure, Set.mem_singleton_iff] at hb exact hb ▸ hyes ha · have hmem : f a ∈ Y.no := hno ha @@ -934,8 +927,8 @@ theorem RPReducibleWithError.trans_polyTimeReducible {s : α → ℝ} (hXY : RPReducibleWithError encA encB s X Y) (hYZ : PolyTimeReducible encB encC Y Z) : RPReducibleWithError encA encC s X Z := by obtain ⟨R, hR, hyes, hno⟩ := hXY - obtain ⟨g, hg, gyes, gno⟩ := polyTimeReducible_iff_tidy.mp hYZ - refine ⟨fun a => g <$> R a, hR.map hg, fun a ha c hc => ?_, fun a ha => ?_⟩ + obtain ⟨g, hg, gyes, gno⟩ := hYZ + refine ⟨fun a => g <$> R a, hR.map hg.tidy, fun a ha c hc => ?_, fun a ha => ?_⟩ · simp only [ProbComp.eval_map, PMF.mem_support_map_iff] at hc obtain ⟨b, hb, rfl⟩ := hc exact gyes (hyes a ha b hb) diff --git a/Complexity/Computability/Complexity/Classes/RP.lean b/Complexity/Computability/Complexity/Classes/RP.lean index e09afdffe..162978254 100644 --- a/Complexity/Computability/Complexity/Classes/RP.lean +++ b/Complexity/Computability/Complexity/Classes/RP.lean @@ -44,7 +44,6 @@ Two runs reject a member with probability at most `1 / 4`, so `RP ⊆ BPP`. ## Main results -* `Cslib.Complexity.mem_RP_iff_tidy`: membership through a tidy verifier. * `Cslib.Complexity.RP_subset_NP`, `Cslib.Complexity.coRP_subset_coNP`. * `Cslib.Complexity.DecidesWithOneSidedError.repeatAny`: repetition reduces the error to `2 ^ (-q(n))`. @@ -92,12 +91,6 @@ theorem mem_RP {A : Set α} : A ∈ RP enc ↔ ∃ (p : Polynomial ℕ) (V : α DecidesWithOneSidedError enc p V A := Iff.rfl -/-- `Cslib.Complexity.mem_RP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_RP_iff_tidy {A : Set α} : A ∈ RP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - DecidesWithOneSidedError enc p V A := by - simp only [mem_RP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_coRP {A : Set α} : A ∈ coRP enc ↔ Aᶜ ∈ RP enc := Iff.rfl /-- A random string accepted by a one-sided-error decider is a certificate: one-sided error gives diff --git a/Complexity/Computability/Complexity/Classes/RP/Closure.lean b/Complexity/Computability/Complexity/Classes/RP/Closure.lean index b422b644f..f35f4dee7 100644 --- a/Complexity/Computability/Complexity/Classes/RP/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/RP/Closure.lean @@ -88,8 +88,8 @@ theorem ZPP_subset_NP_inter_coNP : ZPP enc ⊆ NP enc ∩ coNP enc := fun _ hA = /-- **`RP` is closed under union**: accept when the decider for either problem accepts, on disjoint parts of the random string. -/ theorem union_mem_RP {A B : Set α} (hA : A ∈ RP enc) (hB : B ∈ RP enc) : A ∪ B ∈ RP enc := by - obtain ⟨p₁, V₁, hV₁, h₁⟩ := mem_RP_iff_tidy.mp hA - obtain ⟨p₂, V₂, hV₂, h₂⟩ := mem_RP_iff_tidy.mp hB + obtain ⟨p₁, V₁, hV₁, h₁⟩ := mem_RP.mp hA + obtain ⟨p₂, V₂, hV₂, h₂⟩ := mem_RP.mp hB refine ⟨p₁ + p₂, orVerifier (fun a => p₁.eval (enc a).length) V₁ V₂, by fun_prop, fun a => ⟨fun ha => ?_, fun ha r => ?_⟩⟩ · change 2 ^ (p₁ + p₂).eval (enc a).length ≤ diff --git a/Complexity/Computability/Complexity/Classes/SBP.lean b/Complexity/Computability/Complexity/Classes/SBP.lean index 339fae4c6..5389978d3 100644 --- a/Complexity/Computability/Complexity/Classes/SBP.lean +++ b/Complexity/Computability/Complexity/Classes/SBP.lean @@ -36,7 +36,6 @@ are proved in `Complexity.Computability.Complexity.Classes.ArthurMerlin.Amplific ## Main results -* `Cslib.Complexity.mem_SBP_iff_tidy`: membership through a tidy threshold machine. * `Cslib.Complexity.NP_subset_SBP`, `Cslib.Complexity.BPP_subset_SBP`, `Cslib.Complexity.SBP_subset_PP`. * `Cslib.Complexity.union_mem_SBP`, `Cslib.Complexity.PolyTimeReducible.mem_SBP`: union and @@ -70,22 +69,16 @@ theorem mem_SBP : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, Co ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := Iff.rfl -/-- `Cslib.Complexity.mem_SBP` with a tidy threshold machine, for proofs that compose machines. -/ -theorem mem_SBP_iff_tidy : A ∈ SBP enc ↔ - ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ - ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by - simp only [mem_SBP, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- Replacing `(f, k)` by `(2f + 1, 2k + 1)` makes the threshold positive. -/ theorem mem_SBP_iff_exists_pos_threshold : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by have this : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by - rw [mem_SBP_iff_tidy] + rw [mem_SBP] constructor · rintro ⟨f, hf, k, hk, hA⟩ refine ⟨f + f + 1, SharpP.add_mem (SharpP.add_mem hf hf) SharpP.one_mem, - fun a => k a + k a + 1, by fun_prop, + fun a => k a + k a + 1, by have hk := hk.tidy; fun_prop, fun a => by positivity, fun a => ?_⟩ simp only [Pi.add_apply, Pi.one_apply] constructor @@ -96,7 +89,7 @@ theorem mem_SBP_iff_exists_pos_threshold : A ∈ SBP enc ↔ have := (hA a).2 ha lia · rintro ⟨f, hf, k, hk, -, hA⟩ - exact ⟨f, hf, k, hk, hA⟩ + exact ⟨f, hf, k, (.of_tidy hk), hA⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this /-- Threshold one recognizes precisely the positive #P counts. -/ diff --git a/Complexity/Computability/Complexity/Classes/SharpP.lean b/Complexity/Computability/Complexity/Classes/SharpP.lean index a9dbc66dc..c61dce990 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP.lean @@ -42,7 +42,6 @@ signed routing and the corresponding bidirectional `GapP` characterization. ## Main results -* `Cslib.Complexity.mem_SharpP_iff_tidy`: membership through a tidy verifier. * `Cslib.Complexity.mem_NP_iff_exists_SharpP`: `NP` consists of the supports of functions in `#P`. * `Cslib.Complexity.acceptCount_add`: counting accepted strings by their prefixes. * `Cslib.Complexity.acceptCount_zero`, `Cslib.Complexity.acceptCount_add_acceptCount_not`, @@ -159,13 +158,6 @@ theorem mem_SharpP {f : α → ℕ} : f ∈ SharpP enc ↔ ∃ (p : Polynomial ∀ a, f a = acceptCount V a (p.eval (enc a).length) := Iff.rfl -/-- `Cslib.Complexity.mem_SharpP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_SharpP_iff_tidy {f : α → ℕ} : - f ∈ SharpP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - ∀ a, f a = acceptCount V a (p.eval (enc a).length) := by - simp only [mem_SharpP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_GapP {g : α → ℤ} : g ∈ GapP enc ↔ ∃ f₁ ∈ SharpP enc, ∃ f₂ ∈ SharpP enc, ∀ a, g a = f₁ a - f₂ a := Iff.rfl diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean index 5ad4f59af..1d491867c 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean @@ -50,7 +50,8 @@ theorem SharpP.sum_bits_mem {f : α × List Bool → ℕ} {r : α → ℕ} (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∑ w : Fin (r a) → Bool, f (a, List.ofFn w)) ∈ SharpP enc := by have hr := hr.tidy - obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf + obtain ⟨p, V, hV, hf⟩ := mem_SharpP.mp hf + have hV := hV.tidy let q : α → ℕ := fun a => p.eval (2 * (enc a).length + 1 + r a) let W : α × List Bool → Bool := fun x => V ((x.1, x.2.take (r x.1)), x.2.drop (r x.1)) have hq : ComputableTidilyInPolyTime q enc encUnary := by dsimp [q]; fun_prop diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean b/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean index 1bc14d5f1..26054a307 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Closure.lean @@ -74,8 +74,8 @@ namespace SharpP the bits that the chosen verifier does not read must be `false`. -/ theorem add_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpP enc) (h₂ : f₂ ∈ SharpP enc) : f₁ + f₂ ∈ SharpP enc := by - obtain ⟨p₁, V₁, hV₁, hf₁⟩ := mem_SharpP_iff_tidy.mp h₁ - obtain ⟨p₂, V₂, hV₂, hf₂⟩ := mem_SharpP_iff_tidy.mp h₂ + obtain ⟨p₁, V₁, hV₁, hf₁⟩ := mem_SharpP.mp h₁ + obtain ⟨p₂, V₂, hV₂, hf₂⟩ := mem_SharpP.mp h₂ refine ⟨p₁ + p₂ + 1, selectVerifier (andVerifier (fun a => p₁.eval (enc a).length) V₁ allFalseVerifier) (andVerifier (fun a => p₂.eval (enc a).length) V₂ allFalseVerifier), by fun_prop, @@ -92,8 +92,8 @@ theorem add_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpP enc) (h₂ : f certificate. -/ theorem mul_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpP enc) (h₂ : f₂ ∈ SharpP enc) : f₁ * f₂ ∈ SharpP enc := by - obtain ⟨p₁, V₁, hV₁, hf₁⟩ := mem_SharpP_iff_tidy.mp h₁ - obtain ⟨p₂, V₂, hV₂, hf₂⟩ := mem_SharpP_iff_tidy.mp h₂ + obtain ⟨p₁, V₁, hV₁, hf₁⟩ := mem_SharpP.mp h₁ + obtain ⟨p₂, V₂, hV₂, hf₂⟩ := mem_SharpP.mp h₂ refine ⟨p₁ + p₂, andVerifier (fun a => p₁.eval (enc a).length) V₁ V₂, by fun_prop, fun a => ?_⟩ rw [Pi.mul_apply, hf₁ a, hf₂ a, Polynomial.eval_add, acceptCount_andVerifier] @@ -251,7 +251,8 @@ theorem SharpP.comp_mem {β : Type} {encB : β ↪ List Bool} {f : β → ℕ} { (hf : f ∈ SharpP encB) (hg : ComputableInPolyTime g enc encB) : f ∘ g ∈ SharpP enc := by have hg := hg.tidy - obtain ⟨q, W, hW, hWB⟩ := mem_SharpP_iff_tidy.mp hf + obtain ⟨q, W, hW, hWB⟩ := mem_SharpP.mp hf + have hW := hW.tidy have h := mem_SharpP_of_polyTime_length (V := fun x => W (g x.1, x.2)) (r := fun a => q.eval (encB (g a)).length) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean b/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean index db6f33b4e..b68ba2d2f 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean @@ -46,14 +46,10 @@ independent random choices [Arora and Barak, Chapters 7 and 17][AroraBarak09]. * `Cslib.Complexity.acceptCount_andVerifier`, `Cslib.Complexity.acceptCount_orVerifier`, `Cslib.Complexity.acceptCount_selectVerifier`: counts of the combined verifiers. -* `Cslib.Complexity.computableTidilyInPolyTime_andVerifier`, - `Cslib.Complexity.computableTidilyInPolyTime_orVerifier`, - `Cslib.Complexity.computableTidilyInPolyTime_selectVerifier`: the combined verifiers are - polynomial-time. * `Cslib.Complexity.computableInPolyTime_andVerifier`, `Cslib.Complexity.computableInPolyTime_orVerifier`, - `Cslib.Complexity.computableInPolyTime_selectVerifier`: plain `fun_prop` rules accepting plain - verifier hypotheses. + `Cslib.Complexity.computableInPolyTime_selectVerifier`: the combined verifiers are + polynomial-time. ## References diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean b/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean index 2044384de..ae0e64f93 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean @@ -24,8 +24,7 @@ Parsimonious reductions compose (`ParsimoniousReducible.trans`) and `#P` is clos ## Main definitions -* `Cslib.Complexity.ParsimoniousReducible`: parsimonious polynomial-time reductions, with - `Cslib.Complexity.parsimoniousReducible_iff_tidy` for tidily computable reductions. +* `Cslib.Complexity.ParsimoniousReducible`: parsimonious polynomial-time reductions. * `Cslib.Complexity.SharpPHard`, `Cslib.Complexity.SharpPComplete`. ## Main results @@ -56,13 +55,6 @@ def ParsimoniousReducible (encA : α ↪ List Bool) (encB : β ↪ List Bool) (f (g : β → ℕ) : Prop := ∃ r : α → β, ComputableInPolyTime r encA encB ∧ ∀ a, f a = g (r a) -/-- Parsimonious reducibility with a reduction computable tidily in polynomial time, the form in -which proofs build reductions. -/ -theorem parsimoniousReducible_iff_tidy {encA : α ↪ List Bool} {encB : β ↪ List Bool} {f : α → ℕ} - {g : β → ℕ} : ParsimoniousReducible encA encB f g ↔ - ∃ r : α → β, ComputableTidilyInPolyTime r encA encB ∧ ∀ a, f a = g (r a) := by - simp only [ParsimoniousReducible, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- Every function in `#P`, with any encoding of its instances, reduces parsimoniously to `g`. This is `HardUnder` for `ParsimoniousReducible`. -/ def SharpPHard (encB : β ↪ List Bool) (g : β → ℕ) : Prop := @@ -105,8 +97,8 @@ theorem ParsimoniousReducible.trans (hfg : ParsimoniousReducible encA encB f g) /-- **`#P` is closed under parsimonious reductions.** -/ theorem ParsimoniousReducible.mem_SharpP (hfg : ParsimoniousReducible encA encB f g) (hg : g ∈ SharpP encB) : f ∈ SharpP encA := by - obtain ⟨r, hr, hfg⟩ := parsimoniousReducible_iff_tidy.mp hfg - have h := SharpP.comp_mem hg (.of_tidy hr) + obtain ⟨r, hr, hfg⟩ := hfg + have h := SharpP.comp_mem hg hr rwa [show g ∘ r = f from funext fun a => (hfg a).symm] at h /-- `#P`-hardness transfers along a parsimonious reduction. -/ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Power.lean b/Complexity/Computability/Complexity/Classes/SharpP/Power.lean index cd896c1bd..42b52614a 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Power.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Power.lean @@ -74,10 +74,10 @@ theorem pow_mem_polyTime {f : α → ℕ} {r : α → ℕ} (hf : f ∈ SharpP en (hr : ComputableInPolyTime r enc encUnary) : (fun a => f a ^ r a) ∈ SharpP enc := by have hr := hr.tidy - obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf + obtain ⟨p, V, hV, hf⟩ := mem_SharpP.mp hf let k : α → ℕ := fun a => p.eval (enc a).length have hk : ComputableTidilyInPolyTime k enc encUnary := by dsimp [k]; fun_prop - convert mem_SharpP_of_polyTime_length (polyTime_powerVerifier (.of_tidy hr) (.of_tidy hk) (.of_tidy hV)) + convert mem_SharpP_of_polyTime_length (polyTime_powerVerifier (.of_tidy hr) (.of_tidy hk) hV) (.of_tidy (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk))) using 1 ext a change f a ^ r a = acceptCount (powerVerifier r k V) a (r a * k a) diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean index 5c5e5d3eb..42cf7ffc3 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean @@ -99,7 +99,7 @@ theorem prod_range_mem {f : α × ℕ → ℕ} {r : α → ℕ} (hr : ComputableInPolyTime r enc encUnary) : (fun a => ∏ i ∈ range (r a), f (a, i)) ∈ SharpP enc := by have hr := hr.tidy - obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf + obtain ⟨p, V, hV, hf⟩ := mem_SharpP.mp hf let width : α × ℕ → ℕ := fun x => p.eval ((encPair enc encUnary) x).length let k : α → ℕ := fun a => p.eval (2 * (enc a).length + 1 + r a) let W := andVerifier width V allFalseVerifier diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean index a50656e3f..b9c0e687d 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean @@ -177,8 +177,8 @@ theorem computableInPolySpace_acceptCount {V : α × List Bool → Bool} {r : α theorem SharpP.computableInPolySpace {f : α → ℕ} (hf : f ∈ SharpP enc) : Turing.MultiTapeTM.ComputableInPolySpace f enc encNat := by refine .of_tidy ?_ - obtain ⟨p, V, hV, hf⟩ := mem_SharpP_iff_tidy.mp hf - exact (computableInPolySpace_acceptCount (.of_tidy hV) (.of_tidy (by fun_prop))).tidy.congr fun a => (hf a).symm + obtain ⟨p, V, hV, hf⟩ := mem_SharpP.mp hf + exact (computableInPolySpace_acceptCount hV (.of_tidy (by fun_prop))).tidy.congr fun a => (hf a).symm /-- Every GapP function is computable in polynomial space with binary sign-magnitude output. -/ theorem GapP.computableInPolySpace {g : α → ℤ} (hg : g ∈ GapP enc) : diff --git a/Complexity/Computability/Complexity/Classes/Space.lean b/Complexity/Computability/Complexity/Classes/Space.lean index 44f9038cd..af6ff7c16 100644 --- a/Complexity/Computability/Complexity/Classes/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Space.lean @@ -132,7 +132,8 @@ def NPSPACE (enc : α ↪ List Bool) : Set (Set α) := /-- **Polynomial time is within polynomial space.** -/ theorem P_subset_PSPACE : P enc ⊆ PSPACE enc := fun A hA => by - obtain ⟨f, ⟨t, s, -, hs, hf⟩, hA⟩ := mem_P_iff_tidy.mp hA + obtain ⟨f, hf, hA⟩ := mem_P.mp hA + obtain ⟨t, s, -, hs, hf⟩ := hf.tidy exact ⟨f, ⟨t, s, hs, hf.computableInTimeAndSpace⟩, hA⟩ /-- **A deterministic polynomial-space machine is a nondeterministic one**, with one computation diff --git a/Complexity/Computability/Complexity/Classes/TFNP.lean b/Complexity/Computability/Complexity/Classes/TFNP.lean index 54ea5a325..dbfd1f304 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP.lean @@ -194,22 +194,10 @@ theorem mem_FNP : R ∈ FNP enc ↔ ∀ a w, R a w ↔ V (a, w) = true := Iff.rfl -/-- `FNP` with tidy verifiers, the form in which proofs build them. -/ -theorem mem_FNP_iff_tidy : R ∈ FNP enc ↔ - (∃ p : Polynomial ℕ, ∀ a w, R a w → w.length ≤ p.eval (enc a).length) ∧ - ∃ V : α × List Bool → Bool, ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ - ∀ a w, R a w ↔ V (a, w) = true := by - simp only [mem_FNP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_FPSearch : R ∈ FPSearch enc ↔ R ∈ FNP enc ∧ ∃ f : α → Option (List Bool), ComputableInPolyTime f enc (encOption encBits) ∧ SolvesSearch R f := Iff.rfl -/-- `FPSearch` with tidy solvers, the form in which proofs build them. -/ -theorem mem_FPSearch_iff_tidy : R ∈ FPSearch enc ↔ R ∈ FNP enc ∧ ∃ f : α → Option (List Bool), - ComputableTidilyInPolyTime f enc (encOption encBits) ∧ SolvesSearch R f := by - simp only [mem_FPSearch, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_TFNP : R ∈ TFNP enc ↔ R ∈ FNP enc ∧ IsTotalSearch R := Iff.rfl /-- Every search problem in `FPSearch` is in `FNP`. -/ @@ -226,15 +214,15 @@ theorem mem_FNP_iff_exists_bounded : R ∈ FNP enc ↔ ComputableInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by have this : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by - rw [mem_FNP_iff_tidy] + rw [mem_FNP] constructor · rintro ⟨⟨p, hp⟩, V, hV, hR⟩ - exact ⟨p, V, hV, fun a w => ⟨fun h => ⟨hp a w h, (hR a w).1 h⟩, fun h => (hR a w).2 h.2⟩⟩ + exact ⟨p, V, hV.tidy, fun a w => ⟨fun h => ⟨hp a w h, (hR a w).1 h⟩, fun h => (hR a w).2 h.2⟩⟩ · rintro ⟨p, V, hV, hR⟩ refine ⟨⟨p, fun a w h => ((hR a w).1 h).1⟩, fun x => decide (x.2.length ≤ p.eval (enc x.1).length) && V x, ?_, fun a w => ?_⟩ - · exact bool_and' (unary_le' (length_bits.comp (snd enc encBits)) - ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV + · exact .of_tidy (bool_and' (unary_le' (length_bits.comp (snd enc encBits)) + ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV) · simp only [hR a w, Bool.and_eq_true, decide_eq_true_eq] simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this @@ -259,9 +247,9 @@ attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **Domains of `FNP` relations are in `NP`**: a solution, framed and padded, is a certificate. -/ theorem searchDomain_mem_NP (hR : R ∈ FNP enc) : searchDomain R ∈ NP enc := by - obtain ⟨⟨p, hp⟩, V, hV, hR⟩ := mem_FNP_iff_tidy.mp hR + obtain ⟨⟨p, hp⟩, V, hV, hR⟩ := mem_FNP.mp hR exact mem_NP_of_witness (encW := encBits) ⟨fun w => w, fun _ => rfl, id'.exists_degree⟩ - (.of_tidy hV) + hV (fun a w => (hR a w).symm) fun a w h => ⟨w, h, hp a w h⟩ /-- The search problem of a verifier: the certificates of the prescribed length that it accepts. -/ @@ -274,10 +262,10 @@ theorem verifierSearch_mem_FNP {p : Polynomial ℕ} {V : α × List Bool → Boo (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : verifierSearch enc p V ∈ FNP enc := by have hV := hV.tidy - refine mem_FNP_iff_tidy.mpr ⟨⟨p, fun a w h => h.1.le⟩, + refine mem_FNP.mpr ⟨⟨p, fun a w h => h.1.le⟩, fun x => decide (x.2.length = p.eval (enc x.1).length) && V x, ?_, fun a w => ?_⟩ - · exact bool_and' (decide_eq' (length_bits.comp (snd enc encBits)) - ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV + · exact .of_tidy (bool_and' (decide_eq' (length_bits.comp (snd enc encBits)) + ((unary_eval p).comp ((encoding_length enc).comp (fst enc encBits)))) hV) · simp only [verifierSearch, Bool.and_eq_true, decide_eq_true_eq] /-- A verifier verifies exactly the domain of its search problem. -/ @@ -329,9 +317,11 @@ theorem searchDomain_searchSum : searchDomain (searchSum R S) = searchDomain R /-- `FNP` is closed under disjoint sums. -/ theorem searchSum_mem_FNP (hR : R ∈ FNP enc) (hS : S ∈ FNP enc) : searchSum R S ∈ FNP enc := by - obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP_iff_tidy.mp hR - obtain ⟨⟨q, hq⟩, W, hW, hSW⟩ := mem_FNP_iff_tidy.mp hS - refine mem_FNP_iff_tidy.mpr ⟨⟨p + q + 1, fun a w h => ?_⟩, + obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP.mp hR + obtain ⟨⟨q, hq⟩, W, hW, hSW⟩ := mem_FNP.mp hS + have hV := hV.tidy + have hW := hW.tidy + refine mem_FNP.mpr ⟨⟨p + q + 1, fun a w h => ?_⟩, fun x => !x.2.isEmpty && if x.2.headD false then V (x.1, x.2.tail) else W (x.1, x.2.tail), ?_, fun a w => ?_⟩ · simp only [Polynomial.eval_add, Polynomial.eval_one] @@ -347,7 +337,7 @@ theorem searchSum_mem_FNP (hR : R ∈ FNP enc) (hS : S ∈ FNP enc) : searchSum · have htail : ComputableTidilyInPolyTime (fun x : α × List Bool => (x.1, x.2.tail)) (encPair enc encBits) (encPair enc encBits) := (fst enc encBits).prod (bitsTail.comp (snd enc encBits)) - refine bool_and' (bool_not.comp ?_) (cond ?_ (hV.comp htail) (hW.comp htail)) + refine .of_tidy (bool_and' (bool_not.comp ?_) (cond ?_ (hV.comp htail) (hW.comp htail))) · fun_prop · fun_prop · match w with @@ -381,9 +371,9 @@ disjoint and `searchSum R S` is in `FPSearch`, the domain of `R` is in `P`: an i exactly when the solver returns a solution tagged `true`. -/ theorem searchDomain_mem_P_of_searchSum_mem_FPSearch (hRS : searchSum R S ∈ FPSearch enc) (hdisj : Disjoint (searchDomain R) (searchDomain S)) : searchDomain R ∈ P enc := by - obtain ⟨-, f, hf, hsolve⟩ := mem_FPSearch_iff_tidy.mp hRS - refine mem_P_iff_tidy.mpr ⟨fun a => ((f a).getD []).headD false, ?_, fun a => ?_⟩ - · have hget := optionGetDWithInput hf + obtain ⟨-, f, hf, hsolve⟩ := mem_FPSearch.mp hRS + refine mem_P.mpr ⟨fun a => ((f a).getD []).headD false, ?_, fun a => ?_⟩ + · have hget := optionGetDWithInput hf.tidy (const [] : ComputableTidilyInPolyTime (fun _ : α => ([] : List Bool)) enc encBits) fun_prop · change a ∈ searchDomain R ↔ ((f a).getD []).headD false = true @@ -418,16 +408,6 @@ def SearchReducible (encA : α ↪ List Bool) (encB : β ↪ List Bool) (R : α ComputableInPolyTime g (encPair encA encBits) encBits ∧ (∀ a, a ∈ searchDomain R → f a ∈ searchDomain S) ∧ ∀ a w, S (f a) w → R a (g (a, w)) -/-- Search reducibility with maps computable tidily in polynomial time, the form in which proofs -build reductions. -/ -theorem searchReducible_iff_tidy {encA : α ↪ List Bool} {encB : β ↪ List Bool} - {R : α → List Bool → Prop} {S : β → List Bool → Prop} : - SearchReducible encA encB R S ↔ ∃ (f : α → β) (g : α × List Bool → List Bool), - ComputableTidilyInPolyTime f encA encB ∧ - ComputableTidilyInPolyTime g (encPair encA encBits) encBits ∧ - (∀ a, a ∈ searchDomain R → f a ∈ searchDomain S) ∧ ∀ a w, S (f a) w → R a (g (a, w)) := by - simp only [SearchReducible, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- `S` is hard for the class `𝒞` of search problems under search reductions: every problem in `𝒞`, with any encoding of its instances, reduces to `S`. This is `HardUnder` for `SearchReducible`. -/ @@ -505,10 +485,11 @@ theorem SearchReducible.mem_TFNP (h : SearchReducible encA encB R T) (hR : R ∈ in `FPSearch` is in `FPSearch`. -/ theorem SearchReducible.mem_FPSearch (h : SearchReducible encA encB R T) (hR : R ∈ FNP encA) (hT : T ∈ FPSearch encB) : R ∈ FPSearch encA := by - obtain ⟨f, g, hf, hg, hdom, hsol⟩ := searchReducible_iff_tidy.mp h - obtain ⟨-, s, hs, hsolve⟩ := mem_FPSearch_iff_tidy.mp hT - refine mem_FPSearch_iff_tidy.mpr ⟨hR, fun a => (s (f a)).elim none fun w => some (g (a, w)), - optionElimWithInput (hs.comp hf) (const none) ((optionSome encBits).comp hg), + obtain ⟨f, g, hf, hg, hdom, hsol⟩ := h + obtain ⟨-, s, hs, hsolve⟩ := Complexity.mem_FPSearch.mp hT + refine Complexity.mem_FPSearch.mpr ⟨hR, fun a => (s (f a)).elim none fun w => some (g (a, w)), + .of_tidy (optionElimWithInput (hs.tidy.comp hf.tidy) (const none) + ((optionSome encBits).comp hg.tidy)), fun a => ⟨fun w ha => ?_, fun ha hR => ?_⟩⟩ · cases hsa : s (f a) with | none => simp [hsa] at ha diff --git a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean index e63dae212..e994ee609 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean @@ -88,15 +88,15 @@ def prefixSearch (R : α → List Bool → Prop) (x : α × List Bool) (v : List /-- The prefix problem of an `FNP` relation is in `FNP`. -/ theorem prefixSearch_mem_FNP (hR : R ∈ FNP enc) : prefixSearch R ∈ FNP (encPair enc encBits) := by - obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP_iff_tidy.mp hR - refine mem_FNP_iff_tidy.mpr + obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP.mp hR + refine mem_FNP.mpr ⟨⟨p, fun x v h => ?_⟩, fun y => V (y.1.1, y.1.2 ++ y.2), ?_, fun x v => hRV _ _⟩ · have h₁ := hp _ _ h have h₂ := Polynomial.eval_mono p (length_le_encPair_left enc encBits x) simp only [List.length_append] at h₁ omega - · exact hV.comp ((fst (encPair enc encBits) encBits).fst'.prod - (bitsAppend (fst (encPair enc encBits) encBits).snd' (snd (encPair enc encBits) encBits))) + · exact .of_tidy (hV.tidy.comp ((fst (encPair enc encBits) encBits).fst'.prod + (bitsAppend (fst (encPair enc encBits) encBits).snd' (snd (encPair enc encBits) encBits)))) /-! ### Search through prefixes -/ @@ -215,16 +215,16 @@ prefixes, and checks the result. -/ theorem FNP_subset_FPSearch_of_NP_subset_P (h : NP (encPair enc encBits) ⊆ P (encPair enc encBits)) : FNP enc ⊆ FPSearch enc := by intro R hR - obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP_iff_tidy.mp hR - obtain ⟨D, hD, hDR⟩ := mem_P_iff_tidy.mp - (h (searchDomain_mem_NP (prefixSearch_mem_FNP (mem_FNP_iff_tidy.mpr ⟨⟨p, hp⟩, V, hV, hRV⟩)))) + obtain ⟨⟨p, hp⟩, V, hV, hRV⟩ := mem_FNP.mp hR + obtain ⟨D, hD, hDR⟩ := mem_P.mp + (h (searchDomain_mem_NP (prefixSearch_mem_FNP (mem_FNP.mpr ⟨⟨p, hp⟩, V, hV, hRV⟩)))) let n : α → ℕ := fun a => p.eval (enc a).length have hn : ComputableTidilyInPolyTime n enc encUnary := (unary_eval p).comp (encoding_length enc) - have hrun := computableTidilyInPolyTime_prefixSearchRun hV hD hn - refine mem_FPSearch_iff_tidy.mpr - ⟨mem_FNP_iff_tidy.mpr ⟨⟨p, hp⟩, V, hV, hRV⟩, fun a => if V (a, prefixSearchRun V D n a) then + have hrun := computableTidilyInPolyTime_prefixSearchRun hV.tidy hD.tidy hn + refine mem_FPSearch.mpr + ⟨mem_FNP.mpr ⟨⟨p, hp⟩, V, hV, hRV⟩, fun a => if V (a, prefixSearchRun V D n a) then some (prefixSearchRun V D n a) else none, ?_, fun a => ?_⟩ - · exact cond (hV.comp (id'.prod hrun)) ((optionSome encBits).comp hrun) (const none) + · exact .of_tidy (cond (hV.tidy.comp (id'.prod hrun)) ((optionSome encBits).comp hrun) (const none)) · have hcorrect := rel_prefixSearchRun hRV (fun a u => (hDR (a, u)).symm) hp (a := a) constructor · intro w hw @@ -274,12 +274,13 @@ theorem searchDomain_searchRel : searchDomain searchRel = SAT := by when `SAT ∈ P`. -/ theorem searchRel_mem_FPSearch_iff : searchRel ∈ FPSearch encCNF ↔ SAT ∈ P encCNF := by refine ⟨fun h => searchDomain_searchRel ▸ searchDomain_mem_P h, fun h => ?_⟩ - obtain ⟨D, hD, hSAT⟩ := mem_P_iff_tidy.mp h + obtain ⟨D, hD, hSAT⟩ := mem_P.mp h have hsearch : ComputableTidilyInPolyTime (search D) encCNF encBits := - (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (snd _ _))) (.of_tidy id')).tidy - refine mem_FPSearch_iff_tidy.mpr + (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.tidy.comp (snd _ _))) (.of_tidy id')).tidy + refine mem_FPSearch.mpr ⟨searchRel_mem_FNP, fun φ => if D φ then some (search D φ) else none, - cond hD ((optionSome encBits).comp hsearch) (const none), fun φ => ⟨fun w hw => ?_, ?_⟩⟩ + .of_tidy (cond hD.tidy ((optionSome encBits).comp hsearch) (const none)), + fun φ => ⟨fun w hw => ?_, ?_⟩⟩ · beta_reduce at hw split_ifs at hw with hDφ cases Option.some_injective _ hw diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean index 826278b9e..1e7063fd9 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean @@ -44,10 +44,8 @@ Each class is defined via *uniform polynomial-time families* on the instance typ bit-length `n : α → ℕ` is computable in polynomial time in unary (`encUnary`), and the neighbor, successor, predecessor or cost maps are computable in polynomial time on pairs `encPair enc encBits` (with costs in binary `encNat`), in the sense of -`Turing.MultiTapeTM.ComputableInPolyTime`. `Cslib.Complexity.mem_PLS_iff_tidy` and its analogues -state membership with tidy certificates (`Turing.MultiTapeTM.ComputableTidilyInPolyTime`), the -form in which proofs build families. By pulling a family back along the instance map of a search -reduction, each class is closed under `SearchReducible` across arbitrary encoded instance types +`Turing.MultiTapeTM.ComputableInPolyTime`. By pulling a family back along the instance map of a +search reduction, each class is closed under `SearchReducible` across arbitrary encoded instance types (`SearchReducible.mem_PLS`, `.mem_PPP`, `.mem_PPAD`, `.mem_PPA`). The canonical circuit-presented problems `LocalOpt`, `Pigeon`, `EndOfLine` and `Leaf`, whose @@ -63,9 +61,7 @@ local search, the numerical cost values through fixed-width binary words with le ## Main definitions -* `Cslib.Complexity.PLS`, `Cslib.Complexity.PPP`, `Cslib.Complexity.PPAD`, `Cslib.Complexity.PPA`, - with `Cslib.Complexity.mem_PLS_iff_tidy`, `Cslib.Complexity.mem_PPP_iff_tidy`, - `Cslib.Complexity.mem_PPAD_iff_tidy` and `Cslib.Complexity.mem_PPA_iff_tidy`. +* `Cslib.Complexity.PLS`, `Cslib.Complexity.PPP`, `Cslib.Complexity.PPAD`, `Cslib.Complexity.PPA`. * `Cslib.Complexity.padBits`, `Cslib.Complexity.evalCircuitOutputs`, `Cslib.Complexity.evalCircuitCode`: circuit-code evaluation normalized to `n`-bit strings. * `Cslib.Complexity.CircuitCode`, `Cslib.Complexity.encPigeon`, `Cslib.Complexity.encLocalOpt`, @@ -340,7 +336,7 @@ theorem pigeonRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × L have hn := hn.tidy have hF := hF.tidy obtain ⟨p, hp⟩ := hn.polyBounded.exists_polynomial - refine mem_FNP_iff_tidy.mpr ⟨⟨2 * p, fun a w h => by + refine mem_FNP.mpr ⟨⟨2 * p, fun a w h => by simp only [Polynomial.eval_mul, Polynomial.eval_ofNat] have := hp a; have := h.1; omega⟩, fun x => decide (x.2.length = 2 * n x.1) && @@ -351,7 +347,7 @@ theorem pigeonRel_mem_FNP {enc : α ↪ List Bool} {n : α → ℕ} {F : α × L · have h2 : ComputableTidilyInPolyTime (fun x : α × List Bool => 2 * n x.1) (encPair enc encBits) encUnary := unary_mul.comp ((const 2).prod (hn.comp (fst enc encBits))) - refine bool_and' (decide_eq' (length_bits.comp (snd enc encBits)) h2) ?_ + refine .of_tidy (bool_and' (decide_eq' (length_bits.comp (snd enc encBits)) h2) ?_) fun_prop · simp [pigeonRel] @@ -481,16 +477,6 @@ theorem mem_PLS : R ∈ PLS enc ↔ R ∈ FNP enc ∧ SearchReducible enc enc R (localOptRel n N C) := Iff.rfl -/-- `PLS` with tidy local-search families, the form in which proofs build them. -/ -theorem mem_PLS_iff_tidy : R ∈ PLS enc ↔ R ∈ FNP enc ∧ - ∃ (n : α → ℕ) (N : α × List Bool → List Bool) (C : α × List Bool → ℕ), - ComputableTidilyInPolyTime n enc encUnary ∧ - ComputableTidilyInPolyTime N (encPair enc encBits) encBits ∧ - ComputableTidilyInPolyTime C (encPair enc encBits) encNat ∧ - (∀ a u, u.length = n a → (N (a, u)).length = n a) ∧ - SearchReducible enc enc R (localOptRel n N C) := by - simp only [mem_PLS, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_PPP : R ∈ PPP enc ↔ R ∈ FNP enc ∧ ∃ (n : α → ℕ) (F : α × List Bool → List Bool), ComputableInPolyTime n enc encUnary ∧ @@ -499,15 +485,6 @@ theorem mem_PPP : R ∈ PPP enc ↔ R ∈ FNP enc ∧ SearchReducible enc enc R (pigeonRel n F) := Iff.rfl -/-- `PPP` with tidy pigeonhole families, the form in which proofs build them. -/ -theorem mem_PPP_iff_tidy : R ∈ PPP enc ↔ R ∈ FNP enc ∧ - ∃ (n : α → ℕ) (F : α × List Bool → List Bool), - ComputableTidilyInPolyTime n enc encUnary ∧ - ComputableTidilyInPolyTime F (encPair enc encBits) encBits ∧ - (∀ a u, u.length = n a → (F (a, u)).length = n a) ∧ - SearchReducible enc enc R (pigeonRel n F) := by - simp only [mem_PPP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_PPAD : R ∈ PPAD enc ↔ R ∈ FNP enc ∧ ∃ (n : α → ℕ) (P S : α × List Bool → List Bool), ComputableInPolyTime n enc encUnary ∧ @@ -518,17 +495,6 @@ theorem mem_PPAD : R ∈ PPAD enc ↔ R ∈ FNP enc ∧ SearchReducible enc enc R (endOfLineRel n P S) := Iff.rfl -/-- `PPAD` with tidy end-of-line families, the form in which proofs build them. -/ -theorem mem_PPAD_iff_tidy : R ∈ PPAD enc ↔ R ∈ FNP enc ∧ - ∃ (n : α → ℕ) (P S : α × List Bool → List Bool), - ComputableTidilyInPolyTime n enc encUnary ∧ - ComputableTidilyInPolyTime P (encPair enc encBits) encBits ∧ - ComputableTidilyInPolyTime S (encPair enc encBits) encBits ∧ - (∀ a u, u.length = n a → (P (a, u)).length = n a) ∧ - (∀ a u, u.length = n a → (S (a, u)).length = n a) ∧ - SearchReducible enc enc R (endOfLineRel n P S) := by - simp only [mem_PPAD, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_PPA : R ∈ PPA enc ↔ R ∈ FNP enc ∧ ∃ (n : α → ℕ) (N₁ N₂ : α × List Bool → List Bool), ComputableInPolyTime n enc encUnary ∧ @@ -539,17 +505,6 @@ theorem mem_PPA : R ∈ PPA enc ↔ R ∈ FNP enc ∧ SearchReducible enc enc R (leafRel n N₁ N₂) := Iff.rfl -/-- `PPA` with tidy parity families, the form in which proofs build them. -/ -theorem mem_PPA_iff_tidy : R ∈ PPA enc ↔ R ∈ FNP enc ∧ - ∃ (n : α → ℕ) (N₁ N₂ : α × List Bool → List Bool), - ComputableTidilyInPolyTime n enc encUnary ∧ - ComputableTidilyInPolyTime N₁ (encPair enc encBits) encBits ∧ - ComputableTidilyInPolyTime N₂ (encPair enc encBits) encBits ∧ - (∀ a u, u.length = n a → (N₁ (a, u)).length = n a) ∧ - (∀ a u, u.length = n a → (N₂ (a, u)).length = n a) ∧ - SearchReducible enc enc R (leafRel n N₁ N₂) := by - simp only [mem_PPA, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- Every uniform polynomial-time local-search family is in `PLS`. -/ theorem localOptRel_mem_PLS {n : α → ℕ} {N : α × List Bool → List Bool} {C : α × List Bool → ℕ} (hn : ComputableInPolyTime n enc encUnary) @@ -557,10 +512,7 @@ theorem localOptRel_mem_PLS {n : α → ℕ} {N : α × List Bool → List Bool} (hC : ComputableInPolyTime C (encPair enc encBits) encNat) (hlen : ∀ a u, u.length = n a → (N (a, u)).length = n a) : localOptRel n N C ∈ PLS enc := by - have hn := hn.tidy - have hN := hN.tidy - have hC := hC.tidy - exact mem_PLS_iff_tidy.mpr ⟨localOptRel_mem_FNP (.of_tidy hn) (.of_tidy hN) (.of_tidy hC), n, N, C, hn, hN, hC, hlen, .refl _ _⟩ + exact mem_PLS.mpr ⟨localOptRel_mem_FNP hn hN hC, n, N, C, hn, hN, hC, hlen, .refl _ _⟩ /-- Every uniform polynomial-time pigeonhole family is in `PPP`. -/ theorem pigeonRel_mem_PPP {n : α → ℕ} {F : α × List Bool → List Bool} @@ -568,9 +520,7 @@ theorem pigeonRel_mem_PPP {n : α → ℕ} {F : α × List Bool → List Bool} (hF : ComputableInPolyTime F (encPair enc encBits) encBits) (hlen : ∀ a u, u.length = n a → (F (a, u)).length = n a) : pigeonRel n F ∈ PPP enc := by - have hn := hn.tidy - have hF := hF.tidy - exact mem_PPP_iff_tidy.mpr ⟨pigeonRel_mem_FNP (.of_tidy hn) (.of_tidy hF), n, F, hn, hF, hlen, .refl _ _⟩ + exact mem_PPP.mpr ⟨pigeonRel_mem_FNP hn hF, n, F, hn, hF, hlen, .refl _ _⟩ /-- Every uniform polynomial-time directed end-of-line family is in `PPAD`. -/ theorem endOfLineRel_mem_PPAD {n : α → ℕ} {P S : α × List Bool → List Bool} @@ -580,11 +530,8 @@ theorem endOfLineRel_mem_PPAD {n : α → ℕ} {P S : α × List Bool → List B (hP_len : ∀ a u, u.length = n a → (P (a, u)).length = n a) (hS_len : ∀ a u, u.length = n a → (S (a, u)).length = n a) : endOfLineRel n P S ∈ PPAD enc := by - have hn := hn.tidy - have hP := hP.tidy - have hS := hS.tidy - exact mem_PPAD_iff_tidy.mpr - ⟨endOfLineRel_mem_FNP (.of_tidy hn) (.of_tidy hP) (.of_tidy hS), n, P, S, hn, hP, hS, hP_len, hS_len, .refl _ _⟩ + exact mem_PPAD.mpr + ⟨endOfLineRel_mem_FNP hn hP hS, n, P, S, hn, hP, hS, hP_len, hS_len, .refl _ _⟩ /-- Every uniform polynomial-time undirected parity family is in `PPA`. -/ theorem leafRel_mem_PPA {n : α → ℕ} {N₁ N₂ : α × List Bool → List Bool} @@ -594,61 +541,58 @@ theorem leafRel_mem_PPA {n : α → ℕ} {N₁ N₂ : α × List Bool → List B (hN₁_len : ∀ a u, u.length = n a → (N₁ (a, u)).length = n a) (hN₂_len : ∀ a u, u.length = n a → (N₂ (a, u)).length = n a) : leafRel n N₁ N₂ ∈ PPA enc := by - have hn := hn.tidy - have hN₁ := hN₁.tidy - have hN₂ := hN₂.tidy - exact mem_PPA_iff_tidy.mpr - ⟨leafRel_mem_FNP (.of_tidy hn) (.of_tidy hN₁) (.of_tidy hN₂), n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, .refl _ _⟩ + exact mem_PPA.mpr + ⟨leafRel_mem_FNP hn hN₁ hN₂, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, .refl _ _⟩ /-! ### Closure under search reductions -/ /-- `PLS` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PLS (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) (hT : T ∈ PLS encB) : R ∈ PLS enc := by - obtain ⟨-, n, N, C, hn, hN, hC, hlen, hT_red⟩ := mem_PLS_iff_tidy.mp hT - obtain ⟨f, g, hf, hg, -, hsol⟩ := searchReducible_iff_tidy.mp (h.trans hT_red) - refine mem_PLS_iff_tidy.mpr ⟨hR, n ∘ f, fun p => N (f p.1, p.2), fun p => C (f p.1, p.2), - hn.comp hf, hN.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), - hC.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), + obtain ⟨-, n, N, C, hn, hN, hC, hlen, hT_red⟩ := Complexity.mem_PLS.mp hT + obtain ⟨f, g, hf, hg, -, hsol⟩ := (h.trans hT_red) + refine Complexity.mem_PLS.mpr ⟨hR, n ∘ f, fun p => N (f p.1, p.2), fun p => C (f p.1, p.2), + hn.comp hf, hN.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), + hC.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), fun a u hu => hlen (f a) u hu, .of_isTotalSearch (isTotalSearch_localOptRel fun a u hu => hlen (f a) u hu) - (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ + (.of_tidy id') hg fun a w hw => hsol a w hw⟩ /-- `PPP` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPP (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) (hT : T ∈ PPP encB) : R ∈ PPP enc := by - obtain ⟨-, n, F, hn, hF, hlen, hT_red⟩ := mem_PPP_iff_tidy.mp hT - obtain ⟨f, g, hf, hg, -, hsol⟩ := searchReducible_iff_tidy.mp (h.trans hT_red) - refine mem_PPP_iff_tidy.mpr ⟨hR, n ∘ f, fun p => F (f p.1, p.2), - hn.comp hf, hF.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), + obtain ⟨-, n, F, hn, hF, hlen, hT_red⟩ := Complexity.mem_PPP.mp hT + obtain ⟨f, g, hf, hg, -, hsol⟩ := (h.trans hT_red) + refine Complexity.mem_PPP.mpr ⟨hR, n ∘ f, fun p => F (f p.1, p.2), + hn.comp hf, hF.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), fun a u hu => hlen (f a) u hu, .of_isTotalSearch (isTotalSearch_pigeonRel fun a u hu => hlen (f a) u hu) - (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ + (.of_tidy id') hg fun a w hw => hsol a w hw⟩ /-- `PPAD` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPAD (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) (hT : T ∈ PPAD encB) : R ∈ PPAD enc := by - obtain ⟨-, n, P, S, hn, hP, hS, hP_len, hS_len, hT_red⟩ := mem_PPAD_iff_tidy.mp hT - obtain ⟨f, g, hf, hg, -, hsol⟩ := searchReducible_iff_tidy.mp (h.trans hT_red) - refine mem_PPAD_iff_tidy.mpr ⟨hR, n ∘ f, fun p => P (f p.1, p.2), fun p => S (f p.1, p.2), - hn.comp hf, hP.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), - hS.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), + obtain ⟨-, n, P, S, hn, hP, hS, hP_len, hS_len, hT_red⟩ := Complexity.mem_PPAD.mp hT + obtain ⟨f, g, hf, hg, -, hsol⟩ := (h.trans hT_red) + refine Complexity.mem_PPAD.mpr ⟨hR, n ∘ f, fun p => P (f p.1, p.2), fun p => S (f p.1, p.2), + hn.comp hf, hP.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), + hS.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), fun a u hu => hP_len (f a) u hu, fun a u hu => hS_len (f a) u hu, .of_isTotalSearch (isTotalSearch_endOfLineRel fun a u hu => hS_len (f a) u hu) - (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ + (.of_tidy id') hg fun a w hw => hsol a w hw⟩ /-- `PPA` is closed under polynomial-time search reductions across arbitrary instance types. -/ theorem SearchReducible.mem_PPA (h : SearchReducible enc encB R T) (hR : R ∈ FNP enc) (hT : T ∈ PPA encB) : R ∈ PPA enc := by - obtain ⟨-, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, hT_red⟩ := mem_PPA_iff_tidy.mp hT - obtain ⟨f, g, hf, hg, -, hsol⟩ := searchReducible_iff_tidy.mp (h.trans hT_red) - refine mem_PPA_iff_tidy.mpr ⟨hR, n ∘ f, fun p => N₁ (f p.1, p.2), fun p => N₂ (f p.1, p.2), - hn.comp hf, hN₁.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), - hN₂.comp ((hf.comp (fst enc encBits)).prod (snd enc encBits)), + obtain ⟨-, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, hT_red⟩ := Complexity.mem_PPA.mp hT + obtain ⟨f, g, hf, hg, -, hsol⟩ := (h.trans hT_red) + refine Complexity.mem_PPA.mpr ⟨hR, n ∘ f, fun p => N₁ (f p.1, p.2), fun p => N₂ (f p.1, p.2), + hn.comp hf, hN₁.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), + hN₂.comp ((hf.comp (.fst enc encBits)).prod (.snd enc encBits)), fun a u hu => hN₁_len (f a) u hu, fun a u hu => hN₂_len (f a) u hu, .of_isTotalSearch (isTotalSearch_leafRel (fun a u hu => hN₁_len (f a) u hu) (fun a u hu => hN₂_len (f a) u hu)) - (.of_tidy id') (.of_tidy hg) fun a w hw => hsol a w hw⟩ + (.of_tidy id') hg fun a w hw => hsol a w hw⟩ /-! ### Inclusions in `TFNP` and between subclasses -/ @@ -689,13 +633,13 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in problem in `PPAD` is in `PPP`. -/ theorem PPAD_subset_PPP : PPAD enc ⊆ PPP enc := by intro R hR' - obtain ⟨hR, n, P, S, hn, hP, hS, -, hS_len, hred⟩ := mem_PPAD_iff_tidy.mp hR' + obtain ⟨hR, n, P, S, hn, hP, hS, -, hS_len, hred⟩ := mem_PPAD.mp hR' have hF : ComputableTidilyInPolyTime (ppadToPppMap n P S) (encPair enc encBits) encBits := by unfold ppadToPppMap fun_prop - exact mem_PPP_iff_tidy.mpr ⟨hR, n, ppadToPppMap n P S, hn, hF, + exact mem_PPP.mpr ⟨hR, n, ppadToPppMap n P S, hn, (.of_tidy hF), fun a u hu => length_ppadToPppMap (hS_len a) hu, - hred.trans (endOfLineRel_searchReducible_pigeonRel hn hP hS hS_len)⟩ + hred.trans (endOfLineRel_searchReducible_pigeonRel hn.tidy hP.tidy hS.tidy hS_len)⟩ /-- Every directed end-of-line family search-reduces to its associated bipartite undirected parity family. -/ @@ -715,7 +659,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in /-- **`PPAD ⊆ PPA`** [Papadimitriou][Papadimitriou1994PPAD]: every problem in `PPAD` is in `PPA`. -/ theorem PPAD_subset_PPA : PPAD enc ⊆ PPA enc := by intro R hR' - obtain ⟨hR, n, P, S, hn, hP, hS, hP_len, hS_len, hred⟩ := mem_PPAD_iff_tidy.mp hR' + obtain ⟨hR, n, P, S, hn, hP, hS, hP_len, hS_len, hred⟩ := mem_PPAD.mp hR' have hn' : ComputableTidilyInPolyTime (fun a => n a + 1) enc encUnary := by fun_prop have hN₁ : ComputableTidilyInPolyTime (ppadToPpaN₁ n P S) (encPair enc encBits) encBits := by unfold ppadToPpaN₁ @@ -723,8 +667,8 @@ theorem PPAD_subset_PPA : PPAD enc ⊆ PPA enc := by have hN₂ : ComputableTidilyInPolyTime (ppadToPpaN₂ n P S) (encPair enc encBits) encBits := by unfold ppadToPpaN₂ isActiveNonZero fun_prop - exact mem_PPA_iff_tidy.mpr - ⟨hR, fun a => n a + 1, ppadToPpaN₁ n P S, ppadToPpaN₂ n P S, hn', hN₁, hN₂, + exact mem_PPA.mpr + ⟨hR, fun a => n a + 1, ppadToPpaN₁ n P S, ppadToPpaN₂ n P S, (.of_tidy hn'), (.of_tidy hN₁), (.of_tidy hN₂), fun a _ hw => length_ppadToPpaN₁ (hP_len a) (hS_len a) hw, fun _ _ hw => length_ppadToPpaN₂ hw, hred.trans (endOfLineRel_searchReducible_leafRel hP_len hS_len)⟩ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean index 09cf1e121..873fd6671 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean @@ -217,25 +217,25 @@ theorem localOptRel_searchReducible_LocalOpt {n : α → ℕ} /-- Circuit `Pigeon` is complete for `PPP` under polynomial-time search reductions. -/ theorem Pigeon_searchComplete : SearchComplete @PPP encPigeon Pigeon := by refine ⟨Pigeon_mem_PPP, fun _ enc R hR => ?_⟩ - obtain ⟨-, n, F, hn, hF, hlen, hred⟩ := mem_PPP_iff_tidy.mp hR - exact hred.trans (pigeonRel_searchReducible_Pigeon (.of_tidy hn) (.of_tidy hF) hlen) + obtain ⟨-, n, F, hn, hF, hlen, hred⟩ := mem_PPP.mp hR + exact hred.trans (pigeonRel_searchReducible_Pigeon hn hF hlen) /-- Circuit `EndOfLine` is complete for `PPAD` under polynomial-time search reductions. -/ theorem EndOfLine_searchComplete : SearchComplete @PPAD encEndOfLine EndOfLine := by refine ⟨EndOfLine_mem_PPAD, fun _ enc R hR => ?_⟩ - obtain ⟨-, n, P, S, hn, hP, hS, hP_len, hS_len, hred⟩ := mem_PPAD_iff_tidy.mp hR - exact hred.trans (endOfLineRel_searchReducible_EndOfLine (.of_tidy hn) (.of_tidy hP) (.of_tidy hS) hP_len hS_len) + obtain ⟨-, n, P, S, hn, hP, hS, hP_len, hS_len, hred⟩ := mem_PPAD.mp hR + exact hred.trans (endOfLineRel_searchReducible_EndOfLine hn hP hS hP_len hS_len) /-- Circuit `Leaf` is complete for `PPA` under polynomial-time search reductions. -/ theorem Leaf_searchComplete : SearchComplete @PPA encLeaf Leaf := by refine ⟨Leaf_mem_PPA, fun _ enc R hR => ?_⟩ - obtain ⟨-, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, hred⟩ := mem_PPA_iff_tidy.mp hR - exact hred.trans (leafRel_searchReducible_Leaf (.of_tidy hn) (.of_tidy hN₁) (.of_tidy hN₂) hN₁_len hN₂_len) + obtain ⟨-, n, N₁, N₂, hn, hN₁, hN₂, hN₁_len, hN₂_len, hred⟩ := mem_PPA.mp hR + exact hred.trans (leafRel_searchReducible_Leaf hn hN₁ hN₂ hN₁_len hN₂_len) /-- Circuit `LocalOpt` is complete for `PLS` under polynomial-time search reductions. -/ theorem LocalOpt_searchComplete : SearchComplete @PLS encLocalOpt LocalOpt := by refine ⟨LocalOpt_mem_PLS, fun _ enc R hR => ?_⟩ - obtain ⟨-, n, N, C, hn, hN, hC, hlen, hred⟩ := mem_PLS_iff_tidy.mp hR - exact hred.trans (localOptRel_searchReducible_LocalOpt (.of_tidy hn) (.of_tidy hN) (.of_tidy hC) hlen) + obtain ⟨-, n, N, C, hn, hN, hC, hlen, hred⟩ := mem_PLS.mp hR + exact hred.trans (localOptRel_searchReducible_LocalOpt hn hN hC hlen) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Time.lean b/Complexity/Computability/Complexity/Classes/Time.lean index bb9731e4b..ba62b4dfa 100644 --- a/Complexity/Computability/Complexity/Classes/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Time.lean @@ -76,7 +76,7 @@ within time and space `O(t' m)` ## Main results * `Cslib.Complexity.DTIME_mono_of_le_mul_add`: `DTIME` absorbs constant factors. -* `Cslib.Complexity.computableInO_indicator_of_mem_DTIME`: a tidy decider within the +* `Cslib.Complexity.computableInO_indicator_of_mem_DTIME`: a decider within the same time and space bounds up to constants. * `Cslib.Complexity.preimage_mem_DTIME`: `DTIME` under timed reductions. * `Cslib.Complexity.DTIME_mono_of_eventually_le`, `Cslib.Complexity.NTIME_mono_of_eventually_le`, @@ -422,7 +422,7 @@ a fair-coin machine halting within a polynomial clock, and a fair-coin machine h clock `T` is a verifier replaying random strings of length `T`. -/ theorem mem_BPP_iff_exists_mem_BPTIME {α : Type} {enc : α ↪ List Bool} {A : Set α} : A ∈ BPP enc ↔ ∃ k, A ∈ BPTIME enc (· ^ k) := by - rw [mem_BPP_iff_tidy] + rw [mem_BPP] constructor · rintro ⟨p, V, hV, hA⟩ -- sample a random string and run the verifier on it @@ -431,7 +431,7 @@ theorem mem_BPP_iff_exists_mem_BPTIME {α : Type} {enc : α ↪ List Bool} {A : have hcount : ComputableTidilyInPolyTime (fun a => p.eval (enc a).length) enc encUnary := (ComputableTidilyInPolyTime.unary_eval p).comp (ComputableTidilyInPolyTime.encoding_length enc) - have hprogram : IsPPTOn enc encBool program := hcount.sampleList.map_with (.of_tidy hV) + have hprogram : IsPPTOn enc encBool program := hcount.sampleList.map_with hV obtain ⟨k, State, hfinite, machine, c, d, heval, hhalt⟩ := hprogram.exists_halting_machine refine ⟨d, c * 2 ^ d, c, k, State, hfinite, machine, MultiTapePTM.DecidesWithBoundedErrorInTime.mono (t := fun a => c * ((enc a).length + 1) ^ d) @@ -445,12 +445,12 @@ theorem mem_BPP_iff_exists_mem_BPTIME {α : Type} {enc : α ↪ List Bool} {A : -- replay the coins refine ⟨Polynomial.C c₁ * Polynomial.X ^ d + Polynomial.C c₂, fun x => decide (machine.runClosedCoins x.2 (enc x.1) = [true]), - ComputableTidilyInPolyTime.decide_eq' + .of_tidy (ComputableTidilyInPolyTime.decide_eq' ((MultiTapePTM.computableTidilyInPolyTime_runClosedCoins machine).comp ((ComputableTidilyInPolyTime.snd enc encBits).prod ((ComputableTidilyInPolyTime.of_eq (encMid := encBits) fun _ => rfl).comp (ComputableTidilyInPolyTime.fst enc encBits)))) - (ComputableTidilyInPolyTime.const [true]), fun a => ?_⟩ + (ComputableTidilyInPolyTime.const [true])), fun a => ?_⟩ have heval : (Polynomial.C c₁ * Polynomial.X ^ d + Polynomial.C c₂).eval (enc a).length = c₁ * (enc a).length ^ d + c₂ := by simp diff --git a/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean b/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean index d4d813936..a313ad63d 100644 --- a/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean +++ b/Complexity/Computability/Complexity/Classes/ValiantVazirani.lean @@ -232,7 +232,7 @@ theorem NP_subset_RPWithPromiseOracle_PromiseUSAT (enc : α ↪ List Bool) : NP enc ⊆ RPWithPromiseOracle PromiseUSAT encCNF enc := by classical intro L hL - obtain ⟨g, hg, hgL⟩ := polyTimeReducible_iff_tidy.mp (CookLevin.SAT_npHard enc L hL) + obtain ⟨g, hg, hgL⟩ := (CookLevin.SAT_npHard enc L hL) obtain ⟨c, d, hlen⟩ := hg.polyBounded_length.exists_le let queries : α × List Bool → List (List Bool) := fun x => (BitString.listRows (11 * (c * ((enc x.1).length + 1) ^ d + 3)) @@ -240,6 +240,7 @@ theorem NP_subset_RPWithPromiseOracle_PromiseUSAT (enc : α ↪ List Bool) : fun b => encCNF (reduce (g x.1, b)) have hqueries : ComputableTidilyInPolyTime queries (encPair enc encBits) (encList encBits) := by have hreduce := computableInPolyTime_reduce.tidy + have hg := hg.tidy fun_prop refine ⟨Polynomial.C 11 * (Polynomial.C c * (Polynomial.X + 1) ^ d + 3) * (Polynomial.C c * (Polynomial.X + 1) ^ d + 2) ^ 2, diff --git a/Complexity/Computability/Complexity/Classes/WPP.lean b/Complexity/Computability/Complexity/Classes/WPP.lean index a99ed5f1f..78a4602ef 100644 --- a/Complexity/Computability/Complexity/Classes/WPP.lean +++ b/Complexity/Computability/Complexity/Classes/WPP.lean @@ -53,7 +53,7 @@ Oracle lowness of `SPP`, `LWPP`, and `WPP` (including fixed-target `LWPPWithFixe ## Main results -* `mem_WPP_iff_tidy`, `mem_LWPP_iff_tidy`: membership through a tidy target machine. +* `mem_WPP`, `mem_LWPP`: membership through a tidy target machine. * `SPP_subset_LWPP`, `LWPP_subset_WPP`, `UP_subset_LWPP`, `UP_subset_WPP`, `coUP_subset_LWPP`, `coUP_subset_WPP`, `FewP_subset_LWPP`, `FewP_subset_WPP`, `WPP_subset_CeqP`, `WPP_subset_coCeqP`. @@ -101,25 +101,12 @@ theorem mem_WPP : A ∈ WPP enc ↔ ∃ g ∈ GapP enc, ∃ f : α → ℤ, (∀ a, f a ≠ 0) ∧ (∀ a, g a = 0 ∨ g a = f a) ∧ ∀ a, a ∈ A ↔ g a = f a := Iff.rfl -/-- `Cslib.Complexity.mem_WPP` with a tidy target machine, for proofs that compose machines. -/ -theorem mem_WPP_iff_tidy : A ∈ WPP enc ↔ ∃ g ∈ GapP enc, ∃ f : α → ℤ, - ComputableTidilyInPolyTime f enc encIntBin ∧ - (∀ a, f a ≠ 0) ∧ (∀ a, g a = 0 ∨ g a = f a) ∧ ∀ a, a ∈ A ↔ g a = f a := by - simp only [mem_WPP, computableInPolyTime_iff_computableTidilyInPolyTime] - theorem mem_LWPP : A ∈ LWPP enc ↔ ∃ g ∈ GapP enc, ∃ f : ℕ → ℤ, ComputableInPolyTime f encUnary encIntBin ∧ (∀ n, f n ≠ 0) ∧ (∀ a, g a = 0 ∨ g a = f (enc a).length) ∧ ∀ a, a ∈ A ↔ g a = f (enc a).length := Iff.rfl -/-- `Cslib.Complexity.mem_LWPP` with a tidy target machine, for proofs that compose machines. -/ -theorem mem_LWPP_iff_tidy : A ∈ LWPP enc ↔ ∃ g ∈ GapP enc, ∃ f : ℕ → ℤ, - ComputableTidilyInPolyTime f encUnary encIntBin ∧ - (∀ n, f n ≠ 0) ∧ (∀ a, g a = 0 ∨ g a = f (enc a).length) ∧ - ∀ a, a ∈ A ↔ g a = f (enc a).length := by - simp only [mem_LWPP, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- The constant target one witnesses the SPP containment. -/ theorem SPP_subset_LWPP : SPP enc ⊆ LWPP enc := by rintro A ⟨g, hg, hr, hA⟩ @@ -170,19 +157,19 @@ theorem WPP_subset_coCeqP : WPP enc ⊆ coCeqP enc := by /-- Complement exchanges the zero and target values. -/ theorem compl_mem_WPP (hA : A ∈ WPP enc) : Aᶜ ∈ WPP enc := by - rw [mem_WPP_iff_tidy] at hA ⊢ + rw [mem_WPP] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA - refine ⟨f - g, GapP.sub_mem' (mem_GapP_of_polyTime (.of_tidy hf)) hg, f, hf, hn, + refine ⟨f - g, GapP.sub_mem' (mem_GapP_of_polyTime hf) hg, f, hf, hn, fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> simp [h] · rcases hr a with h | h <;> simp [hA a, h, (hn a).symm] /-- Products preserve the zero-or-target condition and the target is still nonzero. -/ theorem inter_mem_WPP (hA : A ∈ WPP enc) (hB : B ∈ WPP enc) : A ∩ B ∈ WPP enc := by - rw [mem_WPP_iff_tidy] at hA hB ⊢ + rw [mem_WPP] at hA hB ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA obtain ⟨g', hg', f', hf', hn', hr', hB⟩ := hB - refine ⟨g * g', GapP.mul_mem hg hg', f * f', hf.intBin_mul' hf', + refine ⟨g * g', GapP.mul_mem hg hg', f * f', .of_tidy (hf.tidy.intBin_mul' hf'.tidy), fun a => mul_ne_zero (hn a) (hn' a), fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> rcases hr' a with h' | h' <;> simp [h, h'] · rcases hr a with h | h <;> rcases hr' a with h' | h' <;> @@ -221,9 +208,9 @@ theorem PolyTimeReducible.mem_WPP {encB : β ↪ List Bool} {B : Set β} /-- The complementary gap uses the same length-dependent target. -/ theorem compl_mem_LWPP (hA : A ∈ LWPP enc) : Aᶜ ∈ LWPP enc := by - rw [mem_LWPP_iff_tidy] at hA ⊢ + rw [mem_LWPP] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA - have htarget := mem_GapP_of_polyTime (.of_tidy (hf.comp (.encoding_length enc))) + have htarget := mem_GapP_of_polyTime (hf.comp (.encoding_length enc)) refine ⟨(fun a => f (enc a).length) - g, GapP.sub_mem' htarget hg, f, hf, hn, fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> simp [h] @@ -231,10 +218,10 @@ theorem compl_mem_LWPP (hA : A ∈ LWPP enc) : Aᶜ ∈ LWPP enc := by /-- Multiplying length-dependent targets preserves length dependence. -/ theorem inter_mem_LWPP (hA : A ∈ LWPP enc) (hB : B ∈ LWPP enc) : A ∩ B ∈ LWPP enc := by - rw [mem_LWPP_iff_tidy] at hA hB ⊢ + rw [mem_LWPP] at hA hB ⊢ obtain ⟨g, hg, f, hf, hn, hr, hA⟩ := hA obtain ⟨g', hg', f', hf', hn', hr', hB⟩ := hB - refine ⟨g * g', GapP.mul_mem hg hg', f * f', hf.intBin_mul' hf', + refine ⟨g * g', GapP.mul_mem hg hg', f * f', .of_tidy (hf.tidy.intBin_mul' hf'.tidy), fun n => mul_ne_zero (hn n) (hn' n), fun a => ?_, fun a => ?_⟩ · rcases hr a with h | h <;> rcases hr' a with h' | h' <;> simp [h, h'] · rcases hr a with h | h <;> rcases hr' a with h' | h' <;> @@ -427,10 +414,10 @@ theorem mem_LWPP_of_polyTime_index {g : α → ℤ} {f : ℕ → ℤ} {k : α index `k a = |r(a)|`, which `mem_LWPP_of_polyTime_index` normalizes to a function of `|a|`. -/ theorem PolyTimeReducible.mem_LWPP {encB : β ↪ List Bool} {B : Set β} (h : PolyTimeReducible enc encB A B) (hB : B ∈ LWPP encB) : A ∈ LWPP enc := by - obtain ⟨r, hr, hAB⟩ := polyTimeReducible_iff_tidy.mp h + obtain ⟨r, hr, hAB⟩ := h obtain ⟨g, hg, f, hf, hn, hgr, hB⟩ := hB - exact mem_LWPP_of_polyTime_index (GapP.comp_mem hg (.of_tidy hr)) hf hn - (.of_tidy ((ComputableTidilyInPolyTime.encoding_length encB).comp hr)) + exact mem_LWPP_of_polyTime_index (GapP.comp_mem hg hr) hf hn + (.of_tidy ((ComputableTidilyInPolyTime.encoding_length encB).comp hr.tidy)) (fun a => hgr (r a)) (fun a => (hAB a).trans (hB (r a))) end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean b/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean index eb8ce8e31..46bb9885e 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Bounded.lean @@ -57,7 +57,7 @@ theorem forall_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) (hr : ComputableInPolyTime r enc encUnary) : {a | ∀ i < r a, (a, i) ∈ A} ∈ WPP enc := by have hr := hr.tidy - rw [mem_WPP_iff_tidy] at hA ⊢ + rw [mem_WPP] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := hA let G a := ∏ i ∈ range (r a), g (a, i) let F a := ∏ i ∈ range (r a), f (a, i) @@ -67,7 +67,7 @@ theorem forall_lt_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) have hno (a) (ha : ¬ ∀ i < r a, (a, i) ∈ A) : G a = 0 := prod_eq_zero_of_not_forall hR hA ha refine ⟨G, GapP.prod_range_mem hg (.of_tidy hr), F, - ComputableTidilyInPolyTime.intBin_prod_range hf hr, hF, ?_, ?_⟩ + .of_tidy (ComputableTidilyInPolyTime.intBin_prod_range hf.tidy hr), hF, ?_, ?_⟩ · intro a by_cases ha : ∀ i < r a, (a, i) ∈ A · exact Or.inr (hy a ha) @@ -95,10 +95,11 @@ theorem forall_lt_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) (hr : ComputableInPolyTime r enc encUnary) : {a | ∀ i < r a, (a, i) ∈ A} ∈ LWPP enc := by have hr := hr.tidy - obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP_iff_tidy.mp hA + obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP.mp hA obtain ⟨p, hb⟩ := hr.polyBounded.exists_polynomial let T (x : ℕ × ℕ) := ∏ i ∈ range x.2, f (2 * x.1 + 1 + i) have hT : ComputableTidilyInPolyTime T (encPair encUnary encUnary) encIntBin := by + have hf := hf.tidy apply ComputableTidilyInPolyTime.intBin_prod_range (f := fun x : (ℕ × ℕ) × ℕ => f (2 * x.1.1 + 1 + x.2)) <;> fun_prop have hp : ComputableTidilyInPolyTime (fun n => p.eval n + 1) encUnary encUnary := by fun_prop diff --git a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean index 6be7bbc97..e201e16a1 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean @@ -465,7 +465,7 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ {c : α → ℕ} (hc : c ∈ SharpPWithOracle A enc) : ∃ S : ℕ → ℤ, ComputableTidilyInPolyTime S encUnary encIntBin ∧ (∀ n, S n ≠ 0) ∧ (fun a => S (enc a).length * (c a : ℤ)) ∈ GapP enc := by - obtain ⟨g, hg, f, hf, hfn, hrange, hmem⟩ := mem_LWPP_iff_tidy.mp hA + obtain ⟨g, hg, f, hf, hfn, hrange, hmem⟩ := mem_LWPP.mp hA have hg_eq (w : List Bool) : g w = open Classical in if w ∈ A then f w.length else 0 := by by_cases hw : w ∈ A · simpa only [hw, ↓reduceIte, encBits_apply] using (hmem w).mp hw @@ -485,7 +485,7 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ let D : ℕ → ℤ := fun n => ((List.range (bound n)).map f).prod have hD : ComputableTidilyInPolyTime D encUnary encIntBin := ComputableTidilyInPolyTime.intBin_prod.comp - ((ComputableTidilyInPolyTime.map hf).comp + ((ComputableTidilyInPolyTime.map hf.tidy).comp (ComputableTidilyInPolyTime.range.comp hbound)) have hDn (n : ℕ) : D n ≠ 0 := List.prod_ne_zero (by simp [hfn]) let S : ℕ → ℤ := fun n => D n ^ τ n @@ -503,7 +503,7 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ (encPair (encPair enc encBits) encUnary) encBool := by fun_prop have hK : ComputableTidilyInPolyTime K (encPair enc encBits) encIntBin := ComputableTidilyInPolyTime.intBin_prod.comp - ((ComputableTidilyInPolyTime.map hf).comp + ((ComputableTidilyInPolyTime.map hf.tidy).comp (ComputableTidilyInPolyTime.filterWithInput hlist htest)) let H : α × List Bool → ℤ := fun x => g x.2 * K x have hH : H ∈ GapP (encPair enc encBits) := diff --git a/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean b/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean index 8a5818df4..4014ba63d 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Robustness.lean @@ -235,7 +235,7 @@ theorem mem_WPP_iff_exists_polyTime_targets {α : Type} {enc : α ↪ List Bool} (∀ a, (0 : ℤ) ∉ f a) ∧ (∀ a, a ∈ A → g a ∈ f a) ∧ ∀ a, a ∉ A → g a = 0 := by constructor - · rw [mem_WPP_iff_tidy] + · rw [mem_WPP] rintro ⟨g, hg, f, hf, hn, hr, hA⟩ refine ⟨g, hg, fun a => [f a], by fun_prop, ?_, ?_, ?_⟩ · intro a @@ -256,7 +256,7 @@ theorem mem_LWPP_iff_exists_polyTime_targets {α : Type} {enc : α ↪ List Bool (∀ n, (0 : ℤ) ∉ f n) ∧ (∀ a, a ∈ A → g a ∈ f (enc a).length) ∧ ∀ a, a ∉ A → g a = 0 := by constructor - · rw [mem_LWPP_iff_tidy] + · rw [mem_LWPP] rintro ⟨g, hg, f, hf, hn, hr, hA⟩ refine ⟨g, hg, fun n => [f n], by fun_prop, ?_, ?_, ?_⟩ · intro n diff --git a/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean b/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean index a168f6b63..7f104c8a3 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean @@ -126,12 +126,12 @@ theorem truthTable_mem_WPP (hA : A ∈ WPP (encPair enc encUnary)) {a | d (a, truthTableAnswers A r a) = true} ∈ WPP enc := by have hr := hr.tidy have hd := hd.tidy - rw [mem_WPP_iff_tidy] at hA ⊢ + rw [mem_WPP] at hA ⊢ obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := hA have hF (a) : (∏ i ∈ range (r a), f (a, i)) ≠ 0 := prod_ne_zero_iff.mpr fun i _ => hn (a, i) - refine ⟨answerGap g f r d, answerGap_mem hg (mem_GapP_of_polyTime (.of_tidy hf)) hr hd, - _, ComputableTidilyInPolyTime.intBin_prod_range hf hr, hF, ?_, ?_⟩ + refine ⟨answerGap g f r d, answerGap_mem hg (mem_GapP_of_polyTime hf) hr hd, + _, .of_tidy (ComputableTidilyInPolyTime.intBin_prod_range hf.tidy hr), hF, ?_, ?_⟩ · intro a rw [answerGap_eq hR hA] split_ifs <;> simp @@ -148,14 +148,15 @@ theorem truthTable_mem_LWPP (hA : A ∈ LWPP (encPair enc encUnary)) {a | d (a, truthTableAnswers A r a) = true} ∈ LWPP enc := by have hr := hr.tidy have hd := hd.tidy - obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP_iff_tidy.mp hA + obtain ⟨g, hg, f, hf, hn, hR, hA⟩ := mem_LWPP.mp hA let F (x : α × ℕ) := f ((encPair enc encUnary x).length) have hF : ComputableTidilyInPolyTime F (encPair enc encUnary) encIntBin := - hf.comp (.encoding_length _) + hf.tidy.comp (.encoding_length _) have he := answerGap_eq (f := F) (r := r) (d := d) hR hA obtain ⟨p, hb⟩ := hr.polyBounded.exists_polynomial let T (x : ℕ × ℕ) := ∏ i ∈ range x.2, f (2 * x.1 + 1 + i) have hT : ComputableTidilyInPolyTime T (encPair encUnary encUnary) encIntBin := by + have hf := hf.tidy apply ComputableTidilyInPolyTime.intBin_prod_range (f := fun x : (ℕ × ℕ) × ℕ => f (2 * x.1.1 + 1 + x.2)) <;> fun_prop have hp : ComputableTidilyInPolyTime (fun n => p.eval n + 1) encUnary encUnary := by fun_prop diff --git a/Complexity/Computability/Complexity/Classes/WPP/TwoSided.lean b/Complexity/Computability/Complexity/Classes/WPP/TwoSided.lean index 71b9f7931..a67f8981b 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/TwoSided.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/TwoSided.lean @@ -160,7 +160,7 @@ theorem mem_WPP_iff_exists_disjoint_targets {α : Type} {enc : α ↪ List Bool} (∀ a, (yes a).Disjoint (no a)) ∧ (∀ a, a ∈ A → g a ∈ yes a) ∧ ∀ a, a ∉ A → g a ∈ no a := by constructor - · rw [mem_WPP_iff_tidy] + · rw [mem_WPP] rintro ⟨g, hg, f, hf, hn, hr, hA⟩ refine ⟨g, hg, fun a => [f a], fun _ => [0], by fun_prop, .const _, ?_, ?_, ?_⟩ · intro a @@ -184,7 +184,7 @@ theorem mem_LWPP_iff_exists_disjoint_targets {α : Type} {enc : α ↪ List Bool (∀ a, a ∈ A → g a ∈ yes (enc a).length) ∧ ∀ a, a ∉ A → g a ∈ no (enc a).length := by constructor - · rw [mem_LWPP_iff_tidy] + · rw [mem_LWPP] rintro ⟨g, hg, f, hf, hn, hr, hA⟩ refine ⟨g, hg, fun n => [f n], fun _ => [0], by fun_prop, .const _, ?_, ?_, ?_⟩ · intro n diff --git a/Complexity/Computability/Complexity/Classes/ZPP.lean b/Complexity/Computability/Complexity/Classes/ZPP.lean index b27677843..3166cbfb8 100644 --- a/Complexity/Computability/Complexity/Classes/ZPP.lean +++ b/Complexity/Computability/Complexity/Classes/ZPP.lean @@ -43,7 +43,6 @@ the random strings, and on a non-member the second does. ## Main results -* `Cslib.Complexity.mem_ZPP_iff_tidy`: membership through a tidy verifier. * `Cslib.Complexity.ZPP_subset_RP`, `Cslib.Complexity.ZPP_subset_coRP`. * `Cslib.Complexity.RP_inter_coRP_subset_ZPP`. * `Cslib.Complexity.ZPP_eq_RP_inter_coRP`: `ZPP = RP ∩ coRP`. @@ -90,13 +89,6 @@ theorem mem_ZPP {A : Set α} : A ∈ ZPP enc ↔ ∃ (p : Polynomial ℕ) DecidesWithZeroError enc p V A := Iff.rfl -/-- `Cslib.Complexity.mem_ZPP` with a tidy verifier, for proofs that compose machines. -/ -theorem mem_ZPP_iff_tidy {A : Set α} : A ∈ ZPP enc ↔ ∃ (p : Polynomial ℕ) - (V : α × List Bool → Option Bool), - ComputableTidilyInPolyTime V (encPair enc encBits) (encOption encBool) ∧ - DecidesWithZeroError enc p V A := by - simp only [mem_ZPP, computableInPolyTime_iff_computableTidilyInPolyTime] - namespace DecidesWithZeroError variable {p : Polynomial ℕ} {V : α × List Bool → Option Bool} {A : Set α} @@ -130,13 +122,14 @@ end DecidesWithZeroError /-- **`ZPP` is closed under complement.** -/ theorem compl_mem_ZPP {A : Set α} (hA : A ∈ ZPP enc) : Aᶜ ∈ ZPP enc := by - obtain ⟨p, V, hV, h⟩ := mem_ZPP_iff_tidy.mp hA - refine mem_ZPP_iff_tidy.mpr ⟨p, fun x => (V x).map Bool.not, ?_, h.compl⟩ + obtain ⟨p, V, hV, h⟩ := mem_ZPP.mp hA + refine mem_ZPP.mpr ⟨p, fun x => (V x).map Bool.not, ?_, h.compl⟩ have : ComputableTidilyInPolyTime (fun x => (V x).elim none fun b => some !b) (encPair enc encBits) (encOption encBool) := - ComputableTidilyInPolyTime.optionElimWithInput hV (.const none) + ComputableTidilyInPolyTime.optionElimWithInput hV.tidy (.const none) ((ComputableTidilyInPolyTime.optionSome encBool).comp (ComputableTidilyInPolyTime.bool_not.comp (.snd _ _))) + refine .of_tidy ?_ convert this using 2 with x cases V x <;> rfl @@ -186,8 +179,8 @@ reading the first and the last part of the random string, answer `some true` whe `some false` when `V₂` does, and `none` otherwise. -/ theorem RP_inter_coRP_subset_ZPP : RP enc ∩ coRP enc ⊆ ZPP enc := by rintro A ⟨hA₁, hA₂⟩ - obtain ⟨p₁, V₁, hV₁, h₁⟩ := mem_RP_iff_tidy.mp hA₁ - obtain ⟨p₂, V₂, hV₂, h₂⟩ := mem_RP_iff_tidy.mp (mem_coRP.mp hA₂) + obtain ⟨p₁, V₁, hV₁, h₁⟩ := mem_RP.mp hA₁ + obtain ⟨p₂, V₂, hV₂, h₂⟩ := mem_RP.mp (mem_coRP.mp hA₂) let len (a : α) : ℕ := p₁.eval (enc a).length let V (x : α × List Bool) : Option Bool := if V₁ (x.1, x.2.take (len x.1)) then some true @@ -198,11 +191,11 @@ theorem RP_inter_coRP_subset_ZPP : RP enc ∩ coRP enc ⊆ ZPP enc := by (ComputableTidilyInPolyTime.encoding_length enc)).comp (.fst _ _) have hpoly : ComputableTidilyInPolyTime V (encPair enc encBits) (encOption encBool) := ComputableTidilyInPolyTime.cond - (hV₁.comp ((ComputableTidilyInPolyTime.fst _ _).prod + (hV₁.tidy.comp ((ComputableTidilyInPolyTime.fst _ _).prod (ComputableTidilyInPolyTime.bitsTakeWithInput (.snd _ _) hlen))) (.const _) (ComputableTidilyInPolyTime.cond - (hV₂.comp ((ComputableTidilyInPolyTime.fst _ _).prod + (hV₂.tidy.comp ((ComputableTidilyInPolyTime.fst _ _).prod (ComputableTidilyInPolyTime.bitsDropWithInput (.snd _ _) hlen))) (.const _) (.const _)) refine ⟨p₁ + p₂, V, .of_tidy hpoly, fun a => ?_⟩ diff --git a/Complexity/Computability/Complexity/CookLevin/Completeness.lean b/Complexity/Computability/Complexity/CookLevin/Completeness.lean index 23404c4ee..478fd9291 100644 --- a/Complexity/Computability/Complexity/CookLevin/Completeness.lean +++ b/Complexity/Computability/Complexity/CookLevin/Completeness.lean @@ -41,7 +41,8 @@ open Turing Turing.MultiTapeTM Cslib.Logic.PL /-- Every NP problem reduces to SAT in polynomial time through its verifier's tableau. -/ theorem SAT_npHard : NPHard encCNF SAT := by intro α enc A hA - obtain ⟨p, V, ⟨t, s, ht, -, k, State, hfin, tm, htm⟩, hV⟩ := mem_NP_iff_tidy.mp hA + obtain ⟨p, V, hVpoly, hV⟩ := mem_NP.mp hA + obtain ⟨t, s, ht, -, k, State, hfin, tm, htm⟩ := hVpoly.tidy obtain ⟨c, d, ht⟩ := ht.exists_le have := Fintype.ofFinite State classical diff --git a/Complexity/Computability/Complexity/FineGrained.lean b/Complexity/Computability/Complexity/FineGrained.lean index 8934593c1..872043a1d 100644 --- a/Complexity/Computability/Complexity/FineGrained.lean +++ b/Complexity/Computability/Complexity/FineGrained.lean @@ -148,7 +148,7 @@ theorem DecidableInTimeO.exists_computableInO (h : DecidableInTimeO A enc T) : try simp only [encBool_apply, List.length_singleton] omega -/-- A tidy decider within time `O(t)`, for `t ≤ T`, decides within time `O(T)`. -/ +/-- A decider within time `O(t)`, for `t ≤ T`, decides within time `O(T)`. -/ theorem DecidableInTimeO.of_computableInO {g : α → Bool} {t S : α → ℕ} (hg : ComputableInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) (hT : ∀ a, (t a : ℝ) ≤ T a) : DecidableInTimeO A enc T := by @@ -230,7 +230,7 @@ section Machines variable {α : Type} {enc : α ↪ List Bool} {A B : Set α} -/-- A tidy decider within time `O(t)`, for `t` within a constant times `2 ^ (δ μ a)` times a +/-- A decider within time `O(t)`, for `t` within a constant times `2 ^ (δ μ a)` times a polynomial, decides within time `2 ^ (δ μ a)` times a polynomial. -/ theorem DecidableInExpTime.of_computableInO {μ : α → ℕ} {δ : ℝ} {g : α → Bool} {t S : α → ℕ} (hg : ComputableInO g enc encBool t S) (hA : ∀ a, a ∈ A ↔ g a = true) diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean index f63c1ee34..6e869a68b 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean @@ -317,7 +317,8 @@ instance is mapped to the tableau circuit of a polynomial-time decider on inputs the encoded instance, with the encoded instance as its input. -/ theorem logSpaceReducible_of_mem_P {α : Type} {enc : α ↪ List Bool} {A : Set α} (hA : A ∈ P enc) : LogSpaceReducible enc encCircuitValue A CircuitValue := by - obtain ⟨f, ⟨t, s, ht, -, k, State, hfin, tm, htm⟩, hAf⟩ := mem_P_iff_tidy.mp hA + obtain ⟨f, hfpoly, hAf⟩ := hA + obtain ⟨t, s, ht, -, k, State, hfin, tm, htm⟩ := hfpoly.tidy have := Fintype.ofFinite State classical obtain ⟨C, d, htle⟩ := ht.exists_le diff --git a/Complexity/Computability/Complexity/Problems/Clique.lean b/Complexity/Computability/Complexity/Problems/Clique.lean index 29a697be2..ec852955a 100644 --- a/Complexity/Computability/Complexity/Problems/Clique.lean +++ b/Complexity/Computability/Complexity/Problems/Clique.lean @@ -40,7 +40,7 @@ first-order interpretations. `G.compl.induced = G.inducedᶜ` and `(G.compl, m) ∈ Clique ↔ (G, m) ∈ IndependentSet`. * `Cslib.Complexity.Graph.le_cliqueNum_iff`, `Cslib.Complexity.Graph.cliqueNum_compl`: the clique number is the largest target of `Clique`, and that of the complement is the independence number. -* `Cslib.Complexity.Graph.computableTidilyInPolyTime_compl`: complementing a graph on its declared +* `Cslib.Complexity.Graph.computableInPolyTime_compl`: complementing a graph on its declared vertices is polynomial-time. * `Cslib.Complexity.Clique.mem_NP`: `Clique ∈ NP (encPair encGraph encNat)`. * `Cslib.Complexity.polyTimeReducible_IndependentSet_Clique`: `IndependentSet` reduces to `Clique` diff --git a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean index 166e3fa0f..eb91d597d 100644 --- a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean @@ -291,7 +291,8 @@ end Instance positive and negative rails of its decider's tableau. -/ theorem logSpaceReducible_of_mem_P {α : Type} {enc : α ↪ List Bool} {A : Set α} (hA : A ∈ P enc) : LogSpaceReducible enc encMonotoneCircuitValue A MonotoneCircuitValue := by - obtain ⟨f, ⟨t, s, ht, -, k, State, hfin, tm, htm⟩, hAf⟩ := mem_P_iff_tidy.mp hA + obtain ⟨f, hfpoly, hAf⟩ := hA + obtain ⟨t, s, ht, -, k, State, hfin, tm, htm⟩ := hfpoly.tidy have := Fintype.ofFinite State classical obtain ⟨C, d, htle⟩ := ht.exists_le diff --git a/Complexity/Computability/Complexity/Reduction.lean b/Complexity/Computability/Complexity/Reduction.lean index 0edd8a1a0..ce4074368 100644 --- a/Complexity/Computability/Complexity/Reduction.lean +++ b/Complexity/Computability/Complexity/Reduction.lean @@ -24,7 +24,6 @@ lemmas are instances of the core's. Its body is kept as the `∃` statement, so admissibility goal of an anonymous constructor is `ComputableInPolyTime f encA encB` itself, as `fun_prop` expects. The checked client in `ComplexityTests.NPCompleteness` supplies plain decider, verifier and reduction certificates, then transfers IndependentSet hardness to Clique. -`Cslib.Complexity.polyTimeReducible_iff_tidy` also gives the equivalent tidy formulation. A class of problems is given, as `NP` or `coNP`, by a set of problems for every type of instances and every encoding of them. A problem `B` is hard for such a class `C` when every problem in `C`, @@ -99,7 +98,7 @@ problem to SAT. These are navigation tables, not an exhaustive list of reduction ## Main definitions -* `Cslib.Complexity.PolyTimeReducible`, with `Cslib.Complexity.polyTimeReducible_iff_tidy`. +* `Cslib.Complexity.PolyTimeReducible`. * `Cslib.Complexity.PolyTimeHard`, `Cslib.Complexity.PolyTimeComplete`: hardness and completeness for a class. * `Cslib.Complexity.NPHard`, `Cslib.Complexity.NPComplete`. @@ -160,13 +159,6 @@ theorem polyTimeReducible_iff_manyOneReducibleBy {encA : α ↪ List Bool} {encB PolyTimeReducible encA encB A B ↔ ManyOneReducibleBy (ComputableInPolyTime · encA encB) A B := Iff.rfl -/-- Polynomial-time reducibility with a reduction computable tidily in polynomial time, the form -in which proofs build reductions. -/ -theorem polyTimeReducible_iff_tidy {encA : α ↪ List Bool} {encB : β ↪ List Bool} {A : Set α} - {B : Set β} : PolyTimeReducible encA encB A B ↔ - ∃ f : α → β, ComputableTidilyInPolyTime f encA encB ∧ ∀ a, a ∈ A ↔ f a ∈ B := by - simp only [PolyTimeReducible, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- `B` is hard for the class `C` under polynomial-time many-one reductions: every problem in `C`, with any encoding of its instances, reduces to `B`. This is `HardUnder` for `PolyTimeReducible`. -/ def PolyTimeHard (C : ∀ {α : Type}, (α ↪ List Bool) → Set (Set α)) (encB : β ↪ List Bool) diff --git a/Complexity/Computability/Complexity/Reduction/TruthTable.lean b/Complexity/Computability/Complexity/Reduction/TruthTable.lean index 85b407d60..b718613da 100644 --- a/Complexity/Computability/Complexity/Reduction/TruthTable.lean +++ b/Complexity/Computability/Complexity/Reduction/TruthTable.lean @@ -22,8 +22,7 @@ The query generator is total even outside the used range; unused outputs do not ## Main definitions * `truthTableAnswers`: the semantic answer word for an indexed family. -* `PolyTimeTruthTableReducible`: polynomial-time nonadaptive reduction of encoded languages, with - `polyTimeTruthTableReducible_iff_tidy` for tidily computable query generators and combiners. +* `PolyTimeTruthTableReducible`: polynomial-time nonadaptive reduction of encoded languages. ## Main results @@ -92,17 +91,6 @@ def PolyTimeTruthTableReducible {β : Type} (encA : α ↪ List Bool) (encB : β variable {β : Type} {encA : α ↪ List Bool} {encB : β ↪ List Bool} {L : Set α} {B : Set β} -/-- Polynomial-time truth-table reducibility with functions computable tidily in polynomial time, -the form in which proofs build reductions. -/ -theorem polyTimeTruthTableReducible_iff_tidy : - PolyTimeTruthTableReducible encA encB L B ↔ - ∃ (r : α → ℕ) (q : α × ℕ → β) (d : α × List Bool → Bool), - ComputableTidilyInPolyTime r encA encUnary ∧ - ComputableTidilyInPolyTime q (encPair encA encUnary) encB ∧ - ComputableTidilyInPolyTime d (encPair encA encBits) encBool ∧ - ∀ a, a ∈ L ↔ d (a, truthTableAnswers (q ⁻¹' B) r a) = true := by - simp only [PolyTimeTruthTableReducible, computableInPolyTime_iff_computableTidilyInPolyTime] - /-- Every polynomial-time many-one reduction is a polynomial-time truth-table reduction making a single query. -/ theorem PolyTimeReducible.polyTimeTruthTableReducible @@ -131,13 +119,13 @@ theorem PolyTimeTruthTableReducible.compl_left theorem PolyTimeTruthTableReducible.compl_right (h : PolyTimeTruthTableReducible encA encB L B) : PolyTimeTruthTableReducible encA encB L Bᶜ := by - obtain ⟨r, q, d, hr, hq, hd, hL⟩ := polyTimeTruthTableReducible_iff_tidy.mp h + obtain ⟨r, q, d, hr, hq, hd, hL⟩ := h have hmap : ComputableTidilyInPolyTime (fun x : α × List Bool => x.2.map (!·)) (encPair encA encBits) encBits := ComputableTidilyInPolyTime.bitsMapWithInput (f := fun _ b => !b) (.snd encA encBits) (by fun_prop) - refine polyTimeTruthTableReducible_iff_tidy.mpr ⟨r, q, fun x => d (x.1, x.2.map (!·)), hr, hq, - hd.comp ((ComputableTidilyInPolyTime.fst encA encBits).prod hmap), fun a => ?_⟩ + refine ⟨r, q, fun x => d (x.1, x.2.map (!·)), hr, hq, + hd.comp (.of_tidy ((ComputableTidilyInPolyTime.fst encA encBits).prod hmap)), fun a => ?_⟩ rw [hL a, show q ⁻¹' Bᶜ = (q ⁻¹' B)ᶜ from rfl, truthTableAnswers_compl] simp [List.map_map, Function.comp_def] @@ -157,12 +145,12 @@ theorem truthTable_mem_P {A : Set (α × ℕ)} {r : α → ℕ} {d : α × List have hr := hr.tidy have hd := hd.tidy classical - obtain ⟨f, hf, hAf⟩ := mem_P_iff_tidy.mp hA + obtain ⟨f, hf, hAf⟩ := mem_P.mp hA have hans : ComputableTidilyInPolyTime (fun a => (List.range (r a)).map fun i => f (a, i)) encA encBits := - ComputableTidilyInPolyTime.mapToBitsWithInput (ComputableTidilyInPolyTime.range.comp hr) hf - refine mem_P_iff_tidy.mpr ⟨fun a => d (a, (List.range (r a)).map fun i => f (a, i)), - hd.comp (ComputableTidilyInPolyTime.id'.prod hans), fun a => ?_⟩ + ComputableTidilyInPolyTime.mapToBitsWithInput (ComputableTidilyInPolyTime.range.comp hr) hf.tidy + refine mem_P.mpr ⟨fun a => d (a, (List.range (r a)).map fun i => f (a, i)), + .of_tidy (hd.comp (ComputableTidilyInPolyTime.id'.prod hans)), fun a => ?_⟩ simp [truthTableAnswers_eq_map_range, hAf] /-- **`P` is closed under polynomial-time truth-table reductions.** -/ diff --git a/ComplexityTests/KarpReductions.lean b/ComplexityTests/KarpReductions.lean index c65ab10d0..81473958b 100644 --- a/ComplexityTests/KarpReductions.lean +++ b/ComplexityTests/KarpReductions.lean @@ -261,11 +261,11 @@ info: 'Cslib.Complexity.IndependentSet_npComplete' depends on axioms: #print axioms Cslib.Complexity.IndependentSet_npComplete /-- -info: 'Cslib.Complexity.Graph.computableTidilyInPolyTime_compl' depends on axioms: +info: 'Cslib.Complexity.Graph.computableInPolyTime_compl' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in -#print axioms Cslib.Complexity.Graph.computableTidilyInPolyTime_compl +#print axioms Cslib.Complexity.Graph.computableInPolyTime_compl /-- info: 'Cslib.Complexity.Clique.isVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/PolyTimePlain.lean b/ComplexityTests/PolyTimePlain.lean index a71a608dc..c15abef79 100644 --- a/ComplexityTests/PolyTimePlain.lean +++ b/ComplexityTests/PolyTimePlain.lean @@ -198,9 +198,9 @@ example : firstBit ∈ P encBits := ⟨fun w => w.headD false, (by polytime : ComputableInPolyTime _ encBits encBool), fun _ => Iff.rfl⟩ -/-- Membership in `P` from a tidy certificate, through `mem_P_iff_tidy`. -/ +/-- Membership in `P` from a certificate built by `polytime`, through `mem_P`. -/ example : firstBit ∈ P encBits := - mem_P_iff_tidy.mpr ⟨fun w => w.headD false, by polytime, fun _ => Iff.rfl⟩ + mem_P.mpr ⟨fun w => w.headD false, by polytime, fun _ => Iff.rfl⟩ /-- A reduction stated plainly is the library's polynomial-time reduction, by definition. -/ example {β : Type} {encB : β ↪ List Bool} {A : Set α} {B : Set β} : @@ -213,10 +213,10 @@ example {f : α → Bool} (hf : ComputableInPolyTime f enc encBool) {B : Set Boo (hB : B ∈ P encBool) : {a | f a ∈ B} ∈ P enc := PolyTimeReducible.mem_P ⟨f, by fun_prop, fun _ => Iff.rfl⟩ hB -/-- A tidy reduction, through `polyTimeReducible_iff_tidy`. -/ +/-- A reduction by the identity, with the plain identity certificate. -/ example : PolyTimeReducible encBits encBits {w : List Bool | w.headD false = true} {w | w.headD false = true} := - polyTimeReducible_iff_tidy.mpr ⟨id, .id', fun _ => Iff.rfl⟩ + ⟨id, .id', fun _ => Iff.rfl⟩ /-- Without a hypothesis or a certificate for `f`, `fun_prop` does not claim polynomial time. -/ example {f : α → Bool} (hf : ComputableInPolyTime f enc encBool) : diff --git a/ComplexityTests/TFNP.lean b/ComplexityTests/TFNP.lean index f55139c4b..66fd44002 100644 --- a/ComplexityTests/TFNP.lean +++ b/ComplexityTests/TFNP.lean @@ -210,11 +210,6 @@ example : ∃ n : _ → ℕ, ComputableInPolyTime n encEndOfLine encUnary := by obtain ⟨-, n, -, -, hn, -⟩ := mem_PPAD.mp EndOfLine_mem_PPAD exact ⟨n, hn⟩ -/-- `mem_PPAD_iff_tidy` restates it tidily, for the tidy calculus. -/ -example : ∃ n : _ → ℕ, ComputableTidilyInPolyTime n encEndOfLine encUnary := by - obtain ⟨-, n, -, -, hn, -⟩ := mem_PPAD_iff_tidy.mp EndOfLine_mem_PPAD - exact ⟨n, hn⟩ - /-! ### Axiom guards -/ /-- From c5aa2a1ac682a97cc5ee2d291404e1c2296cde8e Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 13:52:12 -0400 Subject: [PATCH 07/11] refactor(classes): reflow, review docs and lower the tidy surface baseline Lines the restatement pushed past 100 characters are reflowed, docstrings of restated declarations no longer call their certificates tidy, the SAT to CircuitSAT reduction uses a plain certificate, axiom guards whose messages now fit one line are whitespace-lax, and the S3 baseline is lowered: the Classes area goes from 597 tidy statements in 179 modules to the 5 case-1 originals in 3 modules. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Complexity/AffineDisperser/PolyTime.lean | 10 +-- .../Complexity/Classes/Alternation/Game.lean | 3 +- .../Classes/Alternation/GuessVerify.lean | 3 +- .../Classes/Alternation/Savitch.lean | 12 ++-- .../Complexity/Classes/Alternation/TQBF.lean | 6 +- .../Classes/ArthurMerlin/Amplification.lean | 8 ++- .../Complexity/Classes/BPP/Amplification.lean | 4 +- .../BPP/Derandomization/Generator.lean | 25 ++++--- .../Complexity/Classes/Constructible.lean | 4 +- .../Complexity/Classes/FewP.lean | 5 +- .../Complexity/Classes/Hierarchy.lean | 9 ++- .../Classes/Hierarchy/ShortDesc.lean | 3 +- .../Complexity/Classes/Hierarchy/Space.lean | 3 +- .../Complexity/Classes/Hierarchy/Time.lean | 4 +- .../Classes/IP/GraphNonIsomorphism.lean | 3 +- .../Complexity/Classes/IP/Simulation.lean | 3 +- .../Complexity/Classes/Ladner/PolyTime.lean | 3 +- .../Complexity/Classes/MIP/NEXP.lean | 7 +- .../Complexity/Classes/NP/SelfReduction.lean | 7 +- .../Complexity/Classes/NP/Witness.lean | 6 +- .../Complexity/Classes/Oracle/Closure.lean | 6 +- .../Complexity/Classes/Oracle/Lowness.lean | 9 ++- .../Complexity/Classes/Oracle/PP.lean | 3 +- .../Complexity/Classes/Oracle/Space.lean | 12 ++-- .../Complexity/Classes/P/Slices.lean | 8 +-- .../Complexity/Classes/PH/KarpLipton.lean | 9 ++- .../Complexity/Classes/PH/Projection.lean | 3 +- .../Classes/PH/SipserLautemann.lean | 4 +- .../Classes/PP/Characterization.lean | 4 +- .../Complexity/Classes/PP/TruthTable.lean | 3 +- .../Complexity/Classes/Padding.lean | 13 ++-- .../Complexity/Classes/ParityP.lean | 4 +- .../Complexity/Classes/Promise/Basic.lean | 8 ++- .../Computability/Complexity/Classes/RP.lean | 4 +- .../Computability/Complexity/Classes/SBP.lean | 6 +- .../Complexity/Classes/SBP/Amplification.lean | 3 +- .../Classes/SharpP/Aggregation.lean | 10 +-- .../Complexity/Classes/SharpP/Lowness.lean | 6 +- .../Complexity/Classes/SharpP/PolyTime.lean | 4 +- .../Complexity/Classes/SharpP/Products.lean | 3 +- .../Complexity/Classes/SharpP/Space.lean | 3 +- .../Complexity/Classes/Space/Closure.lean | 8 +-- .../GeneralizedGeography/Membership.lean | 3 +- .../Space/GeneralizedGeography/Reduction.lean | 9 ++- .../Classes/Space/TQBF/Membership.lean | 6 +- .../Classes/Space/TQBF/PolyTime.lean | 27 +++++--- .../Complexity/Classes/TFNP.lean | 4 +- .../Classes/TFNP/SearchToDecision.lean | 6 +- .../Complexity/Classes/TFNP/Subclasses.lean | 6 +- .../Complexity/Classes/Time.lean | 9 +-- .../Complexity/Classes/Toda/Hierarchy.lean | 11 ++- .../Computability/Complexity/Classes/WPP.lean | 8 ++- .../Complexity/Classes/WPP/Lowness.lean | 3 +- .../Complexity/CookLevin/Clauses.lean | 5 +- .../Complexity/Fagin/Verifier.lean | 3 +- .../Computability/Complexity/FineGrained.lean | 4 +- .../Complexity/FineGrained/BruteForce.lean | 7 +- .../FineGrained/OrthogonalVectors.lean | 15 ++-- .../Complexity/FineGrained/Reduction.lean | 3 +- .../Complexity/HardnessEncoding/PolyTime.lean | 11 ++- .../Complexity/Parameterized.lean | 20 ++++-- .../Complexity/Parameterized/VertexCover.lean | 7 +- .../Complexity/Problems/CircuitSAT.lean | 7 +- .../Problems/CircuitValue/Compilation.lean | 4 +- .../Problems/CircuitValue/Completeness.lean | 7 +- .../Problems/CircuitValue/Writer.lean | 12 +++- .../Problems/Hamiltonian/Diamond.lean | 6 +- .../Problems/Hamiltonian/Directed.lean | 6 +- .../MonotoneCircuitValue/Completeness.lean | 3 +- .../Complexity/Problems/TSP.lean | 3 +- .../Complexity/Problems/VertexCover.lean | 3 +- .../Computability/PCP/Encoded/Power.lean | 3 +- .../PCP/Encoded/Preprocess/Programs.lean | 3 +- .../PCP/Encoded/Verifier/Reduction.lean | 3 +- .../TreeEval/Reader/Cert/Machine.lean | 12 ++-- .../TreeEval/Reader/Cert/Offset.lean | 20 ++++-- .../TreeEval/Reader/Cert/Regs.lean | 9 ++- .../TreeEval/Reader/Cert/Residue.lean | 16 +++-- .../TreeEval/Reader/Cert/Step.lean | 69 +++++++++++-------- .../TreeEval/Reader/Cert/Weight.lean | 7 +- .../Computability/USTCON/Reader/Cert.lean | 3 +- Complexity/Computability/USTCON/Space.lean | 3 +- ComplexityTests/Axioms.lean | 64 ++++++++++------- ComplexityTests/ClassCorollaries.lean | 3 +- ComplexityTests/CountingAggregation.lean | 3 +- ComplexityTests/CountingGapMachine.lean | 6 +- ComplexityTests/CountingSpace.lean | 15 ++-- ComplexityTests/FineGrained.lean | 6 +- ComplexityTests/InteractiveProofs.lean | 9 +-- ComplexityTests/Kannan.lean | 5 +- ComplexityTests/KarpLipton2.lean | 10 +-- ComplexityTests/NPWitness.lean | 3 +- .../NondeterministicVerifiers.lean | 3 +- ComplexityTests/PCPEncodedPreprocess.lean | 9 ++- ComplexityTests/Parameterized.lean | 3 +- ComplexityTests/TFNP.lean | 3 +- ComplexityTests/TFNPCompleteness.lean | 9 ++- ComplexityTests/WPPBounded.lean | 3 +- ComplexityTests/WPPRobustness.lean | 3 +- ComplexityTests/WPPTruthTable.lean | 6 +- ComplexityTests/WPPTwoSided.lean | 3 +- ComplexityTests/ZooCountingHierarchy.lean | 3 +- 102 files changed, 519 insertions(+), 277 deletions(-) diff --git a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean index a1793e6d3..00a5d70eb 100644 --- a/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean +++ b/Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean @@ -324,7 +324,8 @@ theorem computableInPolyTime_codeBound : unfold codeBound have := ComputableInPolyTime.binary_two_pow fun_prop - exact ComputableInPolyTime.binary_to_unary_bounded hvalue (bound := fun N => 2 * (N + 1) * (N + 1)) (by fun_prop) + exact ComputableInPolyTime.binary_to_unary_bounded hvalue + (bound := fun N => 2 * (N + 1) * (N + 1)) (by fun_prop) codeBound_le /-! ### The multiplication table -/ @@ -398,7 +399,8 @@ theorem computableInPolyTime_monomialBit_explicit' {α : Type} {input : α ↪ L have hu := hu.tidy have hw := hw.tidy have hv := hv.tidy - exact .of_tidy (computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv)) + exact .of_tidy + (computableTidilyInPolyTime_monomialBit_explicit.comp (((hN.prod hu).prod hw).prod hv)) /-- `computableInPolyTime_monomialBit_explicit'` for tidy `fun_prop` inside proofs. -/ private theorem computableTidilyInPolyTime_monomialBit_explicit' {α : Type} @@ -639,8 +641,8 @@ private theorem computableTidilyInPolyTime_explicitDisperserProgram : (computableInPolyTime_symDegree.tidy.comp length_bits)).prod id') /-- **The explicit affine disperser is computable in polynomial time**: on a bit list `x` of length -`N`, the value `explicitDisperser N x` is computed by a tidy multi-tape machine in time polynomial -in `N`. The certificate charges the whole computation: the parameters, the exhaustive searches for +`N`, the value `explicitDisperser N x` is computed by a multi-tape machine in time polynomial in +`N`. The certificate charges the whole computation: the parameters, the exhaustive searches for the irreducible polynomials by trial division, the remainders of the powers of `X`, the multiplication table, and every field operation of `traceSym 1 r t`. -/ theorem computableInPolyTime_explicitDisperser : diff --git a/Complexity/Computability/Complexity/Classes/Alternation/Game.lean b/Complexity/Computability/Complexity/Classes/Alternation/Game.lean index f15e5a549..9da58b095 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/Game.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/Game.lean @@ -239,7 +239,8 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} theorem exists_isGameVerifier_of_mem_AP (h : A ∈ AP enc) : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by - have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V + (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by obtain ⟨t, ht, k, State, hfinite, atm, hdecides⟩ := h obtain ⟨c, d, hle⟩ := ht.exists_le exact ⟨_, atm.gameVerifier enc, atm.computableTidilyInPolyTime_gameVerifier, diff --git a/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean b/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean index fdc74e1c3..a12fcb046 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean @@ -187,7 +187,8 @@ variable {α : Type} {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × Li Stockmeyer][ChandraKozenStockmeyer1981]: a problem with a polynomial-time game verifier is decided in polynomial time by the guess-then-verify machine, which writes the moves of the two players, alternately, and then runs the verifier. -/ -theorem IsGameVerifier.mem_AP (hV : Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool) +theorem IsGameVerifier.mem_AP + (hV : Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool) (h : IsGameVerifier enc p V A) : A ∈ AP enc := by have hV := hV.tidy -- the number of moves, and the word prepared on tape `B` diff --git a/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean b/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean index 003ddf5f9..adfd0b242 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean @@ -296,7 +296,8 @@ noncomputable def savitchVerifier (x : α × List Bool) : Bool := /-- The verifier of the midpoint game is polynomial-time. -/ theorem computableInPolyTime_savitchVerifier : - Turing.MultiTapeTM.ComputableInPolyTime (savitchVerifier (enc := enc) ntm c d) (encPair enc encBits) + Turing.MultiTapeTM.ComputableInPolyTime (savitchVerifier (enc := enc) ntm c d) + (encPair enc encBits) encBool := by refine .of_tidy ?_ have hwidth : ComputableTidilyInPolyTime (fun x : α × List Bool => ntm.codeWidth c d (enc x.1)) @@ -346,8 +347,10 @@ space. The game has `2 * ((W + 1) * W)` moves for the width `W` of the codes, pa polynomial number. -/ theorem exists_isGameVerifier_of_mem_PSPACE (h : A ∈ PSPACE enc) : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by - have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by + Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p + V A := by + have this : ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V + (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := by obtain ⟨k, State, _, ntm, s, hs, hA⟩ := PSPACE_subset_NPSPACE h obtain ⟨c, d, hcd⟩ := hs.exists_le -- the number of rounds of the game is polynomially bounded @@ -387,7 +390,8 @@ theorem AP_eq_PSPACE : AP enc = PSPACE enc := /-- **The problems with polynomial-time game verifiers are exactly those in `PSPACE`.** -/ theorem mem_PSPACE_iff_exists_isGameVerifier : A ∈ PSPACE enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), - Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p V A := + Turing.MultiTapeTM.ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsGameVerifier enc p + V A := ⟨exists_isGameVerifier_of_mem_PSPACE, fun ⟨_, _, hV, h⟩ => h.mem_PSPACE hV⟩ end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean index b0c9b921c..cf0962866 100644 --- a/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean +++ b/Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean @@ -354,7 +354,8 @@ variable {γ : Type} {encIn : γ ↪ List Bool} theorem computableInPolyTime_roundTokens {w i : γ → ℕ} (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => roundTokens (w x) (i x)) encIn (encList encToken) := by + Turing.MultiTapeTM.ComputableInPolyTime (fun x => roundTokens (w x) (i x)) encIn + (encList encToken) := by unfold roundTokens fun_prop @@ -388,7 +389,8 @@ theorem computableInPolyTime_gameReduce {kV : ℕ} {StateV : Type} [Fintype Stat have htab := CookLevin.computableInPolyTime_tableau tmV have hframe := Turing.MultiTapeTM.ComputableInPolyTime.bitsFrame enc have hp : Turing.MultiTapeTM.ComputableInPolyTime (fun a => p.eval (enc a).length) enc encUnary := - (Turing.MultiTapeTM.ComputableInPolyTime.unary_eval p).comp (Turing.MultiTapeTM.ComputableInPolyTime.encoding_length enc) + (Turing.MultiTapeTM.ComputableInPolyTime.unary_eval p).comp + (Turing.MultiTapeTM.ComputableInPolyTime.encoding_length enc) unfold gameReduce fun_prop diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean index 9dd62e170..637bd61f9 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean @@ -193,7 +193,9 @@ theorem mem_MA_iff_exists_forall_errorExponent : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by - have this : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by + have this : A ∈ MA enc ↔ ∃ q : Polynomial ℕ, ∀ e : Polynomial ℕ, ∃ (p : Polynomial ℕ) + (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + IsMerlinArthurVerifierWithErrorExponent enc e q p V A := by rw [mem_MA] refine ⟨fun ⟨q, p, V, hV, h⟩ => ⟨q, fun e => ⟨12 * e * p, _, (computableInPolyTime_merlinArthurRepeat hV _ _ _).tidy, h.repeatMajority e⟩⟩, @@ -352,7 +354,9 @@ theorem mem_AM_iff_forall_errorExponent : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by - have this : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by + have this : A ∈ AM enc ↔ ∀ e : Polynomial ℕ, ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + IsArthurMerlinVerifierWithErrorExponent enc e p q V A := by rw [mem_AM] refine ⟨fun ⟨p, q, V, hV, h⟩ e => ⟨12 * e * p, 12 * e * q, _, (computableInPolyTime_arthurMerlinRepeat hV _ _ _).tidy, h.repeatMajority e⟩, fun h => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean index 9f87a7613..ae804e854 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Amplification.lean @@ -136,7 +136,9 @@ theorem mem_BPP_iff_forall_decidesWithErrorExponent {A : Set α} : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by - have this : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p V A := by + have this : A ∈ BPP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithErrorExponent enc q p + V A := by rw [mem_BPP] refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨12 * q * p, _, (computableInPolyTime_repeatMajority hV _ _).tidy, h.repeatMajority q⟩, fun h => ?_⟩ diff --git a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean index a4ac2f0b1..50e2eea54 100644 --- a/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean +++ b/Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean @@ -91,7 +91,8 @@ theorem exists_computableInO_of_mem_DTIME {A : Set (List Bool)} {t : ℕ → ℕ (h : A ∈ DTIME encBits t) : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ ComputableInO g encBits encBool (fun y => t y.length) fun y => t y.length := by - have this : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ ComputableTidilyInO g encBits encBool (fun y => t y.length) fun y => t y.length := by + have this : ∃ g : List Bool → Bool, (∀ y, y ∈ A ↔ g y = true) ∧ ComputableTidilyInO g encBits + encBool (fun y => t y.length) fun y => t y.length := by obtain ⟨c₁, c₂, s, hA⟩ := h obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA obtain ⟨c, hg⟩ := hg.exists_space_linear @@ -249,8 +250,8 @@ theorem computableInPolyTime_greedyMasks {seed block overlap : γ → ℕ} · simp [length_encList, hw] · exact Nat.le_add_right _ _ -/-- **The generator on lists in polynomial time.** Let `g` be tidily computable within time and -space `O(T n)` on words of length `n`, for a monotone `T`. With computed block size `block x`, +/-- **The generator on lists in polynomial time.** Let `g` be computable within time and space +`O(T n)` on words of length `n`, for a monotone `T`. With computed block size `block x`, masks `masks x` and seed `seed x`, the generator on lists is polynomial-time in `x` when `T (block x)` is polynomially bounded. -/ theorem computableInPolyTime_listGenerator {g : List Bool → Bool} {T : ℕ → ℕ} @@ -263,7 +264,10 @@ theorem computableInPolyTime_listGenerator {g : List Bool → Bool} {T : ℕ → (hbudget : PolyBounded (fun x => (encIn x).length) fun x => T (block x)) : ComputableInPolyTime (fun x => listGenerator g (block x) (masks x) (seed x)) encIn encBits := by - have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by simpa only [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] using hg + have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by + simpa only + [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] + using hg have hblock := hblock.tidy have hmasks := hmasks.tidy have hseed := hseed.tidy @@ -300,7 +304,7 @@ def nwDecider (V : α × List Bool → Bool) (g : List Bool → Bool) (seed bloc V (x, listGenerator g (block x) ((greedyMasks (seed x) (block x) (overlap x)).take (out x)) z)) /-- **The Nisan–Wigderson decider in polynomial time.** Let `V` be polynomial-time and let `g` be -tidily computable within time and space `O(T n)` on words of length `n`, for a monotone `T`. With +computable within time and space `O(T n)` on words of length `n`, for a monotone `T`. With polynomial-time unary parameters, `nwDecider` is polynomial-time when `2 ^ seed x` and `T (block x)` are polynomially bounded in the length of the instance. -/ theorem computableInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List Bool → Bool} @@ -315,7 +319,10 @@ theorem computableInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List (hblockBudget : PolyBounded (fun x => (enc x).length) fun x => T (block x)) : ComputableInPolyTime (nwDecider V g seed block overlap out) enc encBool := by have hV := hV.tidy - have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] using hg + have hg : ComputableTidilyInO g encBits encBool (fun y => T y.length) fun y => T y.length := by + simpa only + [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] + using hg have hseed := hseed.tidy have hblock := hblock.tidy have hoverlap := hoverlap.tidy @@ -329,9 +336,11 @@ theorem computableInPolyTime_nwDecider {V : α × List Bool → Bool} {g : List (encPair enc encBits) (encList encBits) := listTakeWithInput (computableInPolyTime_greedyMasks (.of_tidy (hseed.comp (fst enc encBits))) - (.of_tidy (hblock.comp (fst enc encBits))) (.of_tidy (hoverlap.comp (fst enc encBits))) (hfst hseedBudget)).tidy + (.of_tidy (hblock.comp (fst enc encBits))) (.of_tidy (hoverlap.comp (fst enc encBits))) + (hfst hseedBudget)).tidy (hout.comp (fst enc encBits)) - have hgen := (computableInPolyTime_listGenerator hT (.of_tidy hg) (.of_tidy (hblock.comp (fst enc encBits))) + have hgen := + (computableInPolyTime_listGenerator hT (.of_tidy hg) (.of_tidy (hblock.comp (fst enc encBits))) (.of_tidy hmasks) (.of_tidy (snd enc encBits)) (hfst hblockBudget)).tidy have hvote : ComputableTidilyInPolyTime (fun p : α × List Bool => V (p.1, listGenerator g (block p.1) ((greedyMasks (seed p.1) (block p.1) (overlap p.1)).take diff --git a/Complexity/Computability/Complexity/Classes/Constructible.lean b/Complexity/Computability/Complexity/Classes/Constructible.lean index 21fda57f3..6898d3000 100644 --- a/Complexity/Computability/Complexity/Classes/Constructible.lean +++ b/Complexity/Computability/Complexity/Classes/Constructible.lean @@ -100,7 +100,7 @@ theorem TimeConstructible.computableInO {t : ℕ → ℕ} (ht : TimeConstructibl exact (hs _).trans (Nat.mul_le_mul_right _ (by omega)) · exact (Nat.le_succ _).trans (Nat.le_mul_of_pos_left _ (by omega)) -/-- A tidy computation of `t n` in binary within time `O(t n)` makes `t` time-constructible. -/ +/-- A computation of `t n` in binary within time `O(t n)` makes `t` time-constructible. -/ theorem TimeConstructible.of_computableInO {t : ℕ → ℕ} {T S : List Bool → ℕ} {s : ℕ → ℕ} (c : ℕ) (h : ComputableInO (fun x : List Bool => t x.length) encBits encNat T S) (hT : ∀ x, T x ≤ c * t x.length + c) (hS : ∀ x, S x ≤ s x.length) : TimeConstructible t := by @@ -257,7 +257,7 @@ theorem TimeConstructible.spaceConstructible {t : ℕ → ℕ} (ht : TimeConstru exact ⟨k * c + k, fun n => c * t n + c, ComputableInTimeAndSpace.mono h (fun _ => le_rfl) fun x => by dsimp only; nlinarith⟩ -/-- A tidy computation of `s n` in binary within space `O(s n)` makes `s` space-constructible: +/-- A computation of `s n` in binary within space `O(s n)` makes `s` space-constructible: it halts within a time bound of `n`, its number of configurations. -/ theorem SpaceConstructible.of_computableInO {s : ℕ → ℕ} {T S : List Bool → ℕ} (c : ℕ) (h : ComputableInO (fun x : List Bool => s x.length) encBits encNat T S) diff --git a/Complexity/Computability/Complexity/Classes/FewP.lean b/Complexity/Computability/Complexity/Classes/FewP.lean index e95105e8d..0dc722cfe 100644 --- a/Complexity/Computability/Complexity/Classes/FewP.lean +++ b/Complexity/Computability/Complexity/Classes/FewP.lean @@ -62,7 +62,10 @@ theorem mem_FewP : A ∈ FewP enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ q.eval (enc a).length) ∧ ∀ a, a ∈ A ↔ 0 < acceptCount V a (p.eval (enc a).length) := by - have this : A ∈ FewP enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a, acceptCount V a (p.eval (enc a).length) ≤ q.eval (enc a).length) ∧ ∀ a, a ∈ A ↔ 0 < acceptCount V a (p.eval (enc a).length) := by + have this : A ∈ FewP enc ↔ ∃ (p q : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + (∀ a, acceptCount V a (p.eval (enc a).length) ≤ q.eval (enc a).length) ∧ ∀ a, a ∈ A ↔ 0 < + acceptCount V a (p.eval (enc a).length) := by constructor · rintro ⟨f, ⟨p, V, hV, hf⟩, q, hle, hA⟩ exact ⟨p, q, V, hV.tidy, fun a => hf a ▸ hle a, fun a => by rw [hA a, hf a]⟩ diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Hierarchy.lean index c6dc97e8e..fd4f8e4dc 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy.lean @@ -175,7 +175,8 @@ namespace Diagonal theorem computableInO_verdict : ComputableInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) fun r => (eOut r).length := by - have this : ComputableTidilyInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) fun r => (eOut r).length := by + have this : ComputableTidilyInO verdict eOut encBool (fun r => ((eOut r).length + 1) ^ 2) fun r => + (eOut r).length := by have heq := (ComputableTidilyInO.eq (encList encUnary)).comp ((ComputableTidilyInO.fst (encList encUnary) encBool).prod (ComputableTidilyInO.const (encMid := encList encUnary) [eBit true])) @@ -263,7 +264,8 @@ run and the test. -/ theorem computableInO_diagonal : ComputableInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) fun x => 2 ^ (2 * x.length) := by - have this : ComputableTidilyInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) fun x => 2 ^ (2 * x.length) := by + have this : ComputableTidilyInO diagonal encBits encBool (fun x => 2 ^ (4 * x.length)) + fun x => 2 ^ (2 * x.length) := by obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc have hu : ComputableTidilyInDegree unframe encBits encBits 1 1 := .of_linear (.of_unframe fun _ => rfl) @@ -278,7 +280,8 @@ theorem computableInO_diagonal : obtain ⟨cO, hcO⟩ := hU.length_le -- one power of two absorbs every polynomial factor obtain ⟨C, hC⟩ := PolynomiallyBounded.exists_le_mul_two_pow - (p := fun n => (cD * ((n + 1) ^ max 1 (1 * dd) + 1) + (n + 1) ^ max 1 (1 * dd) + 4 * n + 2) ^ 5) + (p := fun n => (cD * ((n + 1) ^ max 1 (1 * dd) + 1) + (n + 1) ^ max 1 (1 * dd) + 4 * n + 2) ^ + 5) (by fun_prop) set K := 100100 + 44100 * (cO + 1) ^ 2 with hK have hbounds (x : List Bool) := by diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean index cfaf9cbda..ea6208633 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean @@ -61,7 +61,8 @@ theorem shortDesc_eq_decide (x : List Bool) : theorem computableInO_shortDesc : ComputableInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) fun x => x.length + 1 := by - have this : ComputableTidilyInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) fun x => x.length + 1 := by + have this : ComputableTidilyInO shortDesc encBits encBool (fun x => (x.length + 1) ^ 2) fun x => + x.length + 1 := by have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) have ha := ComputableTidilyInDegree.unary_succ.inO_one.comp diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean index 930e85bc3..7ff7d94dc 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean @@ -121,7 +121,8 @@ space linear in the description, the budget and the lengths of the clock and of theorem computableInO_spaceDiagonal {G : ℕ → ℕ} (hG : SpaceConstructible G) : ∃ T, ComputableInO (spaceDiagonal G) encBits encBool T fun x => x.length + G x.length := by - have this : ∃ T, ComputableTidilyInO (spaceDiagonal G) encBits encBool T fun x => x.length + G x.length := by + have this : ∃ T, ComputableTidilyInO (spaceDiagonal G) encBits encBool T fun x => x.length + G + x.length := by obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) diff --git a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean index 0edc554ad..779da1817 100644 --- a/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean @@ -226,7 +226,9 @@ theorem computableInO_timeDiagonal {J : ℕ → ℕ} (hJ : TimeConstructible J) ComputableInO (timeDiagonal J) encBits encBool (fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3) fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := by - have this : ComputableTidilyInO (timeDiagonal J) encBits encBool (fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3) fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3 := by + have this : ComputableTidilyInO (timeDiagonal J) encBits encBool + (fun x => (x.length + 1) ^ 5 * (J x.length + 1) ^ 3) fun x => (x.length + 1) ^ 5 * + (J x.length + 1) ^ 3 := by obtain ⟨dd, ed, hdec⟩ := exists_computableTidilyInDegree_decodeDesc have hu : ComputableTidilyInO unframe encBits encBits (fun x => x.length) fun x => x.length := ComputableTidilyInO.of_linear (.of_unframe fun _ => rfl) diff --git a/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean b/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean index 61725eafb..7b1c07b58 100644 --- a/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean +++ b/Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean @@ -281,7 +281,8 @@ theorem computableInPolyTime_relabel {γ : Type} {input : γ ↪ List Bool} {G : (hkeys : ComputableInPolyTime keys input (encList encUnary)) : ComputableInPolyTime (fun x => relabel (G x) (keys x)) input encBits := by have hn : ComputableInPolyTime (fun x => (G x).distinctVertices.length) input encUnary := - (ComputableInPolyTime.length_list encNat).comp (Graph.computableInPolyTime_distinctVertices.comp hG) + (ComputableInPolyTime.length_list encNat).comp + (Graph.computableInPolyTime_distinctVertices.comp hG) unfold relabel simp only [List.flatMap_def] fun_prop diff --git a/Complexity/Computability/Complexity/Classes/IP/Simulation.lean b/Complexity/Computability/Complexity/Classes/IP/Simulation.lean index 66ca545fa..99ef3be2a 100644 --- a/Complexity/Computability/Complexity/Classes/IP/Simulation.lean +++ b/Complexity/Computability/Complexity/Classes/IP/Simulation.lean @@ -412,7 +412,8 @@ theorem countAccepts_eq_accepted (q : α × History) : number of coins computed in polynomial time. -/ theorem computableInPolySpace_countAccepts [Finite Control] (hfuel : Turing.MultiTapeTM.ComputableInPolyTime fuel enc encUnary) : - Turing.MultiTapeTM.ComputableInPolySpace (countAccepts MUnit enc fuel) (encPair enc encHistory) encNat := by + Turing.MultiTapeTM.ComputableInPolySpace (countAccepts MUnit enc fuel) (encPair enc encHistory) + encNat := by have hfuel := hfuel.tidy refine .of_tidy ?_ have hfuel' : ComputableTidilyInPolyTime (fun q : α × History => fuel q.1) diff --git a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean index 66a200b13..8ded46fff 100644 --- a/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean @@ -151,7 +151,8 @@ theorem computableInPolyTime_capPow {α : Type} {input : α ↪ List Bool} /-! ### Words by index -/ -private theorem computableTidilyInPolyTime_word : ComputableTidilyInPolyTime word encUnary encBits := by +private theorem computableTidilyInPolyTime_word : ComputableTidilyInPolyTime word encUnary + encBits := by have h : word = fun j => (encNat (j + 1)).take ((encNat (j + 1)).length - 1) := by funext j simp [word, encNat_apply, List.dropLast_eq_take] diff --git a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean index c8a8a5bfa..3b0d3e77b 100644 --- a/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean +++ b/Complexity/Computability/Complexity/Classes/MIP/NEXP.lean @@ -196,7 +196,7 @@ theorem consistentHistStep_suffix {h₂ : History} {s : History × Bool × Bool} · exact (List.tail_suffix s.1).trans hs · exact (List.tail_suffix s.1).trans hs -/-- `consistentHist` is computable tidily in polynomial time. -/ +/-- `consistentHist` is computable in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_consistentHist : Turing.MultiTapeTM.ComputableInPolyTime (fun p : History × History => consistentHist p.1 p.2) @@ -654,10 +654,11 @@ theorem computableInPolyTime_checkCert (c d : ℕ) : exact binary_lt' hpow (binary_mul' (const 2) hlen) exact bool_and' (bool_and' (bool_and' h1 h2) h3) h4 -/-- `checkPaddedCert` is computable tidily in polynomial time. -/ +/-- `checkPaddedCert` is computable in polynomial time. -/ @[fun_prop] theorem computableInPolyTime_checkPaddedCert (c d : ℕ) : - Turing.MultiTapeTM.ComputableInPolyTime (checkPaddedCert M c d) (encPair encBits encCert) encBool := by + Turing.MultiTapeTM.ComputableInPolyTime (checkPaddedCert M c d) (encPair encBits encCert) + encBool := by refine .of_tidy ?_ have hunframe : ComputableTidilyInPolyTime unframe encBits encBits := .of_linear (.of_unframe fun _ => rfl) diff --git a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean index 15ddf80e8..249ac321d 100644 --- a/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean +++ b/Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean @@ -275,9 +275,12 @@ finds a satisfying assignment of every satisfiable formula, as a certificate for theorem exists_search (h : SAT ∈ P encCNF) : ∃ g : CNF ℕ → List Bool, ComputableInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by - have this : ∃ g : CNF ℕ → List Bool, ComputableTidilyInPolyTime g encCNF encBits ∧ ∀ φ, verifier (φ, g φ) = true ↔ φ ∈ SAT := by + have this : ∃ g : CNF ℕ → List Bool, ComputableTidilyInPolyTime g encCNF encBits ∧ ∀ φ, verifier + (φ, g φ) = true ↔ φ ∈ SAT := by obtain ⟨D, hD, hSAT⟩ := mem_P.mp h - exact ⟨search D, (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (.of_tidy (snd _ _))).tidy) (.of_tidy id')).tidy, + exact ⟨search D, + (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.comp (.of_tidy (snd _ _))).tidy) + (.of_tidy id')).tidy, fun φ => verifier_search_iff fun ψ _ => (hSAT ψ).symm⟩ simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this diff --git a/Complexity/Computability/Complexity/Classes/NP/Witness.lean b/Complexity/Computability/Complexity/Classes/NP/Witness.lean index 0b1920a8d..e1de7870c 100644 --- a/Complexity/Computability/Complexity/Classes/NP/Witness.lean +++ b/Complexity/Computability/Complexity/Classes/NP/Witness.lean @@ -231,8 +231,10 @@ theorem computableInPolyTime_subsetVerifier {encγ : γ ↪ List Bool} {vs : α (hvs : ComputableInPolyTime vs enc (encList encγ)) {check : α × List γ → Bool} (hcheck : ComputableInPolyTime check (encPair enc (encList encγ)) encBool) : ComputableInPolyTime (subsetVerifier vs check) (encPair enc encBits) encBool := - hcheck.comp ((ComputableInPolyTime.fst enc encBits).prod ((computableInPolyTime_selectDistinct encγ).comp - ((hvs.comp (ComputableInPolyTime.fst enc encBits)).prod (ComputableInPolyTime.snd enc encBits)))) + hcheck.comp + ((ComputableInPolyTime.fst enc encBits).prod ((computableInPolyTime_selectDistinct encγ).comp + ((hvs.comp (ComputableInPolyTime.fst enc encBits)).prod + (ComputableInPolyTime.snd enc encBits)))) /-- **NP membership of subset problems.** If the candidates `vs a` and the check of the selected candidates are polynomial-time, and `check` decides `P a` on duplicate-free lists of candidates, diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean index fb7657de4..2e3ebef96 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Closure.lean @@ -74,7 +74,8 @@ theorem preprocess {f : β → γ} {g : α → β} (hf : ComputableInPolyTimeWit /-- Polynomial-time postprocessing of the result, which may also use the argument. -/ theorem map_with {f : α → β} {g : α → β → γ} (hf : ComputableInPolyTimeWithOracle A f input middle) - (hg : Turing.MultiTapeTM.ComputableInPolyTime (fun pair => g pair.1 pair.2) (encPair input middle) output) : + (hg : Turing.MultiTapeTM.ComputableInPolyTime (fun pair => g pair.1 pair.2) + (encPair input middle) output) : ComputableInPolyTimeWithOracle A (fun a => g a (f a)) input output := by have hg := hg.tidy obtain ⟨program, hprogram, heq⟩ := hf @@ -148,7 +149,8 @@ theorem mem_PWithOracle_self (A : Set (List Bool)) : A ∈ PWithOracle A encBits certificate. -/ theorem PWithOracle_subset_NPWithOracle (A : Set (List Bool)) (enc : α ↪ List Bool) : PWithOracle A enc ⊆ NPWithOracle A enc := fun _ ⟨f, hf, h⟩ => - ⟨0, fun aw => f aw.1, hf.preprocess (.of_tidy (ComputableTidilyInPolyTime.fst enc encBits)), fun a => by + ⟨0, fun aw => f aw.1, hf.preprocess (.of_tidy (ComputableTidilyInPolyTime.fst enc encBits)), + fun a => by simp only [Polynomial.eval_zero, List.length_eq_zero_iff, exists_eq_left, h]⟩ /-- **`P` relative to an oracle is closed under polynomial-time many-one reductions.** -/ diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean b/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean index b5ff6ed76..7fe6b5f5e 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Lowness.lean @@ -105,7 +105,8 @@ theorem inter_mem_PWithOracle {L₁ L₂ : Set α} (h₁ : L₁ ∈ PWithOracle (h₂ : L₂ ∈ PWithOracle A enc) : L₁ ∩ L₂ ∈ PWithOracle A enc := by obtain ⟨f₁, hf₁, hL₁⟩ := h₁ obtain ⟨f₂, hf₂, hL₂⟩ := h₂ - refine ⟨fun a => f₁ a && f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 && p.2) (.of_tidy (by fun_prop)), + refine ⟨fun a => f₁ a && f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 && p.2) + (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [Set.mem_inter_iff, hL₁ a, hL₂ a, Bool.and_eq_true] @@ -114,7 +115,8 @@ theorem union_mem_PWithOracle {L₁ L₂ : Set α} (h₁ : L₁ ∈ PWithOracle (h₂ : L₂ ∈ PWithOracle A enc) : L₁ ∪ L₂ ∈ PWithOracle A enc := by obtain ⟨f₁, hf₁, hL₁⟩ := h₁ obtain ⟨f₂, hf₂, hL₂⟩ := h₂ - refine ⟨fun a => f₁ a || f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 || p.2) (.of_tidy (by fun_prop)), + refine ⟨fun a => f₁ a || f₂ a, (hf₁.prod hf₂).map (g := fun p => p.1 || p.2) + (.of_tidy (by fun_prop)), fun a => ?_⟩ rw [Set.mem_union, hL₁ a, hL₂ a, Bool.or_eq_true] @@ -187,7 +189,8 @@ private theorem replayStepFactor_mem_SharpP [Finite Control] [Finite Operation] (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop exact SharpP.ite_mem (.of_tidy hquery) - (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) (SharpP.comp_mem hNo (.of_tidy hreq))) + (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) + (SharpP.comp_mem hNo (.of_tidy hreq))) (SharpP.ite_mem (.of_tidy hbit) SharpP.zero_mem SharpP.one_mem) private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] diff --git a/Complexity/Computability/Complexity/Classes/Oracle/PP.lean b/Complexity/Computability/Complexity/Classes/Oracle/PP.lean index ad5f5216b..b8ccef510 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/PP.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/PP.lean @@ -147,7 +147,8 @@ theorem exists_mem_PP_mem_PWithOracle_image (hL : L ∈ PWithPPOracle enc) : theorem setOf_le_mem_PP {f : α → ℕ} (hf : f ∈ SharpP enc) : {x : α × ℕ | x.2 ≤ f x.1} ∈ PP (encPair enc encNat) := by refine mem_PP_iff_exists_GapP.2 ⟨fun x => ((f x.1 + 1 : ℕ) : ℤ) - (x.2 : ℕ), - ⟨_, SharpP.add_one_mem (SharpP.comp_mem hf (.of_tidy (ComputableTidilyInPolyTime.fst enc encNat))), _, + ⟨_, SharpP.add_one_mem + (SharpP.comp_mem hf (.of_tidy (ComputableTidilyInPolyTime.fst enc encNat))), _, mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.snd enc encNat)), fun _ => rfl⟩, fun x => ?_⟩ simp only [Set.mem_ofPred_eq, sub_pos, Nat.cast_lt] diff --git a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean index 2f6c96e75..8de135b16 100644 --- a/Complexity/Computability/Complexity/Classes/Oracle/Space.lean +++ b/Complexity/Computability/Complexity/Classes/Oracle/Space.lean @@ -65,13 +65,15 @@ variable {α β : Type} {enc : α ↪ List Bool} length of the encoded instance. -/ theorem exists_computableInO_of_mem_PSPACE {L : Set α} (hL : L ∈ PSPACE enc) : ∃ T S, PolyBounded (fun a => (enc a).length) S ∧ - ∃ f : α → Bool, Turing.MultiTapeTM.ComputableInO f enc encBool T S ∧ ∀ a, a ∈ L ↔ f a = true := + ∃ f : α → Bool, Turing.MultiTapeTM.ComputableInO f enc encBool T S ∧ ∀ a, a ∈ L ↔ f a = + true := let ⟨f, T, S, hf, hS, hL⟩ := mem_PSPACE_iff_computableInO.mp hL ⟨T, S, hS, f, hf, hL⟩ /-- A decider within polynomial space puts a problem in `PSPACE`. -/ theorem mem_PSPACE_of_computableInO {L : Set α} {f : α → Bool} {T S : α → ℕ} - (hf : Turing.MultiTapeTM.ComputableInO f enc encBool T S) (hS : PolyBounded (fun a => (enc a).length) S) + (hf : Turing.MultiTapeTM.ComputableInO f enc encBool T S) + (hS : PolyBounded (fun a => (enc a).length) S) (hL : ∀ a, a ∈ L ↔ f a = true) : L ∈ PSPACE enc := mem_PSPACE_iff_computableInO.mpr ⟨f, T, S, hf, hS, hL⟩ @@ -81,12 +83,14 @@ theorem mem_PSPACE_of_computableInO {L : Set α} {f : α → Bool} {T S : α → polynomial space and certificates of polynomial length is in `PSPACE`, by closure of `PSPACE` under polynomially bounded existential quantification (`Cslib.Complexity.setOf_exists_mem_PSPACE`). -/ theorem mem_PSPACE_of_isVerifier {p : Polynomial ℕ} {V : α × List Bool → Bool} {L : Set α} - {T S : α × List Bool → ℕ} (hV : Turing.MultiTapeTM.ComputableInO V (encPair enc encBits) encBool T S) + {T S : α × List Bool → ℕ} + (hV : Turing.MultiTapeTM.ComputableInO V (encPair enc encBits) encBool T S) (hS : PolyBounded (fun x => (encPair enc encBits x).length) S) (hL : IsVerifier enc p V L) : L ∈ PSPACE enc := by have hB : {x | V x = true} ∈ PSPACE (encPair enc encBits) := mem_PSPACE_of_computableInO hV hS fun _ => Iff.rfl - have hℓ : Turing.MultiTapeTM.ComputableInPolyTime (fun a : α => p.eval (enc a).length) enc encUnary := + have hℓ : Turing.MultiTapeTM.ComputableInPolyTime (fun a : α => p.eval (enc a).length) enc + encUnary := (Turing.MultiTapeTM.ComputableInPolyTime.unary_eval p).comp (.encoding_length enc) have hEq : L = {x | ∃ w : List Bool, w.length = p.eval (enc x).length ∧ (x, w) ∈ {x : α × List Bool | V x = true}} := diff --git a/Complexity/Computability/Complexity/Classes/P/Slices.lean b/Complexity/Computability/Complexity/Classes/P/Slices.lean index d3d9be8b7..05ba18a5a 100644 --- a/Complexity/Computability/Complexity/Classes/P/Slices.lean +++ b/Complexity/Computability/Complexity/Classes/P/Slices.lean @@ -20,14 +20,14 @@ import Mathlib.Data.List.GetD A Boolean family `f : ∀ n, BitString n → Bool` determines the language `Language.ofSlices f` of bit lists `x` with `f x.length x = true`. Reading `x` through `BitString.ofList`, the language is in `Cslib.Complexity.P encBits` exactly when its list evaluator -`fun x => f x.length (BitString.ofList x.length x)` is tidily computable in polynomial time. +`fun x => f x.length (BitString.ofList x.length x)` is computable in polynomial time. ## Main results * `Cslib.Complexity.mem_ofSlices_iff`, `Cslib.Complexity.ofSlices_eq_setOf_ofList`: membership in `Language.ofSlices f` via `BitString.ofList`. * `Cslib.Complexity.ofSlices_mem_P_iff`: `Language.ofSlices f ∈ P encBits` if and only if its list - evaluator is tidily computable in polynomial time. + evaluator is computable in polynomial time. * `Cslib.Complexity.ofSlices_mem_P`: the sufficient direction. -/ @@ -52,8 +52,8 @@ theorem ofSlices_eq_setOf_ofList (f : ∀ N, BitString N → Bool) : {x : List Bool | f x.length (BitString.ofList x.length x) = true} := Set.ext fun x => mem_ofSlices_iff f x -/-- If `fun x => f x.length (BitString.ofList x.length x)` is tidily computable in polynomial time, -then `Language.ofSlices f` belongs to `P encBits`. -/ +/-- If `fun x => f x.length (BitString.ofList x.length x)` is computable in polynomial time, then +`Language.ofSlices f` belongs to `P encBits`. -/ theorem ofSlices_mem_P {f : ∀ n, BitString n → Bool} (hf : ComputableInPolyTime (fun x : List Bool => f x.length (BitString.ofList x.length x)) encBits encBool) : diff --git a/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean b/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean index 7dc7d1be3..ef684914f 100644 --- a/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean +++ b/Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean @@ -242,7 +242,8 @@ private theorem computableTidilyInPolyTime_verifier {f : α × List Bool → CNF (encPair (encPair enc encBits) encCNF) encBool := by have hn' := hn.comp (fst (encPair enc encBits) encCNF) exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn')) - (.of_tidy ((unary_eval W).comp hn')) (.of_tidy (bitsTakeWithInput (fst _ _).snd' ((unary_eval P).comp hn'))) + (.of_tidy ((unary_eval W).comp hn')) + (.of_tidy (bitsTakeWithInput (fst _ _).snd' ((unary_eval P).comp hn'))) (.of_tidy ((encode encCNF).comp (snd _ _)))).tidy exact SAT.computableInPolyTime_verifier.tidy.comp (hφ.prod (SAT.computableInPolyTime_search (.of_tidy hD) (.of_tidy hφ)).tidy) @@ -381,7 +382,8 @@ theorem PolyTimeReducible.exists_mem_PPoly {β : Type} {encB : β ↪ List Bool} (encPair encBits enc) encUnary := (encoding_length enc).comp (snd _ _) exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn)) - (.of_tidy ((unary_eval W).comp hn)) (.of_tidy (fst _ _)) (.of_tidy ((encode encB).comp (hf.tidy.comp (snd _ _))))).tidy + (.of_tidy ((unary_eval W).comp hn)) (.of_tidy (fst _ _)) + (.of_tidy ((encode encB).comp (hf.tidy.comp (snd _ _))))).tidy obtain ⟨M, hM, hgM⟩ := PPoly.exists_of_polyTime (.of_tidy hg) let α_adv : ℕ → List Bool := fun n => familyAdvice (N.eval n) (S.eval n) C have hα : PolynomiallyBounded fun n => (α_adv n).length := by @@ -449,7 +451,8 @@ theorem mem_PPoly_of_exists_frame_append (encPair encBits encBits) encBits := bitsTakeWithInput (snd _ _) ((unary_eval p).comp hn) exact (computableInPolyTime_evalAdvice (.of_tidy ((unary_eval S).comp hn)) - (.of_tidy ((unary_eval W).comp hn)) (.of_tidy hu) (.of_tidy (bitsAppend ((bitsFrame encBits).comp hx) hw))).tidy + (.of_tidy ((unary_eval W).comp hn)) (.of_tidy hu) + (.of_tidy (bitsAppend ((bitsFrame encBits).comp hx) hw))).tidy let D : Language Bool := {z : List Bool | ∃ w : List Bool, w.length = p.eval z.length ∧ V (z, w) = true} have hD : D ∈ PPoly := hNP D ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩ diff --git a/Complexity/Computability/Complexity/Classes/PH/Projection.lean b/Complexity/Computability/Complexity/Classes/PH/Projection.lean index 53e16b9ff..083289e38 100644 --- a/Complexity/Computability/Complexity/Classes/PH/Projection.lean +++ b/Complexity/Computability/Complexity/Classes/PH/Projection.lean @@ -150,7 +150,8 @@ theorem exists_mem_PiP_of_mem_SigmaP_succ {k : ℕ} {A : Set α} (hA : A ∈ Sig (computableInPolyTime_truncateBlocks ps (.of_tidy ((ComputableTidilyInPolyTime.encoding_length enc).comp ((ComputableTidilyInPolyTime.fst _ _).comp hfst))) - (.of_tidy ((ComputableTidilyInPolyTime.encoding_length _).comp hfst)) (.of_tidy (.snd _ _))).tidy)) + (.of_tidy ((ComputableTidilyInPolyTime.encoding_length _).comp hfst)) + (.of_tidy (.snd _ _))).tidy)) · exact (alternation_truncateBlocks (hle y) (P := fun w => V (y.1, y.2 ++ w) = true)).symm end Cslib.Complexity diff --git a/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean b/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean index f84dddb0e..330150c0c 100644 --- a/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean +++ b/Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean @@ -63,7 +63,7 @@ quantifier duality (`Cslib.Complexity.compl_mem_PiP_of_mem_SigmaP`) then give * `Cslib.Complexity.SipserLautemann.exists_shifts_majorityAccepts`, `Cslib.Complexity.SipserLautemann.exists_seed_not_majorityAccepts`: combinatorial completeness and soundness of shifted majority votes. -* `Cslib.Complexity.SipserLautemann.verifier_polyTime`: the matrix verifier is computable tidily in +* `Cslib.Complexity.SipserLautemann.verifier_polyTime`: the matrix verifier is computable in polynomial time. * `Cslib.Complexity.SipserLautemann.isAlternatingVerifier_verifier`: the matrix verifier is a valid `Σ₂` alternating verifier for any `BPP` problem. @@ -343,7 +343,7 @@ def verifier (enc : α ↪ List Bool) (p : Polynomial ℕ) (V : α × List Bool let m := p.eval (enc x.1).length (List.range (shifts m)).any fun i => shiftAccepts enc p V x.1 x.2 i -/-- If `V` is computable tidily in polynomial time, then so is the Sipser–Lautemann matrix verifier +/-- If `V` is computable in polynomial time, then so is the Sipser–Lautemann matrix verifier `verifier enc p V`. -/ @[fun_prop] theorem verifier_polyTime {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × List Bool → Bool} diff --git a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean index 5a856af13..066772e41 100644 --- a/Complexity/Computability/Complexity/Classes/PP/Characterization.lean +++ b/Complexity/Computability/Complexity/Classes/PP/Characterization.lean @@ -100,7 +100,9 @@ theorem mem_PP_iff_decidesByNonstrictMajority {A : Set α} : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p V A := by - have this : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p V A := by + have this : A ∈ PP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesByNonstrictMajority enc p + V A := by constructor · intro hA obtain ⟨p, V, hV, h⟩ := mem_PP.mp (compl_mem_PP hA) diff --git a/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean b/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean index 49f11275a..a81bc6fbf 100644 --- a/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean +++ b/Complexity/Computability/Complexity/Classes/PP/TruthTable.lean @@ -193,7 +193,8 @@ private theorem ppTruthTableGap_mem {M r : α → ℕ} {g : α × ℕ → ℤ} { else newmanAmp (M x.1.1) (r x.1.1 + 1) (-g (x.1.1, x.2))) ∈ GapP (encPair (encPair enc encBits) encUnary) := - GapP.ite_mem (.of_tidy (by fun_prop)) (GapP.comp_mem hpos (.of_tidy hq)) (GapP.comp_mem hneg (.of_tidy hq)) + GapP.ite_mem (.of_tidy (by fun_prop)) (GapP.comp_mem hpos (.of_tidy hq)) + (GapP.comp_mem hneg (.of_tidy hq)) have hp := GapP.prod_range_mem hs (.of_tidy (hr.comp (.fst enc encBits))) have hw : ComputableTidilyInPolyTime (fun x => if d x then (1 : ℤ) else -1) (encPair enc encBits) encIntBin := by fun_prop diff --git a/Complexity/Computability/Complexity/Classes/Padding.lean b/Complexity/Computability/Complexity/Classes/Padding.lean index 7fac3a66f..59d6543e4 100644 --- a/Complexity/Computability/Complexity/Classes/Padding.lean +++ b/Complexity/Computability/Complexity/Classes/Padding.lean @@ -217,7 +217,8 @@ unary in polynomial time with `n ≤ f n`, then every problem decidable by a non within time `O(2 ^ f n)` is decidable deterministically within time `O(2 ^ (d * f n))` for some `d`. -/ theorem NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) - {f : ℕ → ℕ} (hf : Turing.MultiTapeTM.ComputableInPolyTime f encUnary encUnary) (hn : ∀ n, n ≤ f n) : + {f : ℕ → ℕ} (hf : Turing.MultiTapeTM.ComputableInPolyTime f encUnary encUnary) + (hn : ∀ n, n ≤ f n) : NTIME enc (fun n => 2 ^ f n) ⊆ ⋃ d, DTIME enc fun n => 2 ^ (d * f n) := by have hf := hf.tidy intro A hA @@ -259,7 +260,8 @@ theorem NE_subset_E_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) : NE enc ⊆ NTIME_mono (fun n => Nat.pow_le_pow_right (by norm_num) (Nat.mul_le_mul_right n (Nat.le_succ k))) hk obtain ⟨d, hd⟩ := Set.mem_iUnion.mp (NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P hNP - (f := fun n => (k + 1) * n) (.of_tidy (by fun_prop)) (fun n => Nat.le_mul_of_pos_left n (Nat.succ_pos k)) + (f := fun n => (k + 1) * n) (.of_tidy (by fun_prop)) + (fun n => Nat.le_mul_of_pos_left n (Nat.succ_pos k)) hk') exact mem_E_iff.mpr ⟨d * (k + 1), by simpa only [Nat.mul_assoc] using hd⟩ @@ -271,7 +273,8 @@ theorem NEXP_subset_EXP_of_NP_subset_P (hNP : NP encBits ⊆ P encBits) : NEXP e NTIME_mono_of_eventually_le (Filter.eventually_atTop.mpr ⟨1, fun n hn => Nat.pow_le_pow_right (by norm_num) (Nat.pow_le_pow_right hn (Nat.le_succ k))⟩) hk obtain ⟨d, hd⟩ := Set.mem_iUnion.mp (NTIME_two_pow_subset_iUnion_DTIME_of_NP_subset_P hNP - (.of_tidy (ComputableTidilyInPolyTime.unary_pow (k + 1))) (fun n => Nat.le_self_pow (by omega) n) hk') + (.of_tidy (ComputableTidilyInPolyTime.unary_pow (k + 1))) + (fun n => Nat.le_self_pow (by omega) n) hk') refine mem_EXP_iff.mpr ⟨k + 2, DTIME_mono_of_eventually_le (Filter.eventually_atTop.mpr ⟨d, fun n hn => Nat.pow_le_pow_right (by norm_num) ?_⟩) hd⟩ rw [pow_succ' n (k + 1)] @@ -298,8 +301,8 @@ open _root_.Turing.MultiTapeTM.ComputableTidilyInPolyTime variable {α : Type} {enc : α ↪ List Bool} -/-- Pulling back a problem `B ∈ NP encBits` along a function `g : α → List Bool` computable tidily -within time `O(T₀ (enc a).length)` places `g ⁻¹' B` in `NTIME enc (fun n => (T₀ n + 1) ^ d)` for +/-- Pulling back a problem `B ∈ NP encBits` along a function `g : α → List Bool` computable within +time `O(T₀ (enc a).length)` places `g ⁻¹' B` in `NTIME enc (fun n => (T₀ n + 1) ^ d)` for some `d`: a deterministic machine writes `g a` to a buffer tape and hands off to the halting fair-coin certificate verifier for `B`. -/ theorem preimage_mem_NTIME_of_mem_NP {B : Set (List Bool)} {g : α → List Bool} {T₀ : ℕ → ℕ} diff --git a/Complexity/Computability/Complexity/Classes/ParityP.lean b/Complexity/Computability/Complexity/Classes/ParityP.lean index 2eab204a4..b478711a0 100644 --- a/Complexity/Computability/Complexity/Classes/ParityP.lean +++ b/Complexity/Computability/Complexity/Classes/ParityP.lean @@ -134,7 +134,9 @@ variable {enc : α ↪ List Bool} {L : Set α} theorem mem_ParityP : L ∈ ParityP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ ∀ a, a ∈ L ↔ Odd (acceptCount V a (p.eval (enc a).length)) := by - have this : L ∈ ParityP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a, a ∈ L ↔ Odd (acceptCount V a (p.eval (enc a).length)) := by + have this : L ∈ ParityP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a, a ∈ L ↔ Odd + (acceptCount V a (p.eval (enc a).length)) := by classical constructor · rintro ⟨p, L', ⟨f, hf, hL'⟩, h⟩ diff --git a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean index a24b25de9..9850cc492 100644 --- a/Complexity/Computability/Complexity/Classes/Promise/Basic.lean +++ b/Complexity/Computability/Complexity/Classes/Promise/Basic.lean @@ -214,7 +214,10 @@ theorem mem_PromiseNP_iff : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V ComputableInPolyTime V (encPair enc encBits) encBool ∧ (∀ a ∈ Q.yes, ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true) ∧ ∀ a ∈ Q.no, ∀ w : List Bool, w.length = p.eval (enc a).length → V (a, w) = false := by - have this : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ (∀ a ∈ Q.yes, ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true) ∧ ∀ a ∈ Q.no, ∀ w : List Bool, w.length = p.eval (enc a).length → V (a, w) = false := by + have this : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ + (∀ a ∈ Q.yes, ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true) ∧ ∀ a ∈ + Q.no, ∀ w : List Bool, w.length = p.eval (enc a).length → V (a, w) = false := by constructor · rintro ⟨A, ⟨p, V, hV, h⟩, hyes, hno⟩ refine ⟨p, V, hV.tidy, fun a ha => (h a).1 (hyes ha), fun a ha w hw => ?_⟩ @@ -222,7 +225,8 @@ theorem mem_PromiseNP_iff : Q ∈ PromiseNP enc ↔ ∃ (p : Polynomial ℕ) (V exact fun hVw => Set.disjoint_right.1 hno ha ((h a).2 ⟨w, hw, hVw⟩) · rintro ⟨p, V, hV, hyes, hno⟩ refine ⟨{a | ∃ w : List Bool, w.length = p.eval (enc a).length ∧ V (a, w) = true}, - ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩, hyes, Set.disjoint_right.2 fun a ha ⟨w, hw, hVw⟩ => ?_⟩ + ⟨p, V, .of_tidy hV, fun _ => Iff.rfl⟩, hyes, Set.disjoint_right.2 fun a ha ⟨w, hw, hVw⟩ => + ?_⟩ simp [hno a ha w hw] at hVw simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using this diff --git a/Complexity/Computability/Complexity/Classes/RP.lean b/Complexity/Computability/Complexity/Classes/RP.lean index 162978254..7cf3ae9b3 100644 --- a/Complexity/Computability/Complexity/Classes/RP.lean +++ b/Complexity/Computability/Complexity/Classes/RP.lean @@ -206,7 +206,9 @@ theorem mem_RP_iff_forall_decidesWithOneSidedErrorExponent {A : Set α} : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent enc q p V A := by - have this : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent enc q p V A := by + have this : A ∈ RP enc ↔ ∀ q : Polynomial ℕ, ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ DecidesWithOneSidedErrorExponent + enc q p V A := by refine ⟨fun ⟨p, V, hV, h⟩ q => ⟨q * p, _, (computableInPolyTime_repeatAny hV _ _).tidy, h.repeatAny q⟩, fun h => ?_⟩ obtain ⟨p, V, hV, h⟩ := h 1 diff --git a/Complexity/Computability/Complexity/Classes/SBP.lean b/Complexity/Computability/Complexity/Classes/SBP.lean index 5389978d3..0e8644257 100644 --- a/Complexity/Computability/Complexity/Classes/SBP.lean +++ b/Complexity/Computability/Complexity/Classes/SBP.lean @@ -73,7 +73,8 @@ theorem mem_SBP : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, Co theorem mem_SBP_iff_exists_pos_threshold : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by - have this : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by + have this : A ∈ SBP enc ↔ ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 * f a < k a) := by rw [mem_SBP] constructor · rintro ⟨f, hf, k, hk, hA⟩ @@ -183,7 +184,8 @@ theorem exists_SBP_gap_pow (hA : A ∈ SBP enc) {m : ℕ} (hm : 0 < m) : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by - have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by + have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ m * f a < k a) := by obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA refine ⟨f ^ m, SharpP.pow_mem hf m, fun a => k a ^ m, hk.tidy.binary_pow' (.const m), fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ diff --git a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean index 38689b410..2b8f0e021 100644 --- a/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean +++ b/Complexity/Computability/Complexity/Classes/SBP/Amplification.lean @@ -49,7 +49,8 @@ theorem exists_SBP_gap_pow_polyTime (hA : A ∈ SBP enc) {r : α → ℕ} (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by have hr := hr.tidy - have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by + have this : ∃ f ∈ SharpP enc, ∃ k : α → ℕ, ComputableTidilyInPolyTime k enc encNat ∧ + (∀ a, 0 < k a) ∧ ∀ a, (a ∈ A → k a ≤ f a) ∧ (a ∉ A → 2 ^ r a * f a < k a) := by obtain ⟨f, hf, k, hk, hkpos, h⟩ := mem_SBP_iff_exists_pos_threshold.mp hA refine ⟨_, SharpP.pow_mem_polyTime hf (.of_tidy hr), fun a => k a ^ r a, hk.tidy.binary_pow' hr, fun a => pow_pos (hkpos a) _, fun a => ⟨?_, ?_⟩⟩ diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean index 1d491867c..edaafce07 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean @@ -56,7 +56,8 @@ theorem SharpP.sum_bits_mem {f : α × List Bool → ℕ} {r : α → ℕ} let W : α × List Bool → Bool := fun x => V ((x.1, x.2.take (r x.1)), x.2.drop (r x.1)) have hq : ComputableTidilyInPolyTime q enc encUnary := by dsimp [q]; fun_prop have hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool := by dsimp [W]; fun_prop - convert mem_SharpP_of_polyTime_length (.of_tidy hW) (.of_tidy (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hq))) + convert mem_SharpP_of_polyTime_length (.of_tidy hW) + (.of_tidy (ComputableTidilyInPolyTime.unary_add.comp (hr.prod hq))) using 1 ext a change _ = acceptCount W a (r a + q a) @@ -176,9 +177,10 @@ theorem GapP.pow_mem_polyTime {g : α → ℤ} {r : α → ℕ} (hg : g ∈ GapP have hV : ComputableTidilyInPolyTime V (encPair enc encBits) encBool := by dsimp [V]; fun_prop have hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool := by dsimp [W]; fun_prop have hlength := ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk) - refine ⟨_, - mem_SharpP_of_polyTime_length (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW false)) (.of_tidy hlength), - _, mem_SharpP_of_polyTime_length (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW true)) (.of_tidy hlength), + refine ⟨_, mem_SharpP_of_polyTime_length + (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW false)) (.of_tidy hlength), + _, mem_SharpP_of_polyTime_length (.of_tidy (SignedProduct.polyTime_verifier hr hk hV hW true)) + (.of_tidy hlength), fun a => ?_⟩ change g a ^ r a = (acceptCount (SignedProduct.verifier r k V W false) a (r a * k a) : ℤ) - diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean b/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean index cd9a8ec7c..81d2780d5 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Lowness.lean @@ -198,7 +198,8 @@ private theorem replayStepFactor_mem_SharpP [Finite Control] [Finite Operation] (fun x : (α × List Bool) × ℕ => x.1.2.getD x.2 false) (encPair (encPair enc encBits) encUnary) encBool := by fun_prop exact SharpP.ite_mem (.of_tidy hquery) - (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) (SharpP.comp_mem hNo (.of_tidy hreq))) + (SharpP.ite_mem (.of_tidy hbit) (SharpP.comp_mem hYes (.of_tidy hreq)) + (SharpP.comp_mem hNo (.of_tidy hreq))) (SharpP.ite_mem (.of_tidy hbit) SharpP.zero_mem SharpP.one_mem) private theorem replayPathCount_mem_SharpP [Finite Control] [Finite Operation] @@ -469,7 +470,8 @@ open Classical in theorem indicator_compl_mem_SharpPWithOracle_self (A : Set (List Bool)) : (fun q : List Bool => if q ∉ A then 1 else 0) ∈ SharpPWithOracle A encBits := by obtain ⟨fA, hfA, hA_iff⟩ := mem_PWithOracle_self A - refine ⟨0, fun x => !fA x.1, (hfA.preprocess (.of_tidy (by fun_prop))).map (.of_tidy (by fun_prop)), fun q => ?_⟩ + refine ⟨0, fun x => !fA x.1, (hfA.preprocess (.of_tidy (by fun_prop))).map + (.of_tidy (by fun_prop)), fun q => ?_⟩ simp only [Polynomial.eval_zero, acceptCount_zero, hA_iff q] cases fA q <;> simp diff --git a/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean b/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean index 055a6b91b..fc6b1eb14 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean @@ -64,7 +64,9 @@ theorem mem_GapP_of_polyTime {f : α → ℤ} (hf : ComputableInPolyTime f enc e have hf := hf.tidy have hp := mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.intBin_toNat.comp hf)) have hn := mem_SharpP_of_polyTime - (.of_tidy (ComputableTidilyInPolyTime.intBin_toNat.comp (ComputableTidilyInPolyTime.intBin_neg.comp hf))) + (.of_tidy + (ComputableTidilyInPolyTime.intBin_toNat.comp + (ComputableTidilyInPolyTime.intBin_neg.comp hf))) exact ⟨_, hp, _, hn, fun a => by simp only [Function.comp_apply]; lia⟩ /-- A polynomial-time Boolean test may select between two #P functions on the same input. diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean index 42cf7ffc3..872abd16e 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Products.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Products.lean @@ -106,7 +106,8 @@ theorem prod_range_mem {f : α × ℕ → ℕ} {r : α → ℕ} have hk : ComputableTidilyInPolyTime k enc encUnary := by dsimp [k]; fun_prop have hW : ComputableTidilyInPolyTime W (encPair (encPair enc encUnary) encBits) encBool := by dsimp [W, width]; fun_prop - convert mem_SharpP_of_polyTime_length (polyTime_indexedProductVerifier (.of_tidy hr) (.of_tidy hk) (.of_tidy hW)) + convert mem_SharpP_of_polyTime_length + (polyTime_indexedProductVerifier (.of_tidy hr) (.of_tidy hk) (.of_tidy hW)) (.of_tidy (ComputableTidilyInPolyTime.unary_mul.comp (hr.prod hk))) using 1 ext a change _ = acceptCount (indexedProductVerifier r k W) a (r a * k a) diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean index b9c0e687d..1c01e84d4 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Space.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Space.lean @@ -178,7 +178,8 @@ theorem SharpP.computableInPolySpace {f : α → ℕ} (hf : f ∈ SharpP enc) : Turing.MultiTapeTM.ComputableInPolySpace f enc encNat := by refine .of_tidy ?_ obtain ⟨p, V, hV, hf⟩ := mem_SharpP.mp hf - exact (computableInPolySpace_acceptCount hV (.of_tidy (by fun_prop))).tidy.congr fun a => (hf a).symm + exact (computableInPolySpace_acceptCount hV (.of_tidy (by fun_prop))).tidy.congr fun a => + (hf a).symm /-- Every GapP function is computable in polynomial space with binary sign-magnitude output. -/ theorem GapP.computableInPolySpace {g : α → ℤ} (hg : g ∈ GapP enc) : diff --git a/Complexity/Computability/Complexity/Classes/Space/Closure.lean b/Complexity/Computability/Complexity/Classes/Space/Closure.lean index e547a0e3f..054ad6314 100644 --- a/Complexity/Computability/Complexity/Classes/Space/Closure.lean +++ b/Complexity/Computability/Complexity/Classes/Space/Closure.lean @@ -61,8 +61,8 @@ variable {α : Type} {enc : α ↪ List Bool} {A : Set α} /-- **`PSPACE` in the quantitative calculus**: a problem is in `PSPACE` exactly when a Boolean -function deciding it is tidily computable within some time and within space polynomial in the -length of the encoded instance. -/ +function deciding it is computable within some time and within space polynomial in the length of +the encoded instance. -/ theorem mem_PSPACE_iff_computableInO : A ∈ PSPACE enc ↔ ∃ (f : α → Bool) (T S : α → ℕ), ComputableInO f enc encBool T S ∧ PolyBounded (fun a => (enc a).length) S ∧ ∀ a, a ∈ A ↔ f a = true := by @@ -84,8 +84,8 @@ theorem mem_PSPACE_iff_computableInO : A ∈ PSPACE enc ↔ ∃ (f : α → Bool attribute [local fun_prop] Turing.MultiTapeTM.ComputableInPolySpace.tidy in /-- **`PSPACE` within polynomial space**: a problem is in `PSPACE` exactly when a Boolean function -deciding it is tidily computable within space polynomial in the length of the encoded instance -(`Turing.MultiTapeTM.ComputableTidilyInPolySpace`). -/ +deciding it is computable within space polynomial in the length of the encoded instance +(`Turing.MultiTapeTM.ComputableInPolySpace`). -/ theorem mem_PSPACE_iff_computableInPolySpace : A ∈ PSPACE enc ↔ ∃ f : α → Bool, ComputableInPolySpace f enc encBool ∧ ∀ a, a ∈ A ↔ f a = true := by have this : A ∈ PSPACE enc ↔ diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean index 11bf3f252..a2d3f16ad 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean @@ -565,7 +565,8 @@ theorem computableInPolyTime_verifier : (fun p : ((((Graph × ℕ) × List Bool) × Play) × List Bool) => moverBits p.1.1.1.1.2.length p.1.2.2.1 p.2) encStep (encList encBool) := - (computableInPolyTime_moverBits (.of_tidy (hB.comp hX)) (.of_tidy (by fun_prop)) (.of_tidy (snd _ _))).tidy + (computableInPolyTime_moverBits (.of_tidy (hB.comp hX)) (.of_tidy (by fun_prop)) + (.of_tidy (snd _ _))).tidy have hpair : ComputableTidilyInPolyTime (fun p : ((((Graph × ℕ) × List Bool) × Play) × List Bool) => ((p.1.1.1.1, p.1.2), moverBits p.1.1.1.1.2.length p.1.2.2.1 p.2)) diff --git a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean index 9217b885c..d7dd1212e 100644 --- a/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean +++ b/Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean @@ -551,7 +551,8 @@ theorem computableInPolyTime_topNode {j : γ → ℕ} (hj : ComputableInPolyTime j encIn encUnary) : ComputableInPolyTime (fun x => topNode (j x)) encIn encNat := by have hj := hj.tidy - exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 0 (j x)) _ _ by + exact .of_tidy + (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 0 (j x)) _ _ by fun_prop)) @[fun_prop] @@ -569,7 +570,8 @@ theorem computableInPolyTime_bottomNode {j : γ → ℕ} (hj : ComputableInPolyTime j encIn encUnary) : ComputableInPolyTime (fun x => bottomNode (j x)) encIn encNat := by have hj := hj.tidy - exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 2 (j x)) _ _ by + exact .of_tidy + (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 2 (j x)) _ _ by fun_prop)) @[fun_prop] @@ -577,7 +579,8 @@ theorem computableInPolyTime_clauseNode {i : γ → ℕ} (hi : ComputableInPolyTime i encIn encUnary) : ComputableInPolyTime (fun x => clauseNode (i x)) encIn encNat := by have hi := hi.tidy - exact .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 4 (i x)) _ _ by + exact .of_tidy + (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun x => Nat.pair 4 (i x)) _ _ by fun_prop)) @[fun_prop] diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean index d6113fb36..8a1f0cfb3 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean @@ -331,7 +331,7 @@ private theorem pow_le_pow_of_le {x a b : ℕ} (hx : 1 ≤ x) (hab : a ≤ b) : Nat.pow_le_pow_right hx hab /-- **The evaluator in polynomial space.** On a formula whose encoding has length `L`, the -evaluator is tidily computable within time `O(2 ^ L * (L + 1) ^ e)` and space `O((L + 1) ^ e)`, for +evaluator is computable within time `O(2 ^ L * (L + 1) ^ e)` and space `O((L + 1) ^ e)`, for some fixed `e`. The space charges the input, the stack of at most `L` frames, each storing a token and a suffix of the tokens, the value, the flag, the counter of the `2 ^ L` rounds in binary, and the polynomial space of a step; the time charges every round @@ -339,7 +339,9 @@ the polynomial space of a step; the time charges every round theorem exists_computableInO_evaluate : ∃ e, ComputableInO evaluate encQBF encBool (fun φ => 2 ^ (encQBF φ).length * ((encQBF φ).length + 1) ^ e) fun φ => ((encQBF φ).length + 1) ^ e := by - have this : ∃ e, ComputableTidilyInO evaluate encQBF encBool (fun φ => 2 ^ (encQBF φ).length * ((encQBF φ).length + 1) ^ e) fun φ => ((encQBF φ).length + 1) ^ e := by + have this : ∃ e, ComputableTidilyInO evaluate encQBF encBool + (fun φ => 2 ^ (encQBF φ).length * ((encQBF φ).length + 1) ^ e) fun φ => + ((encQBF φ).length + 1) ^ e := by obtain ⟨d, e, hstep⟩ := computableInPolyTime_step.tidy.exists_degree obtain ⟨d₀, e₀, hinit⟩ := init_pt.exists_degree obtain ⟨d₁, e₁, hans⟩ := answer_pt.exists_degree diff --git a/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean b/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean index 2d1f7f643..44fa81712 100644 --- a/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean +++ b/Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean @@ -79,7 +79,8 @@ theorem computableInPolyTime_tokens : /-- A formula is polynomial-time when its tokens are. -/ theorem computableInPolyTime_of_tokens {f : γ → QBF ℕ} {l : γ → List (QBF.Kind × ℕ)} - (hl : Turing.MultiTapeTM.ComputableInPolyTime l encIn (encList encToken)) (h : ∀ x, (f x).tokens = l x) : + (hl : Turing.MultiTapeTM.ComputableInPolyTime l encIn (encList encToken)) + (h : ∀ x, (f x).tokens = l x) : Turing.MultiTapeTM.ComputableInPolyTime f encIn encQBF := by have hl := hl.tidy exact .of_tidy (hl.of_enc_eq fun x => by rw [encQBF_apply, h]) @@ -177,7 +178,8 @@ theorem computableInPolyTime_lit {v : γ → ℕ} {b : γ → Bool} `Cslib.Complexity.encCNF`. -/ @[fun_prop] theorem computableInPolyTime_ofCNF {φ : γ → CNF ℕ} - (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn (encList (encList (encPair encNat encBool)))) : + (hφ : Turing.MultiTapeTM.ComputableInPolyTime φ encIn + (encList (encList (encPair encNat encBool)))) : Turing.MultiTapeTM.ComputableInPolyTime (fun x => QBF.ofCNF (φ x)) encIn encQBF := computableInPolyTime_of_tokens (l := fun x => (φ x).flatMap (fun c => (QBF.Kind.and, 0) :: (c.flatMap (fun l => (QBF.Kind.or, 0) :: (QBF.lit l.1 l.2).tokens) ++ [(QBF.Kind.bot, 0)])) ++ @@ -191,7 +193,8 @@ theorem computableInPolyTime_blockVar {kind i j : γ → ℕ} (hkind : Turing.MultiTapeTM.ComputableInPolyTime kind encIn encUnary) (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) (hj : Turing.MultiTapeTM.ComputableInPolyTime j encIn encUnary) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => blockVar (kind x) (i x) (j x)) encIn encNat := by + Turing.MultiTapeTM.ComputableInPolyTime (fun x => blockVar (kind x) (i x) (j x)) encIn encNat := + by have hkind := hkind.tidy have hi := hi.tidy have hj := hj.tidy @@ -220,7 +223,8 @@ theorem computableInPolyTime_eqBlock {w k i k' i' : γ → ℕ} (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) (hk' : Turing.MultiTapeTM.ComputableInPolyTime k' encIn encUnary) (hi' : Turing.MultiTapeTM.ComputableInPolyTime i' encIn encUnary) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => eqBlock (w x) (k x) (i x) (k' x) (i' x)) encIn encQBF := by + Turing.MultiTapeTM.ComputableInPolyTime (fun x => eqBlock (w x) (k x) (i x) (k' x) (i' x)) encIn + encQBF := by unfold eqBlock fun_prop @@ -231,7 +235,8 @@ theorem computableInPolyTime_isBlock {w k i : γ → ℕ} {u : γ → List Bool} (hk : Turing.MultiTapeTM.ComputableInPolyTime k encIn encUnary) (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) (hu : Turing.MultiTapeTM.ComputableInPolyTime u encIn encBits) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => isBlock (w x) (k x) (i x) (u x)) encIn encQBF := by + Turing.MultiTapeTM.ComputableInPolyTime (fun x => isBlock (w x) (k x) (i x) (u x)) encIn + encQBF := by unfold isBlock fun_prop @@ -249,7 +254,8 @@ theorem computableInPolyTime_halves {w i : γ → ℕ} theorem computableInPolyTime_levelTokens {w i : γ → ℕ} (hw : Turing.MultiTapeTM.ComputableInPolyTime w encIn encUnary) (hi : Turing.MultiTapeTM.ComputableInPolyTime i encIn encUnary) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => levelTokens (w x) (i x)) encIn (encList encToken) := by + Turing.MultiTapeTM.ComputableInPolyTime (fun x => levelTokens (w x) (i x)) encIn + (encList encToken) := by unfold levelTokens fun_prop @@ -275,7 +281,8 @@ theorem computableInPolyTime_savitchFormula {w d : γ → ℕ} {base : γ → QB (hbase : Turing.MultiTapeTM.ComputableInPolyTime base encIn encQBF) (hu : Turing.MultiTapeTM.ComputableInPolyTime u encIn encBits) (hv : Turing.MultiTapeTM.ComputableInPolyTime v encIn encBits) : - Turing.MultiTapeTM.ComputableInPolyTime (fun x => savitchFormula (w x) (d x) (base x) (u x) (v x)) encIn + Turing.MultiTapeTM.ComputableInPolyTime + (fun x => savitchFormula (w x) (d x) (base x) (u x) (v x)) encIn encQBF := by unfold savitchFormula fun_prop @@ -295,7 +302,8 @@ private theorem computableTidilyInPolyTime_index_unary : /-- The numbering of the tableau variables by odd numbers, in binary. -/ @[fun_prop] theorem computableInPolyTime_tabVar : - Turing.MultiTapeTM.ComputableInPolyTime (tabVar (k := k) (State := State)) CookLevin.encVar encNat := by + Turing.MultiTapeTM.ComputableInPolyTime (tabVar (k := k) (State := State)) CookLevin.encVar + encNat := by refine .of_tidy ?_ have := computableTidilyInPolyTime_index_unary (k := k) (State := State) have h : ComputableTidilyInPolyTime (fun v => tabVar (k := k) (State := State) v) @@ -360,7 +368,8 @@ theorem computableInPolyTime_width : /-- **The test of one step or none between codes is polynomial-time**, on the instance and the concatenation of the two codes. -/ theorem computableInPolyTime_edgeTest : - Turing.MultiTapeTM.ComputableInPolyTime (edgeTest enc ntm c d) (encPair enc encBits) encBool := by + Turing.MultiTapeTM.ComputableInPolyTime (edgeTest enc ntm c d) (encPair enc encBits) encBool := + by refine .of_tidy ?_ have hw : ComputableTidilyInPolyTime (fun p : α × List Bool => width enc ntm c d p.1) (encPair enc encBits) encUnary := diff --git a/Complexity/Computability/Complexity/Classes/TFNP.lean b/Complexity/Computability/Complexity/Classes/TFNP.lean index dbfd1f304..3e917139d 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP.lean @@ -213,7 +213,9 @@ theorem mem_FNP_iff_exists_bounded : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by - have this : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval (enc a).length ∧ V (a, w) = true := by + have this : R ∈ FNP enc ↔ ∃ (p : Polynomial ℕ) (V : α × List Bool → Bool), + ComputableTidilyInPolyTime V (encPair enc encBits) encBool ∧ ∀ a w, R a w ↔ w.length ≤ p.eval + (enc a).length ∧ V (a, w) = true := by rw [mem_FNP] constructor · rintro ⟨⟨p, hp⟩, V, hV, hR⟩ diff --git a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean index e994ee609..294d78818 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/SearchToDecision.lean @@ -224,7 +224,8 @@ theorem FNP_subset_FPSearch_of_NP_subset_P refine mem_FPSearch.mpr ⟨mem_FNP.mpr ⟨⟨p, hp⟩, V, hV, hRV⟩, fun a => if V (a, prefixSearchRun V D n a) then some (prefixSearchRun V D n a) else none, ?_, fun a => ?_⟩ - · exact .of_tidy (cond (hV.tidy.comp (id'.prod hrun)) ((optionSome encBits).comp hrun) (const none)) + · exact .of_tidy + (cond (hV.tidy.comp (id'.prod hrun)) ((optionSome encBits).comp hrun) (const none)) · have hcorrect := rel_prefixSearchRun hRV (fun a u => (hDR (a, u)).symm) hp (a := a) constructor · intro w hw @@ -276,7 +277,8 @@ theorem searchRel_mem_FPSearch_iff : searchRel ∈ FPSearch encCNF ↔ SAT ∈ P refine ⟨fun h => searchDomain_searchRel ▸ searchDomain_mem_P h, fun h => ?_⟩ obtain ⟨D, hD, hSAT⟩ := mem_P.mp h have hsearch : ComputableTidilyInPolyTime (search D) encCNF encBits := - (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.tidy.comp (snd _ _))) (.of_tidy id')).tidy + (computableInPolyTime_search (D := fun _ => D) (.of_tidy (hD.tidy.comp (snd _ _))) + (.of_tidy id')).tidy refine mem_FPSearch.mpr ⟨searchRel_mem_FNP, fun φ => if D φ then some (search D φ) else none, .of_tidy (cond hD.tidy ((optionSome encBits).comp hsearch) (const none)), diff --git a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean index 1e7063fd9..9ffdace10 100644 --- a/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean +++ b/Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean @@ -45,7 +45,8 @@ bit-length `n : α → ℕ` is computable in polynomial time in unary (`encUnary neighbor, successor, predecessor or cost maps are computable in polynomial time on pairs `encPair enc encBits` (with costs in binary `encNat`), in the sense of `Turing.MultiTapeTM.ComputableInPolyTime`. By pulling a family back along the instance map of a -search reduction, each class is closed under `SearchReducible` across arbitrary encoded instance types +search reduction, each class is closed under `SearchReducible` across arbitrary encoded instance + types (`SearchReducible.mem_PLS`, `.mem_PPP`, `.mem_PPAD`, `.mem_PPA`). The canonical circuit-presented problems `LocalOpt`, `Pigeon`, `EndOfLine` and `Leaf`, whose @@ -668,7 +669,8 @@ theorem PPAD_subset_PPA : PPAD enc ⊆ PPA enc := by unfold ppadToPpaN₂ isActiveNonZero fun_prop exact mem_PPA.mpr - ⟨hR, fun a => n a + 1, ppadToPpaN₁ n P S, ppadToPpaN₂ n P S, (.of_tidy hn'), (.of_tidy hN₁), (.of_tidy hN₂), + ⟨hR, fun a => n a + 1, ppadToPpaN₁ n P S, ppadToPpaN₂ n P S, (.of_tidy hn'), (.of_tidy hN₁), + (.of_tidy hN₂), fun a _ hw => length_ppadToPpaN₁ (hP_len a) (hS_len a) hw, fun _ _ hw => length_ppadToPpaN₂ hw, hred.trans (endOfLineRel_searchReducible_leafRel hP_len hS_len)⟩ diff --git a/Complexity/Computability/Complexity/Classes/Time.lean b/Complexity/Computability/Complexity/Classes/Time.lean index ba62b4dfa..26fc6ca46 100644 --- a/Complexity/Computability/Complexity/Classes/Time.lean +++ b/Complexity/Computability/Complexity/Classes/Time.lean @@ -183,8 +183,8 @@ private theorem exists_le_length (enc : α ↪ List Bool) (S : α → ℕ) : exact ⟨fun n => (hfin n).toFinset.sup S, fun a => Finset.le_sup (f := S) ((hfin _).mem_toFinset.mpr rfl)⟩ -/-- A Boolean function, tidily computable within a time bound of the length of the encoded -instance, decides a problem within that time. -/ +/-- A Boolean function, computable within a time bound of the length of the encoded instance, +decides a problem within that time. -/ theorem setOf_mem_DTIME_of_computableInO {enc : α ↪ List Bool} {f : α → Bool} {T S : α → ℕ} {t : ℕ → ℕ} (h : Turing.MultiTapeTM.ComputableInO f enc encBool T S) (hT : ∀ a, T a ≤ t (enc a).length) : {a | f a = true} ∈ DTIME enc t := by @@ -211,13 +211,14 @@ theorem DTIME_mono_of_le_mul_add {t₁ t₂ : ℕ → ℕ} {C : ℕ} (h : ∀ n, rw [Nat.mul_add, ← Nat.mul_assoc] at this omega -/-- A problem in `DTIME enc t` is decided by a machine tidily computing its indicator within time +/-- A problem in `DTIME enc t` is decided by a machine computing its indicator within time and space `O(t n)`, on instances whose encoding has length `n`. -/ theorem computableInO_indicator_of_mem_DTIME {A : Set α} {t : ℕ → ℕ} (h : A ∈ DTIME enc t) : Turing.MultiTapeTM.ComputableInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t (enc a).length := by - have this : ComputableTidilyInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t (enc a).length := by + have this : ComputableTidilyInO (indicator A) enc encBool (fun a => t (enc a).length) fun a => t + (enc a).length := by obtain ⟨c₁, c₂, s, hA⟩ := h obtain ⟨g, hg, hgA⟩ := decidableInTimeAndSpace_iff.mp hA obtain ⟨c, hg⟩ := hg.exists_space_linear diff --git a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean index 9e4a34c5f..d9da363c2 100644 --- a/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean +++ b/Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean @@ -268,7 +268,8 @@ theorem computableInPolyTime_trialVerifier {W : α × List Bool → Bool} (hblock : ComputableInPolyTime block input encBits) : ComputableInPolyTime (fun x => trialVerifier W (a x) (u x) (r x) (M x) (level x) (seed x) (block x)) input encBool := - .of_tidy (computableTidilyInPolyTime_trialVerifier hW.tidy ha.tidy hu.tidy hr.tidy hM.tidy hlevel.tidy hseed.tidy hblock.tidy) + .of_tidy (computableTidilyInPolyTime_trialVerifier hW.tidy ha.tidy hu.tidy hr.tidy hM.tidy + hlevel.tidy hseed.tidy hblock.tidy) private theorem computableTidilyInPolyTime_trialsVerifier {W : α × List Bool → Bool} (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) @@ -306,7 +307,8 @@ theorem computableInPolyTime_trialsVerifier {W : α × List Bool → Bool} (hy : ComputableInPolyTime y input encBits) : ComputableInPolyTime (fun x => trialsVerifier W (a x) (u x) (r x) (seeds x) (M x) (Z x) (T x) (B x) (y x)) input encBool := - .of_tidy (computableTidilyInPolyTime_trialsVerifier hW.tidy ha.tidy hu.tidy hr.tidy hseeds.tidy hM.tidy hZ.tidy hT.tidy hB.tidy hy.tidy) + .of_tidy (computableTidilyInPolyTime_trialsVerifier hW.tidy ha.tidy hu.tidy hr.tidy hseeds.tidy + hM.tidy hZ.tidy hT.tidy hB.tidy hy.tidy) private theorem computableTidilyInPolyTime_existsVerifier (ℓ m ρ ζ e : Polynomial ℕ) {W : α × List Bool → Bool} (hW : ComputableTidilyInPolyTime W (encPair enc encBits) encBool) : @@ -457,7 +459,10 @@ theorem exists_isRandomParityRep_alternation {V : α × List Bool → Bool} IsRandomParityRep enc ℓ e ρ ζ W fun a u => Alternation q (ps.map fun p => p.eval (enc a).length) fun w => V (a, u ++ w) = true := by have hV := hV.tidy - have this : ∀ (q : Bool) (ℓ e : Polynomial ℕ), ∃ (ρ ζ : Polynomial ℕ) (W : α × List Bool → Bool), ComputableTidilyInPolyTime W (encPair enc encBits) encBool ∧ IsRandomParityRep enc ℓ e ρ ζ W fun a u => Alternation q (ps.map fun p => p.eval (enc a).length) fun w => V (a, u ++ w) = true := by + have this : ∀ (q : Bool) (ℓ e : Polynomial ℕ), ∃ (ρ ζ : Polynomial ℕ) (W : α × List Bool → Bool), + ComputableTidilyInPolyTime W (encPair enc encBits) encBool ∧ IsRandomParityRep enc ℓ e ρ ζ W + fun a u => Alternation q (ps.map fun p => p.eval (enc a).length) fun w => V (a, u ++ w) = + true := by induction ps with | nil => intro q ℓ e diff --git a/Complexity/Computability/Complexity/Classes/WPP.lean b/Complexity/Computability/Complexity/Classes/WPP.lean index 78a4602ef..e3895ba5a 100644 --- a/Complexity/Computability/Complexity/Classes/WPP.lean +++ b/Complexity/Computability/Complexity/Classes/WPP.lean @@ -53,7 +53,7 @@ Oracle lowness of `SPP`, `LWPP`, and `WPP` (including fixed-target `LWPPWithFixe ## Main results -* `mem_WPP`, `mem_LWPP`: membership through a tidy target machine. +* `mem_WPP`, `mem_LWPP`: membership through a polynomial-time target. * `SPP_subset_LWPP`, `LWPP_subset_WPP`, `UP_subset_LWPP`, `UP_subset_WPP`, `coUP_subset_LWPP`, `coUP_subset_WPP`, `FewP_subset_LWPP`, `FewP_subset_WPP`, `WPP_subset_CeqP`, `WPP_subset_coCeqP`. @@ -323,7 +323,8 @@ theorem mem_WPP_of_finset_targets {ι : Type*} (s : Finset ι) {g : α → ℤ} (hn : ∀ i ∈ s, ∀ a, f i a ≠ 0) (hr : ∀ a, g a = 0 ∨ ∃ i ∈ s, g a = f i a) (hA : ∀ a, a ∈ A ↔ ∃ i ∈ s, g a = f i a) : A ∈ WPP enc := by - have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) enc encIntBin := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using hf + have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) enc encIntBin := by simpa only + [computableInPolyTime_iff_computableTidilyInPolyTime] using hf obtain ⟨G, hG, hR, hGA⟩ := finsetTargetWitness s hg hf hn hr hA exact ⟨G, hG, _, .of_tidy (finset_prod_intBin s hf), fun a => Finset.prod_ne_zero_iff.mpr fun i hi => hn i hi a, hR, hGA⟩ @@ -338,7 +339,8 @@ theorem mem_LWPP_of_finset_targets {ι : Type*} (s : Finset ι) {g : α → ℤ} (hn : ∀ i ∈ s, ∀ n, f i n ≠ 0) (hr : ∀ a, g a = 0 ∨ ∃ i ∈ s, g a = f i (enc a).length) (hA : ∀ a, a ∈ A ↔ ∃ i ∈ s, g a = f i (enc a).length) : A ∈ LWPP enc := by - have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) encUnary encIntBin := by simpa only [computableInPolyTime_iff_computableTidilyInPolyTime] using hf + have hf : ∀ i ∈ s, ComputableTidilyInPolyTime (f i) encUnary encIntBin := by simpa only + [computableInPolyTime_iff_computableTidilyInPolyTime] using hf obtain ⟨G, hG, hR, hGA⟩ := finsetTargetWitness s hg (fun i hi => (hf i hi).comp (.encoding_length enc)) (fun i hi a => hn i hi (enc a).length) hr hA diff --git a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean index e201e16a1..d6564be18 100644 --- a/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean +++ b/Complexity/Computability/Complexity/Classes/WPP/Lowness.lean @@ -521,7 +521,8 @@ private theorem exists_mul_mem_GapP_of_sharpPWithOracle_of_mem_LWPP (hA : A ∈ (hD.comp (.encoding_length enc)).comp (.fst enc encBits) have hF : F ∈ GapP (encPair enc encBits) := GapP.generalWeightedReplay_mem machine hinput_pt.computableInPolyTime - hT'_pt.computableInPolyTime (mem_GapP_of_polyTime (.of_tidy hD'_pt)) (GapP.comp_mem hH (.of_tidy (by fun_prop))) + hT'_pt.computableInPolyTime (mem_GapP_of_polyTime (.of_tidy hD'_pt)) + (GapP.comp_mem hH (.of_tidy (by fun_prop))) have hsum : (fun a => ∑ w : Fin (r a) → Bool, F (a, List.ofFn w)) ∈ GapP enc := GapP.sum_bits_mem hF (.of_tidy hr) refine ⟨S, hS, hSn, ?_⟩ diff --git a/Complexity/Computability/Complexity/CookLevin/Clauses.lean b/Complexity/Computability/Complexity/CookLevin/Clauses.lean index 69d34348d..65e2e1f5e 100644 --- a/Complexity/Computability/Complexity/CookLevin/Clauses.lean +++ b/Complexity/Computability/Complexity/CookLevin/Clauses.lean @@ -18,9 +18,8 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolySpace.P # Polynomial-time construction of tableau clauses All clause families of the existing Cook–Levin tableau are polynomial-time functions of their -input word and unary time/window bounds. Variables use -`encVar`, so the certificates compose with `computableTidilyInPolyTime_relabel` to produce -binary SAT instances. +input word and unary time/window bounds. Variables use `encVar`, so the certificates compose with +`Cslib.Complexity.CookLevin.computableInPolyTime_relabel` to produce binary SAT instances. The machine, its tape count and its finite state type are fixed. Traversals of tapes and situations therefore use fixed lists; the tape-cell window is enumerated from the input bound. diff --git a/Complexity/Computability/Complexity/Fagin/Verifier.lean b/Complexity/Computability/Complexity/Fagin/Verifier.lean index c07522aaf..1fdde7baa 100644 --- a/Complexity/Computability/Complexity/Fagin/Verifier.lean +++ b/Complexity/Computability/Complexity/Fagin/Verifier.lean @@ -375,7 +375,8 @@ theorem _root_.Cslib.Logic.Vocabulary.computableInPolyTime_table (r : Σ n, L.Re {a : γ → EncodedStructure} (ha : ComputableInPolyTime a encIn encStructure) : ComputableInPolyTime (fun x => v.table (a x) r) encIn encBits := by have ha := ha.tidy - exact .of_tidy ((listGetD (encA := encBits) []).comp (((snd encUnary (encList encBits)).comp ha).prod + exact .of_tidy + ((listGetD (encA := encBits) []).comp (((snd encUnary (encList encBits)).comp ha).prod (const (encMid := encUnary) (v.index r)))) /-- The cardinality of the input, in unary. -/ diff --git a/Complexity/Computability/Complexity/FineGrained.lean b/Complexity/Computability/Complexity/FineGrained.lean index 872043a1d..83e531a86 100644 --- a/Complexity/Computability/Complexity/FineGrained.lean +++ b/Complexity/Computability/Complexity/FineGrained.lean @@ -62,8 +62,8 @@ The negation of `ETH` is `Cslib.Complexity.DecidableInSubexpTime`: decidability * `Cslib.Complexity.mem_DTIME_iff_decidableInTimeO`: `DTIME` is `DecidableInTimeO` for bounds in the length of the encoded instance. * `Cslib.Complexity.DecidableInTimeO.exists_computableInO`, - `Cslib.Complexity.DecidableInTimeO.of_computableInO`: deciders within time `O(T)` are tidy - deciders within time `O(T)`, which compose. + `Cslib.Complexity.DecidableInTimeO.of_computableInO`: deciders within time `O(T)` are the + Boolean functions computable within time `O(T)`, which compose. * `Cslib.Complexity.DecidableInTimeO.inter`: restricting to a set decided in polynomial time. * `Cslib.Complexity.DecidableInExpTime.mono`: larger exponents allow more problems. * `Cslib.Complexity.ETH_iff_not_decidableInSubexpTime`. diff --git a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean index 089179abc..05f16baea 100644 --- a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean +++ b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean @@ -150,11 +150,14 @@ length of the encoded formula, on formulas with `n` variables. -/ theorem exists_computableInO_search : ∃ e, ComputableInO search encCNF encBool (fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e := by - have this : ∃ e, ComputableTidilyInO search encCNF encBool (fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e := by + have this : ∃ e, ComputableTidilyInO search encCNF encBool + (fun φ => 2 ^ φ.numVars * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ φ.numVars * + ((encCNF φ).length + 1) ^ e := by obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree - obtain ⟨d₂, _, hans⟩ := (show ComputableTidilyInPolyTime (fun s : State => s.2.2) encState encBool + obtain ⟨d₂, _, hans⟩ := + (show ComputableTidilyInPolyTime (fun s : State => s.2.2) encState encBool by fun_prop).exists_degree obtain ⟨cv, dv, hvs⟩ := SAT.computableInPolyTime_distinctVars.tidy.polyBounded_length.exists_le diff --git a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean index 08818ee69..c448b5759 100644 --- a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean +++ b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean @@ -308,7 +308,9 @@ theorem exists_computableInO_stream {half : CNF ℕ → List ℕ} fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e := by have hhalf := hhalf.tidy have hwrap := hwrap.tidy - have this : ∃ e, ComputableTidilyInO (fun φ => ((halfVectors φ (half φ)).map wrap).flatten ++ fin) encCNF encBits (fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e := by + have this : ∃ e, ComputableTidilyInO (fun φ => ((halfVectors φ (half φ)).map wrap).flatten ++ fin) + encCNF encBits (fun φ => 2 ^ (half φ).length * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ + (half φ).length * ((encCNF φ).length + 1) ^ e := by -- the rounds obtain ⟨dN, _, ⟨tN, sN, ⟨cN, htN⟩, ⟨cN', hsN⟩, hN⟩, _⟩ := (show ComputableTidilyInPolyTime (fun s : StreamState => (s.1, s.2 + 1)) encStreamState @@ -429,7 +431,8 @@ theorem exists_computableInO_stream {half : CNF ℕ → List ℕ} ((encCNF φ).length + 1) ^ 3 := by rw [pow_succ' _ 2] exact Nat.mul_le_mul (by omega) (Nat.pow_le_pow_left (by omega) 2) - have h₇ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ 3 := Nat.le_self_pow (by omega) _ + have h₇ : (encCNF φ).length + 1 ≤ ((encCNF φ).length + 1) ^ 3 := Nat.le_self_pow (by omega) + _ generalize (B (((φ, half φ), 0), 2 ^ (half φ).length) + 1) ^ D = X at h₁ ⊢ generalize (Bb φ + 1) ^ D = Y at h₁ ⊢ generalize ((encNat (half φ).length).length + 1) ^ 2 = K₂ at h₄ ⊢ @@ -457,7 +460,9 @@ theorem exists_computableInO_stream {half : CNF ℕ → List ℕ} simp only [Function.comp_apply] at this ⊢ omega simp [halfVectors, Function.comp_def] - simpa only [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] using this + simpa only + [computableInPolyTime_iff_computableTidilyInPolyTime, computableInO_iff_computableTidilyInO] + using this attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in @@ -503,7 +508,9 @@ a polynomial in the length of the encoded formula, on formulas with `n` variable theorem exists_computableInO_toOV : ∃ e, ComputableInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by - have this : ∃ e, ComputableTidilyInO toOV encCNF encOV (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by + have this : ∃ e, ComputableTidilyInO toOV encCNF encOV + (fun φ => 2 ^ (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e) fun φ => 2 ^ + (φ.numVars - φ.numVars / 2) * ((encCNF φ).length + 1) ^ e := by obtain ⟨e₁, h₁⟩ := OV.exists_computableInO_stream OV.computableInPolyTime_firstVars OV.length_firstVars_le (wrap := fun v => ((frame v).map fun b => [true, b]).flatten) (by fun_prop) [false] diff --git a/Complexity/Computability/Complexity/FineGrained/Reduction.lean b/Complexity/Computability/Complexity/FineGrained/Reduction.lean index eb41ef06b..82b0f0e70 100644 --- a/Complexity/Computability/Complexity/FineGrained/Reduction.lean +++ b/Complexity/Computability/Complexity/FineGrained/Reduction.lean @@ -115,7 +115,8 @@ theorem DecidableInExpTime.of_reduction {f : α → β} have hfO := hf.inO obtain ⟨l, hl⟩ := hfO.length_le_time set K : ℝ := 1 + k * 2 ^ (δ * c) * (2 * l + 1) ^ e + k - refine Complexity.DecidableInExpTime.of_computableInO (.of_tidy (hg.comp hfO)) (fun a => (hfA a).trans (hgB (f a))) + refine Complexity.DecidableInExpTime.of_computableInO (.of_tidy (hg.comp hfO)) + (fun a => (hfA a).trans (hgB (f a))) ⌈K⌉₊ (d * e + d) fun a => ?_ show _ ≤ _ set P : ℝ := ((encA a).length + 1) ^ d diff --git a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean index 3557fa805..51c9d313e 100644 --- a/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean +++ b/Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean @@ -325,7 +325,8 @@ theorem computableInPolyTime_termVal' {α : Type} {input : α ↪ List Bool} (hz : ComputableInPolyTime z input encBits) : ComputableInPolyTime (fun x => termVal (tab x) (w x) (b x) (M x) (E x) (xs x) (z x)) input encBits := - .of_tidy (computableTidilyInPolyTime_termVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hxs.tidy hz.tidy) + .of_tidy (computableTidilyInPolyTime_termVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hxs.tidy + hz.tidy) private theorem computableTidilyInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} {tab : α → List (List (List Bool))} {w b M : α → ℕ} {E pts xs : α → List (List Bool)} @@ -356,7 +357,8 @@ theorem computableInPolyTime_ldeVal' {α : Type} {input : α ↪ List Bool} (hxs : ComputableInPolyTime xs input (encList encBits)) : ComputableInPolyTime (fun x => ldeVal (tab x) (w x) (b x) (M x) (E x) (pts x) (xs x)) input encBits := - .of_tidy (computableTidilyInPolyTime_ldeVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hpts.tidy hxs.tidy) + .of_tidy (computableTidilyInPolyTime_ldeVal' htab.tidy hw.tidy hb.tidy hM.tidy hE.tidy hpts.tidy + hxs.tidy) /-! ### The padded program -/ @@ -410,7 +412,10 @@ theorem computableInPolyTime_paddedProgram (M : ℕ) {gL : List Bool → Bool} { (hgL : ComputableInO gL encBits encBool (fun y => 2 ^ (k * y.length)) fun y => 2 ^ (k * y.length)) : ComputableInPolyTime (paddedProgram M gL) (encPair encBits encUnary) encBool := by - have hgL : ComputableTidilyInO gL encBits encBool (fun y => 2 ^ (k * y.length)) fun y => 2 ^ (k * y.length) := by simpa only [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] using hgL + have hgL : ComputableTidilyInO gL encBits encBool (fun y => 2 ^ (k * y.length)) fun y => 2 ^ + (k * y.length) := by simpa only + [computableInO_iff_computableTidilyInO, computableInPolyTime_iff_computableTidilyInPolyTime] + using hgL refine .of_tidy ?_ have hℓ := computableInPolyTime_padLength.tidy have hb : ComputableTidilyInPolyTime (fun x => blockLength M (padLength x)) diff --git a/Complexity/Computability/Complexity/Parameterized.lean b/Complexity/Computability/Complexity/Parameterized.lean index 9237f1718..19c7eb2fb 100644 --- a/Complexity/Computability/Complexity/Parameterized.lean +++ b/Complexity/Computability/Complexity/Parameterized.lean @@ -412,7 +412,7 @@ private theorem decidableInTimeO_natCast_iff {A : Set α} {T : α → ℕ} : exact DecidableInTimeO.of_computableInO (.of_tidy hg) hA fun _ => le_rfl /-- **`FPT` in terms of fpt-time computability**: a problem is fixed-parameter tractable exactly -when a Boolean function deciding it is tidily computable in fpt time. -/ +when a Boolean function deciding it is computable in fpt time. -/ theorem mem_FPT_iff_computableInFPTTime {A : Set α} : A ∈ FPT encA κ ↔ ∃ g : α → Bool, ComputableInFPTTime g encA encBool κ ∧ ∀ a, a ∈ A ↔ g a = true := by @@ -432,12 +432,14 @@ theorem mem_FPT_iff_computableInFPTTime {A : Set α} : rw [e, decidableInTimeO_natCast_iff] exact ⟨g, hg, hA⟩ -/-- **`XP` in terms of tidy computability.** -/ +/-- **`XP` in terms of computability within explicit bounds.** -/ theorem mem_XP_iff_exists_computableInO {A : Set α} : A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableInO g encA encBool (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) ∧ ∀ a, a ∈ A ↔ g a = true := by - have this : A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableTidilyInO g encA encBool (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) ∧ ∀ a, a ∈ A ↔ g a = true := by + have this : A ∈ XP encA κ ↔ ∃ (g : α → Bool) (f e : ℕ → ℕ), ComputableTidilyInO g encA encBool + (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) + (fun a => f (κ a) * ((encA a).length + 1) ^ e (κ a)) ∧ ∀ a, a ∈ A ↔ g a = true := by have h : ∀ f e : ℕ → ℕ, (fun a => (f (κ a) : ℝ) * ((encA a).length + 1) ^ e (κ a)) = fun a => ((f (κ a) * ((encA a).length + 1) ^ e (κ a) : ℕ) : ℝ) := fun f e => by funext a @@ -470,7 +472,8 @@ theorem XP_eq_P_of_le {K : ℕ} (hκ : ∀ a, κ a ≤ K) : XP encA κ = P encA obtain ⟨g, f, e, hg, hA⟩ := mem_XP_iff_exists_computableInO.mp (XP_subset_XP_of_le_comp (κ' := fun _ => 0) (h := fun _ => K) hκ hA) - exact ⟨g, .of_tidy <| hg.tidy.computableTidilyInPolyTime (.of_forall_le (f 0) (e 0) fun _ => le_rfl) + exact ⟨g, .of_tidy <| hg.tidy.computableTidilyInPolyTime + (.of_forall_le (f 0) (e 0) fun _ => le_rfl) (.of_forall_le (f 0) (e 0) fun _ => le_rfl), hA⟩ /-! ### Boolean closure -/ @@ -480,7 +483,8 @@ theorem compl_mem_FPT {A : Set α} (hA : A ∈ FPT encA κ) : Aᶜ ∈ FPT encA obtain ⟨g, hg, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg.ite ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const false)).computableInFPTTime κ) - ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ), fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ), + fun a => ?_⟩ simp only [Set.mem_compl_iff, hA] cases g a <;> simp @@ -490,7 +494,8 @@ theorem inter_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT en obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite hg₂ - ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const false)).computableInFPTTime κ), fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const false)).computableInFPTTime κ), + fun a => ?_⟩ simp only [Set.mem_inter_iff, hA, hB] cases g₁ a <;> simp @@ -500,7 +505,8 @@ theorem union_mem_FPT {A B : Set α} (hA : A ∈ FPT encA κ) (hB : B ∈ FPT en obtain ⟨g₁, hg₁, hA⟩ := mem_FPT_iff_computableInFPTTime.mp hA obtain ⟨g₂, hg₂, hB⟩ := mem_FPT_iff_computableInFPTTime.mp hB refine mem_FPT_iff_computableInFPTTime.mpr ⟨_, hg₁.ite - ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ) hg₂, fun a => ?_⟩ + ((ComputableInPolyTime.of_tidy (ComputableTidilyInPolyTime.const true)).computableInFPTTime κ) + hg₂, fun a => ?_⟩ simp only [Set.mem_union, hA, hB] cases g₁ a <;> simp diff --git a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean index ab2c7a121..682251ba9 100644 --- a/Complexity/Computability/Complexity/Parameterized/VertexCover.lean +++ b/Complexity/Computability/Complexity/Parameterized/VertexCover.lean @@ -415,7 +415,9 @@ theorem exists_computableInO_search : ∃ e, ComputableInO search (encPair encGraph encNat) encBool (fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e) fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e := by - have this : ∃ e, ComputableTidilyInO search (encPair encGraph encNat) encBool (fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e) fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e := by + have this : ∃ e, ComputableTidilyInO search (encPair encGraph encNat) encBool + (fun x => 2 ^ x.2 * ((encPair encGraph encNat x).length + 1) ^ e) fun x => 2 ^ x.2 * + ((encPair encGraph encNat x).length + 1) ^ e := by obtain ⟨d, _, hstep⟩ := computableTidilyInPolyTime_step.exists_degree obtain ⟨d₀, _, hinit⟩ := computableTidilyInPolyTime_init.exists_degree obtain ⟨d₁, _, hcount⟩ := computableTidilyInPolyTime_count.exists_degree @@ -486,7 +488,8 @@ a polynomial in the length of the encoded instance, for target cover size `k`. - theorem VertexCover_decidableInExpTime_one : DecidableInExpTime VertexCover (encPair encGraph encNat) Prod.snd 1 := by obtain ⟨e, h⟩ := VertexCover.exists_computableInO_search - refine DecidableInExpTime.of_computableInO h (fun x => (VertexCover.search_eq_true_iff x).symm) 1 e + refine DecidableInExpTime.of_computableInO h (fun x => (VertexCover.search_eq_true_iff x).symm) 1 + e fun x => ?_ rw [one_mul, Real.rpow_natCast] push_cast diff --git a/Complexity/Computability/Complexity/Problems/CircuitSAT.lean b/Complexity/Computability/Complexity/Problems/CircuitSAT.lean index d9096bc2e..cb265be20 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitSAT.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitSAT.lean @@ -402,8 +402,9 @@ private theorem computableTidilyInPolyTime_circuitGates : /-- Building the circuit of a formula is polynomial-time, from the encoding `encCNF` of formulas to the binary encoding `encCircuit 1` of circuits. -/ -private theorem computableTidilyInPolyTime_toCircuit : - ComputableTidilyInPolyTime toCircuit encCNF (encCircuit 1) := by +private theorem computableInPolyTime_toCircuit : + ComputableInPolyTime toCircuit encCNF (encCircuit 1) := by + refine .of_tidy ?_ have hg := computableTidilyInPolyTime_circuitGates have hs := computableTidilyInPolyTime_circuitSteps have hvars := SAT.computableInPolyTime_vars.tidy @@ -419,7 +420,7 @@ private theorem computableTidilyInPolyTime_toCircuit : /-- **`SAT` reduces to `CircuitSAT`** in polynomial time. -/ theorem polyTimeReducible_CircuitSAT : PolyTimeReducible encCNF (encCircuit 1) SAT CircuitSAT := - ⟨toCircuit, .of_tidy computableTidilyInPolyTime_toCircuit, + ⟨toCircuit, computableInPolyTime_toCircuit, fun φ => (toCircuit_mem_CircuitSAT_iff φ).symm⟩ end SAT diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean index 99e276fc0..35c152332 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean @@ -147,7 +147,9 @@ theorem exists_uniformCircuitFamily {α : Type} {enc : α ↪ List Bool} have hn := hn.tidy have hm := hm.tidy have hF := hF.tidy - have this : ∃ circuits : (a : α) → Circuit signature (n a) (m a), ComputableTidilyInPolyTime (fun a => (circuits a).code) enc encCode ∧ ∀ a (x : Fin (n a) → Bool) (j : Fin (m a)), (circuits a).eval interpretation x j = (F (a, List.ofFn x)).getD j.val false := by + have this : ∃ circuits : (a : α) → Circuit signature (n a) (m a), ComputableTidilyInPolyTime + (fun a => (circuits a).code) enc encCode ∧ ∀ a (x : Fin (n a) → Bool) (j : Fin (m a)), + (circuits a).eval interpretation x j = (F (a, List.ofFn x)).getD j.val false := by obtain ⟨bits, hbits, hsize, hsem⟩ := exists_uniformOutputBits hn hm hF let circuits (a : α) : Circuit signature (n a) (m a) := Circuit.pi (fun j : Fin (m a) => bits a j.val) diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean index 6e869a68b..a29725a69 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean @@ -189,7 +189,8 @@ omit [DecidableEq State] in theorem numGates_inSpace {T : α → ℕ} (hT : ComputableInSpace T encIn encNat Bs) : ComputableInSpace (fun x => numGates k State (T x)) encIn encNat Bs := by have hT := hT.tidy - exact .of_tidy (budget_natAdd (budget_const 2 hin) (budget_natMul (budget_natAdd hT (budget_const 1 hin)) + exact .of_tidy + (budget_natAdd (budget_const 2 hin) (budget_natMul (budget_natAdd hT (budget_const 1 hin)) (blockSize_inSpace (k := k) (State := State) (.of_tidy hT) hin).tidy)) private theorem gateChunk_inSpace {n i : α → ℕ} (hn : ComputableTidilyInSpace n encIn encNat Bs) @@ -289,7 +290,9 @@ theorem exists_uniformCircuits {α : Type} {enc : α ↪ List Bool} {f : α → ComputableInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval interpretation (fun i => (enc a)[i]) 0 = f a := by have hf := hf.tidy - have this : ∃ circuits : (n : ℕ) → Circuit signature n 1, ComputableTidilyInPolyTime (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval interpretation (fun i => (enc a)[i]) 0 = f a := by + have this : ∃ circuits : (n : ℕ) → Circuit signature n 1, ComputableTidilyInPolyTime + (fun n => (circuits n).code) encUnary encCode ∧ ∀ a, (circuits (enc a).length).eval + interpretation (fun i => (enc a)[i]) 0 = f a := by obtain ⟨t, s, ht, -, tapes, Control, hfin, machine, hmachine⟩ := hf have := Fintype.ofFinite Control classical diff --git a/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean b/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean index 1c8e102b3..4e7961c4c 100644 --- a/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean +++ b/Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean @@ -356,9 +356,15 @@ theorem computableInLogSpace {β : Type} {encOut : β ↪ List Bool} {g : List B encBits fun p => wBudget p.1) (hpoly : PolynomiallyBounded S.numChunks) : ComputableInLogSpace g (encFramed encBits) encOut := by - have hN : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.numChunks p.1.2.1) encStepIn encNat fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hN - have hC : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.chunk p.1.2.1 p.1.2.2) encStepIn encBits fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hC - have hT : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.trailer p.1.2.1) encStepIn encBits fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] using hT + have hN : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.numChunks p.1.2.1) encStepIn + encNat fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] + using hN + have hC : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.chunk p.1.2.1 p.1.2.2) + encStepIn encBits fun p => wBudget p.1 := by simpa only + [computableInSpace_iff_computableTidilyInSpace] using hC + have hT : ComputableTidilyInSpace (fun p : (ℕ × ℕ × ℕ) × Bool => S.trailer p.1.2.1) encStepIn + encBits fun p => wBudget p.1 := by simpa only [computableInSpace_iff_computableTidilyInSpace] + using hT obtain ⟨T, hT'⟩ := tidy_machine hN hC hT have hc (w : List Bool) : S.machine.toStepMachine.Computes (encFramed encBits w) (encOut (g w)) := by diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean index fdbf89a06..ccaf70c76 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean @@ -559,7 +559,8 @@ abbrev encDetour : Detour ↪ List Bool := @[fun_prop] theorem computableInPolyTime_topNode : ComputableInPolyTime (fun i => topNode i) encUnary encNat := - .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun i => Nat.pair 0 i) _ _ by fun_prop)) + .of_tidy (unary_to_binary.comp + (show ComputableTidilyInPolyTime (fun i => Nat.pair 0 i) _ _ by fun_prop)) /-- The row nodes are computable in polynomial time from unary indices. -/ @[fun_prop] @@ -573,7 +574,8 @@ theorem computableInPolyTime_rowNode : @[fun_prop] theorem computableInPolyTime_clauseNode : ComputableInPolyTime (fun j => clauseNode j) encUnary encNat := - .of_tidy (unary_to_binary.comp (show ComputableTidilyInPolyTime (fun j => Nat.pair 2 j) _ _ by fun_prop)) + .of_tidy (unary_to_binary.comp + (show ComputableTidilyInPolyTime (fun j => Nat.pair 2 j) _ _ by fun_prop)) /-- A diamond graph is computable in polynomial time from a layout computable in polynomial time, with the numbers of diamonds, slots and clauses in unary. -/ diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean index 1164efd53..6b4fa80cc 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean @@ -195,7 +195,8 @@ theorem computableInPolyTime_diamondGraph : ComputableInPolyTime diamondGraph encCNF encGraph := (Diamond.computableInPolyTime_graph (.of_tidy ((length_list encNat).comp computableInPolyTime_vars.tidy)) - (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) (.of_tidy computableTidilyInPolyTime_diamondDetours)) + (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) + (.of_tidy computableTidilyInPolyTime_diamondDetours)) /-- The reduction `toDirHamPath` is computable in polynomial time. -/ @[fun_prop] @@ -217,7 +218,8 @@ theorem computableInPolyTime_toDirHamCycle : ComputableInPolyTime toDirHamCycle encCNF encGraph := (Diamond.computableInPolyTime_cycleGraph (.of_tidy ((length_list encNat).comp computableInPolyTime_vars.tidy)) - (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) (.of_tidy computableTidilyInPolyTime_diamondDetours)) + (.of_tidy ((length_list _).comp (fst _ _))) (.of_tidy (length_list _)) + (.of_tidy computableTidilyInPolyTime_diamondDetours)) end SAT diff --git a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean index eb91d597d..92e1b57fb 100644 --- a/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean +++ b/Complexity/Computability/Complexity/Problems/MonotoneCircuitValue/Completeness.lean @@ -279,7 +279,8 @@ theorem computableInLogSpace_dualTableauInstance : refine (dualSpec tm C d).computableInLogSpace (encMonotoneCircuitValue_dualTableauInstance tm C d) (numGates_inSpace (k := k) (State := State) hin (timeBound_inSpace C d hin (.of_tidy hn))) - (.of_tidy (dualChunk_inSpace tm C d hin hn hi)) (.of_tidy (dualTrailer_inSpace tm C d hin hn)) ?_ + (.of_tidy (dualChunk_inSpace tm C d hin hn hi)) (.of_tidy (dualTrailer_inSpace tm C d hin hn)) + ?_ change PolynomiallyBounded fun n => Tableau.numGates k State (timeBound C d n) simp only [Tableau.numGates, Tableau.blockSize, Tableau.colStart, Tableau.gfStart, Tableau.globStart, Tableau.numCols, timeBound] diff --git a/Complexity/Computability/Complexity/Problems/TSP.lean b/Complexity/Computability/Complexity/Problems/TSP.lean index 424acbd54..1d1fb4059 100644 --- a/Complexity/Computability/Complexity/Problems/TSP.lean +++ b/Complexity/Computability/Complexity/Problems/TSP.lean @@ -202,7 +202,8 @@ theorem computableInPolyTime_verifier : unfold encTSP exact (snd _ _).comp (fst _ _) have hlen := computableInPolyTime_tourLength.tidy.comp (hD.prod (snd _ (encList encNat))) - exact (Graph.computableInPolyTime_verifyOrdering (.of_tidy hV) (.of_tidy (binary_le' hlen hb))).tidy + exact (Graph.computableInPolyTime_verifyOrdering (.of_tidy hV) + (.of_tidy (binary_le' hlen hb))).tidy /-- `TSP` belongs to `NP`. -/ theorem mem_NP : TSP ∈ NP encTSP := diff --git a/Complexity/Computability/Complexity/Problems/VertexCover.lean b/Complexity/Computability/Complexity/Problems/VertexCover.lean index 5c497c646..6174236a8 100644 --- a/Complexity/Computability/Complexity/Problems/VertexCover.lean +++ b/Complexity/Computability/Complexity/Problems/VertexCover.lean @@ -297,7 +297,8 @@ theorem isVerifier : theorem computableInPolyTime_verifier : ComputableInPolyTime verifier (encPair (encPair encGraph encNat) encBits) encBool := by refine .of_tidy ?_ - refine (computableInPolyTime_subsetVerifier (encγ := encNat) (.of_tidy (by unfold encGraph; fun_prop)) + refine (computableInPolyTime_subsetVerifier (encγ := encNat) + (.of_tidy (by unfold encGraph; fun_prop)) (.of_tidy (bool_and' ?_ (computableInPolyTime_isCover.tidy.comp (((fst _ _).comp (fst _ _)).prod (snd _ _)))))).tidy exact (((ComputableInPolyTime.length_list_binary encNat).tidy.comp (snd _ _)).decide_eq' diff --git a/Complexity/Computability/PCP/Encoded/Power.lean b/Complexity/Computability/PCP/Encoded/Power.lean index 97ab10d40..d27027380 100644 --- a/Complexity/Computability/PCP/Encoded/Power.lean +++ b/Complexity/Computability/PCP/Encoded/Power.lean @@ -297,7 +297,8 @@ theorem isPolyTime_powerPreprocess [Finite D] [Finite α] {Input : Type} {input have hconvert : ComputableTidilyInPolyTime (id : (PowerAlphabet D α T → PowerAlphabet D α T → Bool) → _) (encPi (encPi encBool)) output := .of_finite _ - simpa only [mapConstraints_id, Function.comp_def] using (isPolyTime_mapConstraints (.of_tidy hp) (.of_tidy hconvert)).tidy + simpa only [mapConstraints_id, Function.comp_def] using + (isPolyTime_mapConstraints (.of_tidy hp) (.of_tidy hconvert)).tidy end Complexity diff --git a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean index 2088085d6..1e9bda648 100644 --- a/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean +++ b/Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean @@ -258,7 +258,8 @@ theorem isPolyTime_preprocessRelation [Finite D] [DecidableEq α] have heval := heval.tidy have hleft := hleft.tidy have hright := hright.tidy - exact .of_tidy ((polytime_preprocessRelation (dartEncoding := dartEncoding) eval fallback heval).comp + exact .of_tidy + ((polytime_preprocessRelation (dartEncoding := dartEncoding) eval fallback heval).comp (hgraph.prod (hdart.prod (hleft.prod hright)))) end Cslib.PCP.Encoded.Graph diff --git a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean index da5ac0f33..4ba67cb94 100644 --- a/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean +++ b/Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean @@ -66,7 +66,8 @@ theorem polyTime_reductionVerifier {graph : Input → Graph C} (width repeats : (reductionVerifier graph width repeats decode eval).PolyTime input := by have hgraph := hgraph.tidy have heval := heval.tidy - obtain ⟨hcoins, hqueries, hverdict⟩ := polyTime_repeatedEdgeVerifier width repeats decode (.of_tidy heval) + obtain ⟨hcoins, hqueries, hverdict⟩ := polyTime_repeatedEdgeVerifier width repeats decode + (.of_tidy heval) exact ⟨hcoins.comp (.of_tidy hgraph), .of_tidy (hqueries.tidy.comp (by fun_prop)), .of_tidy (hverdict.tidy.comp (by fun_prop))⟩ diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean index 448418c1d..721542415 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean @@ -45,7 +45,8 @@ open Turing MultiTapeTM ComputableTidilyInSpace Iter theorem pairFalse_inSpace : ComputableInSpace (fun x : Tuple => (x, false)) encTuple encStepInT fun x => stepBudget (x, false) := by - have this : ComputableTidilyInSpace (fun x : Tuple => (x, false)) encTuple encStepInT fun x => stepBudget (x, false) := + have this : ComputableTidilyInSpace (fun x : Tuple => (x, false)) encTuple encStepInT fun x => + stepBudget (x, false) := ReadMachine.pairFalse_inSpace fun x => by simp only [stepBudget, encStepInT]; omega simpa only [computableInSpace_iff_computableTidilyInSpace] using this @@ -69,7 +70,8 @@ private theorem offsetT_inSpace {st : Tuple × Bool → List Frame} have harg := budget_prod (budget_prod ell_inSpace.tidy height_inSpace.tidy) hdirs have hpo := budget_comp pathOffset_inSpace.tidy harg (.const_mul (2 ^ 30) (((ell_le_stepBudget.add height_le_stepBudget).add (length_le harg)).add (.const 1 _))) - have h₂ := (succ_inSpace (succ_inSpace + have h₂ := + (succ_inSpace (succ_inSpace (.of_tidy (budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace.tidy height_inSpace.tidy))))).tidy refine (budget_comp_lin natAdd linear_succ (budget_prod h₂ hpo)).of_enc_eq fun y => ?_ simp only [offsetT, path_eq_reverse, foldl_cons_dir, List.append_nil] @@ -88,9 +90,9 @@ private theorem addrT_inSpace : budget_comp_lin natAdd linear_succ (budget_prod ha hb) have h := budget_ite (ht 0) (hsome n₁_inSpace.tidy) (budget_ite (ht 1) (hsome (hadd (succ_inSpace ell_inSpace).tidy n₁_inSpace.tidy)) - (budget_ite (ht 4) (hsome (hadd (offsetT_inSpace stack_inSpace.tidy) n₁_inSpace.tidy)) - (budget_ite (ht 5) (hsome (hadd (offsetT_inSpace rest_inSpace.tidy) n₁_inSpace.tidy)) - (budget_const (encB := encOption encNat) none len_le_stepBudget)))) + (budget_ite (ht 4) (hsome (hadd (offsetT_inSpace stack_inSpace.tidy) n₁_inSpace.tidy)) + (budget_ite (ht 5) (hsome (hadd (offsetT_inSpace rest_inSpace.tidy) n₁_inSpace.tidy)) + (budget_const (encB := encOption encNat) none len_le_stepBudget)))) refine (onTuple h).of_enc_eq fun x => ?_ simp only [addrT, decide_eq_true_eq] diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean index 1e4bdbe6d..bd586dc84 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean @@ -201,7 +201,8 @@ theorem encFrame_apply (fr : Frame) : encFrame fr = encFrameTuple (Frame.equiv f theorem frameFinite_inSpace {β : Type} {encB : β ↪ List Bool} (g : Fin 4 × Bool × Fin 3 → β) : ComputableInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB fun fr => (encFrame fr).length := by - have this : ComputableTidilyInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB fun fr => (encFrame fr).length := by + have this : ComputableTidilyInSpace (fun fr : Frame => g (Frame.equiv fr).2) encFrame encB + fun fr => (encFrame fr).length := by have h := budget_finite (encC := encB) g (snd encNat (encFinEnum (Fin 4 × Bool × Fin 3))) exact h.of_encIn_eq Frame.equiv fun _ => rfl simpa only [computableInSpace_iff_computableTidilyInSpace] using this @@ -210,7 +211,8 @@ theorem frameFinite_inSpace {β : Type} {encB : β ↪ List Bool} (g : Fin 4 × theorem round_inSpace : ComputableInSpace (fun fr : Frame => fr.round) encFrame encNat fun fr => (encFrame fr).length := by - have this : ComputableTidilyInSpace (fun fr : Frame => fr.round) encFrame encNat fun fr => (encFrame fr).length := + have this : ComputableTidilyInSpace (fun fr : Frame => fr.round) encFrame encNat fun fr => + (encFrame fr).length := (fst encNat (encFinEnum (Fin 4 × Bool × Fin 3))).of_encIn_eq Frame.equiv fun _ => rfl simpa only [computableInSpace_iff_computableTidilyInSpace] using this @@ -235,14 +237,17 @@ private theorem length_encList_bools (l : List Bool) : theorem dirs_inSpace : ComputableInSpace (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) (encList encFrame) (encList encBool) fun st => 64 * ((encList encFrame st).length + 1) := by - have this : ComputableTidilyInSpace (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) (encList encFrame) (encList encBool) fun st => 64 * ((encList encFrame st).length + 1) := by + have this : ComputableTidilyInSpace + (fun st : List Frame => st.foldl (fun acc fr => fr.dir :: acc) []) (encList encFrame) + (encList encBool) fun st => 64 * ((encList encFrame st).length + 1) := by have hl : (fun st => (encList encFrame st).length) ≼ fun st => 8 * ((encList encFrame st).length + 1) := .of_le fun _ => by omega have hstep : ComputableTidilyInSpace (fun q : List Bool × Frame => q.2.dir :: q.1) (encPair (encList encBool) encFrame) (encList encBool) fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := by have hl₀ : (fun q => (encPair (encList encBool) encFrame q).length) ≼ - fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := .of_le fun _ => by omega + fun q => 2 * ((encPair (encList encBool) encFrame q).length + 1) := .of_le fun _ => by + omega have hd := budget_comp (frameFinite_inSpace (encB := encBool) fun y : Fin 4 × Bool × Fin 3 => y.1.val % 2 == 1).tidy ((snd (encList encBool) encFrame).weaken hl₀) (.of_le fun x => by @@ -316,13 +321,16 @@ theorem pathOffset_inSpace : (encPair (encPair encNat encNat) (encList encBool)) encNat fun q => 2 ^ 30 * (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := by - have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × List Bool => pathOffset q.1.1 q.1.2 q.2) (encPair (encPair encNat encNat) (encList encBool)) encNat fun q => 2 ^ 30 * (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := by + have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × List Bool => pathOffset q.1.1 q.1.2 q.2) + (encPair (encPair encNat encNat) (encList encBool)) encNat fun q => 2 ^ 30 * + (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := by have hl : (fun q => (encPair (encPair encNat encNat) (encList encBool) q).length) ≼ fun q => 2 ^ 22 * (q.1.1 + q.1.2 + (encPair (encPair encNat encNat) (encList encBool) q).length + 1) := .of_le fun _ => by omega have hld := (fst (encPair encNat encNat) (encList encBool)).weaken hl - have hinit := budget_prod (fst' hld) (budget_prod (snd' hld) (budget_const (encB := encNat) 0 hl)) + have hinit := budget_prod (fst' hld) + (budget_prod (snd' hld) (budget_const (encB := encNat) 0 hl)) have hstate (q : (ℕ × ℕ) × List Bool) (j : ℕ) : (encNat3 ((q.2.take j).foldl pathStep' (q.1.1, q.1.2, 0))).length ≤ 8 * (q.1.1 + q.1.2 + 1) := by diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean index 7a05d816e..4ac3565b7 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean @@ -324,16 +324,19 @@ theorem subtractSums_inSpace {p c : α → ℕ} {t : α → Fin 3} {acc : α → have hacc := hacc.tidy have hR := hR.tidy refine .of_tidy ?_ - have harg := budget_prod (budget_prod hp (budget_prod hc hacc)) (get_inSpace (.of_tidy hR) (.of_tidy ht)).tidy + have harg := budget_prod (budget_prod hp (budget_prod hc hacc)) + (get_inSpace (.of_tidy hR) (.of_tidy ht)).tidy have hsub := budget_comp subtractList_inSpace harg (by refine .const_mul 8192 (((length_le harg).add hB).add (.const 1 _))) - exact (set_inSpace (.of_tidy hR) (.of_tidy ht) (.of_tidy hsub)).tidy.of_enc_eq fun x => by rw [subtractSums_eq] + exact (set_inSpace (.of_tidy hR) (.of_tidy ht) (.of_tidy hsub)).tidy.of_enc_eq fun x => by rw + [subtractSums_eq] /-- **The bits of a register**, `l.map (· == 1)`, encoded as themselves. -/ theorem mapEqOne_inSpace : ComputableInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits fun l => 64 * ((encList encNat l).length + 1) := by - have this : ComputableTidilyInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits fun l => 64 * ((encList encNat l).length + 1) := by + have this : ComputableTidilyInSpace (fun l : List ℕ => l.map (· == 1)) (encList encNat) encBits + fun l => 64 * ((encList encNat l).length + 1) := by have hstep : ComputableTidilyInSpace (fun q : List Bool × ℕ => q.1 ++ [q.2 == 1]) (encPair encBits encNat) encBits fun q => 8 * ((encPair encBits encNat q).length + 1) := by have hl : (fun q => (encPair encBits encNat q).length) ≼ diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean index 157c6d0fb..e5321cd7f 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean @@ -46,7 +46,8 @@ private theorem proj3 : theorem addMod_inSpace : ComputableInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by - have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => addMod q.1 q.2.1 q.2.2) encNat3 encNat + fun q => (encNat3 q).length := by obtain ⟨hp, ha, hb⟩ := proj3 exact budget_comp_lin natMod (linear_mul _) (budget_prod (budget_comp_lin natAdd linear_succ (budget_prod ha hb)) hp) @@ -56,7 +57,8 @@ theorem addMod_inSpace : theorem mulMod_inSpace : ComputableInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by - have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat fun q => (encNat3 q).length := by + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ × ℕ => mulMod q.1 q.2.1 q.2.2) encNat3 encNat + fun q => (encNat3 q).length := by obtain ⟨hp, ha, hb⟩ := proj3 exact budget_comp_lin natMod (linear_mul _) (budget_prod (budget_comp_lin natMul (linear_mul _) (budget_prod ha hb)) hp) @@ -66,7 +68,8 @@ theorem mulMod_inSpace : theorem negMod_inSpace : ComputableInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by - have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => negMod q.1 q.2) (encPair encNat encNat) + encNat fun q => (encPair encNat encNat q).length := by have hp := fst encNat encNat have hm := budget_comp_lin natMod (linear_mul _) (budget_prod (snd encNat encNat) hp) exact budget_comp_lin natMod (linear_mul _) @@ -78,7 +81,9 @@ theorem chi_inSpace : ComputableInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) (encPair (encPair encNat encNat) encBool) encNat fun q => (encPair (encPair encNat encNat) encBool q).length := by - have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) (encPair (encPair encNat encNat) encBool) encNat fun q => (encPair (encPair encNat encNat) encBool q).length := by + have this : ComputableTidilyInSpace (fun q : (ℕ × ℕ) × Bool => chi q.1.1 q.2 q.1.2) + (encPair (encPair encNat encNat) encBool) encNat fun q => + (encPair (encPair encNat encNat) encBool q).length := by have hpx := fst (encPair encNat encNat) encBool have hp := fst' hpx have hmod := budget_comp_lin natMod (linear_mul _) (budget_prod (snd' hpx) hp) @@ -108,7 +113,8 @@ theorem powMod_le {p a : ℕ} {k : ℕ} (hk : k ≤ p - 2) : powMod p a k ≤ p theorem unitInv_inSpace : ComputableInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by - have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) encNat fun q => (encPair encNat encNat q).length := by + have this : ComputableTidilyInSpace (fun q : ℕ × ℕ => unitInv q.1 q.2) (encPair encNat encNat) + encNat fun q => (encPair encNat encNat q).length := by have hp := fst encNat encNat have hstep : ComputableTidilyInSpace powStep encNat3 encNat3 fun q => (encNat3 q).length := by obtain ⟨hp, ha, hacc⟩ := proj3 diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean index dc17c11a7..23633aeb2 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean @@ -258,10 +258,10 @@ private theorem branch0_inSpace : else ((((y.1.n₁, y.1.height, y.1.p), y.1.regs), y.1.2.1, (1, 0, 0, [])), [])) encStepInT encStepOut stepBudget := budget_ite hBit - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) - (out_inSpace (budget_prod - (budget_prod (budget_prod n₁_inSpace.tidy (budget_prod height_inSpace.tidy hP)) hRegs) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) + (out_inSpace + (budget_prod (budget_prod (budget_prod n₁_inSpace.tidy (budget_prod height_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 1) (hConstNat 0) (hConstNat 0) hNil)))) /-- The header: reading the height. -/ @@ -275,10 +275,9 @@ private theorem branch1_inSpace : have h := budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace.tidy ell_inSpace.tidy) exact (succ_inSpace (succ_inSpace (.of_tidy h))).tidy.of_enc_eq fun y => by congr 1; omega exact budget_ite hBit - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) - (out_inSpace (budget_prod - (budget_prod (budget_prod ell_inSpace.tidy (budget_prod n₁_inSpace.tidy hP)) hRegs) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) + (out_inSpace (budget_prod (budget_prod (budget_prod ell_inSpace.tidy (budget_prod n₁_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 2) h2e (hConstNat 2) hNil)))) private theorem hReplicate : @@ -314,10 +313,10 @@ private theorem branch2_inSpace : (budget_const (encB := encMode) (.call false 2) len_le_stepBudget) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil) refine (budget_ite hlt (budget_ite hz - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace).tidy (hConstNat 2) hNil))) - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 2) n₁_inSpace.tidy (succ_inSpace (.of_tidy hN₂)).tidy hNil)))) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace).tidy (hConstNat 2) hNil))) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 2) n₁_inSpace.tidy (succ_inSpace (.of_tidy hN₂)).tidy hNil)))) (out_inSpace hfound)).of_enc_eq fun y => ?_ simp only [decide_eq_true_eq] @@ -359,7 +358,9 @@ private theorem branch4_inSpace : have hneg := hModeFinite (encB := encBool) Mode.neg have hcall := hModeFinite (encB := encBool) Mode.isCall have hc := (budget_ite hBit (hSgnVal hP hneg) (hConstNat 0)) - have hmod := (modifyAt_inSpace (get_inSpace (.of_tidy hRegs) (.of_tidy ht)) n₁_inSpace (.of_tidy hP) (.of_tidy hc)).tidy + have hmod := + (modifyAt_inSpace (get_inSpace (.of_tidy hRegs) (.of_tidy ht)) n₁_inSpace (.of_tidy hP) + (.of_tidy hc)).tidy have hset := (set_inSpace (.of_tidy hRegs) (.of_tidy ht) (.of_tidy hmod)).tidy refine (budget_ite hcall (budget_ite (hLt n₁_inSpace.tidy ell_inSpace.tidy) (out_inSpace (withRegsModeCtl_inSpace hset stack_inSpace.tidy hMode @@ -409,7 +410,7 @@ private theorem branch5_inSpace : encStepInT encStepOut stepBudget := by have hempty := budget_comp_linear (of_inO (.of_linear (ListEncoding.isEmpty (enc₁ := encFrame) (enc := encList encFrame)))) - stack_inSpace.tidy + stack_inSpace.tidy have hG := budget_comp tableLength_inSpace.tidy ell_inSpace.tidy (.const_mul 4096 (ell_le_stepBudget.add (.const 1 _))) have hdm := budget_comp_lin natDivMod (linear_mul _) (budget_prod n₁_inSpace.tidy ell_inSpace.tidy) @@ -417,7 +418,8 @@ private theorem branch5_inSpace : have hi := snd' hdm have hx := (get_inSpace (.of_tidy hRegs) (.of_tidy (hRegPlus 1))).tidy have hy := (get_inSpace (.of_tidy hRegs) (.of_tidy (hRegPlus 2))).tidy - have hw := budget_comp weight_inSpace.tidy (budget_prod (budget_prod hP (budget_prod ell_inSpace.tidy hk)) + have hw := budget_comp weight_inSpace.tidy + (budget_prod (budget_prod hP (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy)) (.const_mul 64 (((length_le (budget_prod (budget_prod hP (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy))).add ell_le_stepBudget).add (.const 1 _))) have hacc' := (modifyAt_inSpace (.of_tidy hAcc) (.of_tidy hi) (.of_tidy hP) (.of_tidy hw)).tidy @@ -426,13 +428,15 @@ private theorem branch5_inSpace : mul_le_stepBudget (fun y => by have := length_get_le_regLen y.1 (y.1.stack.headD dfr).target omega) fun y => by omega - have hsub := (subtractSums_inSpace (.of_tidy hP) (.of_tidy (hSgnVal hP hFrNeg)) (.of_tidy hFrTarget) (.of_tidy hAcc) (.of_tidy hRegs) hB).tidy + have hsub := + (subtractSums_inSpace (.of_tidy hP) (.of_tidy (hSgnVal hP hFrNeg)) (.of_tidy hFrTarget) + (.of_tidy hAcc) (.of_tidy hRegs) hB).tidy refine (budget_ite hempty (out_inSpace hTup) (budget_ite (hLt n₁_inSpace.tidy hG) (budget_ite hBit - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hacc'))) - (out_inSpace (withCtl_inSpace - (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hAcc)))) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hacc'))) + (out_inSpace + (withCtl_inSpace (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hAcc)))) (out_inSpace (withRegsModeCtl_inSpace hsub (cons_inSpace (hFrPhase 2) rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call true (g.2.2 + 1)) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil))))).of_enc_eq fun y => ?_ @@ -460,10 +464,12 @@ private theorem scaleT_inSpace {R : Tuple × Bool → Regs} {r : Tuple × Bool (hlen : ∀ y r', ((R y).get r').length = (y.1.regs.get r').length) (hasz : ∀ y, (encNat (a y)).length ≤ (encNat y.1.p).length + (encNat (y.1.stack.headD dfr).round).length + 3) : - ComputableTidilyInSpace (fun y => (R y).scale y.1.p (r y) - (a y)) encStepInT encRegs stepBudget := - (scale_inSpace (.of_tidy hP) (.of_tidy ha) (.of_tidy hR) (.of_tidy hr) len_le_stepBudget (mul_le_stepBudget (fun y => by - rw [hlen]; have := length_get_le_regLen y.1 (r y); omega) fun y => by have := hasz y; omega)).tidy + ComputableTidilyInSpace (fun y => (R y).scale y.1.p (r y) (a y)) encStepInT encRegs + stepBudget := + (scale_inSpace (.of_tidy hP) (.of_tidy ha) (.of_tidy hR) (.of_tidy hr) len_le_stepBudget + (mul_le_stepBudget + (fun y => by rw [hlen]; have := length_get_le_regLen y.1 (r y); omega) + fun y => by have := hasz y; omega)).tidy private theorem hFrame0 : ComputableTidilyInSpace (fun y : Tuple × Bool => (⟨0, 0, y.1.mode.neg, y.1.mode.target⟩ : Frame)) encStepInT encFrame stepBudget := @@ -473,7 +479,8 @@ private theorem hFrame0 : ComputableTidilyInSpace (fun y : Tuple × Bool => private theorem hFrameNext : ComputableTidilyInSpace (fun y : Tuple × Bool => (⟨(y.1.stack.headD dfr).round + 1, 0, (y.1.stack.headD dfr).neg, (y.1.stack.headD dfr).target⟩ : Frame)) encStepInT encFrame stepBudget := - (mkFrame_inSpace (succ_inSpace (.of_tidy hRound)).tidy (hTopFinite (encB := encFinEnum (Fin 4 × Bool × Fin 3)) + (mkFrame_inSpace (succ_inSpace (.of_tidy hRound)).tidy + (hTopFinite (encB := encFinEnum (Fin 4 × Bool × Fin 3)) fun g => (0, g.2.1, g.2.2))).of_enc_eq fun _ => rfl private theorem hRun : ComputableTidilyInSpace @@ -490,13 +497,14 @@ private theorem branch3_inSpace : (.const_mul 8 ((length_le stack_inSpace.tidy).add (.const 1 _)))) height_inSpace.tidy) have hempty := budget_comp_linear (of_inO (.of_linear (ListEncoding.isEmpty (enc₁ := encFrame) (enc := encList encFrame)))) - stack_inSpace.tidy + stack_inSpace.tidy have hph (k : Fin 4) := hTopFinite (encB := encBool) fun g => decide (g.1 = k) have hR0 := scaleT_inSpace hRegs (hModeFinite (encB := encReg) fun m => m.target + 1) (hConstNat (unitVal 0)) (fun _ _ => rfl) fun y => by have : (encNat (unitVal 0)).length = 1 := rfl omega - have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace (.of_tidy hRound)).tidy (fun _ _ => rfl) fun y => by + have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace (.of_tidy hRound)).tidy (fun _ _ => rfl) + fun y => by have := length_encNat_add_le_add (y.1.stack.headD dfr).round 1 have : (encNat 1).length = 1 := rfl omega @@ -511,8 +519,11 @@ private theorem branch3_inSpace : have : (encNat 2).length = 2 := rfl rw [show (y.1.stack.headD dfr).round + 1 + 1 = (y.1.stack.headD dfr).round + 2 by omega] omega - have hout := budget_comp mapEqOne_inSpace.tidy (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy - (.const_mul 64 ((length_le (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy).add + have hout := budget_comp mapEqOne_inSpace.tidy + (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy + (.const_mul 64 + ((length_le + (get_inSpace (.of_tidy hRegs) (.of_tidy (budget_const 2 len_le_stepBudget))).tidy).add (.const 1 _))) have hnext := hLt (succ_inSpace (.of_tidy hRound)).tidy (budget_comp_lin natPred linear_succ hP) refine (budget_ite hcall diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean index 7d5e10093..190a11e8d 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean @@ -188,8 +188,11 @@ theorem weight_inSpace : ComputableInSpace (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => weight w.1.1 w.1.2.1 w.1.2.2 w.2.1 w.2.2) encWeightIn encNat fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := by - have this : ComputableTidilyInSpace (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => weight w.1.1 w.1.2.1 w.1.2.2 w.2.1 w.2.2) encWeightIn encNat fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := by - have hl : (fun w => (encWeightIn w).length) ≼ fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) + have this : ComputableTidilyInSpace + (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => weight w.1.1 w.1.2.1 w.1.2.2 w.2.1 w.2.2) + encWeightIn encNat fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := by + have hl : (fun w => (encWeightIn w).length) ≼ fun w => 64 * + ((encWeightIn w).length + w.1.2.1 + 1) := .of_le fun _ => by omega have hℓle : (fun w : (ℕ × ℕ × ℕ) × List ℕ × List ℕ => w.1.2.1) ≼ fun w => 64 * ((encWeightIn w).length + w.1.2.1 + 1) := .of_le fun _ => by omega diff --git a/Complexity/Computability/USTCON/Reader/Cert.lean b/Complexity/Computability/USTCON/Reader/Cert.lean index d19212189..47d9b8558 100644 --- a/Complexity/Computability/USTCON/Reader/Cert.lean +++ b/Complexity/Computability/USTCON/Reader/Cert.lean @@ -487,7 +487,8 @@ budget of the state. -/ theorem step_inSpace : ComputableInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by - have this : ComputableTidilyInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by + have this : ComputableTidilyInSpace (fun p : State × Bool => machine.step p.1 p.2) + (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by have h := stepT_inSpace.of_encIn_eq (α' := State × Bool) (encIn' := encPair encState encBool) (fun p ↦ (p.1.toTuple, p.2)) fun _ ↦ rfl refine (h.mono_le fun p ↦ ?_).of_enc_eq fun _ ↦ rfl diff --git a/Complexity/Computability/USTCON/Space.lean b/Complexity/Computability/USTCON/Space.lean index 70b74a486..88c9a9e8a 100644 --- a/Complexity/Computability/USTCON/Space.lean +++ b/Complexity/Computability/USTCON/Space.lean @@ -64,7 +64,8 @@ theorem computableInBigO_decide : ∃ t, ComputableInBigO let tS := ReadMachine.stateT encState T stateBudget let tMax (I : USTCONInstance) : ℕ := ∑ i ∈ Finset.range (rounds I + 1), tS (machine.toStepMachine.run (encUSTCON I) i).state - refine ⟨_, ComputableTidilyInBigO.computableInBigO <| (hT.computableTidilyInTimeAndSpace (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) + refine ⟨_, ComputableTidilyInBigO.computableInBigO <| + (hT.computableTidilyInTimeAndSpace (fun I : USTCONInstance ↦ decide (I ∈ USTCON)) rounds hr (fun I ↦ by rw [encBool_apply, ho]) (tMax := tMax) (sMax := fun I ↦ 6 * stateConst * (Nat.log2 (encUSTCON I).length + 2) + 2 * (Nat.log2 (encUSTCON I).length + 2) + 12) fun I i hi ↦ ⟨?_, ?_⟩).weaken diff --git a/ComplexityTests/Axioms.lean b/ComplexityTests/Axioms.lean index 1d33d8ae5..74906191c 100644 --- a/ComplexityTests/Axioms.lean +++ b/ComplexityTests/Axioms.lean @@ -820,9 +820,10 @@ info: 'Cslib.Complexity.SAT.isVerifier' depends on axioms: [propext, Classical.c #print axioms Cslib.Complexity.SAT.isVerifier /-- -info: 'Cslib.Complexity.SAT.computableInPolyTime_verifier' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SAT.computableInPolyTime_verifier' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.SAT.computableInPolyTime_verifier /-- @@ -4082,7 +4083,8 @@ info: 'Turing.MultiTapeTM.ComputableTidilyInPolyTime.unary_to_binary' depends on #print axioms Turing.MultiTapeTM.ComputableTidilyInPolyTime.unary_to_binary /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_parameters' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_parameters' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_parameters @@ -4286,67 +4288,78 @@ info: 'Turing.computableTidilyInPolyTime_windowList' depends on axioms: [propext #print axioms Turing.computableTidilyInPolyTime_windowList /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_featureIndex' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_featureIndex' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_featureIndex /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inPos' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inPos' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_inPos /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_head' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_head' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_head /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cell' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cell' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_cell /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_holds' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_holds' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_holds /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cert' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_cert' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_cert /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_index' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_index' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_index /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_relabel' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_relabel' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_relabel /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_initClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_initClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_initClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_acceptClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_sitClauses @@ -4439,7 +4452,8 @@ info: 'Turing.MultiTapeTM.ComputableTidilyInPolyTime.anyConst' depends on axioms #print axioms Turing.MultiTapeTM.ComputableTidilyInPolyTime.anyConst /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_oneHotClauses @@ -5358,27 +5372,31 @@ info: 'Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses' depends on #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_inputClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_readClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_readClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_readClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_stepClauses /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_tableau' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_tableau' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_tableau /-- -info: 'Cslib.Complexity.CookLevin.computableInPolyTime_reduce' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.CookLevin.computableInPolyTime_reduce' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.CookLevin.computableInPolyTime_reduce /-- diff --git a/ComplexityTests/ClassCorollaries.lean b/ComplexityTests/ClassCorollaries.lean index 5b61714d4..ea1346ca3 100644 --- a/ComplexityTests/ClassCorollaries.lean +++ b/ComplexityTests/ClassCorollaries.lean @@ -98,7 +98,8 @@ example {α : Type} (enc : α ↪ List Bool) : PPT. -/ example : IsOraclePPTOn encBits encNat (fun w => OracleComp.interpret ProbOracleComp.query (BinarySearch.search w (w.length + 1))) := - BinarySearch.isOraclePPTOn_search (.of_tidy ComputableTidilyInPolyTime.id') (.of_tidy (by fun_prop)) + BinarySearch.isOraclePPTOn_search (.of_tidy ComputableTidilyInPolyTime.id') + (.of_tidy (by fun_prop)) example {α : Type} (enc : α ↪ List Bool) : PWithSharpPOracle enc ⊆ PWithPPOracle enc := PWithSharpPOracle_subset_PWithPPOracle diff --git a/ComplexityTests/CountingAggregation.lean b/ComplexityTests/CountingAggregation.lean index 82f38203b..5fcbfa1a8 100644 --- a/ComplexityTests/CountingAggregation.lean +++ b/ComplexityTests/CountingAggregation.lean @@ -28,7 +28,8 @@ example : (fun _ : List Bool => (0 : ℤ) ^ (0 : ℕ)) ∈ GapP encBits := example : (fun w : List Bool => -(2 : ℤ) ^ w.length) ∈ GapP encBits := by have hneg : (fun _ : List Bool × List Bool => (-1 : ℤ)) ∈ GapP (encPair encBits encBits) := GapP.neg_mem GapP.one_mem - convert GapP.sum_bits_mem hneg (.of_tidy (ComputableTidilyInPolyTime.encoding_length encBits)) using 1 + convert GapP.sum_bits_mem hneg (.of_tidy (ComputableTidilyInPolyTime.encoding_length encBits)) + using 1 ext w rw [Finset.sum_const, Finset.card_univ, Fintype.card_fun, Fintype.card_bool, Fintype.card_fin] diff --git a/ComplexityTests/CountingGapMachine.lean b/ComplexityTests/CountingGapMachine.lean index 4166e62fd..e8894ed5f 100644 --- a/ComplexityTests/CountingGapMachine.lean +++ b/ComplexityTests/CountingGapMachine.lean @@ -189,7 +189,8 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [encBits_apply, Polynomial.eval_C, Polynomial.eval_zero, Complexity.acceptCount_true, Nat.reducePow, pow_zero, Nat.cast_ofNat, Nat.cast_one, Int.reduceSub] using exists_verifier_difference_machine encBits (Polynomial.C 2) 0 (fun _ => true) (fun _ => true) - (.of_tidy (ComputableTidilyInPolyTime.const true)) (.of_tidy (ComputableTidilyInPolyTime.const true)) + (.of_tidy (ComputableTidilyInPolyTime.const true)) + (.of_tidy (ComputableTidilyInPolyTime.const true)) -- Unequal all-false families still cancel to zero, without matching their witness lengths. example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCTM k Bool State) @@ -200,7 +201,8 @@ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapeCT simpa only [encBits_apply, Polynomial.eval_C, Polynomial.eval_zero, Complexity.acceptCount_false, Nat.cast_zero, sub_self] using exists_verifier_difference_machine encBits 0 (Polynomial.C 2) (fun _ => false) (fun _ => false) - (.of_tidy (ComputableTidilyInPolyTime.const false)) (.of_tidy (ComputableTidilyInPolyTime.const false)) + (.of_tidy (ComputableTidilyInPolyTime.const false)) + (.of_tidy (ComputableTidilyInPolyTime.const false)) /-- info: 'Turing.MultiTapeCTM.exists_signed_verifier_machine' depends on axioms: diff --git a/ComplexityTests/CountingSpace.lean b/ComplexityTests/CountingSpace.lean index eee6cfcd1..b59d2e665 100644 --- a/ComplexityTests/CountingSpace.lean +++ b/ComplexityTests/CountingSpace.lean @@ -93,19 +93,22 @@ example : ∃ g ∈ SharpP encBits, ∀ b : Bool, g [b] = 0 := SharpP.exists_extension (enc := encBool) SharpP.zero_mem /-- -info: 'Cslib.Complexity.computableInPolySpace_acceptCount' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.computableInPolySpace_acceptCount' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms computableInPolySpace_acceptCount /-- -info: 'Cslib.Complexity.SharpP.computableInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SharpP.computableInPolySpace' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms SharpP.computableInPolySpace /-- -info: 'Cslib.Complexity.GapP.computableInPolySpace' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.GapP.computableInPolySpace' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms GapP.computableInPolySpace /-- info: 'Cslib.Complexity.PP_subset_PSPACE' depends on axioms: [propext, Classical.choice, Quot.sound] diff --git a/ComplexityTests/FineGrained.lean b/ComplexityTests/FineGrained.lean index 870197f54..90fad0b2b 100644 --- a/ComplexityTests/FineGrained.lean +++ b/ComplexityTests/FineGrained.lean @@ -108,11 +108,13 @@ example : satExponent 3 ≤ satExponent 4 := satExponent_mono (by norm_num) /-- A trivial problem is decidable within linear time, in either form. -/ example : DecidableInTimeO (∅ : Set (CNF ℕ)) encCNF fun φ => (encCNF φ).length := - DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) fun _ => le_rfl + DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) fun _ => + le_rfl example : (∅ : Set (CNF ℕ)) ∈ DTIME encCNF id := mem_DTIME_iff_decidableInTimeO.mpr - (DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) fun _ => le_rfl) + (DecidableInTimeO.of_computableInO (.of_tidy (ComputableTidilyInO.const false)) (by simp) + fun _ => le_rfl) /-- The hypotheses in terms of the exponents. -/ example : ETH ↔ 0 < satExponent 3 := ETH_iff_satExponent_pos diff --git a/ComplexityTests/InteractiveProofs.lean b/ComplexityTests/InteractiveProofs.lean index 74c0db1df..2cfee3a41 100644 --- a/ComplexityTests/InteractiveProofs.lean +++ b/ComplexityTests/InteractiveProofs.lean @@ -334,10 +334,11 @@ info: 'Cslib.Complexity.Interaction.computableInPolySpace_evaluate' depends on a #guard_msgs (whitespace := lax) in #print axioms Interaction.computableInPolySpace_evaluate -/-- info: 'Cslib.Complexity.Interaction.computableInPolySpace_countAccepts' depends on axioms: [propext, - Classical.choice, - Quot.sound] -/ -#guard_msgs in +/-- +info: 'Cslib.Complexity.Interaction.computableInPolySpace_countAccepts' depends on axioms: +[propext, Classical.choice, Quot.sound] +-/ +#guard_msgs (whitespace := lax) in #print axioms Interaction.computableInPolySpace_countAccepts /-- info: 'Cslib.Complexity.GameTree.iterate_step_node' depends on axioms: diff --git a/ComplexityTests/Kannan.lean b/ComplexityTests/Kannan.lean index b79688329..53150a14d 100644 --- a/ComplexityTests/Kannan.lean +++ b/ComplexityTests/Kannan.lean @@ -124,9 +124,10 @@ info: 'Cslib.MCSP.exists_verifier_append' depends on axioms: [propext, Classical #print axioms Cslib.MCSP.exists_verifier_append /-- -info: 'Cslib.MCSP.computableInPolyTime_tableVerifier' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.MCSP.computableInPolyTime_tableVerifier' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.MCSP.computableInPolyTime_tableVerifier /-- diff --git a/ComplexityTests/KarpLipton2.lean b/ComplexityTests/KarpLipton2.lean index 40ae8de7e..15ee15c43 100644 --- a/ComplexityTests/KarpLipton2.lean +++ b/ComplexityTests/KarpLipton2.lean @@ -124,9 +124,10 @@ info: 'Cslib.Complexity.SAT.verifier_search' depends on axioms: [propext, Classi #print axioms Cslib.Complexity.SAT.verifier_search /-- -info: 'Cslib.Complexity.SAT.computableInPolyTime_search' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Complexity.SAT.computableInPolyTime_search' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.SAT.computableInPolyTime_search /-- @@ -142,9 +143,10 @@ info: 'Cslib.Circuits.Boolean.evalAdvice_familyAdvice' depends on axioms: [prope #print axioms Cslib.Circuits.Boolean.evalAdvice_familyAdvice /-- -info: 'Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice' depends on axioms: [propext, Classical.choice, Quot.sound] +info: 'Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice' depends on axioms: + [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in +#guard_msgs (whitespace := lax) in #print axioms Cslib.Circuits.Boolean.computableInPolyTime_evalAdvice /-- diff --git a/ComplexityTests/NPWitness.lean b/ComplexityTests/NPWitness.lean index b14d4258c..99b0203a9 100644 --- a/ComplexityTests/NPWitness.lean +++ b/ComplexityTests/NPWitness.lean @@ -43,7 +43,8 @@ theorem isVerifier_even : IsVerifier encUnary (2 * Polynomial.X + 1) isVerifier_witnessVerifier Decoder.unary isHalf_iff fun _ m h => ⟨m, h, by simp; omega⟩ example : {n | ∃ m, m + m = n} ∈ NP encUnary := - mem_NP_of_witness Decoder.unary (p := Polynomial.X) (.of_tidy computableTidilyInPolyTime_isHalf) isHalf_iff + mem_NP_of_witness Decoder.unary (p := Polynomial.X) (.of_tidy computableTidilyInPolyTime_isHalf) + isHalf_iff fun _ m h => ⟨m, h, by simp; omega⟩ -- In: the framed witness `2` for `4`, padded to the certificate length `2 * 4 + 1`. diff --git a/ComplexityTests/NondeterministicVerifiers.lean b/ComplexityTests/NondeterministicVerifiers.lean index d498d088b..47be1e399 100644 --- a/ComplexityTests/NondeterministicVerifiers.lean +++ b/ComplexityTests/NondeterministicVerifiers.lean @@ -235,7 +235,8 @@ guessing `[true]`. -/ example : ∃ (k : ℕ) (State : Type) (_ : Finite State) (machine : MultiTapePTM k Bool State), machine.toNTM.Accepts [] := by obtain ⟨k, State, hfinite, machine, c, d, hdecides, -⟩ := - IsVerifier.exists_decidesInTime (enc := encBits) (p := 1) (A := Set.univ) (.of_tidy polyTime_headD) + IsVerifier.exists_decidesInTime (enc := encBits) (p := 1) (A := Set.univ) + (.of_tidy polyTime_headD) fun _ => ⟨fun _ => ⟨[true], by simp, rfl⟩, fun _ => trivial⟩ exact ⟨k, State, hfinite, machine, ((hdecides []).2).mp trivial⟩ diff --git a/ComplexityTests/PCPEncodedPreprocess.lean b/ComplexityTests/PCPEncodedPreprocess.lean index af6fe7897..d889d323a 100644 --- a/ComplexityTests/PCPEncodedPreprocess.lean +++ b/ComplexityTests/PCPEncodedPreprocess.lean @@ -78,7 +78,8 @@ example : reduced.WellFormed := example : ComputableTidilyInPolyTime (Graph.degreeReduce false rotateReflection [()]) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := - (Graph.isPolyTime_degreeReduce false [()] rotateReflection (.of_tidy isPolyTime_rotateReflection)).tidy + (Graph.isPolyTime_degreeReduce false [()] rotateReflection + (.of_tidy isPolyTime_rotateReflection)).tidy example : (reduced.toGraph (Graph.degreeReduceEval constraintEval)).unsatVal = ((exampleGraph.toGraph constraintEval).degreeReduce @@ -120,7 +121,8 @@ example : preprocessed.WellFormed := example : ComputableTidilyInPolyTime (Graph.preprocess false true rotateReflection [()]) (Graph.encoding encBool) (Graph.encoding (encOption (encPair encBool encBool))) := - (Graph.isPolyTime_preprocess false true rotateReflection [()] (.of_tidy isPolyTime_rotateReflection)).tidy + (Graph.isPolyTime_preprocess false true rotateReflection [()] + (.of_tidy isPolyTime_rotateReflection)).tidy attribute [local fun_prop] ComputableInPolySpace.tidy in attribute [local fun_prop] ComputableInPolyTime.tidy in @@ -269,7 +271,8 @@ private theorem isPolyTime_tablePreprocess : ComputableTidilyInPolyTime tablePre have hdegreeEval := (Graph.isPolyTime_degreeReduceEval (eval := fun table : Bool → Bool → Bool => table) (.of_tidy heval)).tidy have hpre := (Graph.isPolyTime_preprocess (enc := encPi (encPi encBool)) - (fun (_ _ : Bool) => false) (fun _ _ => true) rotateReflection [()] (.of_tidy isPolyTime_rotateReflection)).tidy + (fun (_ _ : Bool) => false) (fun _ _ => true) rotateReflection [()] + (.of_tidy isPolyTime_rotateReflection)).tidy exact (Graph.isPolyTime_tabulateConstraints (.of_tidy hdegreeEval)).tidy.comp hpre example : ComputableTidilyInPolyTime (fun g => tablePreprocess (tablePreprocess g)) diff --git a/ComplexityTests/Parameterized.lean b/ComplexityTests/Parameterized.lean index c32fc1c2e..cd7e9ce20 100644 --- a/ComplexityTests/Parameterized.lean +++ b/ComplexityTests/Parameterized.lean @@ -106,7 +106,8 @@ private theorem mem_SAT_toSAT (φ : CNF ℕ) : φ ∈ ThreeSAT ↔ toSAT φ ∈ private theorem threeSAT_fptReducible_SAT : FPTReducible encCNF encCNF CNF.numVars CNF.numVars ThreeSAT SAT := - FPTReducible.of_computableInPolyTime (.of_tidy toSAT_polyTime) (h := id) numVars_toSAT_le mem_SAT_toSAT + FPTReducible.of_computableInPolyTime (.of_tidy toSAT_polyTime) (h := id) numVars_toSAT_le + mem_SAT_toSAT /-- The reduction does not map the formula `x₀ ∧ (x₀ ∨ x₁ ∨ x₂ ∨ x₃)` to itself. -/ example : toSAT [[(0, true)], [(0, true), (1, true), (2, true), (3, true)]] = [[]] := by decide diff --git a/ComplexityTests/TFNP.lean b/ComplexityTests/TFNP.lean index 66fd44002..5acadc10e 100644 --- a/ComplexityTests/TFNP.lean +++ b/ComplexityTests/TFNP.lean @@ -29,7 +29,8 @@ private theorem emptyRel_mem_TFNP : emptyRel ∈ TFNP encBits := ⟨emptyRel_mem_FNP, fun _ => ⟨[], rfl⟩⟩ private theorem emptyRel_mem_FPSearch : emptyRel ∈ FPSearch encBits := - mem_FPSearch_of_total emptyRel_mem_FNP (.of_tidy (ComputableTidilyInPolyTime.const [])) fun _ => rfl + mem_FPSearch_of_total emptyRel_mem_FNP (.of_tidy (ComputableTidilyInPolyTime.const [])) fun _ => + rfl example : searchDomain emptyRel = Set.univ := isTotalSearch_iff_searchDomain_eq_univ.1 emptyRel_mem_TFNP.2 diff --git a/ComplexityTests/TFNPCompleteness.lean b/ComplexityTests/TFNPCompleteness.lean index c690a1074..99ab19d57 100644 --- a/ComplexityTests/TFNPCompleteness.lean +++ b/ComplexityTests/TFNPCompleteness.lean @@ -19,7 +19,8 @@ open Turing.MultiTapeTM ComputableTidilyInPolyTime example : ∃ code : ℕ → CircuitCode, ComputableInPolyTime code encUnary encCode ∧ ∀ n u, u.length = n → evalCircuitOutputs (code n) u = u := - exists_uniformCircuitCodes (.of_tidy id') (.of_tidy id') (.of_tidy (snd encUnary encBits)) (fun _ _ h => h) + exists_uniformCircuitCodes (.of_tidy id') (.of_tidy id') (.of_tidy (snd encUnary encBits)) + (fun _ _ h => h) -- Each canonical search problem has the advertised class and reduction quantifiers. example : SearchComplete @PPP encPigeon Pigeon := Pigeon_searchComplete @@ -41,12 +42,14 @@ private theorem cost_polytime : /-- A one-bit local-search family can have costs requiring five bits. -/ theorem wideCostFamily_mem_PLS : localOptRel (fun _ : Bool => 1) neighbor cost ∈ PLS encBool := - localOptRel_mem_PLS (.of_tidy (const 1)) (.of_tidy neighbor_polytime) (.of_tidy cost_polytime) (by simp [neighbor]) + localOptRel_mem_PLS (.of_tidy (const 1)) (.of_tidy neighbor_polytime) (.of_tidy cost_polytime) + (by simp [neighbor]) /-- The reduction preserves this family without restricting costs to the vertex width. -/ theorem wideCostFamily_reduces : SearchReducible encBool encLocalOpt (localOptRel (fun _ : Bool => 1) neighbor cost) LocalOpt := - localOptRel_searchReducible_LocalOpt (.of_tidy (const 1)) (.of_tidy neighbor_polytime) (.of_tidy cost_polytime) + localOptRel_searchReducible_LocalOpt (.of_tidy (const 1)) (.of_tidy neighbor_polytime) + (.of_tidy cost_polytime) (by simp [neighbor]) example : localOptRel (fun _ : Bool => 1) neighbor cost false [false] := by diff --git a/ComplexityTests/WPPBounded.lean b/ComplexityTests/WPPBounded.lean index 4cefdd7af..29a03c708 100644 --- a/ComplexityTests/WPPBounded.lean +++ b/ComplexityTests/WPPBounded.lean @@ -48,7 +48,8 @@ theorem joint_mem_LWPP : bitLanguage ∈ LWPP (encPair encBits encUnary) := by have hg : ComputableTidilyInPolyTime g (encPair encBits encUnary) encIntBin := by dsimp only [g] fun_prop - refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy target_polyTime, target_ne_zero, ?_, ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy target_polyTime, target_ne_zero, ?_, + ?_⟩ · intro x cases h : x.1.getD x.2 false <;> simp only [g, h] <;> simp · intro x diff --git a/ComplexityTests/WPPRobustness.lean b/ComplexityTests/WPPRobustness.lean index ab1f51b43..8e50c0db9 100644 --- a/ComplexityTests/WPPRobustness.lean +++ b/ComplexityTests/WPPRobustness.lean @@ -18,7 +18,8 @@ private def language : Set (List Bool) := {w | w.headD false = true} private def gap (w : List Bool) : ℤ := if w.headD false then -1 else 0 -private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (.of_tidy (by unfold gap; fun_prop)) +private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime + (.of_tidy (by unfold gap; fun_prop)) private def targets (n : ℕ) : List ℤ := -1 :: -1 :: List.replicate n (-2) diff --git a/ComplexityTests/WPPTruthTable.lean b/ComplexityTests/WPPTruthTable.lean index 95012e47f..15c637c09 100644 --- a/ComplexityTests/WPPTruthTable.lean +++ b/ComplexityTests/WPPTruthTable.lean @@ -39,7 +39,8 @@ theorem target_ne_zero (n : ℕ) : target n ≠ 0 := by theorem oracle_mem_LWPP : oracle ∈ LWPP encBits := by let g (w : List Bool) : ℤ := if w.getD 0 false then target w.length else 0 have hg : ComputableTidilyInPolyTime g encBits encIntBin := by dsimp [g]; fun_prop - refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy polyTime_target, target_ne_zero, ?_, ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy polyTime_target, target_ne_zero, ?_, + ?_⟩ · intro w dsimp [g] split_ifs <;> simp @@ -87,7 +88,8 @@ example : language ∈ LWPP encBits := truthTable_mem_LWPP joint_mem_LWPP (.of_tidy polyTime_count) (.of_tidy polyTime_combine) example : language ∈ WPP encBits := - truthTable_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) (.of_tidy polyTime_count) (.of_tidy polyTime_combine) + truthTable_mem_WPP (LWPP_subset_WPP joint_mem_LWPP) (.of_tidy polyTime_count) + (.of_tidy polyTime_combine) example : count [true, false] = 2 ∧ count [false, true] = 0 := by decide diff --git a/ComplexityTests/WPPTwoSided.lean b/ComplexityTests/WPPTwoSided.lean index 9d6ac1bc0..51765aea7 100644 --- a/ComplexityTests/WPPTwoSided.lean +++ b/ComplexityTests/WPPTwoSided.lean @@ -18,7 +18,8 @@ private def language : Set (List Bool) := {w | w.headD false = true} private def gap (w : List Bool) : ℤ := if w.headD false then 0 else 1 -private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime (.of_tidy (by unfold gap; fun_prop)) +private theorem gap_mem : gap ∈ GapP encBits := mem_GapP_of_polyTime + (.of_tidy (by unfold gap; fun_prop)) private def yesTargets (n : ℕ) : List ℤ := 0 :: List.replicate n (-2) private def noTargets (n : ℕ) : List ℤ := 1 :: List.replicate (2 * n) 3 diff --git a/ComplexityTests/ZooCountingHierarchy.lean b/ComplexityTests/ZooCountingHierarchy.lean index 8e36767f3..cd80a8a1e 100644 --- a/ComplexityTests/ZooCountingHierarchy.lean +++ b/ComplexityTests/ZooCountingHierarchy.lean @@ -41,7 +41,8 @@ example : {w : List Bool | w.tail.headD false = true} ∈ US encBits := /-- FP counts may be exponentially large: the output encoding is binary. -/ example : (fun w : List Bool => 2 ^ w.length) ∈ SharpP encBits := - mem_SharpP_of_polyTime (.of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp (.encoding_length encBits))) + mem_SharpP_of_polyTime + (.of_tidy (ComputableTidilyInPolyTime.binary_two_pow.comp (.encoding_length encBits))) private def target (n : ℕ) : ℤ := -(2 ^ n : ℤ) From 3dd173357e37aa2d57cc4884b4e8d8c3af66e604 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 14:07:14 -0400 Subject: [PATCH 08/11] refactor(classes): follow main's CNF and graph refactors, review module docs After regenerating the sweep on fresh main: `distinctVars` certificates come from `SAT` (#826), the graph non-isomorphism protocol keeps main's private `image` rule (#828), one long line is reflowed, the TreeEval and USTCON reader docs no longer call their now-plain certificates tidy, and the S3 baseline is lowered again (Classes: 590 tidy statements in 179 modules on main, 5 case-1 originals in 3 modules after). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Classes/ArthurMerlin/GraphNonIsomorphism.lean | 10 ---------- .../Complexity/FineGrained/BruteForce.lean | 2 +- .../Complexity/FineGrained/OrthogonalVectors.lean | 4 ++-- .../Complexity/FineGrained/Sparsification.lean | 2 +- .../Complexity/Problems/GraphIsomorphism.lean | 3 ++- .../Complexity/Problems/Hamiltonian/Sparse.lean | 2 +- .../TreeEval/Reader/Cert/Machine.lean | 2 +- .../Computability/TreeEval/Reader/Cert/Offset.lean | 2 +- .../Computability/TreeEval/Reader/Cert/Regs.lean | 2 +- .../TreeEval/Reader/Cert/Residue.lean | 2 +- .../Computability/TreeEval/Reader/Cert/Step.lean | 2 +- .../Computability/TreeEval/Reader/Cert/Weight.lean | 2 +- Complexity/Computability/TreeEval/Space.lean | 2 +- Complexity/Computability/USTCON/Reader/Cert.lean | 14 +++++++------- 14 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean index 6aba367fd..79095d14a 100644 --- a/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean +++ b/Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean @@ -360,16 +360,6 @@ private theorem computableTidilyInPolyTime_adjIndex (ComputableInPolyTime.tidy (Graph.computableInPolyTime_adjIndex (.of_tidy hG) (.of_tidy hi) (.of_tidy hj))) -@[local fun_prop] -private theorem computableTidilyInPolyTime_image - {γ : Type} {input : γ ↪ List Bool} {n i : γ → ℕ} - {w : γ → List Bool} (hn : ComputableTidilyInPolyTime n input encUnary) - (hw : ComputableTidilyInPolyTime w input encBits) - (hi : ComputableTidilyInPolyTime i input encUnary) : - ComputableTidilyInPolyTime (fun x => GraphIsomorphism.image (n x) (w x) (i x)) input encUnary := - (ComputableInPolyTime.tidy (GraphIsomorphism.computableInPolyTime_image (.of_tidy hn) - (.of_tidy hw) (.of_tidy hi))) - @[local fun_prop] private theorem computableTidilyInPolyTime_distinctVertices : ComputableTidilyInPolyTime Graph.distinctVertices encGraph (encList encNat) := diff --git a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean index 05f16baea..6b0be7638 100644 --- a/Complexity/Computability/Complexity/FineGrained/BruteForce.lean +++ b/Complexity/Computability/Complexity/FineGrained/BruteForce.lean @@ -134,7 +134,7 @@ open ComputableTidilyInPolyTime in /-- The initial state is computed in polynomial time. -/ private theorem computableTidilyInPolyTime_init : ComputableTidilyInPolyTime init encCNF encState := by - have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy + have hvars := SAT.computableInPolyTime_distinctVars.tidy unfold init fun_prop diff --git a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean index c448b5759..8c8699d60 100644 --- a/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean +++ b/Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean @@ -468,7 +468,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in theorem computableInPolyTime_firstVars : ComputableInPolyTime firstVars encCNF (encList encNat) := by - have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy + have hvars := SAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ have h : ComputableTidilyInPolyTime (fun φ => (φ.distinctVars.reverse.drop (φ.distinctVars.length - φ.distinctVars.length / 2)).reverse) @@ -486,7 +486,7 @@ attribute [local fun_prop] ComputableInPolyTime.tidy in open ComputableTidilyInPolyTime in theorem computableInPolyTime_secondVars : ComputableInPolyTime secondVars encCNF (encList encNat) := by - have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy + have hvars := SAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ exact (dropUnary (encA := encNat)).comp (SAT.computableInPolyTime_distinctVars.tidy.prod (show ComputableTidilyInPolyTime (fun φ => φ.distinctVars.length / 2) encCNF diff --git a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean index b35b14980..84a7d9b71 100644 --- a/Complexity/Computability/Complexity/FineGrained/Sparsification.lean +++ b/Complexity/Computability/Complexity/FineGrained/Sparsification.lean @@ -372,7 +372,7 @@ private theorem computableTidilyInPolyTime_root (k : ℕ) : attribute [local fun_prop] ComputableInPolyTime.tidy in private theorem computableTidilyInPolyTime_rounds (M : ℕ) : ComputableTidilyInPolyTime (rounds M) encCNF encNat := by - have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy + have hvars := SAT.computableInPolyTime_distinctVars.tidy have h := unary_div_const M unfold rounds fun_prop diff --git a/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean b/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean index c8deada5b..2ec5a845f 100644 --- a/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean +++ b/Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean @@ -162,7 +162,8 @@ theorem computableInPolyTime_verifier : ((length_list encNat).comp (by fun_prop))) ?_))).tidy refine allWithInput (by fun_prop) (allWithInput (by fun_prop) ?_) exact bool_beq.comp ((hadj (by fun_prop) (by fun_prop) (by fun_prop)).prod - (Graph.computableInPolyTime_adjIndex (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop))).tidy) + (Graph.computableInPolyTime_adjIndex (.of_tidy (by fun_prop)) (.of_tidy (by fun_prop)) + (.of_tidy (by fun_prop))).tidy) /-- `verifier` is a verifier for `GraphIsomorphism` with certificates whose length is the square of the length of the encoded pair of graphs. -/ diff --git a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean index d4a0035b5..6a55981ed 100644 --- a/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean +++ b/Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean @@ -348,7 +348,7 @@ theorem computableInPolyTime_toSparseDirHamPath : (encPair encGraph (encPair encNat encNat)) := by have hgraph := computableInPolyTime_sparseDiamondGraph.tidy have htop := Diamond.computableInPolyTime_topNode.tidy - have hvars := ThreeSAT.computableInPolyTime_distinctVars.tidy + have hvars := SAT.computableInPolyTime_distinctVars.tidy refine .of_tidy ?_ have hn := computableTidilyInPolyTime_numDiamonds unfold toSparseDirHamPath diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean index 721542415..671b4591c 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean @@ -14,7 +14,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla /-! # The Tree Evaluation read machine within its space budget -The halting test, the address and the step of `Cslib.TreeEval.Reader.machine` are tidily computable +The halting test, the address and the step of `Cslib.TreeEval.Reader.machine` are computable within the space budget `Cslib.TreeEval.Reader.stateBudget` of its states, and the step machine simulating it is tidy. diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean index bd586dc84..93fd45f97 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Offset.lean @@ -16,7 +16,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla The offset of the node at a path is a fold over the path from the root: a step adds the length of a table and, to the right child, the length of the body of the left one. With the lengths computed -by iteration, and the path read off the stack, it is tidily computable within work space linear in +by iteration, and the path read off the stack, it is computable within work space linear in the encoded stack, the height and the value length. ## Main results diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean index 4ac3565b7..c70fe8028 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Regs.lean @@ -14,7 +14,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla /-! # Register operations within linear work space -The register operations of `Cslib.TreeEval.Reader` are tidily computable within work space linear +The register operations of `Cslib.TreeEval.Reader` are computable within work space linear in the lengths of their encoded arguments. ## Main results diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean index e5321cd7f..d334b4539 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Residue.lean @@ -14,7 +14,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla /-! # Residues within linear work space -The residue operations of `Cslib.TreeEval.Reader` are tidily computable within work space linear +The residue operations of `Cslib.TreeEval.Reader` are computable within work space linear in the lengths of their encoded arguments. ## Main results diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean index 23633aeb2..166968d86 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean @@ -17,7 +17,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla # The step of the Tree Evaluation read machine within its space budget The halting test, the address and the step of `Cslib.TreeEval.Reader.machine`, on tuples, are -tidily computable within the space budget `Cslib.TreeEval.Reader.stepBudget`: the length of the +computable within the space budget `Cslib.TreeEval.Reader.stepBudget`: the length of the encoded tuple, the value length, the height, and the registers with every entry as long as the prime and the round of the top frame together. On the states the machine reaches, the budget is `O((h + ℓ) log ℓ)`. diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean index 190a11e8d..806686072 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Weight.lean @@ -17,7 +17,7 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla # The weights of table entries within linear work space The weight `Cslib.TreeEval.Reader.weight p ℓ k x y`, the product of `x j` or `1 - x j` over the low -bits of `k` and the same over its high bits for `y`, is tidily computable within work space +bits of `k` and the same over its high bits for `y`, is computable within work space linear in the lengths of its encoded arguments and in `ℓ`. Its products are taken over a counter rather than a list of indices, and they stay short: below `p`, or, for `p = 0`, no longer than the registers together. diff --git a/Complexity/Computability/TreeEval/Space.lean b/Complexity/Computability/TreeEval/Space.lean index 623ac965e..b4f28c18b 100644 --- a/Complexity/Computability/TreeEval/Space.lean +++ b/Complexity/Computability/TreeEval/Space.lean @@ -13,7 +13,7 @@ public import Complexity.Computability.TreeEval.Reader.Size /-! # Tree Evaluation in small space -**Cook and Mertz**: Tree Evaluation of value length `ℓ` and height `H` is tidily computable on +**Cook and Mertz**: Tree Evaluation of value length `ℓ` and height `H` is computable on multi-tape Turing machines in space `O((ℓ + H + 1) · log (ℓ + 2) + log (n + 2))`, where `n` is the length of the encoded instance. On nontrivial instances (`1 ≤ ℓ` and `1 ≤ H`), both `2 ^ ℓ` and `2 ^ H` are at most `n`, so `ℓ, H < |n|` and `|ℓ| ≤ ||n||` (writing `|m|` for the binary length diff --git a/Complexity/Computability/USTCON/Reader/Cert.lean b/Complexity/Computability/USTCON/Reader/Cert.lean index 47d9b8558..b0f1617d5 100644 --- a/Complexity/Computability/USTCON/Reader/Cert.lean +++ b/Complexity/Computability/USTCON/Reader/Cert.lean @@ -17,9 +17,9 @@ import Complexity.Computability.Machines.Turing.MultiTape.Complexity.InSpace.Pla /-! # The read machine for undirected connectivity within linear work space -The halting test, the address and the step of `Cslib.USTCON.Reader.machine` are tidily computable -within work space linear in the length of the encoded state (and the bit read): every step is a -bounded number of operations on the numbers and the heads of the lists of the state — comparisons, +The halting test, the address and the step of `Cslib.USTCON.Reader.machine` are computable within +work space linear in the length of the encoded state (and the bit read): every step is a bounded +number of operations on the numbers and the heads of the lists of the state — comparisons, successors and predecessors, products for the address, divisions by the number of labels, and functions of the finitely many controls, labels and frames. So the step machine simulating the read machine is tidy within space linear in its states and the position of its head @@ -473,17 +473,17 @@ private theorem stepBudget_bool (x : Tuple) (b : Bool) : stepBudget (x, b) = ste (x, false) := by cases b <;> simp [stepBudget, encBool_apply] -/-- The halting test of `machine` is tidily computable within the space budget of the state. -/ +/-- The halting test of `machine` is computable within the space budget of the state. -/ theorem halt_inSpace : ComputableInSpace machine.halt encState encBool stateBudget := .of_tidy ((haltT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl) -/-- The address of `machine` is tidily computable within the space budget of the state. -/ +/-- The address of `machine` is computable within the space budget of the state. -/ theorem addr_inSpace : ComputableInSpace machine.addr encState (encOption encNat) stateBudget := .of_tidy ((addrT_inSpace.of_encIn_eq State.toTuple fun _ ↦ rfl).of_enc_eq fun _ ↦ rfl) -/-- The step of `machine`, on a state and the bit read, is tidily computable within the space -budget of the state. -/ +/-- The step of `machine`, on a state and the bit read, is computable within the space budget of +the state. -/ theorem step_inSpace : ComputableInSpace (fun p : State × Bool => machine.step p.1 p.2) (encPair encState encBool) (encPair encState encBits) fun p => stateBudget p.1 := by From 440c34d4b2d33499ab034c69617a59abdc365501 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 14:08:26 -0400 Subject: [PATCH 09/11] test(classes): plain fun_prop over restated Classes certificates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Client examples for automation parity: plain `fun_prop` composes the plain Buss-kernel, Sipser–Lautemann and Clique certificates with plain hypotheses. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- ComplexityTests/NPCompleteness.lean | 6 ++++++ ComplexityTests/SipserLautemann.lean | 6 ++++++ ComplexityTests/VertexCoverKernel.lean | 13 +++++++++++++ 3 files changed, 25 insertions(+) diff --git a/ComplexityTests/NPCompleteness.lean b/ComplexityTests/NPCompleteness.lean index e3d6659f0..9b2a573f0 100644 --- a/ComplexityTests/NPCompleteness.lean +++ b/ComplexityTests/NPCompleteness.lean @@ -67,4 +67,10 @@ example : ((([], []) : Graph), 1) ∉ Clique := by have := Graph.le_card_of_mem_Clique h simp at this +/-- Plain `fun_prop` composes the plain `Clique` verifier certificate with a plain map. -/ +example {γ : Type} {enc : γ ↪ List Bool} {f : γ → (Graph × ℕ) × List Bool} + (hf : ComputableInPolyTime f enc (encPair (encPair encGraph encNat) encBits)) : + ComputableInPolyTime (fun c => Clique.verifier (f c)) enc encBool := by + fun_prop + end ComplexityTests.NPCompleteness diff --git a/ComplexityTests/SipserLautemann.lean b/ComplexityTests/SipserLautemann.lean index 113e8d36f..141e6fb6f 100644 --- a/ComplexityTests/SipserLautemann.lean +++ b/ComplexityTests/SipserLautemann.lean @@ -214,4 +214,10 @@ info: 'Cslib.Complexity.BPP_subset_PH' depends on axioms: [propext, Classical.ch #guard_msgs in #print axioms Cslib.Complexity.BPP_subset_PH +/-- Plain `fun_prop` uses the plain matrix-verifier certificate from a plain hypothesis. -/ +example {α : Type} {enc : α ↪ List Bool} {p : Polynomial ℕ} {V : α × List Bool → Bool} + (hV : ComputableInPolyTime V (encPair enc encBits) encBool) : + ComputableInPolyTime (fun x => !verifier enc p V x) (encPair enc encBits) encBool := by + fun_prop + end Cslib.Complexity.Tests.SipserLautemann diff --git a/ComplexityTests/VertexCoverKernel.lean b/ComplexityTests/VertexCoverKernel.lean index a644185ef..66d6d7538 100644 --- a/ComplexityTests/VertexCoverKernel.lean +++ b/ComplexityTests/VertexCoverKernel.lean @@ -168,4 +168,17 @@ info: 'Cslib.Complexity.VertexCover_hasPolyKernel' depends on axioms: #guard_msgs (whitespace := lax) in #print axioms Cslib.Complexity.VertexCover_hasPolyKernel +/-! ### Plain automation over the restated kernel certificates -/ + +/-- Plain `fun_prop` composes the plain kernel certificates with plain hypotheses. -/ +example {γ : Type} {enc : γ ↪ List Bool} {x : γ → Graph × ℕ} + (hx : ComputableInPolyTime x enc (encPair encGraph encNat)) : + ComputableInPolyTime (fun c => high (x c)) enc (encList encNat) := by + fun_prop + +example {γ : Type} {enc : γ ↪ List Bool} {G : γ → Graph} {v : γ → ℕ} + (hG : ComputableInPolyTime G enc encGraph) (hv : ComputableInPolyTime v enc encNat) : + ComputableInPolyTime (fun c => degree (G c) (v c)) enc encUnary := by + fun_prop + end ComplexityTests.VertexCoverKernel From 2732585773fffa0ff8947694d83c5e2be4bac4f9 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 14:37:38 -0400 Subject: [PATCH 10/11] refactor(classes): follow the Wave 5 names and MINKT after regenerating After regenerating on main with #835 and #817: `MINKT.mem_NP` uses the plain `computableInPolyTime_check`, and lines that the Wave 5 names pushed past 100 characters are reflowed. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Computability/Complexity/Classes/WPP.lean | 4 +- .../Computability/Kolmogorov/MINKT.lean | 2 +- .../TreeEval/Reader/Cert/Machine.lean | 4 +- .../TreeEval/Reader/Cert/Step.lean | 39 ++++++++++++------- ComplexityTests/WPPBounded.lean | 4 +- ComplexityTests/WPPTruthTable.lean | 4 +- 6 files changed, 35 insertions(+), 22 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/WPP.lean b/Complexity/Computability/Complexity/Classes/WPP.lean index e3895ba5a..7da1be5b7 100644 --- a/Complexity/Computability/Complexity/Classes/WPP.lean +++ b/Complexity/Computability/Complexity/Classes/WPP.lean @@ -400,8 +400,8 @@ theorem mem_LWPP_of_polyTime_index {g : α → ℤ} {f : ℕ → ℤ} {k : α rw [List.nodup_range.erase_eq_filter] exact List.filter_congr fun i _ => by simp [bne, beq_eq_decide] simpa only [h, F, herase] using List.prod_map_erase f (List.mem_range.mpr (hlt a)) - refine ⟨g * h, GapP.mul_mem hg (mem_GapP_of_polyTime (.of_tidy hh)), F, .of_tidy hF, hFn, fun a => ?_, - fun a => ?_⟩ + refine ⟨g * h, GapP.mul_mem hg (mem_GapP_of_polyTime (.of_tidy hh)), F, .of_tidy hF, hFn, + fun a => ?_, fun a => ?_⟩ · rcases hr a with hz | hfk · exact Or.inl (by simp [hz]) · exact Or.inr (by simp [hfk, hmul a]) diff --git a/Complexity/Computability/Kolmogorov/MINKT.lean b/Complexity/Computability/Kolmogorov/MINKT.lean index 1fd58b8d9..d404a6e5f 100644 --- a/Complexity/Computability/Kolmogorov/MINKT.lean +++ b/Complexity/Computability/Kolmogorov/MINKT.lean @@ -259,7 +259,7 @@ is a binary program `p` of length at most `s ≤ |(x, 1^t, 1^s)|`, verified in p running the universal simulator for `t` steps (`check`). -/ theorem mem_NP : MINKT ∈ NP enc := by have h := mem_NP_of_witness (enc := enc) (p := Polynomial.X) Decoder.bits - computableTidilyInPolyTime_check (fun i p => check_eq_true_iff) + computableInPolyTime_check (fun i p => check_eq_true_iff) fun i p hp => ⟨p, hp, by simpa only [encBits_apply, Polynomial.eval_X] using hp.1.trans (size_le_length_enc i)⟩ simpa only [← mem_iff_exists_program, Set.ofPred_mem_eq] using h diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean index 671b4591c..1a3c96db0 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Machine.lean @@ -71,8 +71,8 @@ private theorem offsetT_inSpace {st : Tuple × Bool → List Frame} have hpo := budget_comp pathOffset_inSpace.tidy harg (.const_mul (2 ^ 30) (((ell_le_stepBudget.add height_le_stepBudget).add (length_le harg)).add (.const 1 _))) have h₂ := - (succ_inSpace (succ_inSpace - (.of_tidy (budget_comp_lin natAdd linear_succ (budget_prod ell_inSpace.tidy height_inSpace.tidy))))).tidy + (succ_inSpace (succ_inSpace (.of_tidy (budget_comp_lin natAdd linear_succ + (budget_prod ell_inSpace.tidy height_inSpace.tidy))))).tidy refine (budget_comp_lin natAdd linear_succ (budget_prod h₂ hpo)).of_enc_eq fun y => ?_ simp only [offsetT, path_eq_reverse, foldl_cons_dir, List.append_nil] diff --git a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean index 166968d86..a8ad7e844 100644 --- a/Complexity/Computability/TreeEval/Reader/Cert/Step.lean +++ b/Complexity/Computability/TreeEval/Reader/Cert/Step.lean @@ -152,7 +152,8 @@ private theorem hTop : ComputableTidilyInSpace /-- The rest of the stack. -/ theorem rest_inSpace : ComputableInSpace (fun y : Tuple × Bool => y.1.stack.tail) encStepInT (encList encFrame) stepBudget := - .of_tidy (budget_comp_linear (of_inO (.of_linear (ListEncoding.tail encFrame))) stack_inSpace.tidy) + .of_tidy (budget_comp_linear (of_inO (.of_linear (ListEncoding.tail encFrame))) + stack_inSpace.tidy) /-- A function of the finite fields of the top frame. -/ private theorem hTopFinite {β : Type} {encB : β ↪ List Bool} (g : Fin 4 × Bool × Fin 3 → β) : @@ -259,9 +260,11 @@ private theorem branch0_inSpace : encStepInT encStepOut stepBudget := budget_ite hBit (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 0) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) (out_inSpace - (budget_prod (budget_prod (budget_prod n₁_inSpace.tidy (budget_prod height_inSpace.tidy hP)) hRegs) + (budget_prod + (budget_prod (budget_prod n₁_inSpace.tidy (budget_prod height_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 1) (hConstNat 0) (hConstNat 0) hNil)))) /-- The header: reading the height. -/ @@ -276,8 +279,10 @@ private theorem branch1_inSpace : exact (succ_inSpace (succ_inSpace (.of_tidy h))).tidy.of_enc_eq fun y => by congr 1; omega exact budget_ite hBit (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) - (out_inSpace (budget_prod (budget_prod (budget_prod ell_inSpace.tidy (budget_prod n₁_inSpace.tidy hP)) hRegs) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 1) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hNil))) + (out_inSpace (budget_prod + (budget_prod (budget_prod ell_inSpace.tidy (budget_prod n₁_inSpace.tidy hP)) hRegs) (budget_prod hStackMode (mkCtl_inSpace (hConstTag 2) h2e (hConstNat 2) hNil)))) private theorem hReplicate : @@ -314,9 +319,11 @@ private theorem branch2_inSpace : (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil) refine (budget_ite hlt (budget_ite hz (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace).tidy (hConstNat 2) hNil))) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 2) (succ_inSpace n₁_inSpace).tidy (hConstNat 2) hNil))) (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 2) n₁_inSpace.tidy (succ_inSpace (.of_tidy hN₂)).tidy hNil)))) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 2) n₁_inSpace.tidy (succ_inSpace (.of_tidy hN₂)).tidy hNil)))) (out_inSpace hfound)).of_enc_eq fun y => ?_ simp only [decide_eq_true_eq] @@ -411,9 +418,11 @@ private theorem branch5_inSpace : have hempty := budget_comp_linear (of_inO (.of_linear (ListEncoding.isEmpty (enc₁ := encFrame) (enc := encList encFrame)))) stack_inSpace.tidy - have hG := budget_comp tableLength_inSpace.tidy ell_inSpace.tidy (.const_mul 4096 (ell_le_stepBudget.add + have hG := budget_comp tableLength_inSpace.tidy ell_inSpace.tidy + (.const_mul 4096 (ell_le_stepBudget.add (.const 1 _))) - have hdm := budget_comp_lin natDivMod (linear_mul _) (budget_prod n₁_inSpace.tidy ell_inSpace.tidy) + have hdm := budget_comp_lin natDivMod (linear_mul _) + (budget_prod n₁_inSpace.tidy ell_inSpace.tidy) have hk := fst' hdm have hi := snd' hdm have hx := (get_inSpace (.of_tidy hRegs) (.of_tidy (hRegPlus 1))).tidy @@ -421,7 +430,8 @@ private theorem branch5_inSpace : have hw := budget_comp weight_inSpace.tidy (budget_prod (budget_prod hP (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy)) (.const_mul 64 (((length_le (budget_prod (budget_prod hP - (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy))).add ell_le_stepBudget).add (.const 1 _))) + (budget_prod ell_inSpace.tidy hk)) (budget_prod hx hy))).add ell_le_stepBudget).add + (.const 1 _))) have hacc' := (modifyAt_inSpace (.of_tidy hAcc) (.of_tidy hi) (.of_tidy hP) (.of_tidy hw)).tidy have hB : (fun y : Tuple × Bool => (y.1.regs.get (y.1.stack.headD dfr).target).length * ((encNat y.1.p).length + 1)) ≼ stepBudget := @@ -434,9 +444,11 @@ private theorem branch5_inSpace : refine (budget_ite hempty (out_inSpace hTup) (budget_ite (hLt n₁_inSpace.tidy hG) (budget_ite hBit (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hacc'))) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hacc'))) (out_inSpace - (withCtl_inSpace (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hAcc)))) + (withCtl_inSpace + (mkCtl_inSpace (hConstTag 5) (succ_inSpace n₁_inSpace).tidy (hConstNat 0) hAcc)))) (out_inSpace (withRegsModeCtl_inSpace hsub (cons_inSpace (hFrPhase 2) rest_inSpace.tidy) (hTopFinite (encB := encMode) fun g => .call true (g.2.2 + 1)) (mkCtl_inSpace (hConstTag 3) (hConstNat 0) (hConstNat 0) hNil))))).of_enc_eq fun y => ?_ @@ -503,7 +515,8 @@ private theorem branch3_inSpace : (hConstNat (unitVal 0)) (fun _ _ => rfl) fun y => by have : (encNat (unitVal 0)).length = 1 := rfl omega - have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace (.of_tidy hRound)).tidy (fun _ _ => rfl) + have hRj := scaleT_inSpace hRegs (hRegPlus 2) (succ_inSpace (.of_tidy hRound)).tidy + (fun _ _ => rfl) fun y => by have := length_encNat_add_le_add (y.1.stack.headD dfr).round 1 have : (encNat 1).length = 1 := rfl diff --git a/ComplexityTests/WPPBounded.lean b/ComplexityTests/WPPBounded.lean index 29a03c708..fe45286c6 100644 --- a/ComplexityTests/WPPBounded.lean +++ b/ComplexityTests/WPPBounded.lean @@ -48,8 +48,8 @@ theorem joint_mem_LWPP : bitLanguage ∈ LWPP (encPair encBits encUnary) := by have hg : ComputableTidilyInPolyTime g (encPair encBits encUnary) encIntBin := by dsimp only [g] fun_prop - refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy target_polyTime, target_ne_zero, ?_, - ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy target_polyTime, target_ne_zero, + ?_, ?_⟩ · intro x cases h : x.1.getD x.2 false <;> simp only [g, h] <;> simp · intro x diff --git a/ComplexityTests/WPPTruthTable.lean b/ComplexityTests/WPPTruthTable.lean index 15c637c09..04d54aff5 100644 --- a/ComplexityTests/WPPTruthTable.lean +++ b/ComplexityTests/WPPTruthTable.lean @@ -39,8 +39,8 @@ theorem target_ne_zero (n : ℕ) : target n ≠ 0 := by theorem oracle_mem_LWPP : oracle ∈ LWPP encBits := by let g (w : List Bool) : ℤ := if w.getD 0 false then target w.length else 0 have hg : ComputableTidilyInPolyTime g encBits encIntBin := by dsimp [g]; fun_prop - refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy polyTime_target, target_ne_zero, ?_, - ?_⟩ + refine ⟨g, mem_GapP_of_polyTime (.of_tidy hg), target, .of_tidy polyTime_target, target_ne_zero, + ?_, ?_⟩ · intro w dsimp [g] split_ifs <;> simp From ab87423678193ba2de75e970a081022716981259 Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Sat, 24 Oct 2026 15:16:28 -0400 Subject: [PATCH 11/11] refactor(classes): follow #843, #844 and #848 after regenerating After regenerating on main with #842, #843, #844, #848, #849 and #850: `SharpPWithOracle.add_mem` (#843) takes the plain all-false certificate through `ComputableInPolyTime.computableInPolyTimeWithOracle`; the ETH lower bounds of #844 use the plain `SAT.toThreeColoring` and `toBinary` certificates and `DecidableInTimeO.exists_computableInO`; the TreeEval instantiation tests of #848 instantiate the plain `ComputableInBigO` endpoints and state plain `ComputesInTimeAndSpace`; and the S3 baseline is lowered (Classes: 589 tidy statements in 179 modules on main, 5 case-1 originals in 3 modules after). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Dvi6MU29zU9t8zYfeU51sB --- .../Complexity/Classes/SharpP/Oracle.lean | 2 +- .../PermutationIndependentSet.lean | 10 +- ComplexityTests/TreeEval.lean | 20 +- scripts/tidy_surface_baseline.json | 182 +----------------- 4 files changed, 20 insertions(+), 194 deletions(-) diff --git a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean index 1702c90af..ceea50204 100644 --- a/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean +++ b/Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean @@ -135,7 +135,7 @@ theorem add_mem {f₁ f₂ : α → ℕ} (h₁ : f₁ ∈ SharpPWithOracle A enc obtain ⟨p₂, V₂, hV₂, hf₂⟩ := h₂ have hfalse : ComputableInPolyTimeWithOracle A (allFalseVerifier (α := α)) (encPair enc encBits) encBool := - computableInPolyTime_allFalseVerifier.tidy.computableInPolyTimeWithOracle A + computableInPolyTime_allFalseVerifier.computableInPolyTimeWithOracle A refine ⟨p₁ + p₂ + 1, selectVerifier (andVerifier (fun a => p₁.eval (enc a).length) V₁ allFalseVerifier) (andVerifier (fun a => p₂.eval (enc a).length) V₂ allFalseVerifier), diff --git a/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean b/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean index 655e2b601..ea7752e5a 100644 --- a/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean +++ b/Complexity/Computability/Complexity/FineGrained/PermutationIndependentSet.lean @@ -13,6 +13,7 @@ public import Complexity.Foundations.Data.BitString.List.Binary public import Mathlib.Data.Fin.Tuple.Sort import Complexity.Computability.Complexity.FineGrained.Assignment import Complexity.Computability.Complexity.FineGrained.BruteForce +import Complexity.Computability.Machines.Turing.MultiTape.Complexity.BigO.Plain import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.BitString import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Iteration import Complexity.Computability.Machines.Turing.MultiTape.Complexity.PolyTime.Nat.Binary @@ -364,7 +365,7 @@ for some $\delta > 0$, `ThreeColoring` is not decidable within time $2^{\delta | polynomial in the length of the encoded graph, for graphs with $|V|$ declared vertices. -/ theorem ETH.not_decidableInSubexpTime_ThreeColoring_vertices (h : ETH) : ¬DecidableInSubexpTime ThreeColoring encGraph fun G => G.1.length := - h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring.tidy + h.not_decidableInSubexpTime_of_reduction SAT.computableInPolyTime_toThreeColoring (fun φ _ => SAT.toThreeColoring_mem_iff φ) (k := 93) fun φ hφ => by have := SAT.length_toThreeColoring_le hφ nlinarith @@ -1264,7 +1265,8 @@ theorem decidableInExpTime_ThreeColoring_of_bpis {M : ℕ} (hM : 0 < M) {δ : (fun G => G.1 * Nat.log 2 G.1) δ) : DecidableInExpTime ThreeColoring encGraph (fun H => H.1.length) (1 / M + 10 * δ) := by obtain ⟨e, h⟩ := h - obtain ⟨g, t, c, hg, hgB, ht⟩ := h.exists_computableTidilyInO + obtain ⟨g, t, c, hg, hgB, ht⟩ := h.exists_computableInO + have hg := hg.tidy obtain ⟨d, hstep⟩ := exists_computableTidilyInO_step hg obtain ⟨dn, _, hn⟩ := computableTidilyInPolyTime_rounds.exists_degree obtain ⟨di, _, hi⟩ := computableTidilyInPolyTime_init.exists_degree @@ -1308,7 +1310,7 @@ theorem decidableInExpTime_ThreeColoring_of_bpis {M : ℕ} (hM : 0 < M) {δ : set E := dn + di + 2 * d + 2 * da + d_nd * e + 4 set C₂ : ℝ := c * 2 ^ (5 * δ) * ((c_nd : ℝ) + 1) ^ e + c + 1 set C₀ : ℝ := 3 + C₃ + (2 ^ K_M + 1 : ℝ) * (C₁ + C₂) - refine DecidableInExpTime.of_computableInO hsearch + refine DecidableInExpTime.of_computableInO (.of_tidy hsearch) (fun H => (search_eq_true_iff (fun G => (hgB G).symm) H).symm) ⌈C₀⌉₊ E fun H => ?_ set L := (encGraph H).length set N := H.1.length @@ -1505,7 +1507,7 @@ theorem ETH.not_decidableInSubexpTime_BipartitePermutationIndependentSet_binary fun G => G.1 * Nat.log 2 G.1 := by intro hsub refine h.not_decidableInSubexpTime_BipartitePermutationIndependentSet ?_ - exact hsub.of_reduction BipartitePermutationIndependentSet.computableTidilyInPolyTime_toBinary + exact hsub.of_reduction BipartitePermutationIndependentSet.computableInPolyTime_toBinary (fun _ => Iff.rfl) (c := 1) fun G => by dsimp only [id]; omega /-- **Ceiling-logarithm variant of the Lokshtanov–Marx–Saurabh ETH lower bound** diff --git a/ComplexityTests/TreeEval.lean b/ComplexityTests/TreeEval.lean index 996899a8b..731c0f651 100644 --- a/ComplexityTests/TreeEval.lean +++ b/ComplexityTests/TreeEval.lean @@ -80,14 +80,14 @@ example : ∃ t, ComputableInBigO (fun I : Instance => List.ofFn I.tree.eval) en computableInSpace_eval open Turing MultiTapeTM Reader in -/-- Instantiating `computableTidilyInSpace_eval` on `sample` (`spaceBound 2 2 + 7 = 22`) yields a -finite-state multi-tape machine that tidily computes `[false, true]` from +/-- Instantiating `computableInSpace_eval` on `sample` (`spaceBound 2 2 + 7 = 22`) yields a +finite-state multi-tape machine that computes `[false, true]` from `encInstance ⟨2, 2, sample⟩` within `c * 23` space cells. -/ example : ∃ (t c k : ℕ) (State : Type) (_ : Finite State) (tm : MultiTapeTM k Bool State), - tm.ComputesTidilyInTimeAndSpace (encInstance ⟨2, 2, sample⟩) [false, true] + tm.ComputesInTimeAndSpace (encInstance ⟨2, 2, sample⟩) [false, true] (c * (t + 1)) (c * 23) := by - obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableTidilyInSpace_eval - have h : tm.ComputesTidilyInTimeAndSpace (encInstance ⟨2, 2, sample⟩) + obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableInSpace_eval + have h : tm.ComputesInTimeAndSpace (encInstance ⟨2, 2, sample⟩) (List.ofFn sample.eval) (c * (t ⟨2, 2, sample⟩ + 1)) (c * (spaceBound 2 2 + (encNat ((encInstance ⟨2, 2, sample⟩).length + 1)).length + 1)) := htm ⟨2, 2, sample⟩ @@ -137,14 +137,14 @@ example : ∃ t, ComputableInBigO computableInSpace_eval_log_mul_log_log open Turing MultiTapeTM in -/-- Instantiating `computableTidilyInSpace_eval_log_mul_log_log` on `sampleNontrivial` -(`7 * 3 = 21`) yields a finite-state multi-tape machine that tidily computes `[false, true]` from +/-- Instantiating `computableInSpace_eval_log_mul_log_log` on `sampleNontrivial` +(`7 * 3 = 21`) yields a finite-state multi-tape machine that computes `[false, true]` from `encNontrivialInstance sampleNontrivial` within `c * 22` space cells. -/ example : ∃ (t c k : ℕ) (State : Type) (_ : Finite State) (tm : MultiTapeTM k Bool State), - tm.ComputesTidilyInTimeAndSpace (encNontrivialInstance sampleNontrivial) [false, true] + tm.ComputesInTimeAndSpace (encNontrivialInstance sampleNontrivial) [false, true] (c * (t + 1)) (c * 22) := by - obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableTidilyInSpace_eval_log_mul_log_log - have h : tm.ComputesTidilyInTimeAndSpace (encNontrivialInstance sampleNontrivial) + obtain ⟨t, c, k, State, hfinite, tm, htm⟩ := computableInSpace_eval_log_mul_log_log + have h : tm.ComputesInTimeAndSpace (encNontrivialInstance sampleNontrivial) (List.ofFn sampleNontrivial.1.tree.eval) (c * (t sampleNontrivial + 1)) (c * ((encNat (encNontrivialInstance sampleNontrivial).length).length * (encNat (encNat (encNontrivialInstance sampleNontrivial).length).length).length + 1)) := diff --git a/scripts/tidy_surface_baseline.json b/scripts/tidy_surface_baseline.json index 5abc1b555..787f3a886 100644 --- a/scripts/tidy_surface_baseline.json +++ b/scripts/tidy_surface_baseline.json @@ -1,150 +1,13 @@ { - "Complexity/Computability/Complexity/AffineDisperser/PolyTime.lean": 28, - "Complexity/Computability/Complexity/Classes/AWPP.lean": 1, - "Complexity/Computability/Complexity/Classes/AWPP/Amplification.lean": 1, - "Complexity/Computability/Complexity/Classes/AWPP/OracleWeights.lean": 1, - "Complexity/Computability/Complexity/Classes/Alternation/Game.lean": 1, - "Complexity/Computability/Complexity/Classes/Alternation/GuessVerify.lean": 1, - "Complexity/Computability/Complexity/Classes/Alternation/Savitch.lean": 4, - "Complexity/Computability/Complexity/Classes/Alternation/TQBF.lean": 4, - "Complexity/Computability/Complexity/Classes/ArthurMerlin.lean": 2, - "Complexity/Computability/Complexity/Classes/ArthurMerlin/Amplification.lean": 4, - "Complexity/Computability/Complexity/Classes/ArthurMerlin/GraphNonIsomorphism.lean": 1, - "Complexity/Computability/Complexity/Classes/ArthurMerlin/PH.lean": 2, - "Complexity/Computability/Complexity/Classes/ArthurMerlin/SetLowerBound.lean": 2, - "Complexity/Computability/Complexity/Classes/BPP.lean": 1, - "Complexity/Computability/Complexity/Classes/BPP/Amplification.lean": 1, - "Complexity/Computability/Complexity/Classes/BPP/Derandomization/Generator.lean": 6, - "Complexity/Computability/Complexity/Classes/Constructible.lean": 5, - "Complexity/Computability/Complexity/Classes/EXP.lean": 1, - "Complexity/Computability/Complexity/Classes/FewP.lean": 1, - "Complexity/Computability/Complexity/Classes/Hierarchy.lean": 2, - "Complexity/Computability/Complexity/Classes/Hierarchy/ShortDesc.lean": 1, - "Complexity/Computability/Complexity/Classes/Hierarchy/Space.lean": 1, - "Complexity/Computability/Complexity/Classes/Hierarchy/Time.lean": 1, - "Complexity/Computability/Complexity/Classes/IP/GraphNonIsomorphism.lean": 3, - "Complexity/Computability/Complexity/Classes/IP/PSPACE.lean": 1, - "Complexity/Computability/Complexity/Classes/IP/Simulation.lean": 2, - "Complexity/Computability/Complexity/Classes/IP/TQBF/Words.lean": 12, - "Complexity/Computability/Complexity/Classes/Ladner/PolyTime.lean": 9, - "Complexity/Computability/Complexity/Classes/MIP/NEXP.lean": 5, - "Complexity/Computability/Complexity/Classes/NP.lean": 1, - "Complexity/Computability/Complexity/Classes/NP/GuessVerify.lean": 1, - "Complexity/Computability/Complexity/Classes/NP/Nondeterministic.lean": 1, - "Complexity/Computability/Complexity/Classes/NP/SelfReduction.lean": 2, - "Complexity/Computability/Complexity/Classes/NP/Witness.lean": 6, - "Complexity/Computability/Complexity/Classes/Oracle.lean": 1, - "Complexity/Computability/Complexity/Classes/Oracle/Closure.lean": 3, - "Complexity/Computability/Complexity/Classes/Oracle/PP.lean": 1, - "Complexity/Computability/Complexity/Classes/Oracle/PolyTime.lean": 1, - "Complexity/Computability/Complexity/Classes/Oracle/Space.lean": 4, - "Complexity/Computability/Complexity/Classes/Oracle/TQBF.lean": 2, - "Complexity/Computability/Complexity/Classes/P.lean": 1, - "Complexity/Computability/Complexity/Classes/P/Slices.lean": 2, - "Complexity/Computability/Complexity/Classes/PCP.lean": 1, - "Complexity/Computability/Complexity/Classes/PCP/NP.lean": 2, - "Complexity/Computability/Complexity/Classes/PH.lean": 2, - "Complexity/Computability/Complexity/Classes/PH/KarpLipton.lean": 1, - "Complexity/Computability/Complexity/Classes/PH/Projection.lean": 1, - "Complexity/Computability/Complexity/Classes/PH/SipserLautemann.lean": 1, - "Complexity/Computability/Complexity/Classes/PP.lean": 1, - "Complexity/Computability/Complexity/Classes/PP/Characterization.lean": 1, - "Complexity/Computability/Complexity/Classes/PP/TruthTable.lean": 3, - "Complexity/Computability/Complexity/Classes/Padding.lean": 5, - "Complexity/Computability/Complexity/Classes/ParityP.lean": 3, - "Complexity/Computability/Complexity/Classes/Promise/Basic.lean": 2, - "Complexity/Computability/Complexity/Classes/RP.lean": 2, - "Complexity/Computability/Complexity/Classes/RepeatedTrials.lean": 3, - "Complexity/Computability/Complexity/Classes/SBP.lean": 3, - "Complexity/Computability/Complexity/Classes/SBP/Amplification.lean": 2, - "Complexity/Computability/Complexity/Classes/SPP/FewP.lean": 1, - "Complexity/Computability/Complexity/Classes/SharpP.lean": 1, - "Complexity/Computability/Complexity/Classes/SharpP/Aggregation.lean": 3, - "Complexity/Computability/Complexity/Classes/SharpP/Characterization.lean": 1, - "Complexity/Computability/Complexity/Classes/SharpP/Closure.lean": 3, - "Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean": 4, - "Complexity/Computability/Complexity/Classes/SharpP/Completeness.lean": 1, - "Complexity/Computability/Complexity/Classes/SharpP/GapMachine.lean": 2, - "Complexity/Computability/Complexity/Classes/SharpP/Oracle.lean": 1, - "Complexity/Computability/Complexity/Classes/SharpP/PolyTime.lean": 4, - "Complexity/Computability/Complexity/Classes/SharpP/Power.lean": 2, - "Complexity/Computability/Complexity/Classes/SharpP/Products.lean": 3, - "Complexity/Computability/Complexity/Classes/SharpP/Space.lean": 3, - "Complexity/Computability/Complexity/Classes/SharpP/WeightedReplay.lean": 1, - "Complexity/Computability/Complexity/Classes/Space/Closure.lean": 4, - "Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Membership.lean": 2, - "Complexity/Computability/Complexity/Classes/Space/GeneralizedGeography/Reduction.lean": 9, - "Complexity/Computability/Complexity/Classes/Space/TQBF/Membership.lean": 2, - "Complexity/Computability/Complexity/Classes/Space/TQBF/PolyTime.lean": 27, - "Complexity/Computability/Complexity/Classes/Space/TQBF/Prenex.lean": 2, - "Complexity/Computability/Complexity/Classes/TFNP.lean": 8, - "Complexity/Computability/Complexity/Classes/TFNP/Subclasses.lean": 28, - "Complexity/Computability/Complexity/Classes/TFNP/Subclasses/Completeness.lean": 5, - "Complexity/Computability/Complexity/Classes/Time.lean": 3, - "Complexity/Computability/Complexity/Classes/Toda/Counting.lean": 5, - "Complexity/Computability/Complexity/Classes/Toda/Hierarchy.lean": 3, - "Complexity/Computability/Complexity/Classes/Toda/Isolation.lean": 1, - "Complexity/Computability/Complexity/Classes/UP.lean": 1, - "Complexity/Computability/Complexity/Classes/ValiantVazirani/Reduction.lean": 4, - "Complexity/Computability/Complexity/Classes/WPP.lean": 5, - "Complexity/Computability/Complexity/Classes/WPP/Bounded.lean": 4, - "Complexity/Computability/Complexity/Classes/WPP/TruthTable.lean": 2, - "Complexity/Computability/Complexity/Classes/ZPP.lean": 1, - "Complexity/Computability/Complexity/CookLevin/Clauses.lean": 9, - "Complexity/Computability/Complexity/CookLevin/Encoding.lean": 9, - "Complexity/Computability/Complexity/CookLevin/Parameters.lean": 1, - "Complexity/Computability/Complexity/CookLevin/PolyTime.lean": 2, - "Complexity/Computability/Complexity/Fagin/StrictVerifier.lean": 1, - "Complexity/Computability/Complexity/Fagin/Verifier.lean": 7, - "Complexity/Computability/Complexity/FineGrained.lean": 5, - "Complexity/Computability/Complexity/FineGrained/Assignment.lean": 1, - "Complexity/Computability/Complexity/FineGrained/BruteForce.lean": 2, - "Complexity/Computability/Complexity/FineGrained/OrthogonalVectors.lean": 5, - "Complexity/Computability/Complexity/FineGrained/Reduction.lean": 3, - "Complexity/Computability/Complexity/FineGrained/Sparsification.lean": 1, - "Complexity/Computability/Complexity/HardnessEncoding/PolyTime.lean": 7, - "Complexity/Computability/Complexity/Parameterized.lean": 13, - "Complexity/Computability/Complexity/Parameterized/Kernelization.lean": 1, - "Complexity/Computability/Complexity/Parameterized/VertexCover.lean": 3, - "Complexity/Computability/Complexity/Parameterized/VertexCover/BussKernel.lean": 13, - "Complexity/Computability/Complexity/Problems/CircuitSAT.lean": 1, - "Complexity/Computability/Complexity/Problems/CircuitValue.lean": 1, - "Complexity/Computability/Complexity/Problems/CircuitValue/Compilation.lean": 1, - "Complexity/Computability/Complexity/Problems/CircuitValue/Completeness.lean": 4, - "Complexity/Computability/Complexity/Problems/CircuitValue/Writer.lean": 1, - "Complexity/Computability/Complexity/Problems/Clique.lean": 2, - "Complexity/Computability/Complexity/Problems/Coloring.lean": 4, - "Complexity/Computability/Complexity/Problems/CountingSAT.lean": 1, - "Complexity/Computability/Complexity/Problems/ExactThreeSAT.lean": 3, - "Complexity/Computability/Complexity/Problems/Graph.lean": 5, - "Complexity/Computability/Complexity/Problems/GraphIsomorphism.lean": 2, - "Complexity/Computability/Complexity/Problems/Hamiltonian.lean": 7, - "Complexity/Computability/Complexity/Problems/Hamiltonian/Diamond.lean": 5, - "Complexity/Computability/Complexity/Problems/Hamiltonian/Directed.lean": 3, - "Complexity/Computability/Complexity/Problems/Hamiltonian/Sparse.lean": 7, - "Complexity/Computability/Complexity/Problems/Hamiltonian/Undirected.lean": 2, - "Complexity/Computability/Complexity/Problems/IndependentSet.lean": 4, - "Complexity/Computability/Complexity/Problems/IndependentSet/Sparse.lean": 1, - "Complexity/Computability/Complexity/Problems/IntegerProgramming.lean": 2, - "Complexity/Computability/Complexity/Problems/Knapsack.lean": 2, - "Complexity/Computability/Complexity/Problems/Partition.lean": 2, - "Complexity/Computability/Complexity/Problems/SAT/PolyTime.lean": 8, - "Complexity/Computability/Complexity/Problems/SharpSAT.lean": 3, - "Complexity/Computability/Complexity/Problems/SubsetSum.lean": 8, - "Complexity/Computability/Complexity/Problems/SubsetSum/Mask.lean": 1, - "Complexity/Computability/Complexity/Problems/TQBF/Closed.lean": 1, - "Complexity/Computability/Complexity/Problems/TSP.lean": 3, - "Complexity/Computability/Complexity/Problems/ThreeSAT.lean": 3, - "Complexity/Computability/Complexity/Problems/VertexCover.lean": 4, - "Complexity/Computability/Complexity/Reduction.lean": 1, - "Complexity/Computability/Complexity/Reduction/TruthTable.lean": 2, + "Complexity/Computability/Complexity/Classes/SharpP/Combinators.lean": 3, + "Complexity/Computability/Complexity/Classes/Toda/Counting.lean": 1, + "Complexity/Computability/Complexity/Problems/Clique.lean": 1, "Complexity/Computability/GenericRAM/Native.lean": 6, "Complexity/Computability/GenericRAM/Native/Combinators.lean": 8, "Complexity/Computability/GenericRAM/Native/Nat.lean": 6, "Complexity/Computability/GenericRAM/Simulation/Run.lean": 8, "Complexity/Computability/GenericRAM/Simulation/Turing.lean": 1, "Complexity/Computability/GenericRAM/SparseMemory/Turing.lean": 8, - "Complexity/Computability/MCSP/NP.lean": 2, "Complexity/Computability/Machines/ReadMachine/Tidy.lean": 10, "Complexity/Computability/Machines/Turing/MultiTape/Alternating/Game.lean": 1, "Complexity/Computability/Machines/Turing/MultiTape/Combinators/Encoding.lean": 19, @@ -250,36 +113,6 @@ "Complexity/Computability/Machines/Turing/TM2/PolySpace.lean": 2, "Complexity/Computability/Machines/Turing/TM2/PolyTime.lean": 3, "Complexity/Computability/Machines/Turing/TM2/Simulation.lean": 6, - "Complexity/Computability/PCP/Approximation/MaxExactThreeSAT.lean": 1, - "Complexity/Computability/PCP/Approximation/MaxThreeSAT.lean": 1, - "Complexity/Computability/PCP/Encoded/AddTrivial.lean": 2, - "Complexity/Computability/PCP/Encoded/Amplification.lean": 1, - "Complexity/Computability/PCP/Encoded/Amplification/Arithmetic.lean": 1, - "Complexity/Computability/PCP/Encoded/Amplification/Enumeration.lean": 1, - "Complexity/Computability/PCP/Encoded/Amplification/Iteration.lean": 1, - "Complexity/Computability/PCP/Encoded/AssignmentTester.lean": 2, - "Complexity/Computability/PCP/Encoded/Basic.lean": 10, - "Complexity/Computability/PCP/Encoded/Cloud.lean": 3, - "Complexity/Computability/PCP/Encoded/CloudRotation.lean": 1, - "Complexity/Computability/PCP/Encoded/Composition.lean": 5, - "Complexity/Computability/PCP/Encoded/Composition/Enumeration.lean": 1, - "Complexity/Computability/PCP/Encoded/Constraints.lean": 4, - "Complexity/Computability/PCP/Encoded/DegreeReduction.lean": 5, - "Complexity/Computability/PCP/Encoded/GapTheorem.lean": 1, - "Complexity/Computability/PCP/Encoded/GenericComposition.lean": 5, - "Complexity/Computability/PCP/Encoded/GenericComposition/Enumeration.lean": 1, - "Complexity/Computability/PCP/Encoded/Iteration.lean": 1, - "Complexity/Computability/PCP/Encoded/Power.lean": 1, - "Complexity/Computability/PCP/Encoded/Preprocess.lean": 2, - "Complexity/Computability/PCP/Encoded/Preprocess/Programs.lean": 3, - "Complexity/Computability/PCP/Encoded/SelectedAssignmentTester.lean": 2, - "Complexity/Computability/PCP/Encoded/SelectedComposition.lean": 1, - "Complexity/Computability/PCP/Encoded/SelectedComposition/Enumeration.lean": 1, - "Complexity/Computability/PCP/Encoded/ThreeSAT.lean": 4, - "Complexity/Computability/PCP/Encoded/Verifier.lean": 4, - "Complexity/Computability/PCP/Encoded/Verifier/Reduction.lean": 2, - "Complexity/Computability/PCP/Encoded/Verifier/Repetition.lean": 1, - "Complexity/Computability/PCP/Power/Complexity.lean": 1, "Complexity/Computability/Probabilistic/Adaptive.lean": 5, "Complexity/Computability/Probabilistic/CenteredBinomial.lean": 1, "Complexity/Computability/Probabilistic/CoinTape.lean": 5, @@ -307,15 +140,6 @@ "Complexity/Computability/Probabilistic/Selection.lean": 3, "Complexity/Computability/Probabilistic/Traverse.lean": 1, "Complexity/Computability/Probabilistic/UniformNat.lean": 5, - "Complexity/Computability/TreeEval/Reader/Cert/Machine.lean": 1, - "Complexity/Computability/TreeEval/Reader/Cert/Offset.lean": 5, - "Complexity/Computability/TreeEval/Reader/Cert/Regs.lean": 6, - "Complexity/Computability/TreeEval/Reader/Cert/Residue.lean": 5, - "Complexity/Computability/TreeEval/Reader/Cert/Step.lean": 8, - "Complexity/Computability/TreeEval/Reader/Cert/Weight.lean": 1, - "Complexity/Computability/TreeEval/Space.lean": 2, - "Complexity/Computability/USTCON/Reader/Cert.lean": 3, - "Complexity/Computability/USTCON/Space.lean": 1, "Complexity/Crypto/Computational/Commitment.lean": 13, "Complexity/Crypto/Computational/Encryption/PolyTime.lean": 2, "Complexity/Crypto/Computational/GGM/Evaluation.lean": 3,