Definitions bundle OAIQ6Wl000 of the split of OpenAI, Variable-dimension Weisfeiler–Leman equivalence on general and subcubic graphs
DefinitionOAIQ6Wl000A definitions bundle of the split of OpenAI's proof of OAI.VariableWL.main, carved from OpenAI's openai/math development (OpenAI, Variable-dimension Weisfeiler–Leman equivalence on general and subcubic graphs, OpenAI Math Release, September 25, 2026, result family 133, github.com/openai/math at commit adc7f12, Apache License 2.0) and ported to Lean 4.33.1 and Mathlib 0df444a. The declarations and their proofs are OpenAI's.
Contents. It holds 1632 declarations of OpenAI's Lean: 914 definitions, 56 inductive types or structures, 19 instances and 643 theorems. The definitions and types are OAI.VariableWL.Affine.Bit, OAI.VariableWL.Affine.Fiber, OAI.VariableWL.Affine.SquareVal, OAI.VariableWL.Affine.Vec, OAI.VariableWL.Affine.boundary, OAI.VariableWL.AffineAlphabet.Form, OAI.VariableWL.AffineAlphabet.Program.horizontalLegal, OAI.VariableWL.AffineAlphabet.Program.horizontalOrder, OAI.VariableWL.AffineAlphabet.Program.squareLegal, OAI.VariableWL.AffineAlphabet.Program.squareLegalBody, OAI.VariableWL.AffineAlphabet.Program.squareOrder, OAI.VariableWL.AffineAlphabet.Program.zeroOrder, OAI.VariableWL.AffineAlphabet.SquareCoordinate, OAI.VariableWL.AffineAlphabet.encodeForm, OAI.VariableWL.AffineAlphabet.extend, OAI.VariableWL.AffineAlphabet.formCount, OAI.VariableWL.AffineAlphabet.formNumber, OAI.VariableWL.AffineAlphabet.horizontalEmbedding, OAI.VariableWL.AffineAlphabet.horizontalEncode, OAI.VariableWL.AffineAlphabet.horizontalLegal, OAI.VariableWL.AffineAlphabet.horizontalOrder, OAI.VariableWL.AffineAlphabet.leftEmbedding, OAI.VariableWL.AffineAlphabet.rightEmbedding, OAI.VariableWL.AffineAlphabet.scalarEmbedding, OAI.VariableWL.AffineAlphabet.squareCoordinate, OAI.VariableWL.AffineAlphabet.squareEncode, OAI.VariableWL.AffineAlphabet.squareLegal, OAI.VariableWL.AffineAlphabet.squareOrder, OAI.VariableWL.AffineAlphabet.zeroOrder, OAI.VariableWL.AffineCatalog.Data, OAI.VariableWL.AffineCatalog.Data.constant, OAI.VariableWL.AffineCatalog.Data.core, OAI.VariableWL.AffineCatalog.Data.descriptor, OAI.VariableWL.AffineCatalog.Data.dimension, OAI.VariableWL.AffineCatalog.Data.horizontalDimension, OAI.VariableWL.AffineCatalog.Data.legal, OAI.VariableWL.AffineCatalog.Data.linkLeft, OAI.VariableWL.AffineCatalog.Data.linkLeftConstant, OAI.VariableWL.AffineCatalog.Data.linkRight, OAI.VariableWL.AffineCatalog.Data.linkRightConstant and 930 more.
Sources. They come from these modules of lean/OAI/Combinatorics, in whole or in part: VariableWL_Affine, VariableWL_AffineCatalog, VariableWL_Binary, VariableWL_BinaryMachine, VariableWL_BlockCatalog, VariableWL_BlockCoordinates, VariableWL_BlockDescriptor, VariableWL_BlockExtensions, VariableWL_BlockGame, VariableWL_BlockImages, VariableWL_BlockListing, VariableWL_Blocks, VariableWL_BoundedLoop, VariableWL_CellularCatalog, VariableWL_CellularCircuit, VariableWL_CellularListing, VariableWL_CertifiedRecipe, VariableWL_Circuit, VariableWL_CircuitCatalog, VariableWL_Completeness, VariableWL_Coordinates, VariableWL_Decision, VariableWL_Descriptor, VariableWL_Encoding, VariableWL_ExactProjection, VariableWL_ExponentialRecipe, VariableWL_GeneralGame, VariableWL_GeneralReduction, VariableWL_MachineReduction, VariableWL_MatrixOutput, VariableWL_NumericProgram, VariableWL_NumericRefinement, VariableWL_OneHead, VariableWL_PolyRecipe, VariableWL_PortGraph, VariableWL_PortListing, VariableWL_PrefixAlphabet, VariableWL_PrefixDescriptor, VariableWL_PrefixListing, VariableWL_PrefixParts, VariableWL_PrefixWiring, VariableWL_Procedure, VariableWL_ProductCellular, VariableWL_ProductImages, VariableWL_Program, VariableWL_Recipe, VariableWL_Refinement, VariableWL_Stack, VariableWL_StackSimulation, VariableWL_SubcubicGame, VariableWL_Subdivision, VariableWL_TypedGame, VariableWL_UnaryPower, VariableWL_Wrapping.
Imports. It imports the published bundle Def_VariableWL.
Imported by (directly, in this split): the bundle OAIQ6Wl002.
import Mathlib
import Definitions.Def_VariableWL
section
-- module Solutions.OAIQ6_WL.Compat
namespace OAI
/-! Compatibility with the newer Lean core OpenAI's code was written against: lemmas it uses by
names this environment (Lean 4.33.1, Mathlib 0df444a) does not have yet. Each is the
corresponding `if_pos` / `if_neg` / `dif_pos` / `dif_neg`. The `dite` forms are stated as
`dite p a b`, not with the `if hp : p then …` notation: its eta-expanded lambdas form is a higher-order pattern
that `rw` cannot find (DepthThree, PeriodicTiling 2026-10-25). -/
section OAICompat434
theorem ite_eq_left {α : Sort _} {p : Prop} {_ : Decidable p} {a b : α} (h : p) :
(if p then a else b) = a := if_pos h
theorem ite_eq_right {α : Sort _} {p : Prop} {_ : Decidable p} {a b : α} (h : ¬p) :
(if p then a else b) = b := if_neg h
theorem dite_eq_left {α : Sort _} {p : Prop} {_ : Decidable p} {a : p → α} {b : ¬p → α} (h : p) :
dite p a b = a h := dif_pos h
theorem dite_eq_right {α : Sort _} {p : Prop} {_ : Decidable p} {a : p → α} {b : ¬p → α} (h : ¬p) :
dite p a b = b h := dif_neg h
end OAICompat434
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Affine
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL
class FiniteNumbering (A : Type uVariable1) [Fintype A] where
equiv : A ≃ Fin (Fintype.card A)
noncomputable instance (priority := 10) defaultFiniteNumbering (A : Type uVariable2) [Fintype A] :
FiniteNumbering A := ⟨Fintype.equivFin A⟩
noncomputable def enumeration (A : Type uVariable4) [Fintype A] [FiniteNumbering A] :
A ≃ Fin (Fintype.card A) := FiniteNumbering.equiv
end VariableWL
namespace VariableWL.Affine
abbrev Bit := ZMod 2
abbrev Vec (d : ℕ) := Fin d → Bit
abbrev SquareVal (d e : ℕ) := (Vec d × Vec e) × (Bit × Bit)
open scoped CharTwo
variable {d e : ℕ}
def boundary (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit)
(z : SquareVal d e) : Bit :=
L z.1.1 + R z.1.2 + z.2.1 + z.2.2
def Fiber (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit) (c : Bit) :=
{ z : SquareVal d e | boundary L R z = c }
@[simp] theorem boundary_add (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit)
(z w : SquareVal d e) : boundary L R (z + w) = boundary L R z + boundary L R w := by
simp only [boundary, Prod.fst_add, Prod.snd_add, map_add]
ring
@[simp] theorem boundary_zero (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit) :
boundary L R 0 = 0 := by
simp [boundary]
theorem fiber_nonempty (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit) (c : Bit) :
(Fiber L R c).Nonempty := by
exact ⟨((0, 0), (c, 0)), by simp [Fiber, boundary]⟩
end VariableWL.Affine
namespace VariableWL.Markers
abbrev Bit := ZMod 2
open scoped CharTwo
variable {V : Type uVariable5} {G : SimpleGraph V}
def walkSum (ω : V → V → Bit) : {u v : V} → G.Walk u v → Bit
| _, _, .nil => 0
| u, _, .cons (v := v) _ p => ω u v + walkSum ω p
@[simp] theorem walkSum_nil (ω : V → V → Bit) (u : V) :
walkSum ω (SimpleGraph.Walk.nil : G.Walk u u) = 0 := rfl
@[simp] theorem walkSum_cons (ω : V → V → Bit) {u v w : V}
(h : G.Adj u v) (p : G.Walk v w) :
walkSum ω (.cons h p) = ω u v + walkSum ω p := rfl
@[simp] theorem walkSum_append (ω : V → V → Bit) {u v w : V}
(p : G.Walk u v) (q : G.Walk v w) :
walkSum ω (p.append q) = walkSum ω p + walkSum ω q := by
induction p with
| nil => simp [walkSum]
| cons h p ih => simp [SimpleGraph.Walk.cons_append, walkSum, ih, add_assoc]
@[simp] theorem walkSum_reverse (ω : V → V → Bit)
(hsym : ∀ u v, G.Adj u v → ω u v = ω v u) {u v : V} (p : G.Walk u v) :
walkSum ω p.reverse = walkSum ω p := by
induction p with
| nil => simp [walkSum]
| @cons u v w h p ih =>
simp only [SimpleGraph.Walk.reverse_cons, walkSum_append, ih, walkSum_cons,
walkSum_nil, add_zero]
rw [← hsym u v h, add_comm]
end VariableWL.Markers
namespace VariableWL.ScalarImages
abbrev Bit := ZMod 2
abbrev Pair := Bit × Bit
def sum (x : Pair) : Bit := x.1 + x.2
def buffer (D : Set Bit) : Set Pair := {x | sum x ∈ D}
open scoped CharTwo
theorem buffer_nonempty {D : Set Bit} (hD : D.Nonempty) : (buffer D).Nonempty := by
rcases hD with ⟨a, ha⟩
exact ⟨(0, a), by simpa [buffer, sum] using ha⟩
theorem buffer_image_sum (D : Set Bit) : sum '' buffer D = D := by
ext a
constructor
· rintro ⟨x, hx, rfl⟩
exact hx
· intro ha
exact ⟨(0, a), by simpa [buffer, sum] using ha, by simp [sum]⟩
theorem buffer_image_fst {D : Set Bit} (hD : D.Nonempty) :
Prod.fst '' buffer D = Set.univ := by
rcases hD with ⟨d, hd⟩
apply Set.eq_univ_of_forall
intro a
refine ⟨(a, d + a), ?_, rfl⟩
simpa [buffer, sum, add_comm, add_left_comm] using hd
theorem buffer_image_snd {D : Set Bit} (hD : D.Nonempty) :
Prod.snd '' buffer D = Set.univ := by
rcases hD with ⟨d, hd⟩
apply Set.eq_univ_of_forall
intro a
refine ⟨(d + a, a), ?_, rfl⟩
simpa [buffer, sum, add_assoc] using hd
def andWitness (p q : Prop) : Set Pair :=
{x | (p → x.1 = 0) ∧ (q → x.2 = 0)}
theorem andWitness_nonempty (p q : Prop) : (andWitness p q).Nonempty :=
⟨(0, 0), ⟨fun _ => rfl, fun _ => rfl⟩⟩
theorem andWitness_fst (p q : Prop) :
Prod.fst '' andWitness p q = {a : Bit | p → a = 0} := by
ext a
constructor
· rintro ⟨x, hx, rfl⟩
exact hx.1
· intro ha
exact ⟨(a, 0), ⟨ha, fun _ => rfl⟩, rfl⟩
theorem andWitness_snd (p q : Prop) :
Prod.snd '' andWitness p q = {a : Bit | q → a = 0} := by
ext a
constructor
· rintro ⟨x, hx, rfl⟩
exact hx.2
· intro ha
exact ⟨(0, a), ⟨fun _ => rfl, ha⟩, rfl⟩
theorem andWitness_sum (p q : Prop) :
sum '' andWitness p q = {a : Bit | p ∧ q → a = 0} := by
classical
ext a
constructor
· rintro ⟨x, hx, rfl⟩ ⟨hp, hq⟩
simp [sum, hx.1 hp, hx.2 hq]
· intro ha
by_cases hp : p
· refine ⟨(0, a), ⟨fun _ => rfl, fun hq => ha ⟨hp, hq⟩⟩, ?_⟩
simp [sum]
· refine ⟨(a, 0), ⟨fun h => (hp h).elim, fun _ => rfl⟩, ?_⟩
simp [sum]
end VariableWL.ScalarImages
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Refinement
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL
@[simp] theorem histogram_card (G : Graph) (k s : ℕ) :
(histogram G k s).card = G.order ^ k := by
simp [histogram, Tuple]
end VariableWL
namespace VariableWL
@[simp] theorem histogram_fst (G : Graph) (k s : ℕ) :
(histogram G k (s+1)).map Prod.fst = histogram G k s := by
exact (Multiset.map_map Prod.fst (color G k (s+1)) Finset.univ.val)
end VariableWL
universe uGame1 uGame2 uGame3 uGame4 uGame5 uGame6 uGame7
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Subdivision
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9
namespace VariableWL.Subdivision
variable {P : Type uVariable1} {E : Type uVariable2} {n : ℕ}
abbrev Vertex (P : Type uVariable3) (E : Type uVariable4) (n : ℕ) := P ⊕ (E × Fin n)
abbrev Link (E : Type uVariable5) (n : ℕ) := E × Fin (n+1)
def left (src : E → P) (l : Link E n) : Vertex P E n :=
if h : l.2.val = 0 then .inl (src l.1)
else .inr (l.1, ⟨l.2.val - 1, by omega⟩)
def right (dst : E → P) (l : Link E n) : Vertex P E n :=
if h : l.2.val = n then .inl (dst l.1)
else .inr (l.1, ⟨l.2.val, by omega⟩)
theorem endpoints_ne (hn : 0 < n) (src dst : E → P) (l : Link E n) :
left src l ≠ right dst l := by
unfold left right
split_ifs with h₀ h₁ h₁
· omega
· simp
· simp
· intro h
have hh := congrArg (fun x : Vertex P E n =>
match x with | .inl _ => 0 | .inr x => x.2.val) h
simp only at hh
omega
def supportGraph (hn : 0 < n) (src dst : E → P) (S : Set (Link E n)) :
SimpleGraph (Vertex P E n) where
Adj v w := ∃ l ∈ S,
(v = left src l ∧ w = right dst l) ∨ (v = right dst l ∧ w = left src l)
symm := ⟨by
rintro v w ⟨l, hl, h⟩
exact ⟨l, hl, h.elim (fun h => Or.inr h.symm) (fun h => Or.inl h.symm)⟩⟩
loopless := ⟨by
rintro v ⟨l, _, h⟩
exact endpoints_ne hn src dst l (h.elim (fun h => h.1.symm.trans h.2)
(fun h => h.2.symm.trans h.1))⟩
end VariableWL.Subdivision
namespace VariableWL.Markers
open scoped CharTwo
variable {V : Type uVariable9} {G : SimpleGraph V}
@[simp] theorem walkSum_zero {u v : V} (p : G.Walk u v) :
walkSum (fun _ _ => 0) p = 0 := by
induction p with
| nil => rfl
| cons _ _ ih => simp [walkSum, ih]
end VariableWL.Markers
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Wrapping
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11
namespace VariableWL.Wrapping
open scoped CharTwo
open Markers
abbrev Bit := ZMod 2
variable {I : Type uVariable1} {V : Type uVariable2} [DecidableEq I] {G : SimpleGraph V}
structure RowDiagram (G : SimpleGraph V) (next : Equiv.Perm I) where
boundary : V → I
horizontal : V → V → Option I
symmetric : ∀ u v, G.Adj u v → horizontal u v = horizontal v u
shape : ∀ u v, G.Adj u v →
match horizontal u v with
| none => boundary u = boundary v
| some i => (boundary u = i ∧ boundary v = next i) ∨
(boundary v = i ∧ boundary u = next i)
namespace RowDiagram
variable {next : Equiv.Perm I} (D : RowDiagram G next)
def rowWeight (i : I) (u v : V) : Bit := if D.horizontal u v = some i then 1 else 0
def Wraps (marked : I) : Prop :=
∃ v : V, ∃ p : G.Walk v v, walkSum (D.rowWeight marked) p = 1
end RowDiagram
end VariableWL.Wrapping
namespace VariableWL.Wrapping
variable {I : Type uVariable9} {B : Type uVariable10} {L : Type uVariable11} [Fintype I] [DecidableEq I] [DecidableEq B]
theorem finRotate_no_fixed {r : ℕ} (hr : 2 ≤ r) (i : Fin r) : finRotate r i ≠ i := by
have h : i ∈ (finRotate r).support := by
rw [support_finRotate_of_le hr]
exact Finset.mem_univ i
exact Equiv.Perm.mem_support.mp h
end VariableWL.Wrapping
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_ProductImages
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.ProductImages
open scoped CharTwo
open VariableWL.Affine
variable (r : ℕ) (P : Type uVariable1) (E : Type uVariable2)
structure Instance where
dimension : P → ℕ
dimension_one_or_two : ∀ p, dimension p = 1 ∨ dimension p = 2
source : E → P
target : E → P
domain : E → Fin r → Finset Bool
domain_nonempty : ∀ e i, (domain e i).Nonempty
map : E → Fin r → Bool → Bool
map_injective : ∀ e i, Set.InjOn (map e i) (domain e i)
linearLeft : ∀ e, Vec (dimension (source e)) →ₗ[Bit] Bit
linearRight : ∀ e, Vec (dimension (target e)) →ₗ[Bit] Bit
constantLeft : E → Bit
constantRight : E → Bit
namespace Instance
variable {r : ℕ} {P : Type uVariable3} {E : Type uVariable4} (J : Instance r P E)
abbrev Address (r : ℕ) := Fin r → Bool
def Allowed (e : E) (a : Address r) : Prop := ∀ i, a i ∈ J.domain e i
def mapAddress (e : E) (a : Address r) : Address r := fun i => J.map e i (a i)
def leftForm (e : E) (v : Vec (J.dimension (J.source e))) : Bit :=
J.linearLeft e v + J.constantLeft e
def rightForm (e : E) (v : Vec (J.dimension (J.target e))) : Bit :=
J.linearRight e v + J.constantRight e
structure Witness where
values : ∀ p : P, Address r → Set (Vec (J.dimension p))
nonempty : ∀ p a, (values p a).Nonempty
images : ∀ e a, J.Allowed e a →
J.leftForm e '' values (J.source e) a =
J.rightForm e '' values (J.target e) (J.mapAddress e a)
namespace Witness
variable {J} (Q : J.Witness)
def wireValues (e : E) (a : Address r) : Set Bit :=
J.leftForm e '' Q.values (J.source e) a
end Witness
theorem exists_ambient (e : E) (i : Fin r) :
∃ f : Equiv.Perm Bool, ∀ a ∈ J.domain e i, f a = J.map e i a := by
obtain ⟨f,hf⟩ := Equiv.Perm.exists_extending_pair
(fun a : {a // a ∈ J.domain e i} => a.val)
(fun a : {a // a ∈ J.domain e i} => J.map e i a.val)
Subtype.val_injective (fun a b h => Subtype.ext (J.map_injective e i a.property b.property h))
exact ⟨f, fun a ha => hf ⟨a,ha⟩⟩
noncomputable def ambient (e : E) (i : Fin r) : Equiv.Perm Bool :=
(J.exists_ambient e i).choose
open Subdivision
variable {n : ℕ}
def labels : Vertex P E n → Fin r → Finset Bool
| .inl _, _ => Finset.univ
| .inr (e,_), i => J.domain e i
def Matches (l : Link E n) (i : Fin r) (a b : Bool) : Prop :=
a ∈ J.domain l.1 i ∧ b = if l.2.val = n then J.map l.1 i a else a
theorem matches_left (l : Link E n) (i : Fin r) {a b : Bool} (h : J.Matches l i a b) :
a ∈ J.labels (left J.source l) i := by
unfold left
split_ifs <;> simp only [labels]
· exact Finset.mem_univ _
· exact h.1
theorem matches_right (l : Link E n) (i : Fin r) {a b : Bool} (h : J.Matches l i a b) :
b ∈ J.labels (right J.target l) i := by
unfold right
split_ifs with hn
· exact Finset.mem_univ _
· simp only [labels]
rw [h.2, ite_eq_right hn]
exact h.1
noncomputable def alignment (cut : E → Fin (n+1)) :
Vertex P E n → Fin r → Equiv.Perm Bool
| .inl _, _ => Equiv.refl _
| .inr (e,j), i => if j.val < (cut e).val then Equiv.refl _ else J.ambient e i
end Instance
end VariableWL.ProductImages
namespace VariableWL.ProductImages.Instance
open VariableWL.Affine Subdivision
variable {r n : ℕ} {P : Type uVariable5} {E : Type uVariable6} (J : ProductImages.Instance r P E)
abbrev Shifts (n : ℕ) := (∀ p, Vec (J.dimension p)) × (E × Fin n → Bit)
def shiftLeft (h : J.Shifts n) (l : Link E n) : Bit :=
if h₀ : l.2.val = 0 then J.leftForm l.1 (h.1 (J.source l.1))
else h.2 (l.1, ⟨l.2.val-1, by omega⟩)
def shiftRight (h : J.Shifts n) (l : Link E n) : Bit :=
if h₁ : l.2.val = n then J.rightForm l.1 (h.1 (J.target l.1))
else h.2 (l.1, ⟨l.2.val, by omega⟩)
def ShiftSystem (S : Set (Link E n)) (h : J.Shifts n) : Prop :=
∀ l ∈ S, J.shiftLeft h l = J.shiftRight h l
end VariableWL.ProductImages.Instance
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Blocks
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11 uVariable12 uVariable13 uVariable14 uVariable15 uVariable16 uVariable17 uVariable18
namespace VariableWL.Blocks
open Subdivision
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2}
structure Horizontal (r n : ℕ) (P : Type uVariable3) (E : Type uVariable4) where
row : Fin r
type : Vertex P E n
first : Bool
last : Bool
deriving DecidableEq
structure Vertical (r n : ℕ) (E : Type uVariable5) where
row : Fin r
link : Link E n
label : Bool
deriving DecidableEq
structure Square (r n : ℕ) (E : Type uVariable6) where
row : Fin r
link : Link E n
first : Bool
last : Bool
deriving DecidableEq
abbrev Corner (r n : ℕ) (P : Type uVariable7) (E : Type uVariable8) := Fin r × Vertex P E n × Bool
abbrev Readout (r n : ℕ) (P : Type uVariable9) (E : Type uVariable10) := Horizontal r n P E ⊕ Vertical r n E
abbrev RawBlock (r n : ℕ) (P : Type uVariable11) (E : Type uVariable12) := Horizontal r n P E ⊕ Square r n E
variable (J : ProductImages.Instance r P E)
def matchOutput (l : Link E n) (i : Fin r) (a : Bool) : Bool :=
if l.2.val = n then J.map l.1 i a else a
def ValidHorizontal (h : Horizontal r n P E) : Prop :=
h.first ∈ J.labels h.type h.row ∧ h.last ∈ J.labels h.type (finRotate r h.row)
def ValidSquare (s : Square r n E) : Prop :=
s.first ∈ J.domain s.link.1 s.row ∧ s.last ∈ J.domain s.link.1 (finRotate r s.row)
def Valid : RawBlock r n P E → Prop
| .inl h => ValidHorizontal J h
| .inr s => ValidSquare J s
abbrev Block := { b : RawBlock r n P E // Valid J b }
def row : RawBlock r n P E → Fin r
| .inl h => h.row
| .inr s => s.row
def squareLeft (s : Square r n E) : Horizontal r n P E :=
⟨s.row, left J.source s.link, s.first, s.last⟩
def squareRight (s : Square r n E) : Horizontal r n P E :=
⟨s.row, right J.target s.link, matchOutput J s.link s.row s.first,
matchOutput J s.link (finRotate r s.row) s.last⟩
def squareBottom (s : Square r n E) : Vertical r n E := ⟨s.row, s.link, s.first⟩
def squareTop (s : Square r n E) : Vertical r n E := ⟨finRotate r s.row, s.link, s.last⟩
def HasReadout : RawBlock r n P E → Readout r n P E → Prop
| .inl h, a => a = .inl h
| .inr s, a => a = .inl (squareLeft J s) ∨ a = .inl (squareRight J s) ∨
a = .inr (squareBottom s) ∨ a = .inr (squareTop s)
def end0 : Readout r n P E → Corner r n P E
| .inl h => (h.row, h.type, h.first)
| .inr v => (v.row, left J.source v.link, v.label)
def end1 : Readout r n P E → Corner r n P E
| .inl h => (finRotate r h.row, h.type, h.last)
| .inr v => (v.row, right J.target v.link, matchOutput J v.link v.row v.label)
theorem readout_ne (hr : 2 ≤ r) (hn : 0 < n) (a : Readout r n P E) :
end0 J a ≠ end1 J a := by
cases a with
| inl h =>
intro he
exact Wrapping.finRotate_no_fixed hr h.row (congrArg Prod.fst he).symm
| inr v =>
intro he
exact endpoints_ne hn J.source J.target v.link (congrArg (fun c => c.2.1) he)
def diagram (hr : 2 ≤ r) (hn : 0 < n) (U : Set (Block (n := n) J)) :
SimpleGraph (Corner r n P E) where
Adj v w := ∃ b ∈ U, ∃ a, HasReadout J b.val a ∧
((v = end0 J a ∧ w = end1 J a) ∨ (v = end1 J a ∧ w = end0 J a))
symm := ⟨by
rintro v w ⟨b,hb,a,ha,h⟩
exact ⟨b,hb,a,ha,h.elim (fun h => Or.inr h.symm) (fun h => Or.inl h.symm)⟩⟩
loopless := ⟨by
rintro v ⟨b,hb,a,ha,h⟩
exact readout_ne J hr hn a (h.elim (fun h => h.1.symm.trans h.2)
(fun h => h.2.symm.trans h.1))⟩
theorem finRotate_twice_ne (hr : 3 ≤ r) (i : Fin r) : finRotate r (finRotate r i) ≠ i := by
have : NeZero r := ⟨by omega⟩
intro he
have hh : (1 : Fin r) + 1 = 0 := by
apply add_left_cancel (a := i)
simpa only [finRotate_apply, add_assoc, add_zero] using he
have hval := congrArg Fin.val hh
have h1 : 1 % r = 1 := Nat.mod_eq_of_lt (by omega)
have h2 : 2 % r = 2 := Nat.mod_eq_of_lt (by omega)
norm_num [Fin.val_add, Fin.val_one, h1, h2] at hval
def horizontalTag (v w : Corner r n P E) : Option (Fin r) :=
if w.1 = finRotate r v.1 then some v.1
else if v.1 = finRotate r w.1 then some w.1 else none
theorem horizontalTag_readout (hr : 3 ≤ r) (a : Readout r n P E) :
horizontalTag (end0 J a) (end1 J a) =
(match a with | .inl h => some h.row | .inr _ => none) ∧
horizontalTag (end1 J a) (end0 J a) =
(match a with | .inl h => some h.row | .inr _ => none) := by
cases a with
| inl h =>
dsimp only [horizontalTag, end0, end1]
simp only [ite_eq_right (finRotate_twice_ne hr h.row).symm]
exact ⟨rfl,rfl⟩
| inr v =>
have hne := (Wrapping.finRotate_no_fixed (by omega) v.row).symm
dsimp only [horizontalTag, end0, end1]
simp only [ite_eq_right hne, and_self]
def rowDiagram (hr : 3 ≤ r) (hn : 0 < n) (U : Set (Block (n := n) J)) :
Wrapping.RowDiagram (diagram J (by omega) hn U) (finRotate r) where
boundary := Prod.fst
horizontal := horizontalTag
symmetric := by
rintro v w ⟨b,hb,a,ha,h⟩
rcases h with ⟨rfl,rfl⟩ | ⟨rfl,rfl⟩
· exact (horizontalTag_readout J hr a).1.trans (horizontalTag_readout J hr a).2.symm
· exact (horizontalTag_readout J hr a).2.trans (horizontalTag_readout J hr a).1.symm
shape := by
rintro v w ⟨b,hb,a,ha,h⟩
rcases h with ⟨rfl,rfl⟩ | ⟨rfl,rfl⟩
· rw [(horizontalTag_readout J hr a).1]
cases a with
| inl h => exact Or.inl ⟨rfl,rfl⟩
| inr v => rfl
· rw [(horizontalTag_readout J hr a).2]
cases a with
| inl h => exact Or.inr ⟨rfl,rfl⟩
| inr v => rfl
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision
variable {r n : ℕ} {P : Type uVariable13} {E : Type uVariable14} (J : ProductImages.Instance r P E)
def linksOf : RawBlock r n P E → Finset (Link E n)
| .inl _ => ∅
| .inr s => {s.link}
noncomputable def supportLinks (U : Finset (Block (n := n) J)) : Finset (Link E n) :=
by classical exact U.biUnion (fun b => linksOf b.val)
theorem square_link_mem (U : Finset (Block (n := n) J)) {b : Block (n := n) J}
(hb : b ∈ U) {s : Square r n E} (hs : b.val = .inr s) :
s.link ∈ supportLinks J U := by
classical
apply Finset.mem_biUnion.mpr
exact ⟨b,hb,by simp [hs, linksOf]⟩
noncomputable def aligned (cut : E → Fin (n+1)) (v : Corner r n P E) : Bool :=
J.alignment cut v.2.1 v.1 v.2.2
noncomputable def firstLabel (cut : E → Fin (n+1)) : RawBlock r n P E → Bool
| .inl h => J.alignment cut h.type h.row h.first
| .inr s => J.alignment cut (left J.source s.link) s.row s.first
noncomputable def lastLabel (cut : E → Fin (n+1)) : RawBlock r n P E → Bool
| .inl h => J.alignment cut h.type (finRotate r h.row) h.last
| .inr s => J.alignment cut (left J.source s.link) (finRotate r s.row) s.last
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockImages
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11 uVariable12
namespace VariableWL.Blocks
open scoped CharTwo
open VariableWL.Affine Subdivision
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E)
def dimension : Vertex P E n → ℕ
| .inl p => J.dimension p
| .inr _ => 1
abbrev Value (t : Vertex P E n) := Vec (dimension J t)
def vectorShift (h : J.Shifts n) : ∀ t : Vertex P E n, Value J t
| .inl p => h.1 p
| .inr q => fun _ => h.2 q
def linkLeft (l : Link E n) : Value J (left J.source l) →ₗ[Bit] Bit := by
unfold left
split_ifs with hz
· rw [dite_eq_left hz]
exact J.linearLeft l.1
· rw [dite_eq_right hz]
exact LinearMap.proj (0 : Fin 1)
def linkRight (l : Link E n) : Value J (right J.target l) →ₗ[Bit] Bit := by
unfold right
split_ifs with hz
· rw [dite_eq_left hz]
exact J.linearRight l.1
· rw [dite_eq_right hz]
exact LinearMap.proj (0 : Fin 1)
def leftConstant (l : Link E n) : Bit := if l.2.val = 0 then J.constantLeft l.1 else 0
def rightConstant (l : Link E n) : Bit := if l.2.val = n then J.constantRight l.1 else 0
def linkConstant (l : Link E n) : Bit := leftConstant J l + rightConstant J l
theorem dependent_linear_apply {A : Type uVariable3} (d : A → ℕ) {i j : A} (he : i = j)
(L : Vec (d i) →ₗ[Bit] Bit) (v : ∀ t, Vec (d t)) :
(cast (congrArg (fun t => Vec (d t) →ₗ[Bit] Bit) he) L) (v j) = L (v i) := by
subst j; rfl
theorem linkLeft_eval (h : J.Shifts n) (l : Link E n) :
linkLeft J l (vectorShift J h (left J.source l)) + leftConstant J l =
J.shiftLeft h l := by
by_cases hz : l.2.val = 0
· have he := dependent_linear_apply (dimension J) (i := .inl (J.source l.1))
(j := left J.source l) (by simp only [left, dite_eq_left hz])
(J.linearLeft l.1) (vectorShift J h)
simp only [linkLeft, dite_eq_left hz, leftConstant, ite_eq_left hz,
ProductImages.Instance.shiftLeft, ProductImages.Instance.leftForm]
exact congrArg (fun z => z + J.constantLeft l.1) he
· simp only [linkLeft, dite_eq_right hz, leftConstant, ite_eq_right hz, add_zero,
ProductImages.Instance.shiftLeft]
exact dependent_linear_apply (dimension J)
(i := .inr (l.1, ⟨l.2.val-1, by omega⟩)) (j := left J.source l)
(by simp only [left, dite_eq_right hz]) (LinearMap.proj (0 : Fin 1)) (vectorShift J h)
theorem linkRight_eval (h : J.Shifts n) (l : Link E n) :
linkRight J l (vectorShift J h (right J.target l)) + rightConstant J l =
J.shiftRight h l := by
by_cases hz : l.2.val = n
· have he := dependent_linear_apply (dimension J) (i := .inl (J.target l.1))
(j := right J.target l) (by simp only [right, dite_eq_left hz])
(J.linearRight l.1) (vectorShift J h)
simp only [linkRight, dite_eq_left hz, rightConstant, ite_eq_left hz,
ProductImages.Instance.shiftRight, ProductImages.Instance.rightForm]
exact congrArg (fun z => z + J.constantRight l.1) he
· simp only [linkRight, dite_eq_right hz, rightConstant, ite_eq_right hz, add_zero,
ProductImages.Instance.shiftRight]
exact dependent_linear_apply (dimension J)
(i := .inr (l.1, ⟨l.2.val, by omega⟩)) (j := right J.target l)
(by simp only [right, dite_eq_right hz]) (LinearMap.proj (0 : Fin 1)) (vectorShift J h)
theorem link_equation_iff (h : J.Shifts n) (l : Link E n) :
linkLeft J l (vectorShift J h (left J.source l)) +
linkRight J l (vectorShift J h (right J.target l)) = linkConstant J l ↔
J.shiftLeft h l = J.shiftRight h l := by
rw [← linkLeft_eval J h l, ← linkRight_eval J h l]
unfold linkConstant
constructor <;> intro he
· have hh := congrArg (fun z => z + linkRight J l (vectorShift J h (right J.target l)) +
leftConstant J l) he
simpa [add_assoc, add_comm, add_left_comm] using hh
· have hh := congrArg (fun z => z + leftConstant J l +
linkRight J l (vectorShift J h (right J.target l))) he
simpa [add_assoc, add_comm, add_left_comm] using hh
abbrev ReadoutValue : Readout r n P E → Type
| .inl h => Value J h.type
| .inr _ => Bit
abbrev Potentials := ∀ v : Corner r n P E, Value J v.2.1
def marker (marked i : Fin r) : Bit := if i = marked then 1 else 0
def potentialValues (marked : Fin r) (h : J.Shifts n) (M : Potentials (n := n) J) :
∀ a : Readout r n P E, ReadoutValue J a
| .inl x => M (x.row, x.type, x.first) + M (finRotate r x.row, x.type, x.last) +
marker marked x.row • vectorShift J h x.type
| .inr y => linkLeft J y.link (M (y.row, left J.source y.link, y.label)) +
linkRight J y.link (M (y.row, right J.target y.link, matchOutput J y.link y.row y.label))
theorem potential_square (marked : Fin r) (h : J.Shifts n) (M : Potentials (n := n) J)
(s : Square r n E) (hs : J.shiftLeft h s.link = J.shiftRight h s.link) :
linkLeft J s.link (potentialValues J marked h M (.inl (squareLeft J s))) +
linkRight J s.link (potentialValues J marked h M (.inl (squareRight J s))) +
potentialValues J marked h M (.inr (squareBottom s)) +
potentialValues J marked h M (.inr (squareTop s)) =
marker marked s.row * linkConstant J s.link := by
have he := (link_equation_iff J h s.link).mpr hs
dsimp only [potentialValues, squareLeft, squareRight, squareBottom, squareTop, end0, end1]
simp only [map_add, map_smul, smul_eq_mul]
have ht : (2 : Bit) = 0 := by decide
linear_combination (marker marked s.row) * he +
(linkLeft J s.link (M (s.row, left J.source s.link, s.first)) +
linkLeft J s.link (M (finRotate r s.row, left J.source s.link, s.last)) +
linkRight J s.link (M (s.row, right J.target s.link,
matchOutput J s.link s.row s.first)) +
linkRight J s.link (M (finRotate r s.row, right J.target s.link,
matchOutput J s.link (finRotate r s.row) s.last))) * ht
def gaugePotentials (h g : J.Shifts n) (M : Potentials (n := n) J) (s : Corner r n P E → Bit) :
Potentials (n := n) J := fun v => M v + s v • (vectorShift J g v.2.1 + vectorShift J h v.2.1)
end VariableWL.Blocks
namespace VariableWL.Blocks
open scoped CharTwo
open VariableWL.Affine Subdivision
variable {r n : ℕ} {P : Type uVariable7} {E : Type uVariable8} (J : ProductImages.Instance r P E)
theorem diagram_mono (hr : 2 ≤ r) (hn : 0 < n) {U V : Set (Block (n := n) J)}
(h : U ⊆ V) : diagram J hr hn U ≤ diagram J hr hn V := by
rintro u v ⟨b,hb,a,ha,hh⟩
exact ⟨b,h hb,a,ha,hh⟩
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockCoordinates
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11 uVariable12 uVariable13 uVariable14 uVariable15 uVariable16 uVariable17 uVariable18 uVariable19 uVariable20 uVariable21
namespace VariableWL.Blocks
open Subdivision
variable {r n : ℕ} {P : Type uVariable4} {E : Type uVariable5} (J : ProductImages.Instance r P E)
def anchor : RawBlock r n P E → Corner r n P E
| .inl h => end0 J (.inl h)
| .inr s => end0 J (.inl (squareLeft J s))
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision
variable {r n : ℕ} {P : Type uVariable8} {E : Type uVariable9} (J : ProductImages.Instance r P E)
noncomputable def componentBlocks (hr : 2 ≤ r) (hn : 0 < n)
(U : Finset (Block (n := n) J)) (c : (diagram J hr hn U).ConnectedComponent) :
Finset (Block (n := n) J) := by
classical
exact U.filter fun b => (diagram J hr hn U).connectedComponentMk (anchor J b.val) = c
theorem mem_componentBlocks (hr : 2 ≤ r) (hn : 0 < n)
(U : Finset (Block (n := n) J)) (c : (diagram J hr hn U).ConnectedComponent)
(b : Block (n := n) J) : b ∈ componentBlocks J hr hn U c ↔
b ∈ U ∧ (diagram J hr hn U).connectedComponentMk (anchor J b.val) = c := by
classical
exact Finset.mem_filter
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision
variable {r n : ℕ} {P : Type uVariable15} {E : Type uVariable16} (J : ProductImages.Instance r P E)
noncomputable def typesOf : RawBlock r n P E → Finset (Vertex P E n) := by
classical
exact fun b => match b with
| .inl h => {h.type}
| .inr s => {left J.source s.link, right J.target s.link}
noncomputable def supportTypes (U : Finset (Block (n := n) J)) : Finset (Vertex P E n) := by
classical
exact U.biUnion fun b => typesOf J b.val
noncomputable def addressAt (cut : E → Fin (n+1)) (a : Fin r → Bool)
(t : Vertex P E n) : Fin r → Bool := fun i => (J.alignment cut t i).symm (a i)
def Recovers (cut : E → Fin (n+1)) (U : Finset (Block (n := n) J))
(a : Fin r → Bool) : Prop := ∀ b ∈ U,
firstLabel J cut b.val = a (row b.val) ∧
lastLabel J cut b.val = a (finRotate r (row b.val))
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockExtensions
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8
namespace VariableWL.Blocks
open Subdivision ProductImages.Instance
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E)
def SupportConnected (hn : 0 < n) (C : Finset (Block (n := n) J)) : Prop :=
∀ t ∈ supportTypes J C, ∀ u ∈ supportTypes J C,
(supportGraph hn J.source J.target (supportLinks J C)).Reachable t u
def NoReal (C : Finset (Block (n := n) J)) : Prop :=
∀ p, (.inl p : Vertex P E n) ∉ supportTypes J C
def Avoids (cut : E → Fin (n+1)) (C : Finset (Block (n := n) J)) : Prop :=
∀ l ∈ supportLinks J C, l.2 ≠ cut l.1
def AddressCondition (Q : J.Witness) (cut : E → Fin (n+1))
(C : Finset (Block (n := n) J)) (a : Address r) (h : J.Shifts n) : Prop :=
(∀ p, Sum.inl p ∈ supportTypes J C → h.1 p ∈ Q.values p (addressAt J cut a (.inl p))) ∧
(NoReal J C → ∀ q, Sum.inr q ∈ supportTypes J C →
h.2 q ∈ Q.wireValues q.1 (addressAt J cut a (.inr q)))
def Admissible (hr : 3 ≤ r) (hn : 0 < n) (marked : Fin r) (Q : J.Witness)
(cut : E → Fin (n+1)) (C : Finset (Block (n := n) J)) (h : J.Shifts n) : Prop :=
J.ShiftSystem (supportLinks J C) h ∧
∀ W ⊆ C, W.card = r → (rowDiagram J hr hn W).Wraps marked →
∀ a, Recovers J cut W a → AddressCondition J Q cut C a h
@[simp] theorem addressAt_real (cut : E → Fin (n+1)) (a : Address r) (p : P) :
addressAt J cut a (.inl p) = a := rfl
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision ProductImages.Instance
variable {r n : ℕ} {P : Type uVariable7} {E : Type uVariable8} (J : ProductImages.Instance r P E)
def componentMap (hr : 2 ≤ r) (hn : 0 < n)
{V U : Finset (Block (n := n) J)} (h : V ⊆ U) :
(diagram J hr hn V).ConnectedComponent → (diagram J hr hn U).ConnectedComponent :=
SimpleGraph.ConnectedComponent.map (SimpleGraph.Hom.ofLE (diagram_mono J hr hn h))
@[simp] theorem componentMap_mk (hr : 2 ≤ r) (hn : 0 < n)
{V U : Finset (Block (n := n) J)} (h : V ⊆ U) (v : Corner r n P E) :
componentMap J hr hn h ((diagram J hr hn V).connectedComponentMk v) =
(diagram J hr hn U).connectedComponentMk v := rfl
abbrev ReadoutValues := ∀ a : Readout r n P E, ReadoutValue J a
def OffsetFamily (hr : 3 ≤ r) (hn : 0 < n) (marked : Fin r) (Q : J.Witness)
(U : Finset (Block (n := n) J)) (F : ReadoutValues (n := n) J) : Prop :=
∃ cut : E → Fin (n+1), Avoids J cut U ∧
∃ h : (diagram J (by omega) hn U).ConnectedComponent → J.Shifts n,
∃ M : Potentials (n := n) J,
(∀ c, Admissible J hr hn marked Q cut (componentBlocks J (by omega) hn U c) (h c)) ∧
∀ b ∈ U, ∀ a, HasReadout J b.val a →
F a = potentialValues J marked (h ((diagram J (by omega) hn U).connectedComponentMk
(anchor J b.val))) M a
def representedValues (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r)
(U : Finset (Block (n := n) J))
(h : (diagram J hr hn U).ConnectedComponent → J.Shifts n)
(M : Potentials (n := n) J) : ReadoutValues (n := n) J :=
fun a => potentialValues J marked (h ((diagram J hr hn U).connectedComponentMk (end0 J a))) M a
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_ExactProjection
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10
namespace VariableWL.Blocks
open scoped CharTwo
open Subdivision ProductImages.Instance VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4} (J : ProductImages.Instance r P E)
def RawValue : RawBlock r n P E → Type
| .inl h => Value J h.type
| .inr s => SquareVal (dimension J (left J.source s.link)) (dimension J (right J.target s.link))
instance rawValueAddCommGroup (b : RawBlock r n P E) : AddCommGroup (RawValue J b) := by
cases b <;> dsimp only [RawValue] <;> infer_instance
noncomputable instance rawValueFintype (b : RawBlock r n P E) : Fintype (RawValue J b) := by
cases b <;> dsimp only [RawValue] <;> infer_instance
def boundaryMap (b : RawBlock r n P E) : RawValue J b →+ Bit := by
cases b with
| inl h => exact 0
| inr s =>
exact { toFun := boundary (linkLeft J s.link) (linkRight J s.link)
map_zero' := boundary_zero _ _
map_add' := boundary_add _ _ }
def inhomogeneity (marked : Fin r) : RawBlock r n P E → Bit
| .inl _ => 0
| .inr s => marker marked s.row * linkConstant J s.link
def LegalValue (marked : Fin r) (ε : Bit) (b : RawBlock r n P E) (z : RawValue J b) : Prop :=
boundaryMap J b z = ε * inhomogeneity J marked b
abbrev Valuation (marked : Fin r) (ε : Bit) (b : Block (n := n) J) :=
{z : RawValue J b.val // LegalValue J marked ε b.val z}
noncomputable instance valuationFintype (marked : Fin r) (ε : Bit) (b : Block (n := n) J) :
Fintype (Valuation J marked ε b) := Fintype.ofFinite _
theorem legal_nonempty (marked : Fin r) (ε : Bit) (b : RawBlock r n P E) :
∃ z : RawValue J b, LegalValue J marked ε b z := by
cases b with
| inl h => exact ⟨0,by simp [LegalValue, inhomogeneity, boundaryMap]⟩
| inr s =>
exact fiber_nonempty (linkLeft J s.link) (linkRight J s.link)
(ε * (marker marked s.row * linkConstant J s.link))
def valueOfReadouts (F : ReadoutValues (n := n) J) : (b : RawBlock r n P E) → RawValue J b
| .inl h => F (.inl h)
| .inr s => ((F (.inl (squareLeft J s)), F (.inl (squareRight J s))),
(F (.inr (squareBottom s)), F (.inr (squareTop s))))
def Carries (b : RawBlock r n P E) (z : RawValue J b)
(a : Readout r n P E) (v : ReadoutValue J a) : Prop :=
match b with
| .inl h => a = .inl h ∧ HEq v z
| .inr s =>
(a = .inl (squareLeft J s) ∧ HEq v z.1.1) ∨
(a = .inl (squareRight J s) ∧ HEq v z.1.2) ∨
(a = .inr (squareBottom s) ∧ HEq v z.2.1) ∨
(a = .inr (squareTop s) ∧ HEq v z.2.2)
theorem carries_hasReadout {b : RawBlock r n P E} {z : RawValue J b}
{a : Readout r n P E} {v : ReadoutValue J a} (h : Carries J b z a v) : HasReadout J b a := by
cases b with
| inl _ => exact h.1
| inr _ =>
exact h.elim (fun h => Or.inl h.1)
(fun h => h.elim (fun h => Or.inr (Or.inl h.1))
(fun h => h.elim (fun h => Or.inr (Or.inr (Or.inl h.1)))
(fun h => Or.inr (Or.inr (Or.inr h.1)))))
theorem carries_exists {b : RawBlock r n P E} (z : RawValue J b)
{a : Readout r n P E} (ha : HasReadout J b a) : ∃ v, Carries J b z a v := by
cases b with
| inl h => cases ha; exact ⟨z,rfl,HEq.rfl⟩
| inr s =>
rcases ha with rfl | rfl | rfl | rfl
· exact ⟨z.1.1,Or.inl ⟨rfl,HEq.rfl⟩⟩
· exact ⟨z.1.2,Or.inr (Or.inl ⟨rfl,HEq.rfl⟩)⟩
· exact ⟨z.2.1,Or.inr (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩))⟩
· exact ⟨z.2.2,Or.inr (Or.inr (Or.inr ⟨rfl,HEq.rfl⟩))⟩
theorem offsetFamily_legal (hr : 3 ≤ r) (hn : 0 < n) (marked : Fin r) (Q : J.Witness)
(U : Finset (Block (n := n) J)) {F : ReadoutValues (n := n) J}
(hF : OffsetFamily J hr hn marked Q U F) {b : Block (n := n) J} (hb : b ∈ U) :
LegalValue J marked 1 b.val (valueOfReadouts J F b.val) := by
obtain ⟨cut,hc,h,M,hh,hrep⟩ := hF
let c := (diagram J (by omega) hn U).connectedComponentMk (anchor J b.val)
have hbC : b ∈ componentBlocks J (by omega) hn U c :=
(mem_componentBlocks J (by omega) hn U c b).mpr ⟨hb,rfl⟩
have hsys := (hh c).1
obtain ⟨b,hvalid⟩ := b
cases b with
| inl x => simp [LegalValue, boundaryMap, inhomogeneity]
| inr s =>
have hl := square_link_mem J (componentBlocks J (by omega) hn U c) hbC rfl
have h0 := hrep ⟨.inr s,hvalid⟩ hb (.inl (squareLeft J s)) (Or.inl rfl)
have h1 := hrep ⟨.inr s,hvalid⟩ hb (.inl (squareRight J s)) (Or.inr (Or.inl rfl))
have h2 := hrep ⟨.inr s,hvalid⟩ hb (.inr (squareBottom s)) (Or.inr (Or.inr (Or.inl rfl)))
have h3 := hrep ⟨.inr s,hvalid⟩ hb (.inr (squareTop s)) (Or.inr (Or.inr (Or.inr rfl)))
change linkLeft J s.link (F (.inl (squareLeft J s))) +
linkRight J s.link (F (.inl (squareRight J s))) + F (.inr (squareBottom s)) +
F (.inr (squareTop s)) = 1 * (marker marked s.row * linkConstant J s.link)
rw [h0,h1,h2,h3,one_mul]
exact potential_square J marked (h c) M s (hsys s.link hl)
noncomputable def familyList (hr : 3 ≤ r) (hn : 0 < n) (marked : Fin r) (Q : J.Witness)
(U : Finset (Block (n := n) J)) {F : ReadoutValues (n := n) J}
(hF : OffsetFamily J hr hn marked Q U F) : ∀ b : ↑U, Valuation J marked 1 b.val :=
fun b => ⟨valueOfReadouts J F b.val.val, offsetFamily_legal J hr hn marked Q U hF b.property⟩
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision ProductImages.Instance VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable5} {E : Type uVariable6} (J : ProductImages.Instance r P E)
def OffsetLists (hr : 3 ≤ r) (hn : 0 < n) (marked : Fin r) (Q : J.Witness)
(U : Finset (Block (n := n) J)) : Set (∀ b : ↑U, Valuation J marked 1 b.val) :=
{ξ | ∃ F : ReadoutValues (n := n) J, OffsetFamily J hr hn marked Q U F ∧
∀ b : ↑U, (ξ b).val = valueOfReadouts J F b.val.val}
def restrictList (marked : Fin r) {U V : Finset (Block (n := n) J)} (hVU : V ⊆ U)
(ξ : ∀ b : ↑U, Valuation J marked 1 b.val) : ∀ b : ↑V, Valuation J marked 1 b.val :=
fun b => ξ ⟨b.val,hVU b.property⟩
end VariableWL.Blocks
namespace VariableWL.Blocks
open Subdivision ProductImages.Instance VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable7} {E : Type uVariable8} (J : ProductImages.Instance r P E)
instance readoutValueAddCommGroup (a : Readout r n P E) : AddCommGroup (ReadoutValue J a) := by
cases a <;> dsimp only [ReadoutValue] <;> infer_instance
noncomputable instance readoutValueFintype (a : Readout r n P E) : Fintype (ReadoutValue J a) := by
cases a <;> dsimp only [ReadoutValue] <;> infer_instance
theorem squareLeft_ne_right (hn : 0 < n) (s : Square r n E) :
squareLeft J s ≠ squareRight J s := by
intro h
exact endpoints_ne hn J.source J.target s.link (congrArg Horizontal.type h)
theorem squareBottom_ne_top (hr : 2 ≤ r) (s : Square r n E) :
squareBottom s ≠ squareTop s := by
intro h
exact Wrapping.finRotate_no_fixed hr s.row (congrArg Vertical.row h).symm
theorem carries_unique (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{z : RawValue J b} {a : Readout r n P E} {v w : ReadoutValue J a}
(hv : Carries J b z a v) (hw : Carries J b z a w) : v = w := by
cases b with
| inl h => exact eq_of_heq (hv.2.trans hw.2.symm)
| inr s =>
have hlr := squareLeft_ne_right J hn s
have hbt := squareBottom_ne_top hr s
rcases hv with ⟨hv,hv'⟩ | ⟨hv,hv'⟩ | ⟨hv,hv'⟩ | ⟨hv,hv'⟩ <;>
rcases hw with ⟨hw,hw'⟩ | ⟨hw,hw'⟩ | ⟨hw,hw'⟩ | ⟨hw,hw'⟩
all_goals first | exact eq_of_heq (hv'.trans hw'.symm) | exfalso; aesop
noncomputable def readout {b : RawBlock r n P E} (z : RawValue J b)
{a : Readout r n P E} (ha : HasReadout J b a) : ReadoutValue J a :=
(carries_exists J z ha).choose
theorem readout_carries {b : RawBlock r n P E} (z : RawValue J b)
{a : Readout r n P E} (ha : HasReadout J b a) : Carries J b z a (readout J z ha) :=
(carries_exists J z ha).choose_spec
theorem readout_eq (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{z : RawValue J b} {a : Readout r n P E} (ha : HasReadout J b a)
{v : ReadoutValue J a} (hv : Carries J b z a v) : readout J z ha = v :=
carries_unique J hr hn (readout_carries J z ha) hv
end VariableWL.Blocks
namespace VariableWL.Blocks
variable {r n : ℕ} {P : Type uVariable9} {E : Type uVariable10} [Fintype P] [Fintype E]
noncomputable instance horizontalFintype : Fintype (Horizontal r n P E) := by
classical
refine Fintype.ofInjective (fun h => (h.row,h.type,h.first,h.last)) ?_
rintro ⟨a,b,c,d⟩ ⟨a',b',c',d'⟩ h
simp only [Prod.mk.injEq] at h
rcases h with ⟨rfl,rfl,rfl,rfl⟩
rfl
noncomputable instance verticalFintype : Fintype (Vertical r n E) := by
classical
refine Fintype.ofInjective (fun h => (h.row,h.link,h.label)) ?_
rintro ⟨a,b,c⟩ ⟨a',b',c'⟩ h
simp only [Prod.mk.injEq] at h
rcases h with ⟨rfl,rfl,rfl⟩
rfl
noncomputable instance squareFintype : Fintype (Square r n E) := by
classical
refine Fintype.ofInjective (fun h => (h.row,h.link,h.first,h.last)) ?_
rintro ⟨a,b,c,d⟩ ⟨a',b',c',d'⟩ h
simp only [Prod.mk.injEq] at h
rcases h with ⟨rfl,rfl,rfl,rfl⟩
rfl
noncomputable instance blockFintype (J : ProductImages.Instance r P E) : Fintype (Block (n := n) J) :=
Fintype.ofFinite _
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_GeneralGame
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.General
open Blocks VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E)
variable (marked : Fin r)
abbrev Base (ε : Bit) := Σ b : Block (n := n) J, Valuation J marked ε b
def Agree {ε ε' : Bit} (v : Base (n := n) J marked ε) (w : Base (n := n) J marked ε') : Prop :=
∀ a (hv : HasReadout J v.1.val a) (hw : HasReadout J w.1.val a),
readout J v.2.val hv = readout J w.2.val hw
end VariableWL.General
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_GeneralReduction
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10
namespace VariableWL.Blocks
attribute [local instance] Classical.propDecidable
open VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E) (marked : Fin r)
noncomputable def completeList (U : Finset (Block (n := n) J))
(ξ : ∀ b : ↑U, Valuation J marked 1 b.val) : ∀ b : Block (n := n) J, Valuation J marked 1 b := by
classical
exact fun b => if h : b ∈ U then ξ ⟨b,h⟩ else
⟨Classical.choose (legal_nonempty J marked 1 b.val),Classical.choose_spec (legal_nonempty J marked 1 b.val)⟩
def GlobalPool (hr : 3 ≤ r) (hn : 0 < n) (Q : J.Witness)
(U : Finset (Block (n := n) J)) : Set (∀ b : Block (n := n) J, Valuation J marked 1 b) :=
{ξ | (fun b : ↑U => ξ b.val) ∈ OffsetLists J hr hn marked Q U}
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockGame
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7
namespace VariableWL.Blocks
open scoped CharTwo
open Subdivision VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E) (marked : Fin r)
structure RingSystem where
lists : (b : Fin r → Block (n := n) J) → Set (∀ i, Valuation J marked 1 (b i))
nonempty : ∀ b, (lists b).Nonempty
compatible : ∀ b y, y ∈ lists b → ∀ i j, General.Agree J marked ⟨b i,y i⟩ ⟨b j,y j⟩
transfer : ∀ b y, y ∈ lists b → ∀ c,
∃ z ∈ lists c, ∀ i, General.Agree J marked ⟨b i,y i⟩ ⟨c i,z i⟩
abbrev TypeAddress (t : Vertex P E n) :=
{a : Fin r → Bool // ∀ i, a i ∈ J.labels t i}
def siteRing (t : Vertex P E n) (a : TypeAddress J t) (i : Fin r) : Block (n := n) J :=
⟨.inl ⟨i,t,a.val i,a.val (finRotate r i)⟩,a.property i,a.property (finRotate r i)⟩
def leftAddress (l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) :
TypeAddress J (left J.source l) :=
⟨a,fun i => J.matches_left l i ⟨ha i,rfl⟩⟩
def rightAddress (l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) :
TypeAddress J (right J.target l) :=
⟨fun i => matchOutput J l i (a i),fun i => J.matches_right l i ⟨ha i,rfl⟩⟩
def squareRing (l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a)
(i : Fin r) : Block (n := n) J :=
⟨.inr ⟨i,l,a i,a (finRotate r i)⟩,ha i,ha (finRotate r i)⟩
noncomputable def ringSum {t : Vertex P E n} {a : TypeAddress J t}
(y : ∀ i, Valuation J marked 1 (siteRing J t a i)) : Value J t := ∑ i, (y i).val
def Attained (F : RingSystem J marked (n := n)) (t : Vertex P E n) (a : TypeAddress J t) :
Set (Value J t) := ringSum J marked '' F.lists (siteRing J t a)
theorem attained_nonempty (F : RingSystem J marked (n := n)) (t : Vertex P E n) (a : TypeAddress J t) :
(Attained J marked F t a).Nonempty := (F.nonempty _).image _
theorem agree_carries (hr : 2 ≤ r) (hn : 0 < n) {ε ε' : Bit}
{b c : Block (n := n) J} {y : Valuation J marked ε b} {z : Valuation J marked ε' c}
(h : General.Agree J marked ⟨b,y⟩ ⟨c,z⟩) {a : Readout r n P E}
{v w : ReadoutValue J a} (hv : Carries J b.val y.val a v)
(hw : Carries J c.val z.val a w) : v = w := by
have hh := h a (carries_hasReadout J hv) (carries_hasReadout J hw)
exact (readout_eq J hr hn _ hv).symm.trans (hh.trans (readout_eq J hr hn _ hw))
theorem copy_left (hr : 2 ≤ r) (hn : 0 < n) (l : Link E n)
(a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) (i : Fin r)
(y : Valuation J marked 1 (siteRing J _ (leftAddress J l a ha) i))
(z : Valuation J marked 1 (squareRing J l a ha i))
(h : General.Agree J marked ⟨_,y⟩ ⟨_,z⟩) : y.val = z.val.1.1 := by
exact agree_carries J marked hr hn h (a := .inl (squareLeft J ⟨i,l,a i,a (finRotate r i)⟩))
⟨rfl,HEq.rfl⟩ (Or.inl ⟨rfl,HEq.rfl⟩)
theorem copy_right (hr : 2 ≤ r) (hn : 0 < n) (l : Link E n)
(a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) (i : Fin r)
(y : Valuation J marked 1 (siteRing J _ (rightAddress J l a ha) i))
(z : Valuation J marked 1 (squareRing J l a ha i))
(h : General.Agree J marked ⟨_,y⟩ ⟨_,z⟩) : y.val = z.val.1.2 := by
exact agree_carries J marked hr hn h (a := .inl (squareRight J ⟨i,l,a i,a (finRotate r i)⟩))
⟨rfl,HEq.rfl⟩ (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩))
theorem squareRing_vertical (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a)
{z : ∀ i, Valuation J marked 1 (squareRing J l a ha i)} (hz : z ∈ F.lists _)
(i : Fin r) : (z i).val.2.2 = (z (finRotate r i)).val.2.1 := by
exact agree_carries J marked hr hn (F.compatible _ z hz i (finRotate r i))
(a := .inr (squareTop ⟨i,l,a i,a (finRotate r i)⟩))
(Or.inr (Or.inr (Or.inr ⟨rfl,HEq.rfl⟩)))
(Or.inr (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩)))
theorem squareRing_equation (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a)
{z : ∀ i, Valuation J marked 1 (squareRing J l a ha i)} (hz : z ∈ F.lists _) :
linkLeft J l (∑ i, (z i).val.1.1) + linkRight J l (∑ i, (z i).val.1.2) = linkConstant J l := by
have he (i : Fin r) : linkLeft J l (z i).val.1.1 + linkRight J l (z i).val.1.2 +
(z i).val.2.1 + (z i).val.2.2 = marker marked i * linkConstant J l := by
have h := (z i).property
change linkLeft J l (z i).val.1.1 + linkRight J l (z i).val.1.2 +
(z i).val.2.1 + (z i).val.2.2 = 1 * (marker marked i * linkConstant J l) at h
simpa only [one_mul] using h
have hs := congrArg (fun f : Fin r → Bit => ∑ i, f i) (funext he)
simp only [Finset.sum_add_distrib] at hs
have hv : (∑ i, (z i).val.2.2) = ∑ i, (z i).val.2.1 := by
simp_rw [squareRing_vertical J marked hr hn F l a ha hz]
exact Equiv.sum_comp (finRotate r) (fun i => (z i).val.2.1)
rw [hv] at hs
have hm : (∑ i, marker marked i * linkConstant J l) = linkConstant J l := by
simp [marker]
rw [hm] at hs
simpa only [map_sum,add_assoc,CharTwo.add_self_eq_zero,add_zero] using hs
theorem agree_symm {ε ε' : Bit} {v : General.Base (n := n) J marked ε}
{w : General.Base (n := n) J marked ε'} (h : General.Agree J marked v w) :
General.Agree J marked w v := fun a hw hv => (h a hv hw).symm
theorem attained_link_forward (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a)
{v : Value J (left J.source l)} (hv : v ∈ Attained J marked F _ (leftAddress J l a ha)) :
∃ w ∈ Attained J marked F _ (rightAddress J l a ha),
linkLeft J l v + linkRight J l w = linkConstant J l := by
obtain ⟨y,hy,rfl⟩ := hv
obtain ⟨z,hz,hyz⟩ := F.transfer _ y hy (squareRing J l a ha)
obtain ⟨w,hw,hzw⟩ := F.transfer _ z hz (siteRing J _ (rightAddress J l a ha))
refine ⟨ringSum J marked w,⟨w,hw,rfl⟩,?_⟩
have hl := fun i => copy_left J marked hr hn l a ha i (y i) (z i) (hyz i)
have hr' := fun i => copy_right J marked hr hn l a ha i (w i) (z i) (agree_symm J marked (hzw i))
simpa only [ringSum,hl,hr'] using squareRing_equation J marked hr hn F l a ha hz
theorem attained_link_reverse (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a)
{w : Value J (right J.target l)} (hw : w ∈ Attained J marked F _ (rightAddress J l a ha)) :
∃ v ∈ Attained J marked F _ (leftAddress J l a ha),
linkLeft J l v + linkRight J l w = linkConstant J l := by
obtain ⟨y,hy,rfl⟩ := hw
obtain ⟨z,hz,hyz⟩ := F.transfer _ y hy (squareRing J l a ha)
obtain ⟨w,hw,hzw⟩ := F.transfer _ z hz (siteRing J _ (leftAddress J l a ha))
refine ⟨ringSum J marked w,⟨w,hw,rfl⟩,?_⟩
have hr' := fun i => copy_right J marked hr hn l a ha i (y i) (z i) (hyz i)
have hl := fun i => copy_left J marked hr hn l a ha i (w i) (z i) (agree_symm J marked (hzw i))
simpa only [ringSum,hl,hr'] using squareRing_equation J marked hr hn F l a ha hz
end VariableWL.Blocks
namespace VariableWL.Blocks
open scoped CharTwo
open Subdivision VariableWL.Affine
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4} (J : ProductImages.Instance r P E) (marked : Fin r)
theorem affine_of_boundary (a b c d : Bit) (h : a+b=c+d) : a+c=b+d := by
have ht : (2 : Bit) = 0 := by decide
linear_combination h+(c-b)*ht
theorem attained_link_images (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) :
(fun v => linkLeft J l v + leftConstant J l) '' Attained J marked F _ (leftAddress J l a ha) =
(fun v => linkRight J l v + rightConstant J l) '' Attained J marked F _ (rightAddress J l a ha) := by
ext x
constructor
· rintro ⟨v,hv,rfl⟩
obtain ⟨w,hw,he⟩ := attained_link_forward J marked hr hn F l a ha hv
exact ⟨w,hw,(affine_of_boundary _ _ _ _ he).symm⟩
· rintro ⟨w,hw,rfl⟩
obtain ⟨v,hv,he⟩ := attained_link_reverse J marked hr hn F l a ha hw
exact ⟨v,hv,affine_of_boundary _ _ _ _ he⟩
def realAddress (p : P) (a : ProductImages.Instance.Address r) : TypeAddress J (n := n) (.inl p) :=
⟨a,fun _ => Finset.mem_univ _⟩
def internalAddress (e : E) (j : Fin n) (a : ProductImages.Instance.Address r) (ha : J.Allowed e a) :
TypeAddress J (.inr (e,j)) := ⟨a,ha⟩
def realAttained (F : RingSystem J marked (n := n)) (p : P) (a : ProductImages.Instance.Address r) :
Set (Vec (J.dimension p)) := Attained J marked F (.inl p) (realAddress J p a)
def scalarAttained (F : RingSystem J marked (n := n)) (e : E) (j : Fin n)
(a : ProductImages.Instance.Address r) (ha : J.Allowed e a) : Set Bit :=
(fun v => v (0 : Fin 1)) '' Attained J marked F (.inr (e,j)) (internalAddress J e j a ha)
def addressedAttained (F : RingSystem J marked (n := n)) (t : Vertex P E n)
(a : ProductImages.Instance.Address r) : Set (Value J t) :=
{v | ∃ h : ∀ i, a i ∈ J.labels t i, v ∈ Attained J marked F t ⟨a,h⟩}
theorem addressedAttained_eq (F : RingSystem J marked (n := n)) (t : Vertex P E n)
(a : TypeAddress J t) : addressedAttained J marked F t a.val = Attained J marked F t a := by
ext v
exact ⟨fun ⟨_,h⟩ => h,fun h => ⟨a.property,h⟩⟩
theorem dependent_linear_image {A : Type uVariable5} (d : A → ℕ) {i j : A} (he : i = j)
(L : Vec (d i) →ₗ[Bit] Bit) (Q : ∀ t, Set (Vec (d t))) (c : Bit) :
(fun v => (cast (congrArg (fun t => Vec (d t) →ₗ[Bit] Bit) he) L) v + c) '' Q j =
(fun v => L v + c) '' Q i := by
subst j
rfl
theorem left_image_evaluation (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) :
(fun v => linkLeft J l v + leftConstant J l) '' addressedAttained J marked F (left J.source l) a =
if h : l.2.val = 0 then J.leftForm l.1 '' addressedAttained J marked F (.inl (J.source l.1)) a
else (fun v => v (0 : Fin 1)) '' addressedAttained J marked F (.inr (l.1,⟨l.2.val-1,by omega⟩)) a := by
by_cases hz : l.2.val = 0
· have he := dependent_linear_image (dimension J) (i := .inl (J.source l.1))
(j := left J.source l) (by simp only [left,dite_eq_left hz])
(J.linearLeft l.1) (fun t => addressedAttained J marked F t a) (J.constantLeft l.1)
simp only [linkLeft,dite_eq_left hz,leftConstant,ite_eq_left hz]
exact he
· have he := dependent_linear_image (dimension J) (i := .inr (l.1,⟨l.2.val-1,by omega⟩))
(j := left J.source l) (by simp only [left,dite_eq_right hz])
(LinearMap.proj (0 : Fin 1)) (fun t => addressedAttained J marked F t a) 0
simp only [linkLeft,dite_eq_right hz,leftConstant,ite_eq_right hz,add_zero]
simp only [add_zero] at he
exact he
theorem right_image_evaluation (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) :
(fun v => linkRight J l v + rightConstant J l) '' addressedAttained J marked F (right J.target l) a =
if h : l.2.val = n then J.rightForm l.1 '' addressedAttained J marked F (.inl (J.target l.1)) a
else (fun v => v (0 : Fin 1)) '' addressedAttained J marked F (.inr (l.1,⟨l.2.val,by omega⟩)) a := by
by_cases hz : l.2.val = n
· have he := dependent_linear_image (dimension J) (i := .inl (J.target l.1))
(j := right J.target l) (by simp only [right,dite_eq_left hz])
(J.linearRight l.1) (fun t => addressedAttained J marked F t a) (J.constantRight l.1)
simp only [linkRight,dite_eq_left hz,rightConstant,ite_eq_left hz]
exact he
· have he := dependent_linear_image (dimension J) (i := .inr (l.1,⟨l.2.val,by omega⟩))
(j := right J.target l) (by simp only [right,dite_eq_right hz])
(LinearMap.proj (0 : Fin 1)) (fun t => addressedAttained J marked F t a) 0
simp only [linkRight,dite_eq_right hz,rightConstant,ite_eq_right hz,add_zero]
simp only [add_zero] at he
exact he
theorem wire_images (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(l : Link E n) (a : ProductImages.Instance.Address r) (ha : J.Allowed l.1 a) :
(if h : l.2.val = 0 then J.leftForm l.1 '' addressedAttained J marked F (.inl (J.source l.1)) a
else (fun v => v (0 : Fin 1)) '' addressedAttained J marked F (.inr (l.1,⟨l.2.val-1,by omega⟩)) a) =
(if h : l.2.val = n then J.rightForm l.1 '' addressedAttained J marked F (.inl (J.target l.1))
(fun i => matchOutput J l i (a i))
else (fun v => v (0 : Fin 1)) '' addressedAttained J marked F (.inr (l.1,⟨l.2.val,by omega⟩))
(fun i => matchOutput J l i (a i))) := by
rw [← left_image_evaluation J marked F l a,← right_image_evaluation J marked F l]
exact (congrArg (Set.image _) (addressedAttained_eq J marked F _ (leftAddress J l a ha))).trans
((attained_link_images J marked hr hn F l a ha).trans
(congrArg (Set.image _) (addressedAttained_eq J marked F _ (rightAddress J l a ha))).symm)
theorem attained_first (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(e : E) (a : ProductImages.Instance.Address r) (ha : J.Allowed e a) :
J.leftForm e '' realAttained J marked F (J.source e) a =
scalarAttained J marked F e ⟨0,hn⟩ a ha := by
have h := wire_images J marked hr hn F (e,⟨0,by omega⟩) a ha
simp only [dite_eq_right (Ne.symm hn.ne'),matchOutput,ite_eq_right (Ne.symm hn.ne'),dite_true] at h
exact (congrArg (Set.image (J.leftForm e)) (addressedAttained_eq J marked F _ (realAddress J (J.source e) a))).symm.trans
(h.trans (congrArg (Set.image (fun v => v (0 : Fin 1)))
(addressedAttained_eq J marked F _ (internalAddress J e ⟨0,hn⟩ a ha))))
theorem attained_last (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(e : E) (a : ProductImages.Instance.Address r) (ha : J.Allowed e a) :
scalarAttained J marked F e ⟨n-1,by omega⟩ a ha =
J.rightForm e '' realAttained J marked F (J.target e) (J.mapAddress e a) := by
have h := wire_images J marked hr hn F (e,⟨n,by omega⟩) a ha
simp only [dite_eq_right hn.ne',matchOutput,dite_true,ite_true] at h
exact (congrArg (Set.image (fun v => v (0 : Fin 1)))
(addressedAttained_eq J marked F _ (internalAddress J e ⟨n-1,by omega⟩ a ha))).symm.trans
(h.trans (congrArg (Set.image (J.rightForm e))
(addressedAttained_eq J marked F _ (realAddress J (J.target e) (J.mapAddress e a)))))
theorem attained_internal (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n))
(e : E) (a : ProductImages.Instance.Address r) (ha : J.Allowed e a)
(j : ℕ) (hj : j+1 < n) :
scalarAttained J marked F e ⟨j,by omega⟩ a ha =
scalarAttained J marked F e ⟨j+1,hj⟩ a ha := by
have h := wire_images J marked hr hn F (e,⟨j+1,by omega⟩) a ha
simp only [dite_eq_right (Nat.succ_ne_zero j),dite_eq_right hj.ne,matchOutput,ite_eq_right hj.ne] at h
exact (congrArg (Set.image (fun v => v (0 : Fin 1)))
(addressedAttained_eq J marked F _ (internalAddress J e ⟨j,by omega⟩ a ha))).symm.trans
(h.trans (congrArg (Set.image (fun v => v (0 : Fin 1)))
(addressedAttained_eq J marked F _ (internalAddress J e ⟨j+1,hj⟩ a ha))))
noncomputable def extractedWitness (hr : 2 ≤ r) (hn : 0 < n) (F : RingSystem J marked (n := n)) : J.Witness where
values := realAttained J marked F
nonempty p a := attained_nonempty J marked F _ _
images e a ha := by
calc
_ = scalarAttained J marked F e ⟨0,hn⟩ a ha := attained_first J marked hr hn F e a ha
_ = scalarAttained J marked F e ⟨n-1,by omega⟩ a ha := by
have hs (j : ℕ) (hj : j < n) : scalarAttained J marked F e ⟨0,hn⟩ a ha =
scalarAttained J marked F e ⟨j,hj⟩ a ha := by
induction j with
| zero => rfl
| succ j ih => exact (ih (by omega)).trans (attained_internal J marked hr hn F e a ha j hj)
exact hs _ (by omega)
_ = _ := attained_last J marked hr hn F e a ha
end VariableWL.Blocks
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PortGraph
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9
namespace VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
structure PortGraph (V : Type uVariable1) where
edge : (V × Fin 3) → (V × Fin 3) → Prop
symm : ∀ {a b}, edge a b → edge b a
unique : ∀ {a b c}, edge a b → edge a c → b = c
different : ∀ {a b}, edge a b → a.1 ≠ b.1
def PortGraph.graph {V : Type uVariable2} (Y : PortGraph V) : SimpleGraph V where
Adj v w := ∃ j k, Y.edge (v,j) (w,k)
symm := ⟨fun _ _ ⟨j,k,h⟩ => ⟨k,j,Y.symm h⟩⟩
loopless := ⟨fun _ ⟨_,_,h⟩ => Y.different h rfl⟩
@[ext] structure Vertex {V : Type uVariable3} (color : V → ℕ) where
owner : V
port : Fin 3
level : ℕ
bound : level < color owner + 2
namespace Vertex
variable {V : Type uVariable4} {color : V → ℕ}
def equivSigma : Vertex color ≃ (Σ v : V, Fin 3 × Fin (color v+2)) where
toFun x := ⟨x.owner,x.port,⟨x.level,x.bound⟩⟩
invFun x := ⟨x.1,x.2.1,x.2.2.val,x.2.2.isLt⟩
left_inv _ := rfl
right_inv _ := rfl
noncomputable instance instFintype [Fintype V] : Fintype (Vertex color) :=
Fintype.ofEquiv _ equivSigma.symm
end Vertex
variable {V : Type uVariable5} (Y : PortGraph V) (color : V → ℕ)
def Internal (x y : Vertex color) : Prop :=
x.owner = y.owner ∧
((x.level = 0 ∧ y.level = 0 ∧ x.port ≠ y.port) ∨
(x.port = y.port ∧ (x.level+1 = y.level ∨ y.level+1 = x.level)))
def External (x y : Vertex color) : Prop :=
x.level = 1 ∧ y.level = 1 ∧ Y.edge (x.owner,x.port) (y.owner,y.port)
def graph : SimpleGraph (Vertex color) where
Adj x y := Internal color x y ∨ External Y color x y
symm := ⟨by
intro x y h
rcases h with ⟨ho,(⟨hx,hy,hp⟩ | ⟨hp,hl⟩)⟩ | ⟨hx,hy,he⟩
· exact Or.inl ⟨ho.symm,Or.inl ⟨hy,hx,hp.symm⟩⟩
· exact Or.inl ⟨ho.symm,Or.inr ⟨hp.symm,hl.symm⟩⟩
· exact Or.inr ⟨hy,hx,Y.symm he⟩⟩
loopless := ⟨by
intro x h
rcases h with ⟨_,(⟨_,_,hp⟩ | ⟨_,hl⟩)⟩ | ⟨_,_,he⟩
· exact hp rfl
· omega
· exact Y.different he rfl⟩
end VariableWL.SubcubicRealization
namespace VariableWL.SubcubicRealization
variable {V : Type uVariable8} {W : Type uVariable9} {color : V → ℕ} {color' : W → ℕ}
def vertexEquiv (f : V ≃ W) (ports : V → Equiv.Perm (Fin 3))
(hc : ∀ v, color' (f v) = color v) : Vertex color ≃ Vertex color' where
toFun x := ⟨f x.owner,ports x.owner x.port,x.level,by rw [hc]; exact x.bound⟩
invFun y := ⟨f.symm y.owner,(ports (f.symm y.owner)).symm y.port,y.level,by
rw [← hc,f.apply_symm_apply]; exact y.bound⟩
left_inv x := by apply Vertex.ext <;> simp
right_inv y := by apply Vertex.ext <;> simp
theorem vertexEquiv_internal (f : V ≃ W) (ports : V → Equiv.Perm (Fin 3))
(hc : ∀ v, color' (f v) = color v) (x y : Vertex color) :
Internal color' (vertexEquiv f ports hc x) (vertexEquiv f ports hc y) ↔ Internal color x y := by
change (f x.owner = f y.owner ∧ _) ↔ _
rw [f.injective.eq_iff]
by_cases ho : x.owner = y.owner
· simp only [Internal,vertexEquiv,Equiv.coe_fn_mk,ho,true_and]
simp only [ne_eq,(ports y.owner).injective.eq_iff]
· simp only [ho,false_and,Internal]
theorem vertexEquiv_adj (Y : PortGraph V) (Z : PortGraph W)
(f : V ≃ W) (ports : V → Equiv.Perm (Fin 3))
(hc : ∀ v, color' (f v) = color v) (x y : Vertex color)
(he : Y.edge (x.owner,x.port) (y.owner,y.port) ↔
Z.edge (f x.owner,ports x.owner x.port) (f y.owner,ports y.owner y.port)) :
(graph Z color').Adj (vertexEquiv f ports hc x) (vertexEquiv f ports hc y) ↔
(graph Y color).Adj x y := by
change (Internal color' _ _ ∨ _) ↔ (Internal color x y ∨ _)
rw [vertexEquiv_internal]
change (Internal color x y ∨ x.level=1 ∧ y.level=1 ∧
Z.edge (f x.owner,ports x.owner x.port) (f y.owner,ports y.owner y.port)) ↔ _
rw [← he]
rfl
end VariableWL.SubcubicRealization
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_TypedGame
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9
namespace VariableWL.TypedGame
attribute [local instance] Classical.propDecidable
variable {V : Type uVariable1} {W : Type uVariable2} [Fintype V] [Fintype W]
noncomputable abbrev numbered (G : SimpleGraph V) : Graph :=
⟨Fintype.card V,G.comap (Fintype.equivFin V).symm⟩
noncomputable def numbering (G : SimpleGraph V) : G ≃g (numbered G).graph where
toEquiv := Fintype.equivFin V
map_rel_iff' := by intro x y; change G.Adj _ _ ↔ _; simp
end VariableWL.TypedGame
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PrefixParts
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.PrefixParts
open VariableWL.Affine
open scoped CharTwo
attribute [local instance] Classical.propDecidable
structure Data where
dimension : ℕ
channels : ℕ
positive : 0 < channels
root : Fin channels → ℕ
root_le : ∀ c, root c ≤ dimension
zero_root : root ⟨0,positive⟩ = 0
order : Fin channels → Equiv.Perm (Fin dimension)
legal : Bit → Set (Vec dimension)
nonempty : ∀ ε, (legal ε).Nonempty
coset : ∀ (ξ : Vec dimension), ξ ∈ legal 1 →
∀ z, z ∈ legal 0 ↔ z+ξ ∈ legal 1
namespace Data
@[simp] theorem vec_add_self {a : ℕ} (v : Vec a) : v+v=0 := by
ext i; simp
variable (D : Data)
abbrev Valuation (ε : Bit) := {z : Vec D.dimension // z ∈ D.legal ε}
noncomputable def translate (ξ : D.Valuation 1) : D.Valuation 0 ≃ D.Valuation 1 where
toFun z := ⟨z.val+ξ.val,(D.coset _ ξ.property _).mp z.property⟩
invFun z := ⟨z.val+ξ.val,(D.coset _ ξ.property _).mpr (by rw [add_assoc,vec_add_self,add_zero]; exact z.property)⟩
left_inv z := by ext i; simp
right_inv z := by ext i; simp
def truncate {a : ℕ} (h : ℕ) (u : Vec a) : Vec a := fun i => if i.val<h then u i else 0
theorem truncate_add {a h : ℕ} (u v : Vec a) : truncate h (u+v)=truncate h u+truncate h v := by
ext i; simp only [truncate,Pi.add_apply]; split_ifs <;> simp
theorem truncate_truncate {a h k : ℕ} (hk : h ≤ k) (u : Vec a) :
truncate h (truncate k u)=truncate h u := by
ext i; simp only [truncate]; split_ifs <;> (first | rfl | omega)
@[simp] theorem truncate_zero {a : ℕ} (u : Vec a) : truncate 0 u=0 := by
ext i; simp [truncate]
@[simp] theorem truncate_full {a : ℕ} (u : Vec a) : truncate a u=u := by
ext i; simp [truncate,i.isLt]
abbrev RawTree := Fin D.channels × Fin (D.dimension+1) × Vec D.dimension
def TreeLegal (ε : Bit) (t : D.RawTree) : Prop :=
D.root t.1 ≤ t.2.1.val ∧ ∃ z : D.Valuation ε,
truncate t.2.1.val (z.val ∘ D.order t.1)=t.2.2
abbrev Tree (ε : Bit) := {t : D.RawTree // D.TreeLegal ε t}
abbrev Vertex (ε : Bit) := Unit ⊕ ((Fin D.channels × D.Valuation ε) ⊕ D.Tree ε)
namespace Tree
variable {D} {ε : Bit}
abbrev channel (t : D.Tree ε) := t.val.1
abbrev height (t : D.Tree ε) := t.val.2.1.val
abbrev bits (t : D.Tree ε) := t.val.2.2
def ofValuation (c : Fin D.channels) (h : ℕ) (hqa : D.root c ≤ h) (ha : h ≤ D.dimension)
(z : D.Valuation ε) : D.Tree ε :=
⟨(c,⟨h,by omega⟩,truncate h (z.val ∘ D.order c)),hqa,z,rfl⟩
@[ext] theorem ext {t u : D.Tree ε} (hc : t.channel=u.channel)
(hh : t.height=u.height) (hb : t.bits=u.bits) : t=u := by
apply Subtype.ext
exact Prod.ext hc (Prod.ext (Fin.ext hh) hb)
theorem truncated (t : D.Tree ε) : truncate t.height t.bits=t.bits := by
obtain ⟨_,z,hz⟩ := t.property
change truncate t.height (z.val ∘ D.order t.channel)=t.bits at hz
rw [← hz,truncate_truncate le_rfl]
theorem above_zero (t : D.Tree ε) (i : Fin D.dimension) (hi : t.height ≤ i.val) : t.bits i=0 := by
have h := congrFun t.truncated i
simpa [truncate,show ¬i.val<t.height by omega] using h.symm
theorem height_zero (t : D.Tree ε) (hh : t.height=0) : t.bits=0 := by
rw [← t.truncated,hh,truncate_zero]
end Tree
variable {D}
def TreeStep {ε : Bit} (t u : D.Tree ε) : Prop :=
t.channel=u.channel ∧ t.height+1=u.height ∧ truncate t.height u.bits=t.bits
def Forward {ε : Bit} : D.Vertex ε → D.Vertex ε → Prop
| .inl _, .inr (.inr t) => t.channel.val=0 ∧ t.height=0
| .inr (.inl (c,z)), .inr (.inl (d,w)) => c.val+1=d.val ∧ z=w
| .inr (.inr t), .inr (.inr u) => TreeStep t u
| .inr (.inr t), .inr (.inl (c,z)) =>
t.channel=c ∧ t.height=D.dimension ∧ t.bits=z.val ∘ D.order c
| _, _ => False
variable (D)
def graph (ε : Bit) : SimpleGraph (D.Vertex ε) where
Adj x y := Forward x y ∨ Forward y x
symm := ⟨fun _ _ => Or.symm⟩
loopless := ⟨by
intro x
cases x with
| inl u => simp [Forward]
| inr v =>
cases v with
| inl v => simp only [Forward,or_self]; omega
| inr t => simp only [Forward,TreeStep,or_self]; omega⟩
noncomputable def treeTranslation (ξ : D.Valuation 1) : D.Tree 0 ≃ D.Tree 1 where
toFun t := ⟨(t.channel,t.val.2.1,t.bits+truncate t.height (ξ.val ∘ D.order t.channel)),by
refine ⟨t.property.1,?_⟩
obtain ⟨z,hz⟩ := t.property.2
refine ⟨D.translate ξ z,?_⟩
change truncate t.height ((z.val+ξ.val) ∘ D.order t.channel)=_
have he : (z.val+ξ.val) ∘ D.order t.channel = z.val ∘ D.order t.channel+ξ.val ∘ D.order t.channel := rfl
rw [he,truncate_add,hz]⟩
invFun t := ⟨(t.channel,t.val.2.1,t.bits+truncate t.height (ξ.val ∘ D.order t.channel)),by
refine ⟨t.property.1,?_⟩
obtain ⟨z,hz⟩ := t.property.2
refine ⟨(D.translate ξ).symm z,?_⟩
change truncate t.height ((z.val+ξ.val) ∘ D.order t.channel)=_
have he : (z.val+ξ.val) ∘ D.order t.channel = z.val ∘ D.order t.channel+ξ.val ∘ D.order t.channel := rfl
rw [he,truncate_add,hz]⟩
left_inv t := by
apply Tree.ext
· rfl
· rfl
· change (t.bits+truncate t.height (ξ.val ∘ D.order t.channel))+truncate t.height (ξ.val ∘ D.order t.channel)=t.bits
rw [add_assoc,vec_add_self,add_zero]
right_inv t := by
apply Tree.ext
· rfl
· rfl
· change (t.bits+truncate t.height (ξ.val ∘ D.order t.channel))+truncate t.height (ξ.val ∘ D.order t.channel)=t.bits
rw [add_assoc,vec_add_self,add_zero]
noncomputable def vertexTranslation (ξ : D.Valuation 1) : D.Vertex 0 ≃ D.Vertex 1 :=
Equiv.sumCongr (Equiv.refl Unit) (Equiv.sumCongr
(Equiv.prodCongr (Equiv.refl _) (D.translate ξ)) (D.treeTranslation ξ))
end Data
end VariableWL.PrefixParts
namespace VariableWL.PrefixParts.Data
open VariableWL.Affine
open scoped CharTwo
attribute [local instance] Classical.propDecidable
variable {D : Data} {ε : Bit}
theorem Tree.height_le (t : D.Tree ε) : t.height ≤ D.dimension := Nat.le_of_lt_succ t.val.2.1.isLt
theorem TreeStep.lower_lt {t u : D.Tree ε} (h : TreeStep t u) : t.height < D.dimension := by
have hu := u.height_le
have hh := h.2.1
omega
theorem TreeStep.parent_unique {t u v : D.Tree ε} (h : TreeStep u t) (h' : TreeStep v t) : u=v := by
have hh := h.2.1
have hh' := h'.2.1
apply Tree.ext (h.1.trans h'.1.symm)
· omega
· have hh : u.height=v.height := by omega
rw [← h.2.2,hh,h'.2.2]
theorem TreeStep.child_unique {t u v : D.Tree ε} (h : TreeStep t u) (h' : TreeStep t v)
(hb : u.bits ⟨t.height,h.lower_lt⟩=v.bits ⟨t.height,h'.lower_lt⟩) : u=v := by
have hh := h.2.1
have hh' := h'.2.1
apply Tree.ext (h.1.symm.trans h'.1)
· omega
· ext i
rcases lt_trichotomy i.val t.height with hi | hi | hi
· have hu := congrFun h.2.2 i
have hv := congrFun h'.2.2 i
simpa [truncate,hi] using hu.trans hv.symm
· have he : i=⟨t.height,h.lower_lt⟩ := Fin.ext hi
simpa only [he] using hb
· rw [u.above_zero i (by omega),v.above_zero i (by omega)]
theorem Tree.root_unique {t u : D.Tree ε} (hc : t.channel=u.channel)
(ht : t.height=0) (hu : u.height=0) : t=u :=
Tree.ext hc (ht.trans hu.symm) ((t.height_zero ht).trans (u.height_zero hu).symm)
def bitPort (b : Bit) : Fin 3 := ⟨b.val+1,by have := ZMod.val_lt b; omega⟩
theorem bitPort_ne_zero (b : Bit) : bitPort b ≠ 0 := by
intro h
have := congrArg Fin.val h
simp only [bitPort,Fin.val_zero] at this
omega
theorem bitPort_injective : Function.Injective bitPort := by
intro a b h
apply ZMod.val_injective 2
have he := congrArg Fin.val h
change a.val+1=b.val+1 at he
omega
noncomputable def slot {ε : Bit} : D.Vertex ε → D.Vertex ε → Fin 3
| .inl _, _ => 0
| .inr (.inl (c,_)), .inr (.inl (d,_)) => if d.val<c.val then 0 else 1
| .inr (.inl _), _ => 2
| .inr (.inr _), .inl _ => 0
| .inr (.inr _), .inr (.inl _) => 1
| .inr (.inr t), .inr (.inr u) =>
if u.height<t.height then 0 else
if ht : t.height<D.dimension then bitPort (u.bits ⟨t.height,ht⟩) else 1
theorem slot_parent {t u : D.Tree ε} (h : TreeStep t u) :
slot (.inr (.inr u)) (.inr (.inr t))=0 := by
have hh := h.2.1
simp only [slot,ite_eq_left (show t.height<u.height by omega)]
theorem slot_child {t u : D.Tree ε} (h : TreeStep t u) :
slot (.inr (.inr t)) (.inr (.inr u))=bitPort (u.bits ⟨t.height,h.lower_lt⟩) := by
have hh := h.2.1
simp only [slot,ite_eq_right (show ¬u.height<t.height by omega),dite_eq_left h.lower_lt]
theorem leaf_unique (t : D.Tree ε) {c d : Fin D.channels} {z w : D.Valuation ε}
(h : t.channel=c ∧ t.height=D.dimension ∧ t.bits=z.val ∘ D.order c)
(h' : t.channel=d ∧ t.height=D.dimension ∧ t.bits=w.val ∘ D.order d) : (c,z)=(d,w) := by
have hc : c=d := h.1.symm.trans h'.1
subst d
apply Prod.ext
· rfl
apply Subtype.ext
ext i
have he := congrFun (h.2.2.symm.trans h'.2.2) ((D.order c).symm i)
simpa only [Function.comp_apply,Equiv.apply_symm_apply] using he
theorem leaf_node_unique {t u : D.Tree ε} {c : Fin D.channels} {z : D.Valuation ε}
(h : t.channel=c ∧ t.height=D.dimension ∧ t.bits=z.val ∘ D.order c)
(h' : u.channel=c ∧ u.height=D.dimension ∧ u.bits=z.val ∘ D.order c) : t=u :=
Tree.ext (h.1.trans h'.1.symm) (h.2.1.trans h'.2.1.symm) (h.2.2.trans h'.2.2.symm)
theorem slot_injective (x : D.Vertex ε) :
Function.Injective (fun y : (D.graph ε).neighborSet x => slot x y.val) := by
rintro ⟨y,hy⟩ ⟨z,hz⟩ he
change slot x y=slot x z at he
apply Subtype.ext
change y=z
have hy' : Forward x y ∨ Forward y x := hy
have hz' : Forward x z ∨ Forward z x := hz
rcases x with x | (⟨c,v⟩ | t)
· rcases y with y | (y | u) <;> rcases z with z | (z | w) <;>
simp only [Forward,or_false] at hy' hz'; try contradiction
obtain ⟨huc,hu⟩ := hy'
obtain ⟨hwc,hw⟩ := hz'
exact congrArg (fun a => Sum.inr (Sum.inr a)) (Tree.root_unique (Fin.ext (huc.trans hwc.symm)) hu hw)
· rcases y with y | (⟨d,w⟩ | u) <;> rcases z with z | (⟨e,v'⟩ | t') <;>
simp only [Forward,false_or,or_false] at hy' hz' <;> try contradiction
· have hd : w=v := by rcases hy' with h | h; exact h.2.symm; exact h.2
have he' : v'=v := by rcases hz' with h | h; exact h.2.symm; exact h.2
subst w; subst v'
have hc : d=e := by
apply Fin.ext
simp only [slot] at he
split_ifs at he <;> (rcases hy' with h | h) <;> (rcases hz' with h' | h') <;>
omega
subst e; rfl
· simp only [slot] at he
split_ifs at he <;> have := congrArg Fin.val he <;> norm_num at this
· simp only [slot] at he
split_ifs at he <;> have := congrArg Fin.val he <;> norm_num at this
· exact congrArg (fun a => Sum.inr (Sum.inr a)) (leaf_node_unique hy' hz')
· rcases y with y | (⟨d,w⟩ | u) <;> rcases z with z | (⟨e,v'⟩ | t') <;>
simp only [Forward,false_or,or_false] at hy' hz'
· cases y; cases z; rfl
· have := congrArg Fin.val he; norm_num [slot] at this
· rcases hz' with h | h
· rw [slot_child h] at he
exact (bitPort_ne_zero _ he.symm).elim
· have ht := hy'.2
have hh := h.2.1
omega
· have := congrArg Fin.val he; norm_num [slot] at this
· exact congrArg (fun a => Sum.inr (Sum.inl a)) (leaf_unique t hy' hz')
· rcases hz' with h | h
· have hh := h.lower_lt; omega
· rw [slot_parent h] at he
have := congrArg Fin.val he; norm_num [slot] at this
· rcases hy' with h | h
· rw [slot_child h] at he
exact (bitPort_ne_zero _ he).elim
· have ht := hz'.2
have hh := h.2.1
omega
· rcases hy' with h | h
· have hh := h.lower_lt; omega
· rw [slot_parent h] at he
have := congrArg Fin.val he; norm_num [slot] at this
· rcases hy' with h | h <;> rcases hz' with h' | h'
· rw [slot_child h,slot_child h'] at he
exact congrArg (fun a => Sum.inr (Sum.inr a)) (h.child_unique h' (bitPort_injective he))
· rw [slot_child h,slot_parent h'] at he
exact (bitPort_ne_zero _ he).elim
· rw [slot_parent h,slot_child h'] at he
exact (bitPort_ne_zero _ he.symm).elim
· exact congrArg (fun a => Sum.inr (Sum.inr a)) (h.parent_unique h')
end VariableWL.PrefixParts.Data
namespace VariableWL.PrefixParts.Data
open VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {D : Data}
def portAlphabet : Fin 3 ≃ Option Bit := finSuccEquiv 2
@[simp] theorem portAlphabet_zero : portAlphabet 0=none := rfl
@[simp] theorem portAlphabet_bitPort (b : Bit) : portAlphabet (bitPort b)=some b := by
exact finSuccEquiv_succ b
def shiftPorts (b : Bit) : Equiv.Perm (Fin 3) :=
portAlphabet.trans ((Equiv.optionCongr (Equiv.addRight b)).trans portAlphabet.symm)
@[simp] theorem shiftPorts_zero (b : Bit) : shiftPorts b 0=0 := by
apply portAlphabet.injective
simp [shiftPorts]
@[simp] theorem shiftPorts_bitPort (a b : Bit) : shiftPorts b (bitPort a)=bitPort (a+b) := by
apply portAlphabet.injective
simp [shiftPorts]
noncomputable def localPorts (ξ : D.Valuation 1) : D.Vertex 0 → Equiv.Perm (Fin 3)
| .inr (.inr t) => if h : t.height<D.dimension then
shiftPorts (ξ.val (D.order t.channel ⟨t.height,h⟩)) else Equiv.refl _
| _ => Equiv.refl _
@[simp] theorem localPorts_zero (ξ : D.Valuation 1) (x : D.Vertex 0) : localPorts ξ x 0=0 := by
rcases x with x | (x | t) <;> simp only [localPorts,Equiv.refl_apply]
split_ifs <;> simp
theorem proper_root_reserved {ε : Bit} (t : D.Tree ε)
(hc : t.channel.val ≠ 0) (hh : t.height=D.root t.channel)
{y : D.Vertex ε} (hy : (D.graph ε).Adj (.inr (.inr t)) y) :
slot (.inr (.inr t)) y ≠ 0 := by
have hy' : Forward (.inr (.inr t)) y ∨ Forward y (.inr (.inr t)) := hy
rcases y with y | (⟨c,z⟩ | u)
· simp only [Forward,false_or] at hy'
exact (hc hy'.1).elim
· change (1 : Fin 3) ≠ 0
decide
· rcases hy' with h | h
· rw [slot_child h]
exact bitPort_ne_zero _
· have hroot := u.property.1
change D.root u.channel ≤ u.height at hroot
have hch := h.1
have hht := h.2.1
rw [hch] at hroot
omega
end VariableWL.PrefixParts.Data
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PrefixWiring
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9
namespace VariableWL.SubcubicRealization.PortGraph
attribute [local instance] Classical.propDecidable
variable {V : Type uVariable1}
def ofSlots (G : SimpleGraph V) (slot : V → V → Fin 3)
(hinj : ∀ x, Function.Injective (fun y : G.neighborSet x => slot x y.val)) : PortGraph V where
edge a b := G.Adj a.1 b.1 ∧ a.2=slot a.1 b.1 ∧ b.2=slot b.1 a.1
symm := fun h => ⟨h.1.symm,h.2.2,h.2.1⟩
unique := by
rintro ⟨x,i⟩ ⟨y,j⟩ ⟨z,k⟩ h h'
have he : (⟨y,h.1⟩ : G.neighborSet x)=⟨z,h'.1⟩ := hinj x (h.2.1.symm.trans h'.2.1)
have hy : y=z := congrArg Subtype.val he
subst z
exact Prod.ext rfl (h.2.2.trans h'.2.2.symm)
different := fun h => h.1.ne
@[simp] theorem ofSlots_graph (G : SimpleGraph V) (slot : V → V → Fin 3)
(hinj : ∀ x, Function.Injective (fun y : G.neighborSet x => slot x y.val)) :
(ofSlots G slot hinj).graph=G := by
ext x y
exact ⟨fun ⟨_,_,h⟩ => h.1,fun h => ⟨slot x y,slot y x,h,rfl,rfl⟩⟩
def sigma {B : Type uVariable2} {A : B → Type uVariable9} (Y : ∀ b, PortGraph (A b)) : PortGraph (Σ b,A b) where
edge a b := ∃ h : a.1.1=b.1.1, (Y a.1.1).edge (a.1.2,a.2) (h.symm ▸ b.1.2,b.2)
symm := by
rintro ⟨⟨b,x⟩,i⟩ ⟨⟨c,y⟩,j⟩ ⟨h,he⟩
dsimp at h
subst c
exact ⟨rfl,(Y b).symm he⟩
unique := by
rintro ⟨⟨b,x⟩,i⟩ ⟨⟨c,y⟩,j⟩ ⟨⟨d,z⟩,k⟩ ⟨h,he⟩ ⟨h',he'⟩
dsimp at h h'
subst c
subst d
have hh := (Y b).unique he he'
change (y,j)=(z,k) at hh
cases hh
rfl
different := by
rintro ⟨⟨b,x⟩,i⟩ ⟨⟨c,y⟩,j⟩ ⟨h,he⟩ hxy
dsimp at h
subst c
exact (Y b).different he (eq_of_heq (Sigma.mk.inj_iff.mp hxy).2)
def union (Y Z : PortGraph V)
(hd : ∀ a b c, Y.edge a b → Z.edge a c → False) : PortGraph V where
edge a b := Y.edge a b ∨ Z.edge a b
symm := fun h => h.elim (fun h => Or.inl (Y.symm h)) (fun h => Or.inr (Z.symm h))
unique := by
intro a b c h h'
rcases h with h | h <;> rcases h' with h' | h'
· exact Y.unique h h'
· exact (hd _ _ _ h h').elim
· exact (hd _ _ _ h' h).elim
· exact Z.unique h h'
different := fun h => h.elim Y.different Z.different
end VariableWL.SubcubicRealization.PortGraph
namespace VariableWL.PrefixParts.Data
open VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
noncomputable def ports (D : Data) (ε : Affine.Bit) : PortGraph (D.Vertex ε) :=
PortGraph.ofSlots (D.graph ε) slot slot_injective
@[simp] theorem ports_graph (D : Data) (ε : Affine.Bit) : (D.ports ε).graph=D.graph ε :=
PortGraph.ofSlots_graph _ _ _
end VariableWL.PrefixParts.Data
namespace VariableWL.PrefixParts
open VariableWL.Affine VariableWL.SubcubicRealization
open scoped CharTwo
attribute [local instance] Classical.propDecidable
abbrev Channel {B : Type uVariable3} (D : B → Data) := Σ b, {c : Fin (D b).channels // c.val≠0}
structure Wiring {B : Type uVariable4} (D : B → Data) where
mate : Channel D ≃ Channel D
involutive : Function.Involutive mate
different : ∀ c, (mate c).1≠c.1
root_eq : ∀ c, (D (mate c).1).root (mate c).2.val=(D c.1).root c.2.val
namespace Wiring
variable {B : Type uVariable5} [Fintype B] [FiniteNumbering B] (D : B → Data) (W : Wiring D)
abbrev Vertex (ε : Bit) := Σ b, (D b).Vertex ε
abbrev Root (ε : Bit) (c : Channel D) :=
{t : (D c.1).Tree ε // t.channel=c.2.val ∧ t.height=(D c.1).root c.2.val}
abbrev RootLabel (ε : Bit) := Σ c : Channel D, Root D ε c
def rootVertex {ε : Bit} (x : RootLabel D ε) : Vertex D ε :=
⟨x.1.1,.inr (.inr x.2.val)⟩
omit [Fintype B] in
theorem rootVertex_injective {ε : Bit} : Function.Injective (rootVertex (D := D) (ε := ε)) := by
rintro ⟨⟨b,c⟩,t⟩ ⟨⟨d,e⟩,u⟩ h
have hb : b=d := congrArg Sigma.fst h
subst d
have ht : t.val=u.val := Sum.inr_injective (Sum.inr_injective (eq_of_heq (Sigma.mk.inj_iff.mp h).2))
have hc : c=e := Subtype.ext (t.property.1.symm.trans ((congrArg Data.Tree.channel ht).trans u.property.1))
subst e
have hu : t=u := Subtype.ext ht
subst u
rfl
def pad {a : ℕ} (v : Vec a) : ℕ → Bit := fun j => if h : j<a then v ⟨j,h⟩ else 0
theorem pad_injective {a : ℕ} : Function.Injective (@pad a) := by
intro v w h
ext i
simpa only [pad,dite_eq_left i.isLt] using congrFun h i.val
@[simp] theorem pad_add {a : ℕ} (v w : Vec a) : pad (v+w)=pad v+pad w := by
ext i
simp only [pad,Pi.add_apply]
split_ifs <;> simp
noncomputable def internal (ε : Bit) : PortGraph (Vertex D ε) :=
PortGraph.sigma (fun b => (D b).ports ε)
def rootPorts (ε : Bit) : PortGraph (Vertex D ε) where
edge a b := ∃ x y : RootLabel D ε, a=(rootVertex D x,0) ∧ b=(rootVertex D y,0) ∧
W.mate x.1=y.1 ∧ pad x.2.val.bits=pad y.2.val.bits
symm := by
rintro a b ⟨x,y,rfl,rfl,hm,hv⟩
refine ⟨y,x,rfl,rfl,?_,hv.symm⟩
rw [← hm,W.involutive]
unique := by
rintro a b c ⟨x,y,rfl,rfl,hm,hv⟩ ⟨x',z,hx,rfl,hm',hv'⟩
have hxx : x=x' := rootVertex_injective D (congrArg Prod.fst hx)
subst x'
have hc : y.1=z.1 := hm.symm.trans hm'
have hyz : y=z := by
rcases y with ⟨c,y⟩
rcases z with ⟨d,z⟩
dsimp at hc
subst d
have hb : y.val.bits=z.val.bits := pad_injective (hv.symm.trans hv')
have ht : y.val=z.val := Data.Tree.ext (y.property.1.trans z.property.1.symm)
(y.property.2.trans z.property.2.symm) hb
exact congrArg (Sigma.mk c) (Subtype.ext ht)
subst z
rfl
different := by
rintro a b ⟨x,y,rfl,rfl,hm,_⟩ he
have hblock : x.1.1=y.1.1 := congrArg (fun v : Vertex D ε => v.1) he
exact W.different x.1 (by rw [hm]; exact hblock.symm)
omit [Fintype B] in
theorem internal_root_disjoint (ε : Bit) (a b c : Vertex D ε × Fin 3)
(hi : (internal D ε).edge a b) (hr : (W.rootPorts D ε).edge a c) : False := by
obtain ⟨x,y,rfl,rfl,_,_⟩ := hr
rcases x with ⟨⟨d,e⟩,t⟩
rcases b with ⟨⟨f,v⟩,j⟩
obtain ⟨h,hint⟩ := hi
dsimp [rootVertex] at h
subst f
have hh : ((D d).graph ε).Adj (.inr (.inr t.val)) v := hint.1
have hs : Data.slot (.inr (.inr t.val)) v=0 := hint.2.1.symm
exact Data.proper_root_reserved t.val
(by rw [t.property.1]; exact e.property) (by rw [t.property.1]; exact t.property.2) hh hs
def anchor (ε : Bit) (b : B) : Vertex D ε := ⟨b,.inl ()⟩
def anchorPorts (ε : Bit) : PortGraph (Vertex D ε) where
edge a b :=
(∃ x y : B, a=(anchor D ε x,2) ∧ b=(anchor D ε y,1) ∧
(enumeration B x).val+1=(enumeration B y).val) ∨
(∃ x y : B, b=(anchor D ε x,2) ∧ a=(anchor D ε y,1) ∧
(enumeration B x).val+1=(enumeration B y).val)
symm := fun h => h.symm
unique := by
intro a b c h h'
rcases h with ⟨x,y,rfl,rfl,hxy⟩ | ⟨x,y,rfl,rfl,hxy⟩
· rcases h' with ⟨x',z,hx,rfl,hxz⟩ | ⟨z,x',rfl,hx,hzx⟩
· have hxx : x=x' := congrArg (fun a => a.1.1) hx
subst x'
have hyz : y=z := (enumeration B).injective (Fin.ext (hxy.symm.trans hxz))
subst z
rfl
· have hs : (2 : Fin 3)=1 := congrArg Prod.snd hx
exact ((by decide : (2 : Fin 3)≠1) hs).elim
· rcases h' with ⟨y',z,hy,rfl,hyz⟩ | ⟨z,y',rfl,hy,hzy⟩
· have hs : (1 : Fin 3)=2 := congrArg Prod.snd hy
exact ((by decide : (1 : Fin 3)≠2) hs).elim
· have hyy : y=y' := congrArg (fun a => a.1.1) hy
subst y'
have hxz : x=z := (enumeration B).injective (Fin.ext (by omega))
subst z
rfl
different := by
intro a b he hab
rcases he with ⟨x,y,rfl,rfl,hxy⟩ | ⟨x,y,rfl,rfl,hxy⟩
· have h : x=y := congrArg Sigma.fst hab
subst y
omega
· have h : y=x := congrArg Sigma.fst hab
subst y
omega
theorem internal_anchor_disjoint (ε : Bit) (a b c : Vertex D ε × Fin 3)
(hi : (internal D ε).edge a b) (ha : (anchorPorts D ε).edge a c) : False := by
rcases ha with ⟨x,y,rfl,rfl,_⟩ | ⟨y,x,rfl,rfl,_⟩
all_goals
rcases b with ⟨⟨d,v⟩,j⟩
obtain ⟨h,hint⟩ := hi
dsimp [anchor] at h
subst d
have hs := hint.2.1
change (_ : Fin 3)=Data.slot (.inl ()) v at hs
simp only [Data.slot] at hs
omega
theorem root_anchor_disjoint (ε : Bit) (a b c : Vertex D ε × Fin 3)
(hr : (W.rootPorts D ε).edge a b) (ha : (anchorPorts D ε).edge a c) : False := by
obtain ⟨x,y,rfl,rfl,_,_⟩ := hr
rcases ha with ⟨u,v,hu,_,_⟩ | ⟨u,v,_,hu,_⟩
· have hs : (0 : Fin 3)=2 := congrArg Prod.snd hu
exact (by decide : (0 : Fin 3)≠2) hs
· have hs : (0 : Fin 3)=1 := congrArg Prod.snd hu
exact (by decide : (0 : Fin 3)≠1) hs
noncomputable def ports (ε : Bit) : PortGraph (Vertex D ε) :=
(internal D ε).union ((W.rootPorts D ε).union (anchorPorts D ε) (root_anchor_disjoint D W ε))
(fun a b c hi he => he.elim (internal_root_disjoint D W ε a b c hi)
(internal_anchor_disjoint D ε a b c hi))
end Wiring
end VariableWL.PrefixParts
namespace VariableWL.PrefixParts.Data
open VariableWL.Affine VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
variable {D : Data}
abbrev SortTag (D : Data) := Unit ⊕ (Fin D.channels ⊕ (Σ c : Fin D.channels,
{h : Fin (D.dimension+1) // D.root c ≤ h.val}))
def sort {ε : Bit} : D.Vertex ε → D.SortTag
| .inl _ => .inl ()
| .inr (.inl (c,_)) => .inr (.inl c)
| .inr (.inr t) => .inr (.inr ⟨t.channel,t.val.2.1,t.property.1⟩)
@[simp] theorem sort_translation (ξ : D.Valuation 1) (x : D.Vertex 0) :
sort (D.vertexTranslation ξ x)=sort x := by
rcases x with x | (x | x) <;> rfl
@[simp] theorem localPorts_anchor (ξ : D.Valuation 1) (i : Fin 3) :
localPorts ξ (.inl ()) i=i := rfl
end VariableWL.PrefixParts.Data
namespace VariableWL.PrefixParts.Wiring
open VariableWL.Affine VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable6} [Fintype B] (D : B → Data) (W : Wiring D)
abbrev SortTag := Σ b, (D b).SortTag
variable [FiniteNumbering B] [FiniteNumbering (SortTag D)]
def sort {ε : Bit} (x : Vertex D ε) : SortTag D := ⟨x.1,Data.sort x.2⟩
noncomputable def color {ε : Bit} (x : Vertex D ε) : ℕ :=
(enumeration (SortTag D) (sort D x)).val+1
omit [FiniteNumbering B] in
theorem color_eq_iff {ε δ : Bit} (x : Vertex D ε) (y : Vertex D δ) :
color D x=color D y ↔ sort D x=sort D y := by
unfold color
exact ⟨fun h => (enumeration (SortTag D)).injective (Fin.ext (by omega)),fun h => congrArg (fun t : SortTag D => (enumeration (SortTag D) t).val+1) h⟩
noncomputable def vertexTranslation (ξ : ∀ b, (D b).Valuation 1) : Vertex D 0 ≃ Vertex D 1 :=
Equiv.sigmaCongrRight (fun b => (D b).vertexTranslation (ξ b))
omit [Fintype B] in
@[simp] theorem vertexTranslation_apply (ξ : ∀ b, (D b).Valuation 1) (b : B) (v : (D b).Vertex 0) :
vertexTranslation D ξ ⟨b,v⟩=⟨b,(D b).vertexTranslation (ξ b) v⟩ := rfl
omit [FiniteNumbering B] in
@[simp] theorem color_translation (ξ : ∀ b, (D b).Valuation 1) (x : Vertex D 0) :
color D (vertexTranslation D ξ x)=color D x := by
apply (color_eq_iff D _ _).mpr
exact congrArg (Sigma.mk x.1) (Data.sort_translation _ _)
noncomputable def localPorts (ξ : ∀ b, (D b).Valuation 1) (x : Vertex D 0) : Equiv.Perm (Fin 3) :=
Data.localPorts (ξ x.1) x.2
noncomputable def incidenceTranslation (ξ : ∀ b, (D b).Valuation 1) :
(Vertex D 0 × Fin 3) ≃ (Vertex D 1 × Fin 3) where
toFun a := (vertexTranslation D ξ a.1,localPorts D ξ a.1 a.2)
invFun a := ((vertexTranslation D ξ).symm a.1,
(localPorts D ξ ((vertexTranslation D ξ).symm a.1)).symm a.2)
left_inv a := by simp
right_inv a := by simp
omit [Fintype B] in
@[simp] theorem root_truncated {ε : Bit} (x : RootLabel D ε) :
Data.truncate ((D x.1.1).root x.1.2.val) x.2.val.bits=x.2.val.bits := by
calc
_ = Data.truncate x.2.val.height x.2.val.bits :=
congrArg (fun h => Data.truncate h x.2.val.bits) x.2.property.2.symm
_ = _ := x.2.val.truncated
noncomputable def rootTranslation (ξ : ∀ b, (D b).Valuation 1) : RootLabel D 0 ≃ RootLabel D 1 :=
Equiv.sigmaCongrRight (fun c =>
{ toFun := fun t => ⟨(D c.1).treeTranslation (ξ c.1) t.val,t.property⟩
invFun := fun t => ⟨((D c.1).treeTranslation (ξ c.1)).symm t.val,t.property⟩
left_inv := fun t => Subtype.ext (((D c.1).treeTranslation (ξ c.1)).symm_apply_apply t.val)
right_inv := fun t => Subtype.ext (((D c.1).treeTranslation (ξ c.1)).apply_symm_apply t.val) })
omit [Fintype B] in
@[simp] theorem translate_root_incidence (ξ : ∀ b, (D b).Valuation 1) (x : RootLabel D 0) :
incidenceTranslation D ξ (rootVertex D x,0)=(rootVertex D (rootTranslation D ξ x),0) := by
apply Prod.ext
· rfl
· exact Data.localPorts_zero _ _
noncomputable def rootShift (ξ : ∀ b, (D b).Valuation 1) (c : Channel D) : ℕ → Bit :=
pad (Data.truncate ((D c.1).root c.2.val) ((ξ c.1).val ∘ (D c.1).order c.2.val))
omit [Fintype B] in
@[simp] theorem rootTranslation_bits (ξ : ∀ b, (D b).Valuation 1) (x : RootLabel D 0) :
pad (rootTranslation D ξ x).2.val.bits=pad x.2.val.bits+rootShift D ξ x.1 := by
change pad (x.2.val.bits+Data.truncate x.2.val.height ((ξ x.1.1).val ∘ (D x.1.1).order x.2.val.channel))=_
rw [pad_add,x.2.property.1,x.2.property.2]
rfl
end VariableWL.PrefixParts.Wiring
namespace VariableWL.PrefixParts.Wiring
open VariableWL.Affine VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable7} [Fintype B] [FiniteNumbering B] (D : B → Data) [FiniteNumbering (SortTag D)] (W : Wiring D)
omit [Fintype B] in
@[simp] theorem translate_anchor_incidence (ξ : ∀ b, (D b).Valuation 1) (b : B) (i : Fin 3) :
incidenceTranslation D ξ (anchor D 0 b,i)=(anchor D 1 b,i) := rfl
end VariableWL.PrefixParts.Wiring
namespace VariableWL.PrefixParts.Wiring
open VariableWL.Affine VariableWL.SubcubicRealization
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable8} [Fintype B] [FiniteNumbering B] (D : B → Data) [FiniteNumbering (SortTag D)] (W : Wiring D)
abbrev UncoloredVertex (ε : Bit) := SubcubicRealization.Vertex (@color B _ D _ ε)
noncomputable def uncolored (ε : Bit) : SimpleGraph (UncoloredVertex D ε) :=
SubcubicRealization.graph (W.ports D ε) (color D)
end VariableWL.PrefixParts.Wiring
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Coordinates
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7
namespace VariableWL.BlockCoordinates
open VariableWL.Affine VariableWL.Blocks Subdivision
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (J : ProductImages.Instance r P E)
def Coordinate : RawBlock r n P E → Type
| .inl h => Fin (dimension J h.type)
| .inr s => (Fin (dimension J (left J.source s.link)) ⊕
Fin (dimension J (right J.target s.link))) ⊕ Bool
instance coordinateFintype (b : RawBlock r n P E) : Fintype (Coordinate J b) := by
cases b <;> dsimp only [Coordinate] <;> infer_instance
def coordinateEquiv (b : RawBlock r n P E) : RawValue J b ≃+ (Coordinate J b → Bit) := by
cases b with
| inl h => exact AddEquiv.refl _
| inr s =>
exact {
toFun := fun z => Sum.elim (Sum.elim z.1.1 z.1.2) (fun t => if t then z.2.2 else z.2.1)
invFun := fun f => ((fun i => f (.inl (.inl i)),fun i => f (.inl (.inr i))),
(f (.inr false),f (.inr true)))
left_inv := fun z => by cases z; rfl
right_inv := fun f => by
funext i
rcases i with (i | i) | t
· rfl
· rfl
· cases t <;> rfl
map_add' := fun z w => by
funext i
rcases i with (i | i) | t
· rfl
· rfl
· cases t <;> rfl }
noncomputable def numbering (b : RawBlock r n P E) : Coordinate J b ≃ Fin (Fintype.card (Coordinate J b)) :=
Fintype.equivFin _
noncomputable def encode (b : RawBlock r n P E) : RawValue J b ≃+ Vec (Fintype.card (Coordinate J b)) where
toFun z := coordinateEquiv J b z ∘ (numbering J b).symm
invFun f := (coordinateEquiv J b).symm (f ∘ numbering J b)
left_inv z := by simp only [Function.comp_def,Equiv.symm_apply_apply]; exact (coordinateEquiv J b).symm_apply_apply z
right_inv f := by funext i; simp
map_add' z w := by funext i; exact congrFun ((coordinateEquiv J b).map_add z w) _
def readoutDimension : Readout r n P E → ℕ
| .inl h => dimension J h.type
| .inr _ => 1
def readoutEquiv (a : Readout r n P E) : ReadoutValue J a ≃+ Vec (readoutDimension J a) := by
cases a with
| inl h => exact AddEquiv.refl _
| inr v =>
change Bit ≃+ Vec 1
exact { toFun := fun z _ => z
invFun := fun f => f 0
left_inv := fun _ => rfl
right_inv := fun f => by funext i; have : i=0 := Subsingleton.elim _ _; subst i; rfl
map_add' := fun _ _ => rfl }
theorem coordinate_lift (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) :
∃ e : Fin (readoutDimension J a) ↪ Coordinate J b,
∀ z i, coordinateEquiv J b z (e i)=readoutEquiv J a (readout J z ha) i := by
cases b with
| inl h =>
cases ha
refine ⟨Function.Embedding.refl _,?_⟩
intro z i
rw [readout_eq J hr hn (b := .inl h) (z := z) (a := .inl h) rfl ⟨rfl,HEq.rfl⟩]
rfl
| inr s =>
rcases ha with rfl | rfl | rfl | rfl
· refine ⟨⟨fun i => .inl (.inl i),fun i j h => Sum.inl.inj (Sum.inl.inj h)⟩,?_⟩
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := (.inl (squareLeft J s))) (Or.inl rfl) (Or.inl ⟨rfl,HEq.rfl⟩)]
rfl
· refine ⟨⟨fun i => .inl (.inr i),fun i j h => Sum.inr.inj (Sum.inl.inj h)⟩,?_⟩
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := (.inl (squareRight J s))) (Or.inr (Or.inl rfl)) (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩))]
rfl
· refine ⟨⟨fun _ => .inr false,by intro i j _; apply Fin.ext; have hi : i.val<1 := i.isLt; have hj : j.val<1 := j.isLt; omega⟩,?_⟩
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := (.inr (squareBottom s))) (Or.inr (Or.inr (Or.inl rfl))) (Or.inr (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩)))]
rfl
· refine ⟨⟨fun _ => .inr true,by intro i j _; apply Fin.ext; have hi : i.val<1 := i.isLt; have hj : j.val<1 := j.isLt; omega⟩,?_⟩
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := (.inr (squareTop s))) (Or.inr (Or.inr (Or.inr rfl))) (Or.inr (Or.inr (Or.inr ⟨rfl,HEq.rfl⟩)))]
rfl
noncomputable def readoutEmbedding (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) :
Fin (readoutDimension J a) ↪ Fin (Fintype.card (Coordinate J b)) :=
(coordinate_lift J hr hn ha).choose.trans (numbering J b).toEmbedding
theorem readoutEmbedding_spec (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) (z : RawValue J b) (i : Fin (readoutDimension J a)) :
encode J b z (readoutEmbedding J hr hn ha i)=readoutEquiv J a (readout J z ha) i := by
simpa only [encode,AddEquiv.coe_mk,Equiv.coe_fn_mk,Function.comp_apply,readoutEmbedding,
Function.Embedding.trans_apply,Equiv.toEmbedding_apply,Equiv.symm_apply_apply] using
(coordinate_lift J hr hn ha).choose_spec z i
theorem readoutDimension_le (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) :
readoutDimension J a ≤ Fintype.card (Coordinate J b) := by
simpa using Fintype.card_le_of_injective _ (readoutEmbedding J hr hn ha).injective
theorem exists_readout_order (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) :
∃ e : Equiv.Perm (Fin (Fintype.card (Coordinate J b))),
∀ i : Fin (readoutDimension J a),
e ⟨i.val,lt_of_lt_of_le i.isLt (readoutDimension_le J hr hn ha)⟩=readoutEmbedding J hr hn ha i := by
exact Equiv.Perm.exists_extending_pair
(fun i : Fin (readoutDimension J a) => (⟨i.val,lt_of_lt_of_le i.isLt (readoutDimension_le J hr hn ha)⟩ :
Fin (Fintype.card (Coordinate J b)))) (readoutEmbedding J hr hn ha)
(fun _ _ h => Fin.ext (congrArg (fun x : Fin (Fintype.card (Coordinate J b)) => x.val) h)) (readoutEmbedding J hr hn ha).injective
end VariableWL.BlockCoordinates
namespace VariableWL.BlockCoordinates
open VariableWL.Affine VariableWL.Blocks Subdivision VariableWL.PrefixParts
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4} [Fintype P] [Fintype E]
(J : ProductImages.Instance r P E)
abbrev Proper (b : Block (n := n) J) :=
Σ c : {c : Block (n := n) J // c≠b}, {a : Readout r n P E // HasReadout J b.val a ∧ HasReadout J c.val.val a}
noncomputable instance (priority := 10) defaultProperNumberings :
(b : Block (n := n) J) → FiniteNumbering (Proper J b) :=
fun b=>defaultFiniteNumbering (Proper J b)
variable [∀ b : Block (n := n) J, FiniteNumbering (Proper J b)]
noncomputable def properNumber (b : Block (n := n) J) :
Proper J b ≃ {c : Fin (Fintype.card (Proper J b)+1) // c.val≠0} where
toFun p := ⟨(enumeration (Proper J b) p).succ,by simp⟩
invFun c := (enumeration (Proper J b)).symm ⟨c.val.val-1,by have := c.val.isLt; have := c.property; omega⟩
left_inv p := by simp
right_inv c := by apply Subtype.ext; apply Fin.ext; simp; have := c.property; omega
noncomputable def channelRoot (b : Block (n := n) J)
(c : Fin (Fintype.card (Proper J b)+1)) : ℕ :=
if h : c.val=0 then 0 else readoutDimension J ((properNumber J b).symm ⟨c,h⟩).2.val
noncomputable def channelOrder (hr : 2 ≤ r) (hn : 0 < n) (b : Block (n := n) J)
(c : Fin (Fintype.card (Proper J b)+1)) : Equiv.Perm (Fin (Fintype.card (Coordinate J b.val))) :=
if h : c.val=0 then Equiv.refl _ else
(exists_readout_order J hr hn ((properNumber J b).symm ⟨c,h⟩).2.property.1).choose
noncomputable def data (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r) (b : Block (n := n) J) : Data where
dimension := Fintype.card (Coordinate J b.val)
channels := Fintype.card (Proper J b)+1
positive := Nat.zero_lt_succ _
root := channelRoot J b
root_le c := by
unfold channelRoot
split_ifs with h
· exact Nat.zero_le _
· exact readoutDimension_le J hr hn ((properNumber J b).symm ⟨c,h⟩).2.property.1
zero_root := by simp [channelRoot]
order := channelOrder J hr hn b
legal ε := {z | LegalValue J marked ε b.val ((encode J b.val).symm z)}
nonempty ε := by
obtain ⟨z,hz⟩ := legal_nonempty J marked ε b.val
exact ⟨encode J b.val z,by simpa using hz⟩
coset ξ hξ z := by
change boundaryMap J b.val ((encode J b.val).symm z) = 0 * inhomogeneity J marked b.val ↔
boundaryMap J b.val ((encode J b.val).symm (z+ξ)) = 1 * inhomogeneity J marked b.val
change boundaryMap J b.val ((encode J b.val).symm ξ) = 1 * inhomogeneity J marked b.val at hξ
rw [map_add,map_add,hξ,zero_mul]
exact add_eq_right.symm
noncomputable def valuationEquiv (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r) (b : Block (n := n) J) (ε : Bit) :
Valuation J marked ε b ≃ (data J hr hn marked b).Valuation ε where
toFun z := ⟨encode J b.val z.val,by
change LegalValue J marked ε b.val ((encode J b.val).symm (encode J b.val z.val))
rw [AddEquiv.symm_apply_apply]
exact z.property⟩
invFun z := ⟨(encode J b.val).symm z.val,z.property⟩
left_inv z := Subtype.ext ((encode J b.val).symm_apply_apply _)
right_inv z := Subtype.ext ((encode J b.val).apply_symm_apply _)
def properSwap : (Σ b : Block (n := n) J, Proper J b) ≃ (Σ b : Block (n := n) J, Proper J b) where
toFun x := ⟨x.2.1.val,⟨x.1,Ne.symm x.2.1.property⟩,x.2.2.val,x.2.2.property.symm⟩
invFun x := ⟨x.2.1.val,⟨x.1,Ne.symm x.2.1.property⟩,x.2.2.val,x.2.2.property.symm⟩
left_inv x := by rfl
right_inv x := by rfl
noncomputable def channelEquiv (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r) :
(Σ b : Block (n := n) J, Proper J b) ≃ Channel (data J hr hn marked) where
toFun x := ⟨x.1,properNumber J x.1 x.2⟩
invFun x := ⟨x.1,(properNumber J x.1).symm x.2⟩
left_inv x := by simp
right_inv x := by
rcases x with ⟨b,c⟩
change (⟨b,properNumber J b ((properNumber J b).symm c)⟩ : Channel (data J hr hn marked))=⟨b,c⟩
exact congrArg (fun d : {c : Fin (Fintype.card (Proper J b)+1) // c.val ≠ 0} =>
(⟨b,d⟩ : Channel (data J hr hn marked))) ((properNumber J b).apply_symm_apply c)
theorem channelRoot_number (b : Block (n := n) J) (p : Proper J b) :
channelRoot J b (properNumber J b p).val=readoutDimension J p.2.val := by
rw [channelRoot,dite_eq_right (properNumber J b p).property]
change readoutDimension J ((properNumber J b).symm (properNumber J b p)).2.val=_
rw [Equiv.symm_apply_apply]
noncomputable def wiring (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r) : Wiring (data J hr hn marked) where
mate := (channelEquiv J hr hn marked).symm.trans ((properSwap J).trans (channelEquiv J hr hn marked))
involutive c := by
change (channelEquiv J hr hn marked) ((properSwap J) ((channelEquiv J hr hn marked).symm
((channelEquiv J hr hn marked) ((properSwap J) ((channelEquiv J hr hn marked).symm c)))))=c
rw [Equiv.symm_apply_apply]
change (channelEquiv J hr hn marked) ((channelEquiv J hr hn marked).symm c)=c
exact Equiv.apply_symm_apply _ _
different c := by
obtain ⟨⟨b,p⟩,rfl⟩ := (channelEquiv J hr hn marked).surjective c
change ((channelEquiv J hr hn marked) ((properSwap J) ((channelEquiv J hr hn marked).symm
((channelEquiv J hr hn marked) ⟨b,p⟩)))).1≠b
rw [Equiv.symm_apply_apply]
exact p.1.property
root_eq c := by
obtain ⟨⟨b,p⟩,rfl⟩ := (channelEquiv J hr hn marked).surjective c
change (data J hr hn marked
((channelEquiv J hr hn marked) ((properSwap J) ((channelEquiv J hr hn marked).symm
((channelEquiv J hr hn marked) ⟨b,p⟩)))).1).root
((channelEquiv J hr hn marked) ((properSwap J) ((channelEquiv J hr hn marked).symm
((channelEquiv J hr hn marked) ⟨b,p⟩)))).2.val = _
rw [Equiv.symm_apply_apply]
change channelRoot J p.1.val
(properNumber J p.1.val ⟨⟨b,Ne.symm p.1.property⟩,p.2.val,p.2.property.symm⟩).val =
channelRoot J b (properNumber J b p).val
rw [channelRoot_number,channelRoot_number]
end VariableWL.BlockCoordinates
namespace VariableWL.BlockCoordinates
open VariableWL.Affine VariableWL.Blocks Subdivision VariableWL.PrefixParts
open VariableWL.PrefixParts.Wiring
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable5} {E : Type uVariable6} (J : ProductImages.Instance r P E)
theorem readout_prefix (hr : 2 ≤ r) (hn : 0 < n) {b : RawBlock r n P E}
{a : Readout r n P E} (ha : HasReadout J b a) (z : RawValue J b) :
pad (Data.truncate (readoutDimension J a)
(encode J b z ∘ (exists_readout_order J hr hn ha).choose)) =
pad (readoutEquiv J a (readout J z ha)) := by
funext j
by_cases hj : j<readoutDimension J a
· have hja : j<Fintype.card (Coordinate J b) := lt_of_lt_of_le hj (readoutDimension_le J hr hn ha)
simp only [pad,dite_eq_left hja,dite_eq_left hj,Data.truncate,ite_eq_left hj,Function.comp_apply]
rw [(exists_readout_order J hr hn ha).choose_spec ⟨j,hj⟩]
exact readoutEmbedding_spec J hr hn ha z ⟨j,hj⟩
· simp only [pad,dite_eq_right hj]
split_ifs with hja
· simp only [Data.truncate,ite_eq_right hj]
· rfl
variable [Fintype P] [Fintype E] [∀ b : Block (n := n) J, FiniteNumbering (Proper J b)]
theorem channelOrder_number (hr : 2 ≤ r) (hn : 0 < n) (b : Block (n := n) J) (p : Proper J b) :
channelOrder J hr hn b (properNumber J b p).val=
(exists_readout_order J hr hn p.2.property.1).choose := by
rw [channelOrder,dite_eq_right (properNumber J b p).property]
change (exists_readout_order J hr hn
((properNumber J b).symm (properNumber J b p)).2.property.1).choose=_
rw [Equiv.symm_apply_apply]
theorem data_prefix (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r) (b : Block (n := n) J)
(p : Proper J b) {ε : Bit} (z : Valuation J marked ε b) :
pad (Data.truncate ((data J hr hn marked b).root (properNumber J b p).val)
(((valuationEquiv J hr hn marked b ε) z).val ∘
(data J hr hn marked b).order (properNumber J b p).val)) =
pad (readoutEquiv J p.2.val (readout J z.val p.2.property.1)) := by
change pad (Data.truncate (channelRoot J b (properNumber J b p).val)
(encode J b.val z.val ∘ channelOrder J hr hn b (properNumber J b p).val))=_
rw [channelRoot_number,channelOrder_number]
exact readout_prefix J hr hn p.2.property.1 z.val
@[simp] theorem mate_channel (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r)
(x : Σ b : Block (n := n) J, Proper J b) :
(wiring J hr hn marked).mate (channelEquiv J hr hn marked x)=
channelEquiv J hr hn marked (properSwap J x) := by
change (channelEquiv J hr hn marked) ((properSwap J)
((channelEquiv J hr hn marked).symm ((channelEquiv J hr hn marked) x)))=_
rw [Equiv.symm_apply_apply]
noncomputable def encodeList (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r)
(ξ : ∀ b : Block (n := n) J, Valuation J marked 1 b) :
∀ b, (data J hr hn marked b).Valuation 1 := fun b => valuationEquiv J hr hn marked b 1 (ξ b)
end VariableWL.BlockCoordinates
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_SubcubicGame
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.Subcubic
open VariableWL.Affine VariableWL.Blocks VariableWL.PrefixParts VariableWL.PrefixParts.Wiring
open VariableWL.BlockCoordinates
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} [Fintype P] [Fintype E]
(J : ProductImages.Instance r P E) [∀ b : Block (n := n) J, FiniteNumbering (Proper J b)] [FiniteNumbering (Block (n := n) J)] (hr : 2 ≤ r) (hn : 0 < n) (marked : Fin r)
[FiniteNumbering (SortTag (data (n := n) J hr hn marked))]
noncomputable abbrev graph (ε : Bit) := uncolored (data (n := n) J hr hn marked) (wiring J hr hn marked) ε
noncomputable abbrev finiteGraph (ε : Bit) := TypedGame.numbered (graph J hr hn marked ε)
end VariableWL.Subcubic
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Circuit
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11 uVariable12 uVariable13 uVariable14
namespace VariableWL.Circuit
attribute [local instance] Classical.propDecidable
open VariableWL.ScalarImages
variable (S : Type uVariable1) (A : Type uVariable2) (E : Type uVariable3)
abbrev Gate := S ⊕ A
abbrev Port := S ⊕ (A × Bool)
abbrev target : Port S A → Gate S A
| .inl s => .inl s
| .inr (a,_) => .inr a
abbrev Value : Gate S A → Type
| .inl _ => Bit
| .inr _ => Pair
def output : (g : Gate S A) → Value S A g → Bit
| .inl _ => id
| .inr _ => sum
def input : (p : Port S A) → Value S A (target S A p) → Bit
| .inl _ => id
| .inr (_,false) => Prod.fst
| .inr (_,true) => Prod.snd
structure System where
source : E → Gate S A
destination : E → Port S A
seeds : Set S
tests : Set S
terminal : ∀ s ∈ tests, ∀ e, source e ≠ .inl s
variable {S A E}
namespace System
variable (C : System S A E)
inductive TrueGate : Gate S A → Prop
| seed (s : S) (hs : s ∈ C.seeds) : TrueGate (.inl s)
| scalar (e : E) (s : S) (he : C.destination e=.inl s)
(hs : TrueGate (C.source e)) : TrueGate (.inl s)
| and (a : A) (e f : E) (he : C.destination e=.inr (a,false))
(hf : C.destination f=.inr (a,true))
(hs : TrueGate (C.source e)) (ht : TrueGate (C.source f)) : TrueGate (.inr a)
def TruePort (p : Port S A) : Prop := ∃ e, C.destination e=p ∧ C.TrueGate (C.source e)
theorem true_scalar_iff (s : S) : C.TrueGate (.inl s) ↔ s ∈ C.seeds ∨ C.TruePort (.inl s) := by
constructor
· intro h
cases h with
| seed s hs => exact Or.inl hs
| scalar e s he hs => exact Or.inr ⟨e,he,hs⟩
· rintro (hs | ⟨e,he,hs⟩)
· exact .seed _ hs
· exact .scalar e s he hs
theorem true_and_iff (a : A) : C.TrueGate (.inr a) ↔
C.TruePort (.inr (a,false)) ∧ C.TruePort (.inr (a,true)) := by
constructor
· intro h
cases h with
| and a e f he hf hs ht => exact ⟨⟨e,he,hs⟩,⟨f,hf,ht⟩⟩
· rintro ⟨⟨e,he,hs⟩,⟨f,hf,ht⟩⟩
exact .and a e f he hf hs ht
structure Witness where
gates : ∀ g : Gate S A, Set (Value S A g)
buffers : E → Set Pair
gates_nonempty : ∀ g, (gates g).Nonempty
buffers_nonempty : ∀ e, (buffers e).Nonempty
first : ∀ e, output S A (C.source e) '' gates (C.source e)=Prod.fst '' buffers e
second : ∀ e, output S A (C.source e) '' gates (C.source e)=Prod.snd '' buffers e
last : ∀ e, sum '' buffers e=input S A (C.destination e) '' gates (target S A (C.destination e))
seed : ∀ s ∈ C.seeds, gates (.inl s)={0}
test : ∀ s ∈ C.tests, gates (.inl s)={1}
variable (hfalse : ∀ s ∈ C.tests, ¬ C.TrueGate (.inl s))
noncomputable def gateSets : (g : Gate S A) → Set (Value S A g)
| .inl s => if s ∈ C.tests then {1} else {x | C.TrueGate (.inl s) → x=0}
| .inr a => andWitness (C.TruePort (.inr (a,false))) (C.TruePort (.inr (a,true)))
theorem gateSets_nonempty (g : Gate S A) : (C.gateSets g).Nonempty := by
classical
cases g with
| inl s =>
by_cases hs : s ∈ C.tests
· exact ⟨1,by simp [gateSets,hs]⟩
· exact ⟨0,by simp [gateSets,hs]⟩
| inr a => exact andWitness_nonempty _ _
theorem gateSets_output_scalar {s : S} (hs : s ∉ C.tests) :
output S A (.inl s) '' C.gateSets (.inl s)={x | C.TrueGate (.inl s) → x=0} := by
simp [output,gateSets,hs]
theorem gateSets_output_and (a : A) :
output S A (.inr a) '' C.gateSets (.inr a)={x | C.TrueGate (.inr a) → x=0} := by
rw [output,gateSets,andWitness_sum]
simp only [C.true_and_iff]
theorem gateSets_source (e : E) :
output S A (C.source e) '' C.gateSets (C.source e)={x | C.TrueGate (C.source e) → x=0} := by
cases h : C.source e with
| inl s => exact C.gateSets_output_scalar (fun hs => C.terminal s hs e h)
| inr a => exact C.gateSets_output_and a
include hfalse in
theorem gateSets_input_true {p : Port S A} (hp : C.TruePort p) :
input S A p '' C.gateSets (target S A p)={0} := by
classical
rcases p with s | ⟨a,b⟩
· have ht : C.TrueGate (.inl s) := (C.true_scalar_iff s).mpr (Or.inr hp)
have hnt : s ∉ C.tests := fun hs => hfalse s hs ht
simp [input,target,gateSets,hnt,ht]
· cases b
· change Prod.fst '' andWitness _ _={0}
rw [andWitness_fst]
ext x
simp [hp]
· change Prod.snd '' andWitness _ _={0}
rw [andWitness_snd]
ext x
simp [hp]
noncomputable def bufferSets (e : E) : Set Pair :=
if C.TrueGate (C.source e) then {(0,0)}
else buffer (input S A (C.destination e) '' C.gateSets (target S A (C.destination e)))
theorem bufferSets_nonempty (e : E) : (C.bufferSets e).Nonempty := by
classical
by_cases hs : C.TrueGate (C.source e)
· simp [bufferSets,hs]
· simpa only [bufferSets,ite_eq_right hs] using
buffer_nonempty ((C.gateSets_nonempty _).image _)
theorem bufferSets_first (e : E) :
output S A (C.source e) '' C.gateSets (C.source e)=Prod.fst '' C.bufferSets e := by
classical
rw [C.gateSets_source]
by_cases hs : C.TrueGate (C.source e)
· simp [bufferSets,hs]
· simp only [bufferSets,hs,false_implies,Set.ofPred_true]
exact (buffer_image_fst ((C.gateSets_nonempty _).image _)).symm
theorem bufferSets_second (e : E) :
output S A (C.source e) '' C.gateSets (C.source e)=Prod.snd '' C.bufferSets e := by
classical
rw [C.gateSets_source]
by_cases hs : C.TrueGate (C.source e)
· simp [bufferSets,hs]
· simp only [bufferSets,hs,false_implies,Set.ofPred_true]
exact (buffer_image_snd ((C.gateSets_nonempty _).image _)).symm
include hfalse in
theorem bufferSets_last (e : E) :
sum '' C.bufferSets e=input S A (C.destination e) '' C.gateSets (target S A (C.destination e)) := by
classical
by_cases hs : C.TrueGate (C.source e)
· rw [C.gateSets_input_true hfalse ⟨e,rfl,hs⟩]
simp [bufferSets,hs,sum]
· simpa only [bufferSets,ite_eq_right hs] using buffer_image_sum _
noncomputable def witness : C.Witness where
gates := C.gateSets
buffers := C.bufferSets
gates_nonempty := C.gateSets_nonempty
buffers_nonempty := C.bufferSets_nonempty
first := C.bufferSets_first
second := C.bufferSets_second
last := C.bufferSets_last hfalse
seed s hs := by
have ht : C.TrueGate (.inl s) := .seed s hs
have hnt : s ∉ C.tests := fun he => hfalse s he ht
simp [gateSets,hnt,ht]
test s hs := by simp [gateSets,hs]
end System
end VariableWL.Circuit
namespace VariableWL.Circuit
open VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {S : Type uVariable4} {A : Type uVariable5}
abbrev dimension : Gate S A → ℕ
| .inl _ => 1
| .inr _ => 2
def scalarVector (x : Bit) : Vec 1 := fun _ => x
def pairVector (x : ScalarImages.Pair) : Vec 2 := fun i => if i.val=0 then x.1 else x.2
def scalarValue (x : Vec 1) : Bit := x 0
def pairValue (x : Vec 2) : ScalarImages.Pair := (x 0,x 1)
@[simp] theorem scalarValue_vector (x : Bit) : scalarValue (scalarVector x)=x := rfl
@[simp] theorem pairValue_vector (x : ScalarImages.Pair) : pairValue (pairVector x)=x := by
simp [pairValue,pairVector]
@[simp] theorem scalarVector_value (x : Vec 1) : scalarVector (scalarValue x)=x := by
funext i
exact congrArg x (Subsingleton.elim _ _)
@[simp] theorem pairVector_value (x : Vec 2) : pairVector (pairValue x)=x := by
funext i
fin_cases i <;> rfl
def outputLinear (g : Gate S A) : Vec (dimension g) →ₗ[Bit] Bit :=
match g with
| .inl _ => LinearMap.proj 0
| .inr _ => (LinearMap.proj (0 : Fin 2) : Vec 2 →ₗ[Bit] Bit) + LinearMap.proj 1
def inputLinear (p : Port S A) : Vec (dimension (target S A p)) →ₗ[Bit] Bit :=
match p with
| .inl _ => LinearMap.proj 0
| .inr (_,false) => LinearMap.proj 0
| .inr (_,true) => LinearMap.proj 1
def gateAt {X : Type uVariable6} : Gate S A → X → Gate (S × X) (A × X)
| .inl s,x => .inl (s,x)
| .inr a,x => .inr (a,x)
def portAt {X : Type uVariable7} : Port S A → X → Port (S × X) (A × X)
| .inl s,x => .inl (s,x)
| .inr (a,b),x => .inr ((a,x),b)
@[simp] theorem target_portAt {X : Type uVariable8} (p : Port S A) (x : X) :
target (S × X) (A × X) (portAt p x)=gateAt (target S A p) x := by
cases p <;> rfl
structure Description (r : ℕ) (S : Type uVariable9) (A : Type uVariable10) (E : Type uVariable11) (R : Type uVariable12) where
source : E → Gate S A
destination : E → Port S A
domain : E → Fin r → Finset Bool
domain_nonempty : ∀ e i, (domain e i).Nonempty
map : E → Fin r → Bool → Bool
map_injective : ∀ e i, Set.InjOn (map e i) (domain e i)
requestGate : R → S
requestTest : R → Bool
requestDomain : R → Fin r → Finset Bool
request_nonempty : ∀ b i, (requestDomain b i).Nonempty
namespace Description
open ProductImages.Instance
variable {r : ℕ} {E : Type uVariable13} {R : Type uVariable14} (D : Description r S A E R)
def Allowed (e : E) (a : Address r) : Prop := ∀ i, a i ∈ D.domain e i
def RequestAllowed (b : R) (a : Address r) : Prop := ∀ i, a i ∈ D.requestDomain b i
def mapAddress (e : E) (a : Address r) : Address r := fun i => D.map e i (a i)
abbrev ExpandedEdges := Σ e, {a : Address r // D.Allowed e a}
def requests (v : Bool) : Set (S × Address r) :=
{x | ∃ b, D.requestGate b=x.1 ∧ D.requestTest b=v ∧ D.RequestAllowed b x.2}
def Terminal : Prop := ∀ s a, (s,a) ∈ D.requests true →
∀ e z, D.Allowed e z → gateAt (D.source e) z ≠ .inl (s,a)
abbrev expanded (h : D.Terminal) : System (S × Address r) (A × Address r) D.ExpandedEdges where
source x := gateAt (D.source x.1) x.2.val
destination x := portAt (D.destination x.1) (D.mapAddress x.1 x.2.val)
seeds := D.requests false
tests := D.requests true
terminal := fun ⟨s,a⟩ hs ⟨e,z⟩ => h s a hs e z.val z.property
abbrev Real := Gate S A ⊕ (E ⊕ Unit)
abbrev Comparison := (E ⊕ (E ⊕ E)) ⊕ R
abbrev realDimension : Real (S := S) (A := A) (E := E) → ℕ
| .inl g => dimension g
| .inr (.inl _) => 2
| .inr (.inr _) => 1
abbrev comparisonSource : Comparison (E := E) (R := R) → Real (S := S) (A := A) (E := E)
| .inl (.inl e) => .inl (D.source e)
| .inl (.inr (.inl e)) => .inl (D.source e)
| .inl (.inr (.inr e)) => .inr (.inl e)
| .inr b => .inl (.inl (D.requestGate b))
abbrev comparisonTarget : Comparison (E := E) (R := R) → Real (S := S) (A := A) (E := E)
| .inl (.inl e) => .inr (.inl e)
| .inl (.inr (.inl e)) => .inr (.inl e)
| .inl (.inr (.inr e)) => .inl (target S A (D.destination e))
| .inr _ => .inr (.inr ())
abbrev consistency : ProductImages.Instance r
(Real (S := S) (A := A) (E := E)) (Comparison (E := E) (R := R)) where
dimension := realDimension
dimension_one_or_two p := by
rcases p with (s | a) | (e | u) <;> simp [realDimension,dimension]
source := D.comparisonSource
target := D.comparisonTarget
domain c := match c with
| .inl (.inl e) => D.domain e
| .inl (.inr (.inl e)) => D.domain e
| .inl (.inr (.inr e)) => D.domain e
| .inr b => D.requestDomain b
domain_nonempty c i := by
rcases c with (e | (e | e)) | b
· exact D.domain_nonempty e i
· exact D.domain_nonempty e i
· exact D.domain_nonempty e i
· exact D.request_nonempty b i
map c := match c with
| .inl (.inl _) => fun _ => id
| .inl (.inr (.inl _)) => fun _ => id
| .inl (.inr (.inr e)) => D.map e
| .inr _ => fun _ => id
map_injective c i := by
rcases c with (e | (e | e)) | b
· exact Function.injective_id.injOn
· exact Function.injective_id.injOn
· exact D.map_injective e i
· exact Function.injective_id.injOn
linearLeft c := match c with
| .inl (.inl e) => outputLinear (D.source e)
| .inl (.inr (.inl e)) => outputLinear (D.source e)
| .inl (.inr (.inr _)) => (LinearMap.proj (0 : Fin 2) : Vec 2 →ₗ[Bit] Bit) + LinearMap.proj 1
| .inr _ => LinearMap.proj 0
linearRight c := match c with
| .inl (.inl _) => LinearMap.proj 0
| .inl (.inr (.inl _)) => LinearMap.proj 1
| .inl (.inr (.inr e)) => inputLinear (D.destination e)
| .inr _ => 0
constantLeft _ := 0
constantRight c := match c with
| .inl _ => 0
| .inr b => if D.requestTest b then 1 else 0
end Description
end VariableWL.Circuit
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_CellularCircuit
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10
namespace VariableWL.Circuit
open VariableWL.Affine ProductImages.Instance
attribute [local instance] Classical.propDecidable
variable {S : Type uVariable1} {A : Type uVariable2} {r : ℕ}
noncomputable def decodeGates (Q : ∀ g : Gate S A, Address r → Set (Vec (dimension g))) :
∀ g : Gate (S × Address r) (A × Address r), Set (Value (S × Address r) (A × Address r) g)
| .inl (s,a) => scalarValue '' Q (.inl s) a
| .inr (b,a) => pairValue '' Q (.inr b) a
theorem decodeGates_nonempty (Q : ∀ g : Gate S A, Address r → Set (Vec (dimension g)))
(h : ∀ g a, (Q g a).Nonempty) (g : Gate (S × Address r) (A × Address r)) :
(decodeGates Q g).Nonempty := by
rcases g with ⟨s,a⟩ | ⟨b,a⟩
· exact (h (.inl s) a).image scalarValue
· exact (h (.inr b) a).image pairValue
theorem output_decode (Q : ∀ g : Gate S A, Address r → Set (Vec (dimension g)))
(g : Gate S A) (a : Address r) :
output (S × Address r) (A × Address r) (gateAt g a) '' decodeGates Q (gateAt g a)=
outputLinear g '' Q g a := by
cases g <;> simp only [gateAt,decodeGates,Set.image_image] <;> rfl
theorem input_decode (Q : ∀ g : Gate S A, Address r → Set (Vec (dimension g)))
(p : Port S A) (a : Address r) :
input (S × Address r) (A × Address r) (portAt p a) ''
decodeGates Q (target _ _ (portAt p a))=inputLinear p '' Q (target _ _ p) a := by
rcases p with s | ⟨b,v⟩
· simp only [portAt,target,decodeGates,Set.image_image]
rfl
· cases v <;> simp only [portAt,target,decodeGates,Set.image_image] <;> rfl
noncomputable def encodeGates
(Q : ∀ g : Gate (S × Address r) (A × Address r), Set (Value (S × Address r) (A × Address r) g)) :
∀ g : Gate S A, Address r → Set (Vec (dimension g))
| .inl s,a => scalarVector '' Q (.inl (s,a))
| .inr b,a => pairVector '' Q (.inr (b,a))
theorem encodeGates_nonempty
(Q : ∀ g : Gate (S × Address r) (A × Address r), Set (Value (S × Address r) (A × Address r) g))
(h : ∀ g, (Q g).Nonempty) (g : Gate S A) (a : Address r) : (encodeGates Q g a).Nonempty := by
cases g with
| inl s => exact (h (.inl (s,a))).image scalarVector
| inr b => exact (h (.inr (b,a))).image pairVector
theorem output_encode
(Q : ∀ g : Gate (S × Address r) (A × Address r), Set (Value (S × Address r) (A × Address r) g))
(g : Gate S A) (a : Address r) :
outputLinear g '' encodeGates Q g a=
output (S × Address r) (A × Address r) (gateAt g a) '' Q (gateAt g a) := by
cases g <;> simp only [encodeGates,Set.image_image] <;> rfl
theorem input_encode
(Q : ∀ g : Gate (S × Address r) (A × Address r), Set (Value (S × Address r) (A × Address r) g))
(p : Port S A) (a : Address r) :
inputLinear p '' encodeGates Q (target _ _ p) a=
input (S × Address r) (A × Address r) (portAt p a) '' Q (target _ _ (portAt p a)) := by
rcases p with s | ⟨b,v⟩
· simp only [inputLinear,target,encodeGates,Set.image_image]
rfl
· cases v <;> simp only [inputLinear,target,encodeGates,Set.image_image] <;> rfl
theorem const_image {X : Type uVariable3} {Y : Type uVariable4} (Q : Set X) (hq : Q.Nonempty) (y : Y) :
(fun _ : X => y) '' Q={y} := by
ext z
simp only [Set.mem_image,Set.mem_singleton_iff]
exact ⟨fun ⟨_,_,he⟩ => he.symm,fun he => by subst z; obtain ⟨x,hx⟩ := hq; exact ⟨x,hx,rfl⟩⟩
namespace Description
variable {E : Type uVariable5} {R : Type uVariable6} (D : Description r S A E R)
noncomputable def decodeWitness (h : D.Terminal) (Q : D.consistency.Witness) :
(D.expanded h).Witness where
gates := decodeGates (fun g a => Q.values (.inl g) a)
buffers x := pairValue '' Q.values (.inr (.inl x.1)) x.2.val
gates_nonempty := decodeGates_nonempty _ (fun g a => Q.nonempty (.inl g) a)
buffers_nonempty x := (Q.nonempty (.inr (.inl x.1)) x.2.val).image _
first x := by
change output _ _ (gateAt (D.source x.1) x.2.val) '' _ = _
rw [output_decode]
have hz := Q.images (.inl (.inl x.1)) x.2.val x.2.property
change (fun v => outputLinear (D.source x.1) v+0) '' Q.values (.inl (D.source x.1)) x.2.val=
(fun v : Vec 2 => v 0+0) '' Q.values (.inr (.inl x.1)) x.2.val at hz
simpa only [add_zero,Set.image_image,Function.comp_def,pairValue] using hz
second x := by
change output _ _ (gateAt (D.source x.1) x.2.val) '' _ = _
rw [output_decode]
have hz := Q.images (.inl (.inr (.inl x.1))) x.2.val x.2.property
change (fun v => outputLinear (D.source x.1) v+0) '' Q.values (.inl (D.source x.1)) x.2.val=
(fun v : Vec 2 => v 1+0) '' Q.values (.inr (.inl x.1)) x.2.val at hz
simpa only [add_zero,Set.image_image,Function.comp_def,pairValue] using hz
last x := by
change ScalarImages.sum '' _=input _ _ (portAt (D.destination x.1) (D.mapAddress x.1 x.2.val)) '' _
rw [input_decode]
have hz := Q.images (.inl (.inr (.inr x.1))) x.2.val x.2.property
change (fun v : Vec 2 => (v 0+v 1)+0) '' Q.values (.inr (.inl x.1)) x.2.val=
(fun v => inputLinear (D.destination x.1) v+0) ''
Q.values (.inl (target _ _ (D.destination x.1))) (D.mapAddress x.1 x.2.val) at hz
simpa only [add_zero,Set.image_image,Function.comp_def,pairValue,ScalarImages.sum] using hz
seed s hs := by
obtain ⟨b,hb,hv,ha⟩ := hs
have hz := Q.images (.inr b) s.2 ha
change (fun v : Vec 1 => v 0+0) '' Q.values (.inl (.inl (D.requestGate b))) s.2=
(fun _ : Vec 1 => (0 : Bit)+(if D.requestTest b then (1 : Bit) else 0)) '' Q.values (.inr (.inr ())) s.2 at hz
simp only [add_zero,hv,Bool.false_eq_true,ite_false] at hz
have hc := const_image (Q.values (.inr (.inr ())) s.2) (Q.nonempty _ _) (0 : Bit)
have heq := congrArg (fun t : S => scalarValue '' Q.values (.inl (.inl t)) s.2) hb
exact heq.symm.trans (hz.trans hc)
test s hs := by
obtain ⟨b,hb,hv,ha⟩ := hs
have hz := Q.images (.inr b) s.2 ha
change (fun v : Vec 1 => v 0+0) '' Q.values (.inl (.inl (D.requestGate b))) s.2=
(fun _ : Vec 1 => (0 : Bit)+(if D.requestTest b then (1 : Bit) else 0)) '' Q.values (.inr (.inr ())) s.2 at hz
simp only [add_zero,zero_add,hv,ite_true] at hz
have hc := const_image (Q.values (.inr (.inr ())) s.2) (Q.nonempty _ _) (1 : Bit)
have heq := congrArg (fun t : S => scalarValue '' Q.values (.inl (.inl t)) s.2) hb
exact heq.symm.trans (hz.trans hc)
noncomputable def encodedValues (h : D.Terminal) (Q : (D.expanded h).Witness) :
∀ p : (Real (S := S) (A := A) (E := E)), Address r → Set (Vec (realDimension p))
| .inl g,a => encodeGates Q.gates g a
| .inr (.inl e),a => if ha : D.Allowed e a then pairVector '' Q.buffers ⟨e,⟨a,ha⟩⟩ else Set.univ
| .inr (.inr _),_ => Set.univ
theorem encodedValues_nonempty (h : D.Terminal) (Q : (D.expanded h).Witness)
(p : (Real (S := S) (A := A) (E := E))) (a : Address r) : (D.encodedValues h Q p a).Nonempty := by
rcases p with g | (e | u)
· exact encodeGates_nonempty Q.gates Q.gates_nonempty g a
· dsimp only [encodedValues]
split_ifs with ha
· exact (Q.buffers_nonempty _).image _
· exact Set.univ_nonempty
· exact Set.univ_nonempty
noncomputable def encodeWitness (h : D.Terminal) (Q : (D.expanded h).Witness) :
D.consistency.Witness where
values := D.encodedValues h Q
nonempty := D.encodedValues_nonempty h Q
images c a ha := by
rcases c with (e | (e | e)) | b
· change (fun v => outputLinear (D.source e) v+0) '' encodeGates Q.gates (D.source e) a=
(fun v : Vec 2 => v 0+0) '' D.encodedValues h Q (.inr (.inl e)) a
simp only [add_zero]
have hea : D.Allowed e a := ha
rw [encodedValues,dite_eq_left hea,output_encode,Set.image_image]
exact Q.first ⟨e,⟨a,hea⟩⟩
· change (fun v => outputLinear (D.source e) v+0) '' encodeGates Q.gates (D.source e) a=
(fun v : Vec 2 => v 1+0) '' D.encodedValues h Q (.inr (.inl e)) a
simp only [add_zero]
have hea : D.Allowed e a := ha
rw [encodedValues,dite_eq_left hea,output_encode,Set.image_image]
exact Q.second ⟨e,⟨a,hea⟩⟩
· change (fun v : Vec 2 => (v 0+v 1)+0) '' D.encodedValues h Q (.inr (.inl e)) a=
(fun v => inputLinear (D.destination e) v+0) '' encodeGates Q.gates (target _ _ (D.destination e)) (D.mapAddress e a)
simp only [add_zero]
have hea : D.Allowed e a := ha
rw [encodedValues,dite_eq_left hea,input_encode,Set.image_image]
exact Q.last ⟨e,⟨a,hea⟩⟩
· have hea : D.RequestAllowed b a := ha
change (fun v : Vec 1 => v 0+0) '' (scalarVector '' Q.gates (.inl (D.requestGate b,a)))=
(fun _ : Vec 1 => 0+(if D.requestTest b then (1 : Bit) else 0)) '' Set.univ
simp only [add_zero,zero_add]
rw [const_image _ Set.univ_nonempty,Set.image_image]
change id '' Q.gates (.inl (D.requestGate b,a))={if D.requestTest b then (1 : Bit) else 0}
rw [Set.image_id]
cases hv : D.requestTest b
· simpa only [hv,Bool.false_eq_true,ite_false] using
Q.seed (D.requestGate b,a) ⟨b,rfl,hv,hea⟩
· simpa only [hv,ite_true] using Q.test (D.requestGate b,a) ⟨b,rfl,hv,hea⟩
end Description
end VariableWL.Circuit
namespace VariableWL.Circuit.Cellular
attribute [local instance] Classical.propDecidable
variable (L : Type uVariable7) (J : Type uVariable8) (N : ℕ)
abbrev Triple := L × L × L
variable {L J N}
structure Data (L : Type uVariable9) (J : Type uVariable10) where
rule : L → L → L → L
previous : J → J
next : J → J
initial : J → L
accepting : Set L
namespace Data
variable (D : Data L J)
def state : ℕ → J → L
| 0 => D.initial
| t+1 => fun j => D.rule (state t (D.previous j)) (state t j) (state t (D.next j))
end Data
end VariableWL.Circuit.Cellular
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Binary
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.Binary
attribute [local instance] Classical.propDecidable
abbrev Digits (d : ℕ) := Fin d → Bool
def number : {d : ℕ} → Digits d → ℕ
| 0,_ => 0
| d+1,x => (x 0).toNat+2*number (fun i : Fin d => x i.succ)
theorem number_lt {d : ℕ} (x : Digits d) : number x<2^d := by
induction d with
| zero => simp [number]
| succ d ih =>
have ht := ih (fun i : Fin d => x i.succ)
have hb : (x 0).toNat ≤ 1 := by cases x 0 <;> decide
simp only [number,pow_succ]
omega
theorem number_injective {d : ℕ} : Function.Injective (@number d) := by
induction d with
| zero => intro x y _; exact Subsingleton.elim _ _
| succ d ih =>
intro x y he
have hb : x 0=y 0 := by
dsimp only [number] at he
cases hx : x 0 <;> cases hy : y 0 <;> simp_all only [Bool.toNat_false,Bool.toNat_true] <;> omega
have ht : (fun i : Fin d => x i.succ)=(fun i : Fin d => y i.succ) := by
apply ih
dsimp only [number] at he
rw [hb] at he
omega
funext i
exact Fin.cases hb (fun j => congrFun ht j) i
@[simp] theorem number_false (d : ℕ) : number (fun _ : Fin d => false)=0 := by
induction d with
| zero => rfl
| succ d ih => simp [number,ih]
@[simp] theorem number_true (d : ℕ) : number (fun _ : Fin d => true)+1=2^d := by
induction d with
| zero => rfl
| succ d ih => simp only [number,Bool.toNat_true,pow_succ]; omega
noncomputable def equivalence (d : ℕ) : Digits d ≃ Fin (2^d) :=
Equiv.ofBijective (fun x => ⟨number x,number_lt x⟩)
((Fintype.bijective_iff_injective_and_card _).mpr ⟨fun x y h => number_injective (congrArg Fin.val h), by simp⟩)
@[simp] theorem equivalence_val {d : ℕ} (x : Digits d) : (equivalence d x).val=number x := rfl
def domain {d : ℕ} (bit : Bool) (h i : Fin d) : Finset Bool :=
if i<h then {bit} else if i=h then {!bit} else Finset.univ
def table {d : ℕ} (h i : Fin d) (x : Bool) : Bool := if i≤h then !x else x
def Allowed {d : ℕ} (bit : Bool) (h : Fin d) (x : Digits d) : Prop := ∀ i, x i ∈ domain bit h i
def flip {d : ℕ} (h : Fin d) (x : Digits d) : Digits d := fun i => table h i (x i)
theorem domain_nonempty {d : ℕ} (bit : Bool) (h i : Fin d) : (domain bit h i).Nonempty := by
unfold domain
split_ifs <;> simp
theorem table_injective {d : ℕ} (h i : Fin d) : Function.Injective (table h i) := by
intro x y he
unfold table at he
split_ifs at he with h
· exact Bool.not_injective he
· exact he
theorem allowed_iff {d : ℕ} (bit : Bool) (h : Fin d) (x : Digits d) :
Allowed bit h x ↔ x h = !bit ∧ ∀ i, i<h → x i=bit := by
constructor
· intro hx
exact ⟨by simpa [domain] using hx h,fun i hi => by simpa [domain,hi] using hx i⟩
· rintro ⟨hh,hlt⟩ i
by_cases hi : i<h
· simp [domain,hi,hlt i hi]
· by_cases he : i=h
· subst i
simp [domain,hh]
· simp [domain,hi,he]
theorem number_flip {d : ℕ} (h : Fin d) (x : Digits d) (hx : Allowed true h x) :
number (flip h x)=number x+1 := by
induction d with
| zero => exact Fin.elim0 h
| succ d ih =>
cases h using Fin.cases with
| zero =>
have hh : x 0=false := (allowed_iff true 0 x).mp hx |>.1
have ht : (fun i : Fin d => flip 0 x i.succ)=(fun i : Fin d => x i.succ) := by
funext i
simp [flip,table]
simp only [number]
rw [ht]
simp [flip,table,hh,Nat.add_comm]
| succ h =>
obtain ⟨hh,hlt⟩ := (allowed_iff true h.succ x).mp hx
have hz : x 0=true := hlt 0 (Fin.succ_pos h)
have htail : Allowed true h (fun i : Fin d => x i.succ) :=
(allowed_iff true h _).mpr ⟨hh,fun i hi => hlt i.succ (Fin.succ_lt_succ_iff.mpr hi)⟩
have ht : (fun i : Fin d => flip h.succ x i.succ)=flip h (fun i : Fin d => x i.succ) := by
funext i
simp [flip,table]
have he := ih h (fun i : Fin d => x i.succ) htail
simp only [number]
rw [ht]
simp only [flip,table,Fin.zero_le,ite_eq_left,hz,Bool.not_true,Bool.toNat_false,Bool.toNat_true,zero_add]
omega
def cyclicDomain {d : ℕ} (bit : Bool) (h : Option (Fin d)) (i : Fin d) : Finset Bool :=
match h with | none => {bit} | some h => domain bit h i
def cyclicTable {d : ℕ} (h : Option (Fin d)) (i : Fin d) (x : Bool) : Bool :=
match h with | none => !x | some h => table h i x
def CyclicAllowed {d : ℕ} (bit : Bool) (h : Option (Fin d)) (x : Digits d) : Prop :=
∀ i, x i ∈ cyclicDomain bit h i
def cyclicFlip {d : ℕ} (h : Option (Fin d)) (x : Digits d) : Digits d := fun i => cyclicTable h i (x i)
theorem cyclicDomain_nonempty {d : ℕ} (bit : Bool) (h : Option (Fin d)) (i : Fin d) :
(cyclicDomain bit h i).Nonempty := by
cases h with
| none => exact Finset.singleton_nonempty _
| some h => exact domain_nonempty bit h i
theorem cyclicTable_injective {d : ℕ} (h : Option (Fin d)) (i : Fin d) :
Function.Injective (cyclicTable h i) := by
cases h with
| none => exact Bool.not_injective
| some h => exact table_injective h i
end VariableWL.Binary
namespace VariableWL.Binary
attribute [local instance] Classical.propDecidable
def GreaterAt {d : ℕ} (μ x : Digits d) (h : Fin d) : Prop :=
μ h=false ∧ x h=true ∧ ∀ i, h < i → x i=μ i
def thresholdDomain {d : ℕ} (μ : Digits d) (h : Option {h : Fin d // μ h=false}) (i : Fin d) : Finset Bool :=
match h with
| none => {μ i}
| some h => if h.val < i then {μ i} else if i=h.val then {true} else Finset.univ
def ThresholdAllowed {d : ℕ} (μ : Digits d) (h : Option {h : Fin d // μ h=false}) (x : Digits d) : Prop :=
∀ i, x i ∈ thresholdDomain μ h i
theorem thresholdDomain_nonempty {d : ℕ} (μ : Digits d) (h : Option {h : Fin d // μ h=false}) (i : Fin d) :
(thresholdDomain μ h i).Nonempty := by
cases h with
| none => exact Finset.singleton_nonempty _
| some h => simp only [thresholdDomain]; split_ifs <;> simp
end VariableWL.Binary
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_ProductCellular
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9
namespace VariableWL.Circuit.ProductCellular
open Binary ProductImages.Instance
attribute [local instance] Classical.propDecidable
variable {L : Type uVariable1} {d m : ℕ}
abbrev Address (d : ℕ) := Fin (d+d) → Bool
def timeBits (x : Address d) : Digits d := fun i => x (i.castAdd d)
def positionBits (x : Address d) : Digits d := fun i => x (Fin.natAdd d i)
def join {α : Type uVariable2} (x y : Fin d → α) : Fin (d+d) → α := Fin.addCases x y
@[simp] theorem join_left {α : Type uVariable3} (x y : Fin d → α) (i : Fin d) : join x y (i.castAdd d)=x i :=
Fin.addCases_left i
@[simp] theorem join_right {α : Type uVariable4} (x y : Fin d → α) (i : Fin d) : join x y (Fin.natAdd d i)=y i :=
Fin.addCases_right i
@[simp] theorem join_addNat {α : Type uVariable5} (x y : Fin d → α) (i : Fin d) : join x y (i.addNat d)=y i := by
rw [← Fin.natAdd_eq_addNat]
exact join_right x y i
@[simp] theorem time_join (x y : Digits d) : timeBits (join x y)=x := by funext i; simp [timeBits]
@[simp] theorem position_join (x y : Digits d) : positionBits (join x y)=y := by funext i; simp [positionBits]
@[simp] theorem join_parts (x : Address d) : join (timeBits x) (positionBits x)=x := by
funext i
refine Fin.addCases (fun j => ?_) (fun j => ?_) i <;> simp [timeBits,positionBits]
theorem all_parts {P : Fin (d+d) → Prop} : (∀ i, P i) ↔
(∀ i : Fin d, P (i.castAdd d)) ∧ (∀ i : Fin d, P (Fin.natAdd d i)) := Fin.forall_fin_add P
abbrev Kind (d : ℕ) := (Fin d × Option (Fin d)) ⊕ (Fin d ⊕ ((Fin d × Option (Fin d)) ⊕ Bool))
abbrev Edge (L : Type uVariable6) (d : ℕ) := Cellular.Triple L × Kind d
def left (h : Fin d) (j : Option (Fin d)) : Kind d := .inl (h,j)
def center (h : Fin d) : Kind d := .inr (.inl h)
def right (h : Fin d) (j : Option (Fin d)) : Kind d := .inr (.inr (.inl (h,j)))
def same (v : Bool) : Kind d := .inr (.inr (.inr v))
def timeDomain : Kind d → Fin d → Finset Bool
| .inl (h,_) => Binary.domain true h
| .inr (.inl h) => Binary.domain true h
| .inr (.inr (.inl (h,_))) => Binary.domain true h
| .inr (.inr (.inr _)) => fun _ => Finset.univ
def positionDomain : Kind d → Fin d → Finset Bool
| .inl (_,j) => cyclicDomain true j
| .inr (.inl _) => fun _ => Finset.univ
| .inr (.inr (.inl (_,j))) => cyclicDomain false j
| .inr (.inr (.inr _)) => fun _ => Finset.univ
def timeMap : Kind d → Fin d → Bool → Bool
| .inl (h,_) => table h
| .inr (.inl h) => table h
| .inr (.inr (.inl (h,_))) => table h
| .inr (.inr (.inr _)) => fun _ => id
def positionMap : Kind d → Fin d → Bool → Bool
| .inl (_,j) => cyclicTable j
| .inr (.inl _) => fun _ => id
| .inr (.inr (.inl (_,j))) => cyclicTable j
| .inr (.inr (.inr _)) => fun _ => id
def source : Edge L d → Gate L (Cellular.Triple L × Bool)
| ((a,_,_),.inl _) => .inl a
| ((_,b,_),.inr (.inl _)) => .inl b
| ((_,_,c),.inr (.inr (.inl _))) => .inl c
| (abc,.inr (.inr (.inr v))) => .inr (abc,v)
def destination (rule : L → L → L → L) : Edge L d → Port L (Cellular.Triple L × Bool)
| (abc,.inl _) => .inr ((abc,false),false)
| (abc,.inr (.inl _)) => .inr ((abc,false),true)
| (abc,.inr (.inr (.inl _))) => .inr ((abc,true),true)
| (abc,.inr (.inr (.inr false))) => .inr ((abc,true),false)
| ((a,b,c),.inr (.inr (.inr true))) => .inl (rule a b c)
theorem timeDomain_nonempty (k : Kind d) (i : Fin d) : (timeDomain k i).Nonempty := by
rcases k with ⟨h,j⟩ | h | ⟨h,j⟩ | v
all_goals simp only [timeDomain]
all_goals first | exact Binary.domain_nonempty _ _ _ | exact ⟨false,Finset.mem_univ _⟩
theorem positionDomain_nonempty (k : Kind d) (i : Fin d) : (positionDomain k i).Nonempty := by
rcases k with ⟨h,j⟩ | h | ⟨h,j⟩ | v
all_goals simp only [positionDomain]
all_goals first | exact cyclicDomain_nonempty _ _ _ | exact ⟨false,Finset.mem_univ _⟩
theorem timeMap_injective (k : Kind d) (i : Fin d) : Function.Injective (timeMap k i) := by
rcases k with ⟨h,j⟩ | h | ⟨h,j⟩ | v
all_goals first | exact table_injective _ _ | exact Function.injective_id
theorem positionMap_injective (k : Kind d) (i : Fin d) : Function.Injective (positionMap k i) := by
rcases k with ⟨h,j⟩ | h | ⟨h,j⟩ | v
all_goals first | exact cyclicTable_injective _ _ | exact Function.injective_id
structure Data (L : Type uVariable7) (d m : ℕ) where
rule : L → L → L → L
input : Fin m → L
blank : L
accepting : Set L
fits : m < 2^d
namespace Data
variable (D : Data L d m)
noncomputable def threshold : Digits d := (Binary.equivalence d).symm ⟨m,D.fits⟩
@[simp] theorem number_threshold : number D.threshold=m := by
have h := congrArg Fin.val ((Binary.equivalence d).apply_symm_apply ⟨m,D.fits⟩)
exact h
abbrev Request := (Fin m ⊕ Option {h : Fin d // D.threshold h=false}) ⊕ {f : L // f ∈ D.accepting}
def requestGate : D.Request → L
| .inl (.inl j) => D.input j
| .inl (.inr _) => D.blank
| .inr f => f.val
def requestTest : D.Request → Bool
| .inl _ => false
| .inr _ => true
noncomputable def inputBits (j : Fin m) : Digits d := (Binary.equivalence d).symm ⟨j.val,j.isLt.trans D.fits⟩
@[simp] theorem number_inputBits (j : Fin m) : number (D.inputBits j)=j.val :=
congrArg Fin.val ((Binary.equivalence d).apply_symm_apply ⟨j.val,j.isLt.trans D.fits⟩)
noncomputable def requestTimeDomain : D.Request → Fin d → Finset Bool
| .inl _ => fun _ => {false}
| .inr _ => fun _ => {true}
noncomputable def requestPositionDomain : D.Request → Fin d → Finset Bool
| .inl (.inl j) => fun i => {D.inputBits j i}
| .inl (.inr h) => thresholdDomain D.threshold h
| .inr _ => fun _ => Finset.univ
noncomputable def description : Description (d+d) L (Cellular.Triple L × Bool) (Edge L d) D.Request where
source := source
destination := destination D.rule
domain e := join (timeDomain e.2) (positionDomain e.2)
domain_nonempty e i := Fin.addCases (fun j => by simpa using timeDomain_nonempty e.2 j)
(fun j => by simpa using positionDomain_nonempty e.2 j) i
map e := join (timeMap e.2) (positionMap e.2)
map_injective e i := by
apply Function.Injective.injOn
exact Fin.addCases (fun j => by simpa using timeMap_injective e.2 j)
(fun j => by simpa using positionMap_injective e.2 j) i
requestGate := D.requestGate
requestTest := D.requestTest
requestDomain b := join (D.requestTimeDomain b) (D.requestPositionDomain b)
request_nonempty b i := by
refine Fin.addCases (fun j => ?_) (fun j => ?_) i
· rcases b with (j|h)|f <;> simp [requestTimeDomain]
· rcases b with (j|h)|f
· simp [requestPositionDomain]
· simpa [requestPositionDomain] using thresholdDomain_nonempty D.threshold h _
· simp [requestPositionDomain]
@[simp] theorem allowed_parts (abc : Cellular.Triple L) (k : Kind d) (x : Address d) :
D.description.Allowed (abc,k) x ↔
(∀ i, timeBits x i ∈ timeDomain k i) ∧ (∀ i, positionBits x i ∈ positionDomain k i) := by
unfold Description.Allowed
rw [all_parts]
simp only [description,join_left,join_right,timeBits,positionBits]
@[simp] theorem time_mapAddress (e : Edge L d) (x : Address d) :
timeBits (D.description.mapAddress e x)=fun i => timeMap e.2 i (timeBits x i) := by
funext i
simp [Description.mapAddress,description,timeBits]
@[simp] theorem position_mapAddress (e : Edge L d) (x : Address d) :
positionBits (D.description.mapAddress e x)=fun i => positionMap e.2 i (positionBits x i) := by
funext i
simp [Description.mapAddress,description,positionBits]
@[simp] theorem request_parts (b : D.Request) (x : Address d) :
D.description.RequestAllowed b x ↔
(∀ i, timeBits x i ∈ D.requestTimeDomain b i) ∧
(∀ i, positionBits x i ∈ D.requestPositionDomain b i) := by
unfold Description.RequestAllowed
rw [all_parts]
simp only [description,join_left,join_right,timeBits,positionBits]
noncomputable def initial (j : Fin (2^d)) : L := if h : j.val < m then D.input ⟨j.val,h⟩ else D.blank
theorem tests_exact (f : L) (x : Address d) : (f,x) ∈ D.description.requests true ↔
number (timeBits x)=2^d-1 ∧ f ∈ D.accepting := by
classical
have ht : (∀ i, timeBits x i=true) ↔ number (timeBits x)=2^d-1 := by
have hb := number_true d
constructor
· intro h; rw [funext h]; omega
· intro h
have he := number_injective (a₁ := timeBits x) (a₂ := fun _ => true) (by omega)
exact congrFun he
constructor
· rintro ⟨b,hg,hb,hreq⟩
rcases b with (j|h)|f'
· cases hb
· cases hb
· have hp := (D.request_parts _ _).mp hreq
change f'.val=f at hg
exact ⟨ht.mp (fun i => Finset.mem_singleton.mp (hp.1 i)),hg ▸ f'.property⟩
· rintro ⟨hx,hf⟩
refine ⟨.inr ⟨f,hf⟩,rfl,rfl,(D.request_parts _ _).mpr ⟨?_,?_⟩⟩
· intro i; simpa [requestTimeDomain] using ht.mpr hx i
· intro i; simp [requestPositionDomain]
theorem terminal : D.description.Terminal := by
intro f x hx e z hz he
obtain ⟨ht,_⟩ := (D.tests_exact f x).mp hx
rcases e with ⟨⟨a,b,c⟩,(⟨h,j⟩|h|⟨h,j⟩|v)⟩
all_goals try { cases he }
all_goals
have hxz : z=x := congrArg (fun g : Gate (L × Address d) ((Cellular.Triple L × Bool) × Address d) =>
match g with | .inl s => s.2 | .inr s => s.2) he
have hh := (D.allowed_parts _ _ _).mp hz |>.1
have hi := number_flip h (timeBits z) hh
have hb := number_lt (Binary.flip h (timeBits z))
rw [hxz,ht] at hi
rw [hxz] at hb
have hpow : 0<2^d := pow_pos (by decide) _
omega
end Data
end VariableWL.Circuit.ProductCellular
namespace VariableWL.Circuit.ProductCellular
open Binary
attribute [local instance] Classical.propDecidable
variable {L : Type uVariable8} {d m : ℕ}
instance powTwoNeZero (d : ℕ) : NeZero (2^d) := ⟨pow_ne_zero _ (by decide)⟩
noncomputable def position (x : Address d) : Fin (2^d) := Binary.equivalence d (positionBits x)
@[simp] theorem position_index_join (t p : Digits d) : position (join t p)=Binary.equivalence d p := by
simp only [position,ProductCellular.position_join]
namespace Data
variable (D : Data L d m)
noncomputable abbrev system := D.description.expanded D.terminal
noncomputable def cellular : Cellular.Data L (Fin (2^d)) where
rule := D.rule
previous := fun j => j-1
next := fun j => j+1
initial := D.initial
accepting := D.accepting
noncomputable abbrev state (t : ℕ) (j : Fin (2^d)) := D.cellular.state t j
@[simp] theorem same_allowed (abc : Cellular.Triple L) (v : Bool) (x : Address d) :
D.description.Allowed (abc,same v) x := by
simp [allowed_parts,timeDomain,positionDomain,same]
def gateMeaning : Gate (L × Address d) ((Cellular.Triple L × Bool) × Address d) → Prop
| .inl (f,x) => D.state (number (timeBits x)) (position x)=f
| .inr (((a,b,_),false),x) => 0 < number (timeBits x) ∧
D.state (number (timeBits x)-1) (position x-1)=a ∧ D.state (number (timeBits x)-1) (position x)=b
| .inr (((a,b,c),true),x) => 0 < number (timeBits x) ∧
D.state (number (timeBits x)-1) (position x-1)=a ∧ D.state (number (timeBits x)-1) (position x)=b ∧
D.state (number (timeBits x)-1) (position x+1)=c
def portMeaning : Port (L × Address d) ((Cellular.Triple L × Bool) × Address d) → Prop
| .inl s => D.gateMeaning (.inl s)
| .inr (((abc,false),x),false) => 0 < number (timeBits x) ∧
D.state (number (timeBits x)-1) (position x-1)=abc.1
| .inr (((abc,false),x),true) => 0 < number (timeBits x) ∧
D.state (number (timeBits x)-1) (position x)=abc.2.1
| .inr (((abc,true),x),false) => D.gateMeaning (.inr ((abc,false),x))
| .inr (((abc,true),x),true) => 0 < number (timeBits x) ∧
D.state (number (timeBits x)-1) (position x+1)=abc.2.2
end Data
end VariableWL.Circuit.ProductCellular
namespace VariableWL.Circuit.ProductCellular
open Binary
attribute [local instance] Classical.propDecidable
variable {L : Type uVariable9} {d m : ℕ}
noncomputable def previousTime (x : Address d) : Digits d :=
(Binary.equivalence d).symm ⟨number (timeBits x)-1,Nat.lt_of_le_of_lt (Nat.sub_le _ _) (number_lt _)⟩
noncomputable def backAddress (x : Address d) (j : Fin (2^d)) : Address d :=
join (previousTime x) ((Binary.equivalence d).symm j)
@[simp] theorem number_previousTime (x : Address d) : number (previousTime x)=number (timeBits x)-1 :=
congrArg Fin.val ((Binary.equivalence d).apply_symm_apply _)
@[simp] theorem time_backAddress (x : Address d) (j : Fin (2^d)) :
number (timeBits (backAddress x j))=number (timeBits x)-1 := by
simp only [backAddress,time_join,number_previousTime]
@[simp] theorem position_backAddress (x : Address d) (j : Fin (2^d)) : position (backAddress x j)=j := by
simp only [backAddress,position_index_join,Equiv.apply_symm_apply]
end VariableWL.Circuit.ProductCellular
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Program
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation
variable {Γ : Type}
abbrev Symbol (Γ : Type) := Option (Bool ⊕ Γ)
def bitSymbol (b : Bool) : Symbol Γ := some (.inl b)
def typedWordCells (w : Word) (i : ℤ) : Symbol Γ :=
if 0 ≤ i then w[i.toNat]?.map bitSymbol |>.join else none
structure Program (Q Γ : Type) (k : ℕ) where
transition : Option Q → (Fin (k+1) → Symbol Γ) →
Option (Option Q × (Fin (k+1) → Symbol Γ × Motion))
structure State (Q Γ : Type) (k : ℕ) where
control : Option Q
heads : Fin (k+1) → ℤ
cells : Fin (k+1) → ℤ → Symbol Γ
namespace Program
variable {Q Γ : Type} {k : ℕ}
def initial (w : Word) : State Q Γ k where
control := none
heads := fun _ => 0
cells := fun j => if j=0 then typedWordCells w else fun _ => none
def step (P : Program Q Γ k) (s : State Q Γ k) : Option (State Q Γ k) :=
(P.transition s.control (fun j => s.cells j (s.heads j))).map fun data =>
{ control := data.1
heads := fun j => s.heads j + (data.2 j).2.displacement
cells := fun j i => if i=s.heads j then (data.2 j).1 else s.cells j i }
def run (P : Program Q Γ k) (w : Word) : ℕ → State Q Γ k
| 0 => initial w
| n+1 => (P.step (P.run w n)).getD (P.run w n)
def OutputsWithin (P : Program Q Γ k) (w out : Word) (bound : ℕ) : Prop :=
∃ t ≤ bound, P.step (P.run w t)=none ∧
(P.run w t).cells 0 = typedWordCells out
noncomputable section
variable [Fintype Q] [Fintype Γ]
def controlCode : Option Q → Fin (Fintype.card Q+1)
| none => ⟨0, by omega⟩
| some q => ⟨(Fintype.equivFin Q q).val+1, by omega⟩
def symbolCode : Symbol Γ → Fin (Fintype.card Γ+3)
| none => ⟨0, by omega⟩
| some (.inl false) => ⟨1, by omega⟩
| some (.inl true) => ⟨2, by omega⟩
| some (.inr a) => ⟨(Fintype.equivFin Γ a).val+3, by omega⟩
def controlDecode := Function.invFun (controlCode (Q:=Q))
def symbolDecode := Function.invFun (symbolCode (Γ:=Γ))
def compile (P : Program Q Γ k) : Machine where
states := Fintype.card Q
workSymbols := Fintype.card Γ
extraTapes := k
transition := fun q as =>
(P.transition (controlDecode q) (fun j => symbolDecode (as j))).map fun d =>
(controlCode d.1, fun j => (symbolCode (d.2 j).1, (d.2 j).2))
def encodeState (P : Program Q Γ k) (s : State Q Γ k) : Configuration P.compile where
control := controlCode s.control
heads := s.heads
cells := fun j i => symbolCode (s.cells j i)
end
end Program
end VariableWL.Computation
namespace VariableWL.Computation
variable {Γ : Type}
def stackCells (w : Word) (i : ℤ) : Symbol Γ := typedWordCells w (i+w.length)
def stackHead (w : Word) : ℤ := -(w.length:ℤ)
namespace Stack
inductive Action where
| keep | pop | push (b : Bool)
deriving DecidableEq,Fintype
def Action.apply : Action → Word → Word
| .keep,w => w
| .pop,w => w.tail
| .push b,w => b::w
def Action.firstMove : Action → Option Bool → Motion
| .push _,_ => .left
| .pop,some _ => .right
| _,_ => .stay
def Action.firstWrite (a : Action) (top : Option Bool) : Symbol Γ :=
if a=.pop then none else top.bind bitSymbol
def Action.secondWrite (a : Action) (current : Symbol Γ) : Symbol Γ :=
match a with
| .push b => bitSymbol b
| _ => current
structure Machine (Q : Type) (k : ℕ) where
start : Q
output : Fin (k+1)
transition : Q → (Fin (k+1) → Option Bool) → Option (Q × (Fin (k+1) → Action))
structure State (Q : Type) (k : ℕ) where
control : Q
tapes : Fin (k+1) → Word
variable {Q : Type} {k : ℕ}
def Machine.step (M : Machine Q k) (s : State Q k) : Option (State Q k) :=
(M.transition s.control (fun j => (s.tapes j).head?)).map fun d =>
{control := d.1,tapes := fun j => (d.2 j).apply (s.tapes j)}
def Machine.initial (M : Machine Q k) (w : Word) : State Q k where
control := M.start
tapes := fun j => if j=0 then w.reverse else []
def Machine.run (M : Machine Q k) (w : Word) : ℕ → State Q k
| 0 => M.initial w
| n+1 => (M.step (M.run w n)).getD (M.run w n)
def Machine.OutputsWithin (M : Machine Q k) (w out : Word) (T : ℕ) : Prop :=
∃ t ≤ T, M.step (M.run w t)=none ∧ (M.run w t).tapes M.output=out
end Stack
end VariableWL.Computation
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Stack
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation
variable {Q Γ : Type} {k : ℕ}
namespace Program
variable {Q Γ : Type} {k : ℕ}
def evolve (P : Program Q Γ k) (s : State Q Γ k) : ℕ → State Q Γ k
| 0 => s
| n+1 => (P.step (P.evolve s n)).getD (P.evolve s n)
end Program
namespace Stack
inductive Control (Q : Type) (k : ℕ) where
| read
| put (b : Bool)
| back
| execute (q : Q)
| pending (q : Q) (acts : Fin (k+1) → Action)
| output
deriving Fintype
def readBit : Symbol PUnit → Option Bool
| some (.inl b) => some b
| _ => none
@[simp] theorem readBit_bit (b : Bool) : readBit (bitSymbol b)=some b := rfl
@[simp] theorem readBit_none : readBit none=none := rfl
@[simp] theorem readBit_bind (b : Option Bool) : readBit (b.bind bitSymbol)=b := by
cases b <;> rfl
def marker : Symbol PUnit := some (.inr PUnit.unit)
def instruction (q : Control Q k) (io : Symbol PUnit × Motion)
(work : Fin (k+1) → Symbol PUnit × Motion) :
Option (Option (Control Q k) × (Fin (k+2) → Symbol PUnit × Motion)) :=
some (some q, Fin.cases io work)
def Machine.program (M : Machine Q k) : Program (Control Q k) PUnit (k+1) where
transition q cells :=
match q with
| none =>
match readBit (cells 0) with
| none => instruction (.execute M.start) (none,.stay)
(fun j => (cells j.succ,.stay))
| some b => instruction (.put b) (marker,.right)
(fun j => (cells j.succ,if j=0 then .left else .stay))
| some .read =>
match readBit (cells 0) with
| none => instruction .back (none,.left) (fun j => (cells j.succ,.stay))
| some b => instruction (.put b) (none,.right)
(fun j => (cells j.succ,if j=0 then .left else .stay))
| some (.put b) => instruction .read (cells 0,.stay)
(fun j => (if j=0 then bitSymbol b else cells j.succ,.stay))
| some .back =>
match cells 0 with
| some (.inr _) => instruction (.execute M.start) (none,.stay)
(fun j => (cells j.succ,.stay))
| _ => instruction .back (cells 0,.left) (fun j => (cells j.succ,.stay))
| some (.execute q) =>
match M.transition q (fun j => readBit (cells j.succ)) with
| none => instruction .output (cells 0,.stay) (fun j => (cells j.succ,.stay))
| some (q',acts) => instruction (.pending q' acts) (cells 0,.stay)
(fun j => ((acts j).firstWrite (readBit (cells j.succ)),
(acts j).firstMove (readBit (cells j.succ))))
| some (.pending q acts) => instruction (.execute q) (cells 0,.stay)
(fun j => ((acts j).secondWrite (cells j.succ),.stay))
| some .output =>
match readBit (cells M.output.succ) with
| none => none
| some b => instruction .output (bitSymbol b,.right)
(fun j => (if j=M.output then none else cells j.succ,
if j=M.output then .right else .stay))
def Machine.execState (_M : Machine Q k) (s : State Q k) :
Computation.State (Control Q k) PUnit (k+1) where
control := some (.execute s.control)
heads := Fin.cases 0 (fun j => stackHead (s.tapes j))
cells := Fin.cases (fun _ => none) (fun j => stackCells (s.tapes j))
def intermediate (s : Computation.State Q Γ k) (q : Option Q)
(data : Fin (k+1) → Symbol Γ × Motion) : Computation.State Q Γ k where
control := q
heads := fun j => s.heads j + (data j).2.displacement
cells := fun j i => if i=s.heads j then (data j).1 else s.cells j i
end Stack
end VariableWL.Computation
namespace VariableWL.Computation
variable {Q Γ : Type} {k : ℕ}
namespace Stack
def tapeState (q : Option Q) (h : ℤ) (c : ℤ → Symbol Γ) (ws : Fin (k+1) → Word) :
Computation.State Q Γ (k+1) where
control := q
heads := Fin.cases h (fun j => stackHead (ws j))
cells := Fin.cases c (fun j => stackCells (ws j))
def firstData (ws : Fin (k+1) → Word) (io : Symbol Γ × Motion)
(acts : Fin (k+1) → Action) : Fin (k+2) → Symbol Γ × Motion :=
Fin.cases io (fun j => ((acts j).firstWrite (ws j).head?,(acts j).firstMove (ws j).head?))
def secondData (s : Computation.State Q Γ (k+1)) (acts : Fin (k+1) → Action) :
Fin (k+2) → Symbol Γ × Motion :=
Fin.cases (s.cells 0 (s.heads 0),.stay)
(fun j => ((acts j).secondWrite (s.cells j.succ (s.heads j.succ)),.stay))
def inputTapes (w : Word) : Fin (k+1) → Word := fun j => if j=0 then w.reverse else []
def pushInput (b : Bool) : Fin (k+1) → Action := fun j => if j=0 then .push b else .keep
def inputCells (p w : Word) (i : ℤ) : Symbol PUnit :=
if i=0 then marker else typedWordCells w (i-p.length)
def Machine.loading (_M : Machine Q k) (p w : Word) :
Computation.State (Control Q k) PUnit (k+1) :=
tapeState (some .read) p.length (inputCells p w) (inputTapes p)
end Stack
end VariableWL.Computation
namespace VariableWL.Computation.Stack
variable {Q : Type} {k : ℕ}
def Machine.backState (_M : Machine Q k) (n : ℕ) (ws : Fin (k+1) → Word) :
Computation.State (Control Q k) PUnit (k+1) :=
tapeState (some .back) n (fun i => if i=0 then marker else none) ws
end VariableWL.Computation.Stack
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_OneHead
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10
namespace VariableWL.Computation
variable {Q Γ : Type} {k : ℕ}
namespace Stack
def Machine.outputState (M : Machine Q k) (p remaining : Word) (ws : Fin (k+1) → Word) :
Computation.State (Control Q k) PUnit (k+1) :=
tapeState (some .output) p.length (typedWordCells p) (Function.update ws M.output remaining)
noncomputable def Machine.compile [Fintype Q] (M : Machine Q k) : VariableWL.Machine :=
M.program.compile
end Stack
end VariableWL.Computation
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_StackSimulation
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11 uVariable12 uVariable13 uVariable14 uVariable15 uVariable16 uVariable17 uVariable18 uVariable19
namespace VariableWL.BoundedSimulation
inductive Steps {S : Type uVariable9} (f : S → Option S) : ℕ → S → S → Prop where
| zero (a) : Steps f 0 a a
| succ {n a b c} : f a=some b → Steps f n b c → Steps f (n+1) a c
noncomputable def evolve {S : Type uVariable11} (f : S → Option S) (a : S) : ℕ → S
| 0 => a
| t+1 => (f (evolve f a t)).getD (evolve f a t)
def Within {S : Type uVariable14} (f : S → Option S) (a b : S) (N : ℕ) : Prop :=
∃ n ≤ N, Steps f n a b
end VariableWL.BoundedSimulation
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_MachineReduction
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.RealizationSize
open VariableWL.Affine Blocks Subdivision
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} [Fintype P] [Fintype E]
variable (J : ProductImages.Instance r P E)
omit [Fintype P] [Fintype E] in
theorem dimension_le_two (t : Subdivision.Vertex P E n) : Blocks.dimension J t ≤ 2 := by
cases t with
| inl p => rcases J.dimension_one_or_two p with h|h <;> simp [Blocks.dimension,h]
| inr q => simp [Blocks.dimension]
omit [Fintype P] [Fintype E] in
theorem coordinate_card (b : RawBlock r n P E) : Fintype.card (BlockCoordinates.Coordinate J b) ≤ 6 := by
cases b with
| inl h =>
have hd : Blocks.dimension J h.type ≤ 6 := (dimension_le_two J h.type).trans (by omega)
simpa [BlockCoordinates.Coordinate] using hd
| inr s =>
have hl := dimension_le_two J (left J.source s.link)
have hr := dimension_le_two J (right J.target s.link)
simpa only [BlockCoordinates.Coordinate,Fintype.card_sum,Fintype.card_fin,Fintype.card_bool] using
(show Blocks.dimension J (left J.source s.link)+Blocks.dimension J (right J.target s.link)+2 ≤ 6 by omega)
end VariableWL.RealizationSize
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Encoding
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack
open VariableWL.BoundedSimulation
abbrev Stores (k : ℕ) := Fin (k+1) → Word
abbrev Heads (k : ℕ) := Fin (k+1) → Option Bool
abbrev Actions (k : ℕ) := Fin (k+1) → Action
def heads {k : ℕ} (s : Stores k) : Heads k := fun j => (s j).head?
def execute {k : ℕ} (a : Actions k) (s : Stores k) : Stores k := fun j => (a j).apply (s j)
def nop {k : ℕ} : Actions k := fun _ => .keep
@[simp] theorem execute_nop {k : ℕ} (s : Stores k) : execute nop s=s := rfl
inductive Code (k : ℕ) where
| skip
| action (a : Heads k → Actions k)
| seq (a b : Code k)
| branch (p : Heads k → Bool) (a b : Code k)
| loop (p : Heads k → Bool) (body : Code k)
namespace Code
variable {k : ℕ}
def Control : Code k → Type
| .skip => Unit
| .action _ => Bool
| .seq a b => a.Control ⊕ b.Control
| .branch _ a b => Unit ⊕ (a.Control ⊕ b.Control)
| .loop _ a => Unit ⊕ a.Control
noncomputable instance controlFintype (C : Code k) : Fintype C.Control := by
induction C with
| skip => exact inferInstanceAs (Fintype Unit)
| action => exact inferInstanceAs (Fintype Bool)
| seq a b ha hb => exact inferInstanceAs (Fintype (a.Control ⊕ b.Control))
| branch p a b ha hb => exact inferInstanceAs (Fintype (Unit ⊕ (a.Control ⊕ b.Control)))
| loop p a ha => exact inferInstanceAs (Fintype (Unit ⊕ a.Control))
def start : (C : Code k) → C.Control
| .skip => ()
| .action _ => false
| .seq a _ => .inl a.start
| .branch _ _ _ => .inl ()
| .loop _ _ => .inl ()
def transition : (C : Code k) → C.Control → Heads k → Option (C.Control × Actions k)
| .skip,_,_ => none
| .action a,false,h => some (true,a h)
| .action _,true,_ => none
| .seq a b,.inl q,h =>
match a.transition q h with
| some (q',u) => some (.inl q',u)
| none => some (.inr b.start,nop)
| .seq _ b,.inr q,h => (b.transition q h).map (fun (q',u) => (.inr q',u))
| .branch p a b,.inl _,h => some (if p h then .inr (.inl a.start) else .inr (.inr b.start),nop)
| .branch _ a _,.inr (.inl q),h => (a.transition q h).map (fun (q',u) => (.inr (.inl q'),u))
| .branch _ _ b,.inr (.inr q),h => (b.transition q h).map (fun (q',u) => (.inr (.inr q'),u))
| .loop p a,.inl _,h => if p h then some (.inr a.start,nop) else none
| .loop _ a,.inr q,h =>
match a.transition q h with
| some (q',u) => some (.inr q',u)
| none => some (.inl (),nop)
def machine (C : Code k) (output : Fin (k+1)) : Machine C.Control k where
start := C.start
output := output
transition := C.transition
def step (C : Code k) (s : State C.Control k) : Option (State C.Control k) :=
(C.transition s.control (heads s.tapes)).map fun (q,a) => ⟨q,execute a s.tapes⟩
def liftState {Q R : Type} (f : Q → R) (s : State Q k) : State R k := ⟨f s.control,s.tapes⟩
inductive Eval : Code k → Stores k → ℕ → Stores k → Prop where
| skip (s) : Eval .skip s 0 s
| action (a) (s) : Eval (.action a) s 1 (execute (a (heads s)) s)
| seq {a b s t u n m} : Eval a s n t → Eval b t m u → Eval (.seq a b) s (n+1+m) u
| branch_true {p a b s t n} : p (heads s)=true → Eval a s n t → Eval (.branch p a b) s (n+1) t
| branch_false {p a b s t n} : p (heads s)=false → Eval b s n t → Eval (.branch p a b) s (n+1) t
| loop_false {p a s} : p (heads s)=false → Eval (.loop p a) s 0 s
| loop_true {p a s t u n m} : p (heads s)=true → Eval a s n t →
Eval (.loop p a) t m u → Eval (.loop p a) s (n+2+m) u
end Code
end VariableWL.Computation.Stack
namespace VariableWL.Encoding
attribute [local instance] Classical.propDecidable
noncomputable def matrix (G : Graph) : Word := by
classical
exact List.ofFn fun p : Fin (G.order*G.order) => decide (G.graph.Adj p.divNat p.modNat)
@[simp] theorem matrix_length (G : Graph) : (matrix G).length=G.order*G.order := List.length_ofFn
end VariableWL.Encoding
namespace VariableWL.Computation.Stack
namespace Code
variable {k : ℕ}
def one (j : Fin (k+1)) (a : Action) : Actions k := fun i => if i=j then a else .keep
theorem execute_one (j : Fin (k+1)) (a : Action) (s : Stores k) :
execute (one j a) s=Function.update s j (a.apply (s j)) := by
funext i
by_cases hi : i=j
· subst i; simp [execute,one]
· simp [execute,one,hi,Action.apply]
def push (j : Fin (k+1)) (b : Bool) : Code k := .action (fun _ => one j (.push b))
def pop (j : Fin (k+1)) : Code k := .action (fun _ => one j .pop)
def clear (j : Fin (k+1)) : Code k := .loop (fun h => (h j).isSome) (pop j)
theorem eval_push (j : Fin (k+1)) (b : Bool) (s : Stores k) :
Eval (push j b) s 1 (Function.update s j (b::s j)) := by
simpa only [push,execute_one,Action.apply] using Eval.action (fun _ => one j (.push b)) s
theorem eval_pop (j : Fin (k+1)) (s : Stores k) :
Eval (pop j) s 1 (Function.update s j (s j).tail) := by
simpa only [pop,execute_one,Action.apply] using Eval.action (fun _ => one j .pop) s
theorem eval_clear_update (j : Fin (k+1)) (s : Stores k) (w : Word) :
Eval (clear j) (Function.update s j w) (3*w.length) (Function.update s j []) := by
induction w with
| nil => exact Eval.loop_false (by simp [heads])
| cons b w ih =>
have hb := eval_pop j (Function.update s j (b::w))
simp only [Function.update_self,List.tail_cons,Function.update_idem] at hb
have he := Eval.loop_true (p := fun h => (h j).isSome) (by simp [heads]) hb ih
convert he using 1 <;> simp [clear,List.length_cons]; omega
theorem eval_clear (j : Fin (k+1)) (s : Stores k) :
Eval (clear j) s (3*(s j).length) (Function.update s j []) := by
simpa only [Function.update_eq_self] using eval_clear_update j s (s j)
def transfer (j t : Fin (k+1)) (f : Bool → Bool) : Code k :=
.loop (fun h => (h j).isSome) (.action fun h i =>
if i=j then .pop else if i=t then .push (f ((h j).getD false)) else .keep)
def pairStore (s : Stores k) (j t : Fin (k+1)) (w u : Word) : Stores k :=
Function.update (Function.update s j w) t u
theorem transfer_action (j t : Fin (k+1)) (hjt : j≠t) (f : Bool → Bool)
(s : Stores k) (b : Bool) (w u : Word) :
execute (fun i => if i=j then .pop else if i=t then
.push (f (((heads (pairStore s j t (b::w) u)) j).getD false)) else .keep)
(pairStore s j t (b::w) u) = pairStore s j t w (f b::u) := by
funext i
by_cases hi : i=j
· subst i
simp [execute,pairStore,hjt,Action.apply]
· by_cases ht : i=t
· subst i
simp [execute,pairStore,heads,hjt,Ne.symm hjt,Action.apply]
· simp [execute,pairStore,hi,ht,Action.apply]
theorem eval_transfer_pair (j t : Fin (k+1)) (hjt : j≠t) (f : Bool → Bool)
(s : Stores k) (w u : Word) :
Eval (transfer j t f) (pairStore s j t w u) (3*w.length)
(pairStore s j t [] (w.reverse.map f++u)) := by
induction w generalizing u with
| nil => exact Eval.loop_false (by simp [heads,pairStore,hjt])
| cons b w ih =>
have ha := Eval.action (fun h i => if i=j then .pop else if i=t then
.push (f ((h j).getD false)) else .keep) (pairStore s j t (b::w) u)
rw [transfer_action j t hjt f] at ha
have he := Eval.loop_true (p := fun h => (h j).isSome) (by simp [heads,pairStore,hjt]) ha (ih (f b::u))
convert he using 1 <;> simp only [transfer,List.length_cons,List.reverse_cons,List.map_append,List.map_cons,List.map_nil,
List.append_assoc,List.singleton_append]; omega
theorem eval_transfer (j t : Fin (k+1)) (hjt : j≠t) (f : Bool → Bool) (s : Stores k) :
Eval (transfer j t f) s (3*(s j).length)
(pairStore s j t [] ((s j).reverse.map f++s t)) := by
have he := eval_transfer_pair j t hjt f s (s j) (s t)
simpa only [pairStore,Function.update_eq_self] using he
end Code
end VariableWL.Computation.Stack
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Decision
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Encoding
attribute [local instance] Classical.propDecidable
def entry (n : ℕ) (v : Word) (i j : Fin n) : Bool := v.getD (i.val*n+j.val) false
def MatrixValid (n : ℕ) (v : Word) : Prop :=
v.length=n*n ∧ (∀ i j : Fin n, entry n v i j=entry n v j i) ∧
(∀ i : Fin n, entry n v i i=false)
end VariableWL.Encoding
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_UnaryPower
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Code
variable {k : ℕ}
def tripleStore (s : Stores k) (j t u : Fin (k+1)) (w a b : Word) : Stores k :=
Function.update (pairStore s j t w a) u b
def distribute (j t u : Fin (k+1)) (f : Bool → Bool) : Code k :=
.loop (fun h => (h j).isSome) (.action fun h i =>
if i=j then .pop else if i=t then .push ((h j).getD false)
else if i=u then .push (f ((h j).getD false)) else .keep)
theorem distribute_action (j t u : Fin (k+1)) (hjt : j≠t) (hju : j≠u) (htu : t≠u)
(f : Bool → Bool) (s : Stores k) (b : Bool) (w a v : Word) :
execute (fun i => if i=j then .pop else if i=t then .push ((heads (tripleStore s j t u (b::w) a v) j).getD false)
else if i=u then .push (f ((heads (tripleStore s j t u (b::w) a v) j).getD false)) else .keep)
(tripleStore s j t u (b::w) a v)=tripleStore s j t u w (b::a) (f b::v) := by
funext i
by_cases hi : i=j
· subst i; simp [execute,tripleStore,pairStore,hju,hjt,Action.apply]
· by_cases hit : i=t
· subst i; simp [execute,tripleStore,pairStore,htu,hjt,Ne.symm hjt,hju,heads,Action.apply]
· by_cases hiu : i=u
· subst i; simp [execute,tripleStore,pairStore,Ne.symm hju,Ne.symm htu,hju,hjt,heads,Action.apply]
· simp [execute,tripleStore,pairStore,hi,hit,hiu,Action.apply]
theorem eval_distribute (j t u : Fin (k+1)) (hjt : j≠t) (hju : j≠u) (htu : t≠u)
(f : Bool → Bool) (s : Stores k) (w a b : Word) :
Eval (distribute j t u f) (tripleStore s j t u w a b) (3*w.length)
(tripleStore s j t u [] (w.reverse++a) (w.reverse.map f++b)) := by
induction w generalizing a b with
| nil => exact Eval.loop_false (by simp [heads,tripleStore,pairStore,hju,hjt])
| cons c w ih =>
have he := Eval.action (fun h i => if i=j then .pop else if i=t then .push ((h j).getD false)
else if i=u then .push (f ((h j).getD false)) else .keep) (tripleStore s j t u (c::w) a b)
rw [distribute_action j t u hjt hju htu f] at he
have hh := Eval.loop_true (p := fun h => (h j).isSome)
(by simp [heads,tripleStore,pairStore,hjt,hju]) he (ih (c::a) (f c::b))
convert hh using 1 <;> simp only [distribute,List.length_cons,List.reverse_cons,
List.map_append,List.map_cons,List.map_nil,List.append_assoc,List.singleton_append]; omega
def duplicate (j t u : Fin (k+1)) (f : Bool → Bool) : Code k :=
.seq (distribute j t u f) (transfer t j id)
theorem eval_duplicate (j t u : Fin (k+1)) (hjt : j≠t) (hju : j≠u) (htu : t≠u)
(f : Bool → Bool) (s : Stores k) (ht : s t=[]) :
Eval (duplicate j t u f) s (6*(s j).length+1)
(Function.update s u ((s j).reverse.map f++s u)) := by
have he := eval_distribute j t u hjt hju htu f s (s j) [] (s u)
have hin : tripleStore s j t u (s j) [] (s u)=s := by
simp only [tripleStore,pairStore,← ht,Function.update_eq_self]
rw [hin] at he
let s' := tripleStore s j t u [] ((s j).reverse++[]) ((s j).reverse.map f++s u)
have htrans := eval_transfer t j (Ne.symm hjt) id s'
have hs' : s' t=(s j).reverse := by simp [s',tripleStore,pairStore,htu]
have hj' : s' j=[] := by simp [s',tripleStore,pairStore,hjt,hju]
rw [hs',hj'] at htrans
simp only [List.reverse_reverse,List.map_id_fun,id_eq,List.append_nil,List.length_reverse] at htrans
have hout : pairStore s' t j [] (s j)=Function.update s u ((s j).reverse.map f++s u) := by
funext i
by_cases hi : i=j
· subst i; simp [pairStore,hju]
· by_cases hit : i=t
· subst i; simp [pairStore,Ne.symm hjt,htu,ht]
· by_cases hiu : i=u
· subst i; simp [pairStore,s',tripleStore,Ne.symm hju,Ne.symm htu]
· simp [pairStore,s',tripleStore,hi,hit,hiu]
rw [hout] at htrans
have hh := Eval.seq he htrans
unfold duplicate
have hn : 6*(s j).length+1=3*(s j).length+1+3*(s j).length := by omega
rw [hn]
exact hh
theorem eval_length_add (j t u : Fin (k+1)) (hjt : j≠t) (hju : j≠u) (htu : t≠u)
(s : Stores k) (ht : s t=[]) (m : ℕ) (hu : s u=List.replicate m true) :
Eval (duplicate j t u (fun _ => true)) s (6*(s j).length+1)
(Function.update s u (List.replicate ((s j).length+m) true)) := by
have h := eval_duplicate j t u hjt hju htu (fun _ => true) s ht
simpa only [List.map_const',List.length_reverse,hu,← List.replicate_add] using h
end VariableWL.Computation.Stack.Code
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BinaryMachine
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.BinaryMachine
open Code
def value : Word → ℕ → ℕ
| [],q => q
| b::w,q => value w (2*q+b.toNat)
end VariableWL.Computation.Stack.BinaryMachine
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BoundedLoop
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Code
variable {k l : ℕ}
noncomputable def put (e : Fin (k+1) ↪ Fin (l+1)) (s : Stores k) (t : Stores l) : Stores l := by
classical
exact fun j => if h : ∃ i, e i=j then s h.choose else t j
theorem put_apply (e : Fin (k+1) ↪ Fin (l+1)) (s : Stores k) (t : Stores l) (i : Fin (k+1)) :
put e s t (e i)=s i := by
classical
unfold put
rw [dite_eq_left ⟨i,rfl⟩]
congr 1
exact e.injective (Exists.choose_spec (show ∃ a, e a=e i from ⟨i,rfl⟩))
theorem put_outside (e : Fin (k+1) ↪ Fin (l+1)) (s : Stores k) (t : Stores l) {j : Fin (l+1)}
(h : ¬∃ i, e i=j) : put e s t j=t j := by
classical
exact dite_eq_right h
theorem put_self (e : Fin (k+1) ↪ Fin (l+1)) (s : Stores l) : put e (s ∘ e) s=s := by
funext j
by_cases h : ∃ i, e i=j
· obtain ⟨i,rfl⟩ := h
exact put_apply e (s ∘ e) s i
· exact put_outside e (s ∘ e) s h
theorem put_put (e : Fin (k+1) ↪ Fin (l+1)) (s s' : Stores k) (t : Stores l) :
put e s' (put e s t)=put e s' t := by
funext j
by_cases h : ∃ i, e i=j
· obtain ⟨i,rfl⟩ := h
rw [put_apply,put_apply]
· rw [put_outside e s' _ h,put_outside e s _ h,put_outside e s' _ h]
noncomputable def liftAction (e : Fin (k+1) ↪ Fin (l+1)) (a : Actions k) : Actions l := by
classical
exact fun j => if h : ∃ i, e i=j then a h.choose else .keep
theorem liftAction_apply (e : Fin (k+1) ↪ Fin (l+1)) (a : Actions k) (i : Fin (k+1)) :
liftAction e a (e i)=a i := by
classical
unfold liftAction
rw [dite_eq_left ⟨i,rfl⟩]
congr 1
exact e.injective (Exists.choose_spec (show ∃ b, e b=e i from ⟨i,rfl⟩))
theorem liftAction_outside (e : Fin (k+1) ↪ Fin (l+1)) (a : Actions k) {j : Fin (l+1)}
(h : ¬∃ i, e i=j) : liftAction e a j=.keep := by
classical
exact dite_eq_right h
theorem execute_liftAction (e : Fin (k+1) ↪ Fin (l+1)) (a : Actions k) (s : Stores k) (t : Stores l) :
execute (liftAction e a) (put e s t)=put e (execute a s) t := by
funext j
by_cases h : ∃ i, e i=j
· obtain ⟨i,rfl⟩ := h
simp only [execute,liftAction_apply,put_apply]
· simp only [execute,liftAction_outside e a h,put_outside e s t h,
put_outside e (execute a s) t h,Action.apply]
theorem heads_put (e : Fin (k+1) ↪ Fin (l+1)) (s : Stores k) (t : Stores l) :
heads (put e s t) ∘ e=heads s := by
funext i
simp only [Function.comp_apply,heads,put_apply]
noncomputable def rename (e : Fin (k+1) ↪ Fin (l+1)) : Code k → Code l
| .skip => .skip
| .action a => .action fun h => liftAction e (a (h ∘ e))
| .seq a b => .seq (rename e a) (rename e b)
| .branch p a b => .branch (fun h => p (h ∘ e)) (rename e a) (rename e b)
| .loop p a => .loop (fun h => p (h ∘ e)) (rename e a)
theorem eval_rename (e : Fin (k+1) ↪ Fin (l+1)) {C : Code k} {s s' : Stores k} {n : ℕ}
(h : Eval C s n s') (t : Stores l) : Eval (rename e C) (put e s t) n (put e s' t) := by
induction h with
| skip s => exact Eval.skip _
| action a s =>
have hh := Eval.action (fun h : Heads l => liftAction e (a (h ∘ e))) (put e s t)
rw [heads_put,execute_liftAction] at hh
exact hh
| seq _ _ ia ib => exact Eval.seq ia ib
| @branch_true p a b s u n hp ha ih =>
exact Eval.branch_true (by simpa only [heads_put] using hp) ih
| @branch_false p a b s u n hp ha ih =>
exact Eval.branch_false (by simpa only [heads_put] using hp) ih
| loop_false hp => exact Eval.loop_false (by simpa only [heads_put] using hp)
| @loop_true p a s u v n m hp ha hb ia ib =>
exact Eval.loop_true (by simpa only [heads_put] using hp) ia ib
theorem eval_rename_from (e : Fin (k+1) ↪ Fin (l+1)) {C : Code k} {s' : Stores k} {n : ℕ}
(t : Stores l) (h : Eval C (t ∘ e) n s') : Eval (rename e C) t n (put e s' t) := by
simpa only [put_self] using eval_rename e h t
end VariableWL.Computation.Stack.Code
namespace VariableWL.Computation.Stack.BoundedLoop
open Code
variable (k : ℕ)
def embed : Fin (k+1) ↪ Fin (k+3) := Fin.castAddEmb 2
def counter : Fin (k+3) := ⟨k+1,by omega⟩
def scratch : Fin (k+3) := ⟨k+2,by omega⟩
theorem counter_ne (i : Fin (k+1)) : embed k i≠counter k := by
intro h
have := congrArg Fin.val h
change i.val=k+1 at this
omega
theorem scratch_ne (i : Fin (k+1)) : embed k i≠scratch k := by
intro h
have := congrArg Fin.val h
change i.val=k+2 at this
omega
theorem counter_scratch : counter k≠scratch k := by
intro h
have := congrArg Fin.val h
simp only [counter,scratch] at this
omega
noncomputable def state (s : Stores k) (n : ℕ) : Stores (k+2) :=
put (embed k) s (fun j => if j=counter k then List.replicate n true else [])
@[simp] theorem state_embed (s : Stores k) (n : ℕ) (i : Fin (k+1)) :
state k s n (embed k i)=s i := put_apply _ _ _ _
@[simp] theorem state_counter (s : Stores k) (n : ℕ) :
state k s n (counter k)=List.replicate n true := by
rw [state,put_outside]
· simp only [ite_true]
· rintro ⟨i,hi⟩
exact counter_ne k i hi
@[simp] theorem state_scratch (s : Stores k) (n : ℕ) :
state k s n (scratch k)=[] := by
rw [state,put_outside]
· simp only [Ne.symm (counter_scratch k),ite_false]
· rintro ⟨i,hi⟩
exact scratch_ne k i hi
theorem cases_index (j : Fin (k+3)) :
(∃ i : Fin (k+1), embed k i=j) ∨ j=counter k ∨ j=scratch k := by
by_cases h : j.val<k+1
· left
exact ⟨⟨j.val,h⟩,Fin.ext rfl⟩
· right
have : j.val=k+1 ∨ j.val=k+2 := by omega
rcases this with h|h
· exact .inl (Fin.ext h)
· exact .inr (Fin.ext h)
theorem update_counter (s : Stores k) (n m : ℕ) :
Function.update (state k s n) (counter k) (List.replicate m true)=state k s m := by
funext j
rcases cases_index k j with ⟨i,rfl⟩|rfl|rfl
· simp only [Function.update_of_ne (counter_ne k i),state_embed]
· simp only [Function.update_self,state_counter]
· simp only [Function.update_of_ne (Ne.symm (counter_scratch k)),state_scratch]
theorem put_state (s t : Stores k) (n : ℕ) : put (embed k) t (state k s n)=state k t n := by
exact put_put _ _ _ _
noncomputable def loopBody (a : Code k) : Code (k+2) := .seq (pop (counter k)) (rename (embed k) a)
noncomputable def loop (a : Code k) : Code (k+2) := .loop (fun h => (h (counter k)).isSome) (loopBody k a)
noncomputable def program (i : Fin (k+1)) (a : Code k) : Code (k+2) :=
.seq (duplicate (embed k i) (scratch k) (counter k) (fun _ => true)) (loop k a)
theorem eval_body {a : Code k} {s t : Stores k} {c : ℕ} (h : Eval a s c t) (n : ℕ) :
Eval (loopBody k a) (state k s (n+1)) (c+2) (state k t n) := by
have hp := eval_pop (counter k) (state k s (n+1))
rw [state_counter,List.replicate_succ,List.tail_cons,update_counter] at hp
have hb := eval_rename (embed k) h (state k s n)
rw [put_state,put_state] at hb
have he := Eval.seq hp hb
have hn : c+2=1+1+c := by omega
rw [hn]
exact he
def total : ℕ → (ℕ → ℕ) → ℕ
| 0,_ => 0
| n+1,T => T 0+4+total n (fun j => T (j+1))
theorem eval_loop (a : Code k) (n : ℕ) (S : ℕ → Stores k) (T : ℕ → ℕ)
(h : ∀ j<n, Eval a (S j) (T j) (S (j+1))) :
Eval (loop k a) (state k (S 0) n) (total n T) (state k (S n) 0) := by
induction n generalizing S T with
| zero => exact Eval.loop_false (by simp only [heads,state_counter,List.replicate_zero,List.head?_nil,Option.isSome_none])
| succ n ih =>
have h0 := eval_body k (h 0 (by omega)) n
have ht := ih (fun j => S (j+1)) (fun j => T (j+1)) (by intro j hj; exact h (j+1) (by omega))
have he := Eval.loop_true (p := fun h => (h (counter k)).isSome)
(by simp [heads,List.replicate_succ]) h0 ht
have hn : total (n+1) T=(T 0+2)+2+total n (fun j => T (j+1)) := by simp only [total]
rw [hn]
exact he
theorem eval_program (i : Fin (k+1)) (a : Code k) (S : ℕ → Stores k) (T : ℕ → ℕ)
(h : ∀ j<(S 0 i).length, Eval a (S j) (T j) (S (j+1))) :
Eval (program k i a) (state k (S 0) 0)
(6*(S 0 i).length+2+total (S 0 i).length T) (state k (S (S 0 i).length) 0) := by
have hd := eval_length_add (embed k i) (scratch k) (counter k) (scratch_ne k i)
(counter_ne k i) (Ne.symm (counter_scratch k)) (state k (S 0) 0)
(state_scratch k _ _) 0 (state_counter k _ _)
simp only [state_embed,Nat.add_zero,update_counter] at hd
have he := Eval.seq hd (eval_loop k a _ S T h)
have hn : 6*(S 0 i).length+2+total (S 0 i).length T=
(6*(S 0 i).length+1)+1+total (S 0 i).length T := by omega
rw [hn]
exact he
theorem total_bound (n B : ℕ) (T : ℕ → ℕ) (h : ∀ j<n, T j≤B) : total n T≤(B+4)*n := by
induction n generalizing T with
| zero => simp [total]
| succ n ih =>
have hi := ih (fun j => T (j+1)) (by intro j hj; exact h (j+1) (by omega))
have h0 := h 0 (by omega)
simp only [total]
nlinarith
theorem program_bound (n B : ℕ) (T : ℕ → ℕ) (h : ∀ j<n, T j≤B) :
6*n+2+total n T≤(B+10)*n+2 := by
have := total_bound n B T h
nlinarith
end VariableWL.Computation.Stack.BoundedLoop
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Procedure
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
def extend (e : ℕ) (s : Stores k) : Stores (k+e) :=
fun j => if h : j.val<k+1 then s ⟨j.val,h⟩ else []
@[simp] theorem extend_front (e : ℕ) (s : Stores k) (i : Fin (k+1)) :
extend e s (⟨i.val,by omega⟩ : Fin (k+e+1))=s i := by
simp only [extend, i.isLt, dite_true]
theorem extend_back (e : ℕ) (s : Stores k) (j : Fin (k+e+1)) (h : k+1≤j.val) :
extend e s j=[] := by simp only [extend,show ¬j.val<k+1 by omega,dite_false]
theorem extend_zero (s : Stores k) : extend 0 s=s := by
funext i
exact extend_front 0 s i
def widen (k e f : ℕ) (h : e≤f) : Fin (k+e+1) ↪ Fin (k+f+1) :=
Fin.castLEEmb (by omega)
theorem extend_project (e f : ℕ) (h : e≤f) (s : Stores k) :
extend f s ∘ widen k e f h=extend e s := by
funext i
simp only [extend,Function.comp_apply,widen,Fin.coe_castLEEmb,Fin.val_castLE]
theorem extend_put (e f : ℕ) (h : e≤f) (s t : Stores k) :
put (widen k e f h) (extend e t) (extend f s)=extend f t := by
classical
funext j
by_cases hj : j.val<k+e+1
· let i : Fin (k+e+1) := ⟨j.val,hj⟩
have he : widen k e f h i=j := Fin.ext rfl
rw [←he,put_apply]
have hp := congrFun (extend_project e f h t) i
exact hp.symm
· have hout : ¬∃i, widen k e f h i=j := by
rintro ⟨i,hi⟩
have hv := congrArg Fin.val hi
change i.val=j.val at hv
omega
rw [put_outside _ _ _ hout]
rw [extend_back _ _ _ (by omega),extend_back _ _ _ (by omega)]
theorem eval_widen {e f : ℕ} (h : e≤f) {C : Code (k+e)} {s t : Stores k} {n : ℕ}
(hc : Eval C (extend e s) n (extend e t)) :
Eval (rename (widen k e f h) C) (extend f s) n (extend f t) := by
have he := eval_rename_from (widen k e f h) (t := extend f s)
(by simpa only [extend_project] using hc)
rw [extend_put] at he
exact he
def Realizes (f : Stores k → Stores k) (T : Stores k → ℕ) : Prop :=
∃ e : ℕ, ∃ C : Code (k+e), ∀ s, ∃ n≤T s, Eval C (extend e s) n (extend e (f s))
theorem monotone {f : Stores k → Stores k} {T U : Stores k → ℕ}
(h : Realizes f T) (hTU : ∀ s, T s≤U s) : Realizes f U := by
obtain ⟨e,C,hC⟩ := h
refine ⟨e,C,fun s => ?_⟩
obtain ⟨n,hn,he⟩ := hC s
exact ⟨n,hn.trans (hTU s),he⟩
theorem direct (C : Code k) (f : Stores k → Stores k) (T : Stores k → ℕ)
(h : ∀s,∃n≤T s,Eval C s n (f s)) : Realizes f T := by
refine ⟨0,C,fun s => ?_⟩
simpa only [extend_zero] using h s
theorem seq {f g : Stores k → Stores k} {T U : Stores k → ℕ}
(hf : Realizes f T) (hg : Realizes g U) :
Realizes (g ∘ f) (fun s => T s+1+U (f s)) := by
obtain ⟨e,A,hA⟩ := hf
obtain ⟨f',B,hB⟩ := hg
let a := widen k e (max e f') (Nat.le_max_left _ _)
let b := widen k f' (max e f') (Nat.le_max_right _ _)
refine ⟨max e f',.seq (rename a A) (rename b B),fun s => ?_⟩
obtain ⟨n,hn,heA⟩ := hA s
obtain ⟨m,hm,heB⟩ := hB (f s)
exact ⟨n+1+m,by dsimp only; omega, Eval.seq (eval_widen _ heA) (eval_widen _ heB)⟩
theorem clear (i : Fin (k+1)) :
Realizes (fun s : Stores k => Function.update s i []) (fun s => 3*(s i).length) :=
direct (Code.clear i) _ _ (fun s => ⟨_,le_rfl,eval_clear i s⟩)
theorem push (i : Fin (k+1)) (b : Bool) :
Realizes (fun s : Stores k => Function.update s i (b::s i)) (fun _ => 1) :=
direct (Code.push i b) _ _ (fun s => ⟨_,le_rfl,eval_push i b s⟩)
theorem pop (i : Fin (k+1)) :
Realizes (fun s : Stores k => Function.update s i (s i).tail) (fun _ => 1) :=
direct (Code.pop i) _ _ (fun s => ⟨_,le_rfl,eval_pop i s⟩)
theorem action (a : Heads k → Actions k) :
Realizes (fun s => execute (a (heads s)) s) (fun _ => 1) :=
direct (.action a) _ _ (fun s => ⟨_,le_rfl,Eval.action a s⟩)
end VariableWL.Computation.Stack.Procedure
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
def front (k e : ℕ) : Fin (k+1) ↪ Fin (k+e+1) := Fin.castLEEmb (by omega)
theorem heads_extend (e : ℕ) (s : Stores k) : heads (extend e s) ∘ front k e=heads s := by
funext i
change (extend e s (⟨i.val,_⟩ : Fin (k+e+1))).head?=(s i).head?
rw [extend_front]
theorem branch (p : Heads k → Bool) {f g : Stores k → Stores k} {T U : Stores k → ℕ}
(hf : Realizes f T) (hg : Realizes g U) :
Realizes (fun s => if p (heads s) then f s else g s)
(fun s => (if p (heads s) then T s else U s)+1) := by
obtain ⟨e,A,hA⟩ := hf
obtain ⟨f',B,hB⟩ := hg
let a := widen k e (max e f') (Nat.le_max_left _ _)
let b := widen k f' (max e f') (Nat.le_max_right _ _)
let p' : Heads (k+max e f') → Bool := fun h => p (h ∘ front k (max e f'))
refine ⟨max e f',.branch p' (rename a A) (rename b B),fun s => ?_⟩
have hps : p' (heads (extend (max e f') s))=p (heads s) := by change p (heads (extend (max e f') s) ∘ front k (max e f'))=p (heads s); rw [heads_extend]
cases hp : p (heads s) with
| false =>
obtain ⟨n,hn,he⟩ := hB s
simp only [hp,Bool.false_eq_true,ite_false]
exact ⟨n+1,by omega,Eval.branch_false (hps.trans hp) (eval_widen _ he)⟩
| true =>
obtain ⟨n,hn,he⟩ := hA s
simp only [hp,ite_true]
exact ⟨n+1,by omega,Eval.branch_true (hps.trans hp) (eval_widen _ he)⟩
theorem state_extend (e : ℕ) (s : Stores k) :
BoundedLoop.state (k+e) (extend e s) 0=extend (e+2) s := by
funext j
rcases BoundedLoop.cases_index (k+e) j with ⟨i,rfl⟩|rfl|rfl
· rw [BoundedLoop.state_embed]
rfl
· rw [BoundedLoop.state_counter, List.replicate_zero]
exact (extend_back _ _ _ (by change k+1≤k+e+1; omega)).symm
· rw [BoundedLoop.state_scratch]
exact (extend_back _ _ _ (by change k+1≤k+e+2; omega)).symm
theorem total_mono (n : ℕ) (A B : ℕ → ℕ) (h : ∀j<n,A j≤B j) :
BoundedLoop.total n A≤BoundedLoop.total n B := by
induction n generalizing A B with
| zero => rfl
| succ n ih =>
have hi := ih (fun j=>A (j+1)) (fun j=>B (j+1)) (by intro j hj; exact h (j+1) (by omega))
have h0 := h 0 (by omega)
simp only [BoundedLoop.total]
omega
theorem countedLoop (i : Fin (k+1)) {f : Stores k → Stores k} {T : Stores k → ℕ}
(hf : Realizes f T) :
Realizes (fun s => (f^[(s i).length]) s)
(fun s => 6*(s i).length+2+BoundedLoop.total (s i).length (fun j => T ((f^[j]) s))) := by
classical
obtain ⟨e,A,hA⟩ := hf
let i' : Fin (k+e+1) := ⟨i.val,by omega⟩
refine ⟨e+2,BoundedLoop.program (k+e) i' A,fun s => ?_⟩
let S (j : ℕ) := extend e ((f^[j]) s)
let τ (j : ℕ) := (hA ((f^[j]) s)).choose
have ht (j : ℕ) : τ j≤T ((f^[j]) s) := (hA ((f^[j]) s)).choose_spec.1
have hb (j : ℕ) : Eval A (S j) (τ j) (S (j+1)) := by
have he := (hA ((f^[j]) s)).choose_spec.2
simpa only [S,Function.iterate_succ_apply'] using he
have he := BoundedLoop.eval_program (k+e) i' A S τ (fun j _ => hb j)
have hs : S 0=extend e s := rfl
have hl : (S 0 i').length=(s i).length := by rw [hs,extend_front]
rw [hl,hs,state_extend,state_extend] at he
have hn := total_mono (s i).length τ (fun j => T ((f^[j]) s)) (fun j _ => ht j)
exact ⟨_,by dsimp only; omega,he⟩
theorem countedLoop_bound (i : Fin (k+1)) {f : Stores k → Stores k} {T B : Stores k → ℕ}
(hf : Realizes f T) (hB : ∀s j,j<(s i).length → T ((f^[j]) s)≤B s) :
Realizes (fun s => (f^[(s i).length]) s) (fun s => (B s+10)*(s i).length+2) := by
apply monotone (countedLoop i hf)
intro s
exact BoundedLoop.program_bound _ _ _ (hB s)
end VariableWL.Computation.Stack.Procedure
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
@[simp] theorem extend_front' (e : ℕ) (s : Stores k) (i : Fin (k+1)) :
extend e s (front k e i)=s i := extend_front e s i
theorem state_base (s : Stores k) : BoundedLoop.state k s 0=extend 2 s := by
simpa only [extend_zero,Nat.add_zero] using state_extend 0 s
attribute [local simp] BoundedLoop.counter_ne BoundedLoop.scratch_ne BoundedLoop.counter_scratch
theorem extend_update (e : ℕ) (s : Stores k) (i : Fin (k+1)) (w : Word) :
Function.update (extend e s) (front k e i) w=extend e (Function.update s i w) := by
funext j
by_cases hj : j.val<k+1
· have he : j=front k e ⟨j.val,hj⟩ := Fin.ext rfl
rw [he]
by_cases hi : (⟨j.val,hj⟩ : Fin (k+1))=i
· rw [hi,Function.update_self,extend_front',Function.update_self]
· have hne : front k e ⟨j.val,hj⟩≠front k e i := fun h => hi ((front k e).injective h)
rw [Function.update_of_ne hne,extend_front',extend_front',Function.update_of_ne hi]
· have hi : j≠front k e i := by
intro he
have hv := congrArg Fin.val he
change j.val=i.val at hv
omega
rw [Function.update_of_ne hi,extend_back _ _ _ (by omega),extend_back _ _ _ (by omega)]
theorem reverseCopy (j u : Fin (k+1)) (hju : j≠u) (f : Bool → Bool) :
Realizes (fun s : Stores k => Function.update s u ((s j).reverse.map f++s u))
(fun s => 6*(s j).length+1) := by
let j' := front k 1 j
let u' := front k 1 u
let tmp : Fin (k+1+1) := ⟨k+1,by omega⟩
have hjt : j'≠tmp := by
intro h; have hv := congrArg Fin.val h; change j.val=k+1 at hv; omega
have hut : u'≠tmp := by
intro h; have hv := congrArg Fin.val h; change u.val=k+1 at hv; omega
have hju' : j'≠u' := fun h => hju ((front k 1).injective h)
refine ⟨1,duplicate j' tmp u' f,fun s => ?_⟩
have ht : extend 1 s tmp=[] := extend_back _ _ _ (by rfl)
have he := eval_duplicate j' tmp u' hjt hju' (Ne.symm hut) f (extend 1 s) ht
simp only [j',u',extend_front',extend_update] at he
exact ⟨_,le_rfl,he⟩
def pushWord (i : Fin (k+1)) : Word → Code k
| [] => .skip
| b::w => .seq (pushWord i w) (Code.push i b)
theorem eval_pushWord (i : Fin (k+1)) (w : Word) (s : Stores k) :
Eval (pushWord i w) s (2*w.length) (Function.update s i (w++s i)) := by
induction w with
| nil => simpa only [pushWord,List.length_nil,List.nil_append,Function.update_eq_self,Nat.mul_zero] using Eval.skip s
| cons b w ih =>
have he := Eval.seq ih (eval_push i b (Function.update s i (w++s i)))
simpa only [pushWord,List.length_cons,Function.update_self,Function.update_idem,
List.cons_append,show 2*(w.length+1)=2*w.length+1+1 by omega] using he
theorem prepend (i : Fin (k+1)) (w : Word) :
Realizes (fun s : Stores k => Function.update s i (w++s i)) (fun _ => 2*w.length) :=
direct (pushWord i w) _ _ (fun s => ⟨_,le_rfl,eval_pushWord i w s⟩)
theorem constant (i : Fin (k+1)) (w : Word) :
Realizes (fun s : Stores k => Function.update s i w) (fun s => 3*(s i).length+1+2*w.length) := by
have h := seq (clear i) (prepend i w)
simpa only [Function.comp_def,Function.update_self,Function.update_idem,List.append_nil] using h
theorem lengthAdd (j u : Fin (k+1)) (hju : j≠u) :
Realizes (fun s : Stores k => Function.update s u (List.replicate (s j).length true++s u))
(fun s => 6*(s j).length+1) := by
simpa only [List.map_const',List.length_reverse] using reverseCopy j u hju (fun _ => true)
theorem copy (j u : Fin (k+1)) :
Realizes (fun s : Stores k => Function.update s u (s j))
(fun s => 9*(s j).length+3*(s u).length+3) := by
let j' := BoundedLoop.embed k j
let u' := BoundedLoop.embed k u
let tmp := BoundedLoop.counter k
let data := BoundedLoop.scratch k
let C := Code.seq (duplicate j' tmp data id) (.seq (Code.clear u') (Code.transfer data u' id))
refine ⟨2,C,fun s => ?_⟩
let s₀ := BoundedLoop.state k s 0
let s₁ := Function.update s₀ data (s j).reverse
let s₂ := Function.update s₁ u' []
have hd := eval_duplicate j' tmp data (BoundedLoop.counter_ne k j)
(BoundedLoop.scratch_ne k j) (BoundedLoop.counter_scratch k) id s₀ (by simp [s₀,tmp])
have hds : Eval (duplicate j' tmp data id) s₀ (6*(s j).length+1) s₁ := by
simpa only [s₀,j',data,BoundedLoop.state_embed,BoundedLoop.state_scratch,List.map_id_fun,id_eq,List.append_nil] using hd
have h₁ : s₁ u'=s u := by
simp [s₁,s₀,u',data]
have hc := eval_clear u' s₁
rw [h₁] at hc
have h₂ : s₂ data=(s j).reverse := by
simp [s₂,s₁,u',data,Ne.symm (BoundedLoop.scratch_ne k u)]
have hu₂ : s₂ u'=[] := Function.update_self ..
have ht := eval_transfer data u' (Ne.symm (BoundedLoop.scratch_ne k u)) id s₂
rw [h₂,hu₂] at ht
simp only [List.length_reverse,List.reverse_reverse,List.map_id_fun,id_eq,List.append_nil] at ht
have hout : pairStore s₂ data u' [] (s j)=BoundedLoop.state k (Function.update s u (s j)) 0 := by
funext z
rcases BoundedLoop.cases_index k z with ⟨i,rfl⟩|rfl|rfl
· by_cases hi : i=u
· subst i
simp [pairStore,u']
· have hne : BoundedLoop.embed k i≠u' := fun h => hi ((BoundedLoop.embed k).injective h)
simp [pairStore,s₂,s₁,s₀,u',data,hi,show BoundedLoop.embed k i≠BoundedLoop.embed k u from hne]
· simp [pairStore,s₂,s₁,s₀,u',data,Ne.symm (BoundedLoop.counter_ne k u)]
· simp [pairStore,u',data,Ne.symm (BoundedLoop.scratch_ne k u)]
rw [hout] at ht
have he := Eval.seq hds (Eval.seq hc ht)
rw [show C=Code.seq (duplicate j' tmp data id) (.seq (Code.clear u') (Code.transfer data u' id)) from rfl]
refine ⟨(6*(s j).length+1)+1+(3*(s u).length+1+3*(s j).length),by dsimp only; omega,?_⟩
simpa only [s₀,state_base] using he
end VariableWL.Computation.Stack.Procedure
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
def join (k e w : ℕ) : Fin (k+e+w+1) ↪ Fin (k+(e+w)+1) := Fin.castLEEmb (by omega)
theorem extend_nested (e w : ℕ) (s : Stores k) :
extend (e+w) s ∘ join k e w=extend w (extend e s) := by
funext i
change (if h:i.val<k+1 then s ⟨i.val,h⟩ else []) =
(if h:i.val<k+e+1 then (if h':i.val<k+1 then s ⟨i.val,h'⟩ else []) else [])
split_ifs <;> first | rfl | omega
theorem put_nested (e w : ℕ) (s t : Stores k) :
put (join k e w) (extend w (extend e t)) (extend (e+w) s)=extend (e+w) t := by
funext j
let i : Fin (k+e+w+1) := ⟨j.val,by have := j.isLt; omega⟩
have he : join k e w i=j := Fin.ext rfl
rw [←he,put_apply]
exact (congrFun (extend_nested e w t) i).symm
theorem localRegisters (e : ℕ) {f : Stores (k+e) → Stores (k+e)} {T : Stores (k+e) → ℕ}
{g : Stores k → Stores k} {U : Stores k → ℕ}
(hf : Realizes f T) (hfg : ∀s,f (extend e s)=extend e (g s))
(hT : ∀s,T (extend e s)≤U s) : Realizes g U := by
obtain ⟨w,C,hC⟩ := hf
refine ⟨e+w,rename (join k e w) C,fun s => ?_⟩
obtain ⟨n,hn,he⟩ := hC (extend e s)
rw [hfg] at he
have hr := eval_rename_from (join k e w) (extend (e+w) s)
(by simpa only [extend_nested] using he)
rw [put_nested] at hr
exact ⟨n,hn.trans (hT s),hr⟩
theorem iterate_update {f : Word → Word} (i : Fin (k+1)) (s : Stores k) (n : ℕ) :
((fun t : Stores k=>Function.update t i (f (t i)))^[n]) s=
Function.update s i ((f^[n]) (s i)) := by
induction n with
| zero => simp only [Function.iterate_zero, id_eq,Function.update_eq_self]
| succ n ih =>
rw [Function.iterate_succ_apply',ih,Function.update_self,Function.update_idem,Function.iterate_succ_apply']
theorem iterate_tail (w : Word) (n : ℕ) : (List.tail^[n]) w=w.drop n := by
induction n with
| zero => simp
| succ n ih => rw [Function.iterate_succ_apply',ih,List.tail_drop]
theorem countedPop (bound target : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s target ((s target).drop (s bound).length))
(fun s=>11*(s bound).length+2) := by
have h := countedLoop_bound bound (pop target) (B := fun _=>1) (by intros; exact le_rfl)
simpa only [iterate_update,iterate_tail] using h
end VariableWL.Computation.Stack.Procedure
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_NumericRefinement
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.NumericRefinement
structure Data where
leftOrder : ℕ
rightOrder : ℕ
dimension : ℕ
leftMatrix : Word
rightMatrix : Word
attribute [local instance] Classical.propDecidable
end VariableWL.NumericRefinement
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
def aux (k : ℕ) : Fin (k+1+1) := ⟨k+1,by omega⟩
theorem front_ne_aux (i : Fin (k+1)) : front k 1 i≠aux k := by
intro h
have hv := congrArg Fin.val h
change i.val=k+1 at hv
omega
theorem aux_ne_front (i : Fin (k+1)) : aux k≠front k 1 i := Ne.symm (front_ne_aux i)
@[simp] theorem extend_aux (s : Stores k) : extend 1 s (aux k)=[] := extend_back _ _ _ (by rfl)
theorem clear_aux (s : Stores k) : Function.update (extend 1 s) (aux k) []=extend 1 s := by
rw [←extend_aux s,Function.update_eq_self]
theorem pushHead (a o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o ((s a).head?.getD false::s o)) (fun _=>1) := by
have h := action (fun h : Heads k=>one o (.push ((h a).getD false)))
simpa only [execute_one,Action.apply,heads] using h
theorem lookup (a ix o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o [(s a).getD (s ix).length false])
(fun s=>12*(s a).length+11*(s ix).length+3*(s o).length+12) := by
let a' := front k 1 a
let i' := front k 1 ix
let o' := front k 1 o
let q := aux k
have hf := seq (copy a' q) (seq (countedPop i' q)
(seq (clear o') (seq (pushHead q o') (clear q))))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',i',o',q]
simp only [Function.update_self,Function.update_of_ne (front_ne_aux ix),
Function.update_of_ne (aux_ne_front o),Function.update_idem,extend_front',List.head?_drop]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
rfl
· intro s
dsimp only [Function.comp_def,a',i',o',q]
simp only [Function.update_self,Function.update_of_ne (front_ne_aux ix),
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),
extend_front',extend_aux,List.length_nil,List.length_drop]
omega
end VariableWL.Computation.Stack.Procedure
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
theorem iterate_lengthAdd (a o : Fin (k+1)) (h : a≠o) (n : ℕ) (s : Stores k) :
((fun t : Stores k=>Function.update t o (List.replicate (t a).length true++t o))^[n]) s=
Function.update s o (List.replicate (n*(s a).length) true++s o) := by
induction n with
| zero => simp
| succ n ih =>
rw [Function.iterate_succ_apply',ih,Function.update_of_ne h,Function.update_self,
Function.update_idem,←List.append_assoc,←List.replicate_add]
congr 3
ring
theorem multiplyAdd (a b o : Fin (k+1)) (hao : a≠o) :
Realizes (fun s : Stores k=>Function.update s o
(List.replicate ((s b).length*(s a).length) true++s o))
(fun s=>(6*(s a).length+11)*(s b).length+2) := by
have h := countedLoop_bound b (lengthAdd a o hao) (B := fun s=>6*(s a).length+1)
(by intro s j _; rw [iterate_lengthAdd a o hao,Function.update_of_ne hao])
simpa only [iterate_lengthAdd a o hao,Nat.add_assoc] using h
theorem multiply (a b o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (List.replicate ((s a).length*(s b).length) true))
(fun s=>20*((s a).length+1)*((s b).length+1)+3*(s o).length+10) := by
let a' := front k 1 a
let b' := front k 1 b
let o' := front k 1 o
let q := aux k
have hf := seq (multiplyAdd a' b' q (front_ne_aux a)) (seq (copy q o') (clear q))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,Nat.mul_comm]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),List.length_replicate]
nlinarith
end VariableWL.Computation.Stack.Procedure
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Recipe
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Procedure
open Code
variable {k : ℕ}
theorem length_fast (a o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (List.replicate (s a).length true))
(fun s=>20*((s a).length+1)+3*(s o).length) := by
let a' := front k 1 a
let o' := front k 1 o
let q := aux k
have hf := seq (lengthAdd a' q (front_ne_aux a)) (seq (copy q o') (clear q))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),List.length_replicate]
omega
theorem add_fast (a b o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (List.replicate ((s a).length+(s b).length) true))
(fun s=>20*((s a).length+(s b).length+1)+3*(s o).length) := by
let a' := front k 1 a
let b' := front k 1 b
let o' := front k 1 o
let q := aux k
have hf := seq (lengthAdd b' q (front_ne_aux b))
(seq (lengthAdd a' q (front_ne_aux a)) (seq (copy q o') (clear q)))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux a),Function.update_idem,←List.replicate_add]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux a),Function.update_of_ne (front_ne_aux o),
Function.update_of_ne (aux_ne_front o),List.length_append,List.length_replicate]
omega
theorem subtract_fast (a b o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (List.replicate ((s a).length-(s b).length) true))
(fun s=>20*((s a).length+(s b).length+1)+3*(s o).length) := by
let a' := front k 1 a
let b' := front k 1 b
let o' := front k 1 o
let q := aux k
have hf := seq (lengthAdd a' q (front_ne_aux a))
(seq (countedPop b' q) (seq (copy q o') (clear q)))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux b),Function.update_idem,List.drop_replicate]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,Function.update_self,
Function.update_of_ne (front_ne_aux b),Function.update_of_ne (front_ne_aux o),
Function.update_of_ne (aux_ne_front o),List.length_drop,List.length_replicate]
omega
theorem reverse (a o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (s a).reverse)
(fun s=>20*((s a).length+1)+3*(s o).length) := by
let a' := front k 1 a
let o' := front k 1 o
let q := aux k
have hf := seq (reverseCopy a' q (front_ne_aux a) id) (seq (copy q o') (clear q))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',o',q]
simp only [extend_front',extend_aux,List.append_nil,List.map_id_fun,id_eq,Function.update_self]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',o',q]
simp only [extend_front',extend_aux,List.append_nil,List.map_id_fun,id_eq,Function.update_self,
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),List.length_reverse]
omega
theorem append (a b o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o (s a++s b))
(fun s=>20*((s a).length+(s b).length+1)+3*(s o).length) := by
let a' := front k 1 a
let b' := front k 1 b
let o' := front k 1 o
let q := aux k
have hf := seq (reverseCopy a' q (front_ne_aux a) id)
(seq (copy b' o') (seq (reverseCopy q o' (aux_ne_front o) id) (clear q)))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,List.map_id_fun,id_eq,Function.update_self,
Function.update_of_ne (front_ne_aux b),Function.update_of_ne (aux_ne_front o),List.reverse_reverse,
Function.update_idem]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',b',o',q]
simp only [extend_front',extend_aux,List.append_nil,List.map_id_fun,id_eq,Function.update_self,
Function.update_of_ne (front_ne_aux b),Function.update_of_ne (front_ne_aux o),
Function.update_of_ne (aux_ne_front o),List.length_reverse]
omega
theorem drop (a ix o : Fin (k+1)) :
Realizes (fun s : Stores k=>Function.update s o ((s a).drop (s ix).length))
(fun s=>24*((s a).length+1)+11*(s ix).length+3*(s o).length) := by
let a' := front k 1 a
let i' := front k 1 ix
let o' := front k 1 o
let q := aux k
have hf := seq (copy a' q) (seq (countedPop i' q) (seq (copy q o') (clear q)))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,a',i',o',q]
simp only [extend_front',Function.update_self,Function.update_of_ne (front_ne_aux ix),
Function.update_idem]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,a',i',o',q]
simp only [extend_front',extend_aux,Function.update_self,Function.update_of_ne (front_ne_aux ix),
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),List.length_drop,List.length_nil]
omega
end VariableWL.Computation.Stack.Procedure
namespace VariableWL.Computation.Stack.Recipe
open Procedure
abbrev Env (n : ℕ) := Fin n → Word
def cons {n : ℕ} (w : Word) (v : Env n) : Env (n+1) := Fin.cons w v
structure Certified (n : ℕ) where
value : Env n → Word
time : Env n → ℕ
compiled : ∀ (k : ℕ) (ρ : Fin n → Fin (k+1)) (o : Fin (k+1)),
Realizes (fun s : Stores k=>Function.update s o (value (s ∘ ρ)))
(fun s=>time (s ∘ ρ)+3*(s o).length)
variable {n m : ℕ}
def reindex (P : Certified n) (φ : Fin n → Fin m) : Certified m where
value := fun v=>P.value (v ∘ φ)
time := fun v=>P.time (v ∘ φ)
compiled k ρ o := P.compiled k (ρ ∘ φ) o
def input (i : Fin n) : Certified n where
value := fun v=>v i
time := fun v=>9*(v i).length+3
compiled k ρ o := by
simpa only [Function.comp_apply,Nat.add_assoc,Nat.add_left_comm,Nat.add_comm] using copy (ρ i) o
def literal (w : Word) : Certified n where
value := fun _=>w
time := fun _=>1+2*w.length
compiled k ρ o := by
simpa only [Nat.add_assoc,Nat.add_left_comm,Nat.add_comm] using constant o w
theorem env_front (k : ℕ) (ρ : Fin n → Fin (k+1)) (s : Stores k) :
extend 1 s ∘ (front k 1 ∘ ρ)=s ∘ ρ := by
funext i
exact extend_front' 1 s (ρ i)
theorem env_cons (k : ℕ) (ρ : Fin n → Fin (k+1)) (s : Stores k) (w : Word) :
Function.update (extend 1 s) (aux k) w ∘ Fin.cons (aux k) (front k 1 ∘ ρ)=cons w (s ∘ ρ) := by
funext i
refine Fin.cases ?_ (fun j=>?_) i
· simp only [Function.comp_apply,Fin.cons_zero,Function.update_self,cons]
· simp only [Function.comp_apply,Fin.cons_succ,Function.update_of_ne (front_ne_aux (ρ j)),
extend_front',cons]
def bind (P : Certified n) (Q : Certified (n+1)) : Certified n where
value := fun v=>Q.value (cons (P.value v) v)
time := fun v=>P.time v+Q.time (cons (P.value v) v)+3*(P.value v).length+2
compiled k ρ o := by
let ρ' := front k 1 ∘ ρ
let o' := front k 1 o
let q := aux k
have hf := seq (P.compiled (k+1) ρ' q)
(seq (Q.compiled (k+1) (Fin.cons q ρ') o') (clear q))
apply localRegisters 1 hf
· intro s
dsimp only [Function.comp_def,ρ',o',q]
rw [show (fun x => extend 1 s (front k 1 (ρ x)))=s ∘ ρ by exact env_front k ρ s]
have hc := env_cons k ρ s (P.value (s ∘ ρ))
dsimp only [Function.comp_def] at hc
dsimp only [Function.comp_def]
rw [hc]
rw [Function.update_comm (front_ne_aux o),Function.update_idem,clear_aux,extend_update]
· intro s
dsimp only [Function.comp_def,ρ',o',q]
rw [show (fun x => extend 1 s (front k 1 (ρ x)))=s ∘ ρ by exact env_front k ρ s]
have hc := env_cons k ρ s (P.value (s ∘ ρ))
dsimp only [Function.comp_def] at hc
dsimp only [Function.comp_def]
rw [hc]
simp only [extend_aux,List.length_nil,Nat.mul_zero,Nat.add_zero,
Function.update_of_ne (front_ne_aux o),Function.update_of_ne (aux_ne_front o),
Function.update_self,extend_front']
omega
def headBranch (p : (Fin n → Option Bool) → Bool) (P Q : Certified n) : Certified n where
value := fun v=>if p (fun i=>(v i).head?) then P.value v else Q.value v
time := fun v=>(if p (fun i=>(v i).head?) then P.time v else Q.time v)+1
compiled k ρ o := by
have h := branch (fun h=>p (h ∘ ρ)) (P.compiled k ρ o) (Q.compiled k ρ o)
have he : (fun s : Stores k => if p (heads s ∘ ρ) then Function.update s o (P.value (s ∘ ρ))
else Function.update s o (Q.value (s ∘ ρ)))=
(fun s : Stores k => Function.update s o (if p (fun i=>(s (ρ i)).head?) then P.value (s ∘ ρ) else Q.value (s ∘ ρ))) := by
funext s
change (if p (fun i=>(s (ρ i)).head?) then _ else _)=_
split <;> rfl
rw [he] at h
apply monotone h
intro s
change (if p (fun i=>(s (ρ i)).head?) then P.time (s ∘ ρ)+3*(s o).length
else Q.time (s ∘ ρ)+3*(s o).length)+1 ≤ _
dsimp only [Function.comp_apply]
split_ifs <;> omega
def test (p : (Fin n → Option Bool) → Bool) : Certified n :=
headBranch p (literal [true]) (literal [false])
theorem test_value (p : (Fin n → Option Bool) → Bool) (v : Env n) :
(test p).value v=[p (fun i=>(v i).head?)] := by
simp only [test,headBranch,literal]
split <;> rename_i h <;> simp_all
def length (i : Fin n) : Certified n where
value := fun v=>List.replicate (v i).length true
time := fun v=>20*((v i).length+1)
compiled k ρ o := by simpa only [Function.comp_apply] using length_fast (ρ i) o
def add (i j : Fin n) : Certified n where
value := fun v=>List.replicate ((v i).length+(v j).length) true
time := fun v=>20*((v i).length+(v j).length+1)
compiled k ρ o := by simpa only [Function.comp_apply] using add_fast (ρ i) (ρ j) o
def subtract (i j : Fin n) : Certified n where
value := fun v=>List.replicate ((v i).length-(v j).length) true
time := fun v=>20*((v i).length+(v j).length+1)
compiled k ρ o := by simpa only [Function.comp_apply] using subtract_fast (ρ i) (ρ j) o
def multiply (i j : Fin n) : Certified n where
value := fun v=>List.replicate ((v i).length*(v j).length) true
time := fun v=>20*((v i).length+1)*((v j).length+1)+10
compiled k ρ o := by
simpa only [Function.comp_apply,Nat.add_assoc,Nat.add_left_comm,Nat.add_comm] using Procedure.multiply (ρ i) (ρ j) o
def reverse (i : Fin n) : Certified n where
value := fun v=>(v i).reverse
time := fun v=>20*((v i).length+1)
compiled k ρ o := by simpa only [Function.comp_apply] using Procedure.reverse (ρ i) o
def append (i j : Fin n) : Certified n where
value := fun v=>v i++v j
time := fun v=>20*((v i).length+(v j).length+1)
compiled k ρ o := by simpa only [Function.comp_apply] using Procedure.append (ρ i) (ρ j) o
def drop (i j : Fin n) : Certified n where
value := fun v=>(v i).drop (v j).length
time := fun v=>24*((v i).length+1)+11*(v j).length
compiled k ρ o := by simpa only [Function.comp_apply] using Procedure.drop (ρ i) (ρ j) o
def lookup (i j : Fin n) : Certified n where
value := fun v=>[(v i).getD (v j).length false]
time := fun v=>12*(v i).length+11*(v j).length+12
compiled k ρ o := by
simpa only [Function.comp_apply,Nat.add_assoc,Nat.add_left_comm,Nat.add_comm] using Procedure.lookup (ρ i) (ρ j) o
end VariableWL.Computation.Stack.Recipe
namespace VariableWL.Computation.Stack.Recipe
open Procedure
variable {n : ℕ}
def foldValue (Q : Certified (n+2)) (v : Env n) (w : Word) : ℕ → Word
| 0 => w
| j+1 => Q.value (cons (foldValue Q v w j) (cons (List.replicate j true) v))
def foldTime (Q : Certified (n+2)) (v : Env n) (w : Word) (j : ℕ) : ℕ :=
Q.time (cons (foldValue Q v w j) (cons (List.replicate j true) v))+
3*(foldValue Q v w j).length+2
noncomputable def frame {k : ℕ} (s : Stores k) (j : ℕ) (w : Word) : Stores (k+2) :=
Function.update (BoundedLoop.state k s j) (BoundedLoop.scratch k) w
@[simp] theorem frame_front {k : ℕ} (s : Stores k) (j : ℕ) (w : Word) (i : Fin (k+1)) :
frame s j w (BoundedLoop.embed k i)=s i := by
rw [frame,Function.update_of_ne (BoundedLoop.scratch_ne k i),BoundedLoop.state_embed]
@[simp] theorem frame_index {k : ℕ} (s : Stores k) (j : ℕ) (w : Word) :
frame s j w (BoundedLoop.counter k)=List.replicate j true := by
rw [frame,Function.update_of_ne (BoundedLoop.counter_scratch k),BoundedLoop.state_counter]
@[simp] theorem frame_acc {k : ℕ} (s : Stores k) (j : ℕ) (w : Word) :
frame s j w (BoundedLoop.scratch k)=w := Function.update_self ..
def foldInputs (k : ℕ) (ρ : Fin n → Fin (k+1)) : Fin (n+2) → Fin (k+2+1) :=
Fin.cons (BoundedLoop.scratch k) (Fin.cons (BoundedLoop.counter k) (BoundedLoop.embed k ∘ ρ))
theorem frame_env {k : ℕ} (ρ : Fin n → Fin (k+1)) (s : Stores k) (j : ℕ) (w : Word) :
frame s j w ∘ foldInputs k ρ=cons w (cons (List.replicate j true) (s ∘ ρ)) := by
funext i
refine Fin.cases ?_ (fun i=>Fin.cases ?_ (fun i=>?_) i) i
· simp only [foldInputs,Function.comp_apply,Fin.cons_zero,frame_acc,cons]
· simp only [foldInputs,Function.comp_apply,Fin.cons_succ,Fin.cons_zero,frame_index,cons]
· simp only [foldInputs,Function.comp_apply,Fin.cons_succ,frame_front,cons]
theorem frame_initial {k : ℕ} (s : Stores k) (w : Word) :
Function.update (extend 2 s) (BoundedLoop.scratch k) w=frame s 0 w := by
rw [←state_base]
rfl
theorem frame_step {k : ℕ} (s : Stores k) (j : ℕ) (w v : Word) :
Function.update (Function.update (frame s j w) (BoundedLoop.scratch k) v)
(BoundedLoop.counter k)
(true::Function.update (frame s j w) (BoundedLoop.scratch k) v (BoundedLoop.counter k))=
frame s (j+1) v := by
rw [Function.update_of_ne (BoundedLoop.counter_scratch k),frame_index,←List.replicate_succ]
unfold frame
rw [Function.update_idem,Function.update_comm (Ne.symm (BoundedLoop.counter_scratch k)),BoundedLoop.update_counter]
theorem frame_finish {k : ℕ} (s : Stores k) (j : ℕ) (w : Word) (o : Fin (k+1)) :
Function.update (Function.update (Function.update (frame s j w) (BoundedLoop.embed k o) w)
(BoundedLoop.scratch k) []) (BoundedLoop.counter k) []=
extend 2 (Function.update s o w) := by
funext z
rcases BoundedLoop.cases_index k z with ⟨i,rfl⟩|rfl|rfl
· have ht : extend 2 (Function.update s o w) (BoundedLoop.embed k i)=Function.update s o w i :=
extend_front 2 _ i
rw [ht,Function.update_of_ne (BoundedLoop.counter_ne k i),
Function.update_of_ne (BoundedLoop.scratch_ne k i)]
by_cases hi : i=o
· subst i; simp only [Function.update_self]
· rw [Function.update_of_ne (fun h=>hi ((BoundedLoop.embed k).injective h)),
Function.update_of_ne hi,frame_front]
· rw [Function.update_self,extend_back _ _ _ (by rfl)]
· rw [Function.update_of_ne (Ne.symm (BoundedLoop.counter_scratch k)),Function.update_self,
extend_back _ _ _ (by change k+1≤k+2; omega)]
def foldBody {k : ℕ} (Q : Certified (n+2)) (ρ : Fin n → Fin (k+1)) (s : Stores (k+2)) : Stores (k+2) :=
let t := Function.update s (BoundedLoop.scratch k) (Q.value (s ∘ foldInputs k ρ))
Function.update t (BoundedLoop.counter k) (true::t (BoundedLoop.counter k))
theorem iterate_foldBody {k : ℕ} (Q : Certified (n+2)) (ρ : Fin n → Fin (k+1))
(s : Stores k) (w : Word) (j : ℕ) :
((foldBody Q ρ)^[j]) (frame s 0 w)=frame s j (foldValue Q (s ∘ ρ) w j) := by
induction j with
| zero => rfl
| succ j ih =>
rw [Function.iterate_succ_apply',ih]
unfold foldBody
rw [frame_env,frame_step]
rfl
def fold (b z : Fin n) (Q : Certified (n+2)) : Certified n where
value := fun v=>foldValue Q v (v z) (v b).length
time := fun v=>9*(v z).length+9*(v b).length+
BoundedLoop.total (v b).length (foldTime Q v (v z))+
12*(foldValue Q v (v z) (v b).length).length+20
compiled k ρ o := by
let q := BoundedLoop.counter k
let a := BoundedLoop.scratch k
let ρ' := BoundedLoop.embed k ∘ ρ
let o' := BoundedLoop.embed k o
have hb := seq (Q.compiled (k+2) (foldInputs k ρ) a) (push q true)
have hf := seq (copy (ρ' z) a) (seq (countedLoop (ρ' b) hb)
(seq (copy a o') (seq (clear a) (clear q))))
apply localRegisters 2 hf
· intro s
dsimp only [Function.comp_def,ρ',o',a,q]
rw [show extend 2 s (BoundedLoop.embed k (ρ z))=s (ρ z) from extend_front 2 s (ρ z)]
rw [frame_initial]
change Function.update (Function.update (Function.update
(((foldBody Q ρ)^[(frame s 0 (s (ρ z)) (BoundedLoop.embed k (ρ b))).length])
(frame s 0 (s (ρ z)))) (BoundedLoop.embed k o)
((((foldBody Q ρ)^[(frame s 0 (s (ρ z)) (BoundedLoop.embed k (ρ b))).length])
(frame s 0 (s (ρ z)))) (BoundedLoop.scratch k)))
(BoundedLoop.scratch k) []) (BoundedLoop.counter k) []=_
rw [frame_front,iterate_foldBody,frame_acc,frame_finish]
rfl
· intro s
dsimp only [Function.comp_def,ρ',o',a,q]
rw [show extend 2 s (BoundedLoop.embed k (ρ z))=s (ρ z) from extend_front 2 s (ρ z)]
rw [show extend 2 s (BoundedLoop.scratch k)=[] from extend_back 2 s _ (by change k+1≤k+2; omega)]
rw [frame_initial,frame_front]
have hj (j : ℕ) :
((fun t : Stores (k+2) => Function.update
(Function.update t (BoundedLoop.scratch k) (Q.value (fun x=>t (foldInputs k ρ x))))
(BoundedLoop.counter k) (true::t (BoundedLoop.counter k)))^[j]) (frame s 0 (s (ρ z)))=
frame s j (foldValue Q (s ∘ ρ) (s (ρ z)) j) := by
have heq : foldBody Q ρ=(fun t : Stores (k+2) => Function.update
(Function.update t (BoundedLoop.scratch k) (Q.value (fun x=>t (foldInputs k ρ x))))
(BoundedLoop.counter k) (true::t (BoundedLoop.counter k))) := by
funext t
unfold foldBody
simp only [Function.comp_def,Function.update_of_ne (BoundedLoop.counter_scratch k)]
rw [←heq]
exact iterate_foldBody Q ρ s (s (ρ z)) j
have henv (j : ℕ) : (fun x=>frame s j (foldValue Q (s ∘ ρ) (s (ρ z)) j) (foldInputs k ρ x))=
cons (foldValue Q (s ∘ ρ) (s (ρ z)) j) (cons (List.replicate j true) (s ∘ ρ)) :=
frame_env ρ s j _
simp only [hj,henv,frame_acc,frame_front,List.length_nil,Nat.mul_zero,Nat.add_zero,
Function.update_of_ne (Ne.symm (BoundedLoop.scratch_ne k o)),
Function.update_of_ne (Ne.symm (BoundedLoop.counter_ne k o)),
Function.update_of_ne (BoundedLoop.counter_scratch k),frame_index,List.length_replicate]
have he : (fun j=>Q.time (cons (foldValue Q (s ∘ ρ) (s (ρ z)) j)
(cons (List.replicate j true) (s ∘ ρ)))+3*(foldValue Q (s ∘ ρ) (s (ρ z)) j).length+1+1)=
foldTime Q (s ∘ ρ) (s (ρ z)) := by funext j; simp only [foldTime]
rw [he]
simp only [Function.comp_def]
omega
end VariableWL.Computation.Stack.Recipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_CertifiedRecipe
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Recipe
variable {n m : ℕ}
namespace Certified
abbrev reindex (P : Certified n) (φ : Fin n → Fin m) : Certified m := Recipe.reindex P φ
abbrev bind (P : Certified n) (Q : Certified (n+1)) : Certified n := Recipe.bind P Q
end Certified
@[simp] theorem cons_zero (w : Word) (v : Env n) : cons w v 0=w := rfl
@[simp] theorem cons_succ (w : Word) (v : Env n) (i : Fin n) : cons w v i.succ=v i := rfl
@[simp] theorem reindex_value (P : Certified n) (φ : Fin n → Fin m) (v : Env m) :
(P.reindex φ).value v=P.value (v ∘ φ) := rfl
@[simp] theorem bind_value (P : Certified n) (Q : Certified (n+1)) (v : Env n) :
(P.bind Q).value v=Q.value (cons (P.value v) v) := rfl
@[simp] theorem input_value (i : Fin n) (v : Env n) : (input i).value v=v i := rfl
@[simp] theorem literal_value (w : Word) (v : Env n) : (literal w).value v=w := rfl
@[simp] theorem cons_comp_succ (w : Word) (v : Env n) : cons w v ∘ Fin.succ=v := rfl
def unary (P : Certified n) (op : Fin (n+1) → Certified (n+1)) : Certified n := P.bind (op 0)
def binary (P Q : Certified n) (op : Fin (n+2) → Fin (n+2) → Certified (n+2)) : Certified n :=
P.bind ((Q.reindex Fin.succ).bind (op 1 0))
def len (P : Certified n) : Certified n := unary P length
def plus (P Q : Certified n) : Certified n := binary P Q add
def minus (P Q : Certified n) : Certified n := binary P Q subtract
def times (P Q : Certified n) : Certified n := binary P Q multiply
def cat (P Q : Certified n) : Certified n := binary P Q append
def rev (P : Certified n) : Certified n := unary P reverse
def atIndex (P Q : Certified n) : Certified n := binary P Q lookup
def tailAt (P Q : Certified n) : Certified n := binary P Q drop
@[simp] theorem len_value (P : Certified n) (v : Env n) :
(len P).value v=List.replicate (P.value v).length true := rfl
@[simp] theorem plus_value (P Q : Certified n) (v : Env n) :
(plus P Q).value v=List.replicate ((P.value v).length+(Q.value v).length) true := rfl
@[simp] theorem minus_value (P Q : Certified n) (v : Env n) :
(minus P Q).value v=List.replicate ((P.value v).length-(Q.value v).length) true := rfl
@[simp] theorem times_value (P Q : Certified n) (v : Env n) :
(times P Q).value v=List.replicate ((P.value v).length*(Q.value v).length) true := rfl
@[simp] theorem cat_value (P Q : Certified n) (v : Env n) :
(cat P Q).value v=P.value v++Q.value v := rfl
@[simp] theorem rev_value (P : Certified n) (v : Env n) : (rev P).value v=(P.value v).reverse := rfl
@[simp] theorem atIndex_value (P Q : Certified n) (v : Env n) :
(atIndex P Q).value v=[(P.value v).getD (Q.value v).length false] := rfl
@[simp] theorem tailAt_value (P Q : Certified n) (v : Env n) :
(tailAt P Q).value v=(P.value v).drop (Q.value v).length := rfl
def asBool (P : Certified n) : Certified n := P.bind (test (fun h=>h 0==some true))
def isZero (P : Certified n) : Certified n := P.bind (test (fun h=>h 0==none))
def choose (B P Q : Certified n) : Certified n :=
B.bind (headBranch (fun h=>h 0==some true) (P.reindex Fin.succ) (Q.reindex Fin.succ))
def lessEq (P Q : Certified n) : Certified n := isZero (minus P Q)
def equal (P Q : Certified n) : Certified n := isZero (plus (minus P Q) (minus Q P))
def conj (P Q : Certified n) : Certified n :=
choose P (asBool Q) (literal [false])
@[simp] theorem asBool_value (P : Certified n) (v : Env n) :
(asBool P).value v=[decide ((P.value v).head?=some true)] := by
simp only [asBool,bind_value,test_value,cons_zero]
congr 1
apply Bool.eq_iff_iff.mpr
simp only [beq_iff_eq,decide_eq_true_eq]
@[simp] theorem isZero_value (P : Certified n) (v : Env n) :
(isZero P).value v=[decide ((P.value v).length=0)] := by
simp only [isZero,bind_value,test_value,cons_zero]
congr 1
apply Bool.eq_iff_iff.mpr
simp only [beq_iff_eq,decide_eq_true_eq,List.head?_eq_none_iff,List.length_eq_zero_iff]
@[simp] theorem choose_value (B P Q : Certified n) (v : Env n) :
(choose B P Q).value v=if (B.value v).head?=some true then P.value v else Q.value v := by
simp only [choose,bind_value,headBranch,cons_zero,beq_iff_eq,reindex_value,cons_comp_succ]
split_ifs <;> simp_all
@[simp] theorem lessEq_value (P Q : Certified n) (v : Env n) :
(lessEq P Q).value v=[decide ((P.value v).length≤(Q.value v).length)] := by
simp only [lessEq,isZero_value,minus_value,List.length_replicate,Nat.sub_eq_zero_iff_le]
@[simp] theorem equal_value (P Q : Certified n) (v : Env n) :
(equal P Q).value v=[decide ((P.value v).length=(Q.value v).length)] := by
simp only [equal,isZero_value,plus_value,minus_value,List.length_replicate]
congr 1
apply Bool.eq_iff_iff.mpr
simp only [decide_eq_true_eq]
omega
@[simp] theorem conj_value (P Q : Certified n) (v : Env n) :
(conj P Q).value v=[decide ((P.value v).head?=some true) && decide ((Q.value v).head?=some true)] := by
rw [conj,choose_value]
split_ifs <;> rename_i h <;> simp [h,asBool_value]
def liftIndices (φ : Fin n → Fin m) : Fin (n+2) → Fin (m+2) :=
Fin.cons 0 (Fin.cons 1 (fun i=>(φ i).succ.succ))
theorem lift_env (φ : Fin n → Fin m) (v : Env m) (a b : Word) :
cons a (cons b v) ∘ liftIndices φ=cons a (cons b (v ∘ φ)) := by
funext i
refine Fin.cases ?_ (fun i=>Fin.cases ?_ (fun i=>?_) i) i <;> rfl
theorem foldValue_reindex (Q : Certified (n+2)) (φ : Fin n → Fin m) (v : Env m) (w : Word) (j : ℕ) :
foldValue (Q.reindex (liftIndices φ)) v w j=foldValue Q (v ∘ φ) w j := by
induction j with
| zero => rfl
| succ j ih => simp only [foldValue,reindex_value,ih,lift_env]
def iterate (B Z : Certified n) (Q : Certified (n+2)) : Certified n :=
B.bind ((Z.reindex Fin.succ).bind (fold 1 0 (Q.reindex (liftIndices (fun i=>i.succ.succ)))))
theorem iterate_value (B Z : Certified n) (Q : Certified (n+2)) (v : Env n) :
(iterate B Z Q).value v=foldValue Q v (Z.value v) (B.value v).length := by
simp only [iterate,bind_value,reindex_value,cons_comp_succ,fold,cons_zero]
change foldValue _ (cons (Z.value v) (cons (B.value v) v)) (Z.value v) (B.value v).length=_
rw [foldValue_reindex]
rfl
def collect (B : Certified n) (Q : Certified (n+1)) : Certified n :=
iterate B (literal []) (cat (input 0) (asBool (Q.reindex Fin.succ)))
theorem collect_value (B : Certified n) (Q : Certified (n+1)) (v : Env n) :
(collect B Q).value v=(List.range (B.value v).length).map
(fun i=>decide ((Q.value (cons (List.replicate i true) v)).head?=some true)) := by
rw [collect,iterate_value]
generalize (B.value v).length=j
induction j with
| zero => rfl
| succ j ih =>
rw [foldValue,cat_value,input_value,cons_zero,ih,asBool_value,reindex_value,cons_comp_succ]
rw [List.range_succ,List.map_append]
rfl
@[simp] theorem decide_bool (b : Bool) : decide (b=true)=b := by cases b <;> rfl
def all (B : Certified n) (Q : Certified (n+1)) : Certified n :=
iterate B (literal [true]) (conj (input 0) (Q.reindex Fin.succ))
theorem all_value (B : Certified n) (Q : Certified (n+1)) (v : Env n) :
(all B Q).value v=[(List.range (B.value v).length).all
(fun i=>decide ((Q.value (cons (List.replicate i true) v)).head?=some true))] := by
rw [all,iterate_value]
generalize (B.value v).length=j
induction j with
| zero => rfl
| succ j ih =>
simp only [foldValue,conj_value,input_value,cons_zero,ih,List.head?_cons,
reindex_value,cons_comp_succ,List.range_succ,List.all_append,
List.all_cons,List.all_nil,Bool.and_true,Option.some.injEq,decide_bool]
rfl
def countTrue (B : Certified n) (Q : Certified (n+1)) : Certified n :=
iterate B (literal []) (choose (Q.reindex Fin.succ) (cat (literal [true]) (input 0)) (input 0))
theorem countTrue_value (B : Certified n) (Q : Certified (n+1)) (v : Env n) :
(countTrue B Q).value v=List.replicate ((List.range (B.value v).length).countP
(fun i=>decide ((Q.value (cons (List.replicate i true) v)).head?=some true))) true := by
rw [countTrue,iterate_value]
generalize (B.value v).length=j
induction j with
| zero => rfl
| succ j ih =>
simp only [foldValue,choose_value,reindex_value,cons_comp_succ,cat_value,literal_value,
input_value,cons_zero,List.range_succ,List.countP_append,List.countP_cons,List.countP_nil,
Nat.zero_add]
split_ifs <;> rename_i h <;> simp_all [List.replicate_succ]
def power (B E : Certified n) : Certified n :=
iterate E (literal [true]) (times (input 0) (B.reindex (fun i=>i.succ.succ)))
end VariableWL.Computation.Stack.Recipe
namespace VariableWL.Computation.Stack.Recipe
variable {n : ℕ}
theorem count_range_lt (a b : ℕ) :
(List.range a).countP (fun i=>decide (i<b))=min a b := by
induction a with
| zero => simp
| succ a ih =>
rw [List.range_succ,List.countP_append,ih]
simp only [List.countP_cons,List.countP_nil,Nat.zero_add]
split_ifs <;> rename_i h <;> simp only [decide_eq_true_eq] at h <;> omega
theorem count_range_multiples (a b : ℕ) (hb : 0<b) :
(List.range a).countP (fun i=>decide ((i+1)*b≤a))=a/b := by
have he : (List.range a).countP (fun i=>decide ((i+1)*b≤a))=
(List.range a).countP (fun i=>decide (i<a/b)) := by
apply List.countP_congr
intro i _
simp only [decide_eq_true_eq,←Nat.le_div_iff_mul_le hb]
omega
rw [he,count_range_lt,min_eq_right (Nat.div_le_self a b)]
def divide (i j : Fin n) : Certified n :=
choose (isZero (input j)) (literal [])
(countTrue (input i) (lessEq (times (plus (input 0) (literal [true])) (input j.succ)) (input i.succ)))
theorem divide_value (i j : Fin n) (v : Env n) :
(divide i j).value v=List.replicate ((v i).length/(v j).length) true := by
rw [divide,choose_value]
by_cases h : (v j).length=0
· have hz : ((isZero (input j)).value v).head?=some true := by
rw [isZero_value,input_value]
simp only [h,decide_true,List.head?_cons]
rw [ite_eq_left hz,literal_value,h,Nat.div_zero,List.replicate_zero]
· have hz : ((isZero (input j)).value v).head?≠some true := by
rw [isZero_value,input_value]
simp only [h,decide_false,List.head?_cons,ne_eq,Option.some.injEq,Bool.false_eq_true,not_false_eq_true]
rw [ite_eq_right hz,countTrue_value]
simp only [lessEq_value,times_value,plus_value,input_value,cons_zero,cons_succ,
literal_value,List.length_replicate,List.length_cons,List.length_nil,Nat.zero_add,
List.head?_cons,Option.some.injEq,decide_bool]
rw [count_range_multiples _ _ (by omega)]
def quotient (A B : Certified n) : Certified n := binary A B divide
def remainder (A B : Certified n) : Certified n := minus A (times (quotient A B) B)
theorem quotient_value (A B : Certified n) (v : Env n) :
(quotient A B).value v=List.replicate ((A.value v).length/(B.value v).length) true := by
simp only [quotient,binary,bind_value,reindex_value,cons_comp_succ,divide_value]
rfl
theorem remainder_value (A B : Certified n) (v : Env n) :
(remainder A B).value v=List.replicate ((A.value v).length%(B.value v).length) true := by
simp only [remainder,minus_value,times_value,quotient_value,List.length_replicate,Nat.mod_eq_sub_div_mul]
def minimum (A B : Certified n) : Certified n := choose (lessEq A B) (len A) (len B)
theorem minimum_value (A B : Certified n) (v : Env n) :
(minimum A B).value v=List.replicate (min (A.value v).length (B.value v).length) true := by
simp only [minimum,choose_value,lessEq_value,List.head?_cons,Option.some.injEq,decide_eq_true_eq,len_value,Nat.min_def]
split_ifs <;> rfl
theorem min_mul_cap (x c b : ℕ) : min (min x c*b) c=min (x*b) c := by
by_cases hb : b=0
· simp [hb]
· have h : c≤c*b := by simpa only [Nat.mul_one] using Nat.mul_le_mul_left c (show 1≤b by omega)
rw [←Nat.mul_min_mul_right,min_assoc,min_eq_right h]
def boundedPower (B E C : Certified n) : Certified n :=
iterate E (minimum (literal [true]) C)
(minimum (times (input 0) (B.reindex (fun i=>i.succ.succ))) (C.reindex (fun i=>i.succ.succ)))
theorem boundedPower_value (B E C : Certified n) (v : Env n) :
(boundedPower B E C).value v=List.replicate (min ((B.value v).length^(E.value v).length) (C.value v).length) true := by
rw [boundedPower,iterate_value]
generalize (E.value v).length=j
induction j with
| zero => rw [foldValue,minimum_value,literal_value]; rfl
| succ j ih =>
rw [foldValue,minimum_value,times_value,input_value,cons_zero,ih,List.length_replicate]
simp only [List.length_replicate,reindex_value]
change List.replicate (min (min ((B.value v).length^j) (C.value v).length*(B.value v).length)
(C.value v).length) true=_
rw [min_mul_cap,pow_succ]
end VariableWL.Computation.Stack.Recipe
namespace VariableWL.Computation.Stack.Recipe
variable {n m : ℕ}
def Growth (f : ℕ → ℕ) : Prop := ∃ c d : ℕ, ∀N, f N≤c*(N+1)^d
namespace Growth
theorem constant (a : ℕ) : Growth (fun _=>a) := ⟨a,0,by intro N; simp⟩
theorem ident : Growth id := ⟨1,1,by intro N; simp⟩
theorem add {f g : ℕ → ℕ} (hf : Growth f) (hg : Growth g) : Growth (fun N=>f N+g N) := by
obtain ⟨a,b,ha⟩ := hf
obtain ⟨c,d,hc⟩ := hg
refine ⟨a+c,b+d,fun N=>?_⟩
have h1 := (ha N).trans (Nat.mul_le_mul_left a (Nat.pow_le_pow_right (by omega : 0<N+1) (by omega : b≤b+d)))
have h2 := (hc N).trans (Nat.mul_le_mul_left c (Nat.pow_le_pow_right (by omega : 0<N+1) (by omega : d≤b+d)))
nlinarith
theorem mul {f g : ℕ → ℕ} (hf : Growth f) (hg : Growth g) : Growth (fun N=>f N*g N) := by
obtain ⟨a,b,ha⟩ := hf
obtain ⟨c,d,hc⟩ := hg
refine ⟨a*c,b+d,fun N=>?_⟩
exact (Nat.mul_le_mul (ha N) (hc N)).trans_eq (by rw [pow_add]; ring)
theorem comp {f g : ℕ → ℕ} (hf : Growth f) (hg : Growth g) : Growth (f ∘ g) := by
obtain ⟨a,b,ha⟩ := hf
obtain ⟨c,d,hc⟩ := hg
refine ⟨a*(c+1)^b,d*b,fun N=>?_⟩
have hpos : 1≤(N+1)^d := Nat.succ_le_of_lt (pow_pos (by omega) _)
have hh : g N+1≤(c+1)*(N+1)^d := by have := hc N; nlinarith
refine (ha (g N)).trans ((Nat.mul_le_mul_left a (Nat.pow_le_pow_left hh b)).trans_eq ?_)
rw [mul_pow,←pow_mul]
ring
theorem pow {f : ℕ → ℕ} (hf : Growth f) (d : ℕ) : Growth (fun N=>(f N)^d) := by
induction d with
| zero => simpa only [pow_zero] using constant 1
| succ d ih => simpa only [pow_succ] using mul ih hf
end Growth
def EnvBound (C : ℕ) (v : Env n) : Prop := ∀i,(v i).length≤C
def Poly (P : Certified n) : Prop := ∃f : ℕ → ℕ, Growth f ∧
∀C v, EnvBound C v → P.time v+(P.value v).length≤f C
theorem envBound_cons {C : ℕ} {v : Env n} {w : Word} (hv : EnvBound C v) (hw : w.length≤C) :
EnvBound C (cons w v) := by
intro i
exact Fin.cases hw (fun j=>hv j) i
theorem poly_of_bound (P : Certified n) (c d : ℕ)
(h : ∀C v,EnvBound C v → P.time v+(P.value v).length≤c*(C+1)^d) : Poly P :=
⟨fun C=>c*(C+1)^d,⟨c,d,fun _=>le_rfl⟩,h⟩
theorem poly_reindex {P : Certified n} (h : Poly P) (φ : Fin n → Fin m) : Poly (P.reindex φ) := by
obtain ⟨f,hf,hP⟩ := h
refine ⟨f,hf,fun C v hv=>hP C (v ∘ φ) (fun i=>hv (φ i))⟩
theorem poly_input (i : Fin n) : Poly (input i) := by
apply poly_of_bound _ 13 1
intro C v hv
have := hv i
change 9*(v i).length+3+(v i).length≤13*(C+1)^1
simp only [pow_one]
omega
theorem poly_literal (w : Word) : Poly (literal (n := n) w) := by
exact ⟨fun _=>1+3*w.length,Growth.constant _,by intro C v hv; change 1+2*w.length+w.length≤1+3*w.length; omega⟩
theorem poly_bind {P : Certified n} {Q : Certified (n+1)} (hP : Poly P) (hQ : Poly Q) : Poly (P.bind Q) := by
obtain ⟨f,hf,hP⟩ := hP
obtain ⟨g,hg,hQ⟩ := hQ
refine ⟨fun C=>4*f C+g (f C+C)+2,?_,?_⟩
· exact ((Growth.constant 4 |>.mul hf).add (hg.comp (hf.add Growth.ident))).add (Growth.constant 2)
· intro C v hv
have h1 := hP C v hv
have hev : EnvBound (f C+C) (cons (P.value v) v) :=
envBound_cons (fun i=>(hv i).trans (by omega)) (by omega)
have h2 := hQ (f C+C) (cons (P.value v) v) hev
change P.time v+Q.time (cons (P.value v) v)+3*(P.value v).length+2+
(Q.value (cons (P.value v) v)).length≤4*f C+g (f C+C)+2
omega
theorem poly_headBranch (p : (Fin n → Option Bool) → Bool) {P Q : Certified n}
(hP : Poly P) (hQ : Poly Q) : Poly (headBranch p P Q) := by
obtain ⟨f,hf,hP⟩ := hP
obtain ⟨g,hg,hQ⟩ := hQ
refine ⟨fun C=>f C+g C+1,(hf.add hg).add (Growth.constant 1),?_⟩
intro C v hv
have h1 := hP C v hv
have h2 := hQ C v hv
change (if p (fun i=>(v i).head?) then P.time v else Q.time v)+1+
(if p (fun i=>(v i).head?) then P.value v else Q.value v).length≤f C+g C+1
split <;> omega
theorem poly_test (p : (Fin n → Option Bool) → Bool) : Poly (test p) :=
poly_headBranch p (poly_literal _) (poly_literal _)
theorem poly_length (i : Fin n) : Poly (length i) := by
apply poly_of_bound _ 21 1
intro C v hv
have := hv i
change 20*((v i).length+1)+(List.replicate (v i).length true).length≤_
simp only [List.length_replicate,pow_one]
omega
theorem poly_add (i j : Fin n) : Poly (add i j) := by
apply poly_of_bound _ 42 1
intro C v hv
have := hv i
have := hv j
change 20*((v i).length+(v j).length+1)+(List.replicate ((v i).length+(v j).length) true).length≤_
simp only [List.length_replicate,pow_one]
omega
theorem poly_subtract (i j : Fin n) : Poly (subtract i j) := by
apply poly_of_bound _ 42 1
intro C v hv
have := hv i
have := hv j
change 20*((v i).length+(v j).length+1)+(List.replicate ((v i).length-(v j).length) true).length≤_
simp only [List.length_replicate,pow_one]
omega
theorem poly_multiply (i j : Fin n) : Poly (multiply i j) := by
apply poly_of_bound _ 31 2
intro C v hv
have h1 := hv i
have h2 := hv j
have hh := Nat.mul_le_mul h1 h2
change 20*((v i).length+1)*((v j).length+1)+10+
(List.replicate ((v i).length*(v j).length) true).length≤_
simp only [List.length_replicate,pow_two]
nlinarith
theorem poly_reverse (i : Fin n) : Poly (reverse i) := by
apply poly_of_bound _ 21 1
intro C v hv
have := hv i
change 20*((v i).length+1)+(v i).reverse.length≤_
simp only [List.length_reverse,pow_one]
omega
theorem poly_append (i j : Fin n) : Poly (append i j) := by
apply poly_of_bound _ 42 1
intro C v hv
have := hv i
have := hv j
change 20*((v i).length+(v j).length+1)+((v i)++(v j)).length≤_
simp only [List.length_append,pow_one]
omega
theorem poly_drop (i j : Fin n) : Poly (drop i j) := by
apply poly_of_bound _ 36 1
intro C v hv
have := hv i
have := hv j
change 24*((v i).length+1)+11*(v j).length+((v i).drop (v j).length).length≤_
simp only [List.length_drop,pow_one]
omega
theorem poly_lookup (i j : Fin n) : Poly (lookup i j) := by
apply poly_of_bound _ 24 1
intro C v hv
have := hv i
have := hv j
change 12*(v i).length+11*(v j).length+12+[_].length≤_
simp only [List.length_cons,List.length_nil,pow_one]
omega
theorem poly_unary {P : Certified n} (o : Fin (n+1) → Certified (n+1))
(hP : Poly P) (ho : ∀i,Poly (o i)) : Poly (unary P o) := poly_bind hP (ho _)
theorem poly_binary {P Q : Certified n} (o : Fin (n+2) → Fin (n+2) → Certified (n+2))
(hP : Poly P) (hQ : Poly Q) (ho : ∀i j,Poly (o i j)) : Poly (binary P Q o) :=
poly_bind hP (poly_bind (poly_reindex hQ Fin.succ) (ho _ _))
theorem poly_len {P : Certified n} (hP : Poly P) : Poly (len P) := poly_unary length hP poly_length
theorem poly_plus {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (plus P Q) := poly_binary add hP hQ poly_add
theorem poly_minus {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (minus P Q) := poly_binary subtract hP hQ poly_subtract
theorem poly_times {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (times P Q) := poly_binary multiply hP hQ poly_multiply
theorem poly_cat {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (cat P Q) := poly_binary append hP hQ poly_append
theorem poly_rev {P : Certified n} (hP : Poly P) : Poly (rev P) := poly_unary reverse hP poly_reverse
theorem poly_atIndex {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (atIndex P Q) := poly_binary lookup hP hQ poly_lookup
theorem poly_tailAt {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (tailAt P Q) := poly_binary drop hP hQ poly_drop
theorem poly_asBool {P : Certified n} (hP : Poly P) : Poly (asBool P) := poly_bind hP (poly_test _)
theorem poly_isZero {P : Certified n} (hP : Poly P) : Poly (isZero P) := poly_bind hP (poly_test _)
theorem poly_choose {B P Q : Certified n} (hB : Poly B) (hP : Poly P) (hQ : Poly Q) : Poly (choose B P Q) :=
poly_bind hB (poly_headBranch _ (poly_reindex hP _) (poly_reindex hQ _))
theorem poly_lessEq {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (lessEq P Q) := poly_isZero (poly_minus hP hQ)
theorem poly_equal {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (equal P Q) :=
poly_isZero (poly_plus (poly_minus hP hQ) (poly_minus hQ hP))
theorem poly_conj {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (conj P Q) :=
poly_choose hP (poly_asBool hQ) (poly_literal _)
theorem poly_minimum {P Q : Certified n} (hP : Poly P) (hQ : Poly Q) : Poly (minimum P Q) :=
poly_choose (poly_lessEq hP hQ) (poly_len hP) (poly_len hQ)
end VariableWL.Computation.Stack.Recipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PolyRecipe
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.Recipe
variable {n m : ℕ}
@[simp] theorem reindex_time (P : Certified n) (φ : Fin n → Fin m) (v : Env m) :
(P.reindex φ).time v=P.time (v ∘ φ) := rfl
@[simp] theorem bind_time (P : Certified n) (Q : Certified (n+1)) (v : Env n) :
(P.bind Q).time v=P.time v+Q.time (cons (P.value v) v)+3*(P.value v).length+2 := rfl
theorem fold_time (b z : Fin n) (Q : Certified (n+2)) (v : Env n) :
(fold b z Q).time v=9*(v z).length+9*(v b).length+
BoundedLoop.total (v b).length (foldTime Q v (v z))+
12*(foldValue Q v (v z) (v b).length).length+20 := rfl
theorem foldTime_reindex (Q : Certified (n+2)) (φ : Fin n → Fin m) (v : Env m) (w : Word) (j : ℕ) :
foldTime (Q.reindex (liftIndices φ)) v w j=foldTime Q (v ∘ φ) w j := by
simp only [foldTime,reindex_time,foldValue_reindex,lift_env]
theorem iterate_time (B Z : Certified n) (Q : Certified (n+2)) (v : Env n) :
(iterate B Z Q).time v=B.time v+Z.time v+12*(B.value v).length+12*(Z.value v).length+
BoundedLoop.total (B.value v).length (foldTime Q v (Z.value v))+
12*(foldValue Q v (Z.value v) (B.value v).length).length+24 := by
simp only [iterate,bind_time,reindex_time,cons_comp_succ,fold_time]
change B.time v+(Z.time v+(9*(Z.value v).length+9*(B.value v).length+
BoundedLoop.total (B.value v).length (foldTime (Q.reindex (liftIndices (fun i=>i.succ.succ)))
(cons (Z.value v) (cons (B.value v) v)) (Z.value v))+
12*(foldValue (Q.reindex (liftIndices (fun i=>i.succ.succ)))
(cons (Z.value v) (cons (B.value v) v)) (Z.value v) (B.value v).length).length+20)+
3*(Z.value v).length+2)+3*(B.value v).length+2=_
have he : foldTime (Q.reindex (liftIndices (fun i=>i.succ.succ)))
(cons (Z.value v) (cons (B.value v) v)) (Z.value v)=foldTime Q v (Z.value v) := by
funext j
rw [foldTime_reindex]
rfl
rw [he,foldValue_reindex]
change B.time v+(Z.time v+(9*(Z.value v).length+9*(B.value v).length+
BoundedLoop.total (B.value v).length (foldTime Q v (Z.value v))+
12*(foldValue Q v (Z.value v) (B.value v).length).length+20)+
3*(Z.value v).length+2)+3*(B.value v).length+2=_
omega
theorem poly_iterate {B Z : Certified n} {Q : Certified (n+2)}
(hB : Poly B) (hZ : Poly Z) (hQ : Poly Q)
(f : ℕ → ℕ) (hf : Growth f)
(hacc : ∀C v,EnvBound C v → ∀j≤(B.value v).length,(foldValue Q v (Z.value v) j).length≤f C) :
Poly (iterate B Z Q) := by
obtain ⟨b,hb,hB⟩ := hB
obtain ⟨z,hz,hZ⟩ := hZ
obtain ⟨q,hq,hQ⟩ := hQ
let D : ℕ → ℕ := fun C=>b C+f C+C
have hD : Growth D := (hb.add hf).add Growth.ident
refine ⟨fun C=>13*(b C+z C+f C)+(q (D C)+3*f C+6)*b C+24,?_,?_⟩
· exact (((Growth.constant 13).mul ((hb.add hz).add hf)).add
((((hq.comp hD).add ((Growth.constant 3).mul hf)).add (Growth.constant 6)).mul hb)).add (Growth.constant 24)
· intro C v hv
have h1 := hB C v hv
have h2 := hZ C v hv
have h3 := hacc C v hv (B.value v).length le_rfl
have hcost (j : ℕ) (hj : j<(B.value v).length) : foldTime Q v (Z.value v) j≤q (D C)+3*f C+2 := by
have h4 := hacc C v hv j (by omega)
have hev : EnvBound (D C) (cons (foldValue Q v (Z.value v) j) (cons (List.replicate j true) v)) := by
apply envBound_cons
· apply envBound_cons
· intro i; have := hv i; dsimp only [D]; omega
· simp only [List.length_replicate]; dsimp only [D]; omega
· dsimp only [D]; omega
have h5 := hQ (D C) _ hev
unfold foldTime
omega
have htot := BoundedLoop.total_bound (B.value v).length (q (D C)+3*f C+2) _ hcost
have htot' : BoundedLoop.total (B.value v).length (foldTime Q v (Z.value v))≤
(q (D C)+3*f C+6)*b C := by
apply htot.trans
have hm := Nat.mul_le_mul_left (q (D C)+3*f C+6) (show (B.value v).length≤b C by omega)
simpa only [Nat.add_assoc] using hm
rw [iterate_time,iterate_value]
change B.time v+Z.time v+12*(B.value v).length+12*(Z.value v).length+
BoundedLoop.total (B.value v).length (foldTime Q v (Z.value v))+
12*(foldValue Q v (Z.value v) (B.value v).length).length+24+
(foldValue Q v (Z.value v) (B.value v).length).length≤
13*(b C+z C+f C)+(q (D C)+3*f C+6)*b C+24
omega
theorem collect_prefix (Q : Certified (n+1)) (v : Env n) (j : ℕ) :
(foldValue (cat (input 0) (asBool (Q.reindex Fin.succ))) v [] j).length=j := by
have h := collect_value (literal (List.replicate j true)) Q v
rw [collect,iterate_value] at h
simp only [literal_value,List.length_replicate] at h
rw [h,List.length_map,List.length_range]
theorem all_prefix (Q : Certified (n+1)) (v : Env n) (j : ℕ) :
(foldValue (conj (input 0) (Q.reindex Fin.succ)) v [true] j).length=1 := by
have h := all_value (literal (List.replicate j true)) Q v
rw [all,iterate_value] at h
simp only [literal_value,List.length_replicate] at h
rw [h]
rfl
theorem countTrue_prefix (Q : Certified (n+1)) (v : Env n) (j : ℕ) :
(foldValue (choose (Q.reindex Fin.succ) (cat (literal [true]) (input 0)) (input 0)) v [] j).length≤j := by
have h := countTrue_value (literal (List.replicate j true)) Q v
rw [countTrue,iterate_value] at h
simp only [literal_value,List.length_replicate] at h
rw [h,List.length_replicate]
exact (List.countP_le_length).trans_eq (List.length_range (n := j))
theorem poly_collect {B : Certified n} {Q : Certified (n+1)} (hB : Poly B) (hQ : Poly Q) : Poly (collect B Q) := by
obtain ⟨b,hb,h⟩ := hB
apply poly_iterate ⟨b,hb,h⟩ (poly_literal _) (poly_cat (poly_input _) (poly_asBool (poly_reindex hQ _))) b hb
intro C v hv j hj
rw [literal_value,collect_prefix]
have hh := h C v hv
omega
theorem poly_all {B : Certified n} {Q : Certified (n+1)} (hB : Poly B) (hQ : Poly Q) : Poly (all B Q) := by
apply poly_iterate hB (poly_literal _) (poly_conj (poly_input _) (poly_reindex hQ _)) (fun _=>1) (Growth.constant 1)
intro C v hv j hj
rw [literal_value,all_prefix]
theorem poly_countTrue {B : Certified n} {Q : Certified (n+1)} (hB : Poly B) (hQ : Poly Q) : Poly (countTrue B Q) := by
obtain ⟨b,hb,h⟩ := hB
apply poly_iterate ⟨b,hb,h⟩ (poly_literal _)
(poly_choose (poly_reindex hQ _) (poly_cat (poly_literal _) (poly_input _)) (poly_input _)) b hb
intro C v hv j hj
rw [literal_value]
have hh := h C v hv
exact (countTrue_prefix Q v j).trans (by omega)
theorem poly_divide (i j : Fin n) : Poly (divide i j) :=
poly_choose (poly_isZero (poly_input _)) (poly_literal _)
(poly_countTrue (poly_input _) (poly_lessEq (poly_times (poly_plus (poly_input _) (poly_literal _)) (poly_input _)) (poly_input _)))
theorem poly_quotient {A B : Certified n} (hA : Poly A) (hB : Poly B) : Poly (quotient A B) :=
poly_binary divide hA hB poly_divide
theorem poly_remainder {A B : Certified n} (hA : Poly A) (hB : Poly B) : Poly (remainder A B) :=
poly_minus hA (poly_times (poly_quotient hA hB) hB)
theorem boundedPower_prefix (B C : Certified n) (v : Env n) (j : ℕ) :
(foldValue (minimum (times (input 0) (B.reindex (fun i=>i.succ.succ))) (C.reindex (fun i=>i.succ.succ)))
v ((minimum (literal [true]) C).value v) j).length≤(C.value v).length := by
have h := boundedPower_value B (literal (List.replicate j true)) C v
rw [boundedPower,iterate_value] at h
simp only [literal_value,List.length_replicate] at h
rw [h,List.length_replicate]
exact min_le_right _ _
theorem poly_boundedPower {B E C : Certified n} (hB : Poly B) (hE : Poly E) (hC : Poly C) :
Poly (boundedPower B E C) := by
obtain ⟨c,hc,h⟩ := hC
apply poly_iterate hE (poly_minimum (poly_literal _) ⟨c,hc,h⟩)
(poly_minimum (poly_times (poly_input _) (poly_reindex hB _)) (poly_reindex ⟨c,hc,h⟩ _)) c hc
intro N v hv j hj
have hh := h N v hv
exact (boundedPower_prefix B C v j).trans (by omega)
end VariableWL.Computation.Stack.Recipe
namespace VariableWL.Computation.Stack
namespace PolyRecipe
open Recipe
structure Expr (n : ℕ) where
program : Certified n
polynomial : Poly program
variable {n m : ℕ}
def Expr.value (P : Expr n) := P.program.value
def Expr.number (P : Expr n) (v : Env n) := (P.value v).length
def Expr.bit (P : Expr n) (v : Env n) := decide ((P.value v).head?=some true)
def Expr.reindex (P : Expr n) (φ : Fin n → Fin m) : Expr m :=
⟨P.program.reindex φ,poly_reindex P.polynomial φ⟩
def Expr.up (P : Expr n) : Expr (n+1) := P.reindex Fin.succ
def Expr.up₂ (P : Expr n) : Expr (n+2) := P.reindex (fun i=>i.succ.succ)
def input (i : Fin n) : Expr n := ⟨Recipe.input i,poly_input i⟩
def literal (w : Word) : Expr n := ⟨Recipe.literal w,poly_literal w⟩
def numeral (a : ℕ) : Expr n := literal (List.replicate a true)
def add (P Q : Expr n) : Expr n := ⟨plus P.program Q.program,poly_plus P.polynomial Q.polynomial⟩
def sub (P Q : Expr n) : Expr n := ⟨minus P.program Q.program,poly_minus P.polynomial Q.polynomial⟩
def mul (P Q : Expr n) : Expr n := ⟨times P.program Q.program,poly_times P.polynomial Q.polynomial⟩
def div (P Q : Expr n) : Expr n := ⟨quotient P.program Q.program,poly_quotient P.polynomial Q.polynomial⟩
def mod (P Q : Expr n) : Expr n := ⟨remainder P.program Q.program,poly_remainder P.polynomial Q.polynomial⟩
def capPow (P Q C : Expr n) : Expr n :=
⟨boundedPower P.program Q.program C.program,poly_boundedPower P.polynomial Q.polynomial C.polynomial⟩
def eq (P Q : Expr n) : Expr n := ⟨equal P.program Q.program,poly_equal P.polynomial Q.polynomial⟩
def le (P Q : Expr n) : Expr n := ⟨lessEq P.program Q.program,poly_lessEq P.polynomial Q.polynomial⟩
def choose (B P Q : Expr n) : Expr n :=
⟨Recipe.choose B.program P.program Q.program,poly_choose B.polynomial P.polynomial Q.polynomial⟩
def neg (P : Expr n) : Expr n := choose P (literal [false]) (literal [true])
def lt (P Q : Expr n) : Expr n := neg (le Q P)
def conj (P Q : Expr n) : Expr n := ⟨Recipe.conj P.program Q.program,poly_conj P.polynomial Q.polynomial⟩
def bitEq (P Q : Expr n) : Expr n := choose P Q (neg Q)
def lookup (P Q : Expr n) : Expr n := ⟨atIndex P.program Q.program,poly_atIndex P.polynomial Q.polynomial⟩
def all (B : Expr n) (Q : Expr (n+1)) : Expr n := ⟨Recipe.all B.program Q.program,poly_all B.polynomial Q.polynomial⟩
def collect (B : Expr n) (Q : Expr (n+1)) : Expr n :=
⟨Recipe.collect B.program Q.program,poly_collect B.polynomial Q.polynomial⟩
def count (B : Expr n) (Q : Expr (n+1)) : Expr n :=
⟨countTrue B.program Q.program,poly_countTrue B.polynomial Q.polynomial⟩
@[simp] theorem reindex_value (P : Expr n) (φ : Fin n → Fin m) (v : Env m) :
(P.reindex φ).value v=P.value (v ∘ φ) := rfl
@[simp] theorem up_value (P : Expr n) (v : Env n) (w : Word) : P.up.value (cons w v)=P.value v := rfl
@[simp] theorem up₂_value (P : Expr n) (v : Env n) (w z : Word) : P.up₂.value (cons z (cons w v))=P.value v := rfl
@[simp] theorem input_value (i : Fin n) (v : Env n) : (input i).value v=v i := rfl
@[simp] theorem literal_value (w : Word) (v : Env n) : (literal w).value v=w := rfl
@[simp] theorem numeral_number (a : ℕ) (v : Env n) : (numeral a).number v=a := List.length_replicate ..
@[simp] theorem reindex_number (P : Expr n) (φ : Fin n → Fin m) (v : Env m) :
(P.reindex φ).number v=P.number (v ∘ φ) := rfl
@[simp] theorem up_number (P : Expr n) (v : Env n) (w : Word) : P.up.number (cons w v)=P.number v := rfl
@[simp] theorem up₂_number (P : Expr n) (v : Env n) (w z : Word) : P.up₂.number (cons z (cons w v))=P.number v := rfl
@[simp] theorem input_number (i : Fin n) (v : Env n) : (input i).number v=(v i).length := rfl
@[simp] theorem add_number (P Q : Expr n) (v : Env n) : (add P Q).number v=P.number v+Q.number v := by
simp only [Expr.number,Expr.value,add,plus_value,List.length_replicate]
@[simp] theorem sub_number (P Q : Expr n) (v : Env n) : (sub P Q).number v=P.number v-Q.number v := by
simp only [Expr.number,Expr.value,sub,minus_value,List.length_replicate]
@[simp] theorem mul_number (P Q : Expr n) (v : Env n) : (mul P Q).number v=P.number v*Q.number v := by
simp only [Expr.number,Expr.value,mul,times_value,List.length_replicate]
@[simp] theorem div_number (P Q : Expr n) (v : Env n) : (div P Q).number v=P.number v/Q.number v := by
simp only [Expr.number,Expr.value,div,quotient_value,List.length_replicate]
@[simp] theorem mod_number (P Q : Expr n) (v : Env n) : (mod P Q).number v=P.number v%Q.number v := by
simp only [Expr.number,Expr.value,mod,remainder_value,List.length_replicate]
@[simp] theorem capPow_number (P Q C : Expr n) (v : Env n) :
(capPow P Q C).number v=min (P.number v^Q.number v) (C.number v) := by
simp only [Expr.number,Expr.value,capPow,boundedPower_value,List.length_replicate]
@[simp] theorem eq_value (P Q : Expr n) (v : Env n) : (eq P Q).value v=[decide (P.number v=Q.number v)] :=
equal_value ..
@[simp] theorem le_value (P Q : Expr n) (v : Env n) : (le P Q).value v=[decide (P.number v≤Q.number v)] :=
lessEq_value ..
@[simp] theorem choose_value (B P Q : Expr n) (v : Env n) :
(choose B P Q).value v=if B.bit v then P.value v else Q.value v := by
simp only [Expr.value,Expr.bit,choose,Recipe.choose_value]
by_cases h : (B.program.value v).head?=some true <;> simp [h]
@[simp] theorem neg_value (P : Expr n) (v : Env n) : (neg P).value v=[!(P.bit v)] := by
rw [neg,choose_value,literal_value,literal_value]
cases P.bit v <;> rfl
@[simp] theorem lt_value (P Q : Expr n) (v : Env n) : (lt P Q).value v=[decide (P.number v<Q.number v)] := by
simp only [lt,neg_value,Expr.bit,le_value,List.head?_cons,Option.some.injEq,decide_bool]
congr 1
apply Bool.eq_iff_iff.mpr
simp
theorem bit_singleton (P : Expr n) (v : Env n) (b : Bool) (h : P.value v=[b]) : P.bit v=b := by
unfold Expr.bit
simp only [h,List.head?_cons,Option.some.injEq,decide_bool]
@[simp] theorem eq_bit (P Q : Expr n) (v : Env n) : (eq P Q).bit v=decide (P.number v=Q.number v) := bit_singleton _ _ _ (eq_value P Q v)
@[simp] theorem le_bit (P Q : Expr n) (v : Env n) : (le P Q).bit v=decide (P.number v≤Q.number v) := bit_singleton _ _ _ (le_value P Q v)
@[simp] theorem lt_bit (P Q : Expr n) (v : Env n) : (lt P Q).bit v=decide (P.number v<Q.number v) := bit_singleton _ _ _ (lt_value P Q v)
@[simp] theorem neg_bit (P : Expr n) (v : Env n) : (neg P).bit v=!(P.bit v) := bit_singleton _ _ _ (neg_value P v)
@[simp] theorem conj_value (P Q : Expr n) (v : Env n) : (conj P Q).value v=[P.bit v && Q.bit v] := Recipe.conj_value ..
@[simp] theorem conj_bit (P Q : Expr n) (v : Env n) : (conj P Q).bit v=(P.bit v && Q.bit v) := bit_singleton _ _ _ (conj_value P Q v)
@[simp] theorem choose_bit (B P Q : Expr n) (v : Env n) :
(choose B P Q).bit v=if B.bit v then P.bit v else Q.bit v := by
change decide (((choose B P Q).value v).head?=some true)=_
rw [choose_value]
split <;> rfl
@[simp] theorem bitEq_bit (P Q : Expr n) (v : Env n) : (bitEq P Q).bit v=decide (P.bit v=Q.bit v) := by
rw [bitEq,choose_bit,neg_bit]
cases P.bit v <;> cases Q.bit v <;> rfl
@[simp] theorem lookup_value (P Q : Expr n) (v : Env n) : (lookup P Q).value v=[(P.value v).getD (Q.number v) false] :=
atIndex_value ..
@[simp] theorem lookup_bit (P Q : Expr n) (v : Env n) : (lookup P Q).bit v=(P.value v).getD (Q.number v) false := bit_singleton _ _ _ (lookup_value P Q v)
@[simp] theorem all_value (B : Expr n) (Q : Expr (n+1)) (v : Env n) :
(all B Q).value v=[(List.range (B.number v)).all (fun i=>Q.bit (cons (List.replicate i true) v))] := Recipe.all_value ..
@[simp] theorem all_bit (B : Expr n) (Q : Expr (n+1)) (v : Env n) :
(all B Q).bit v=(List.range (B.number v)).all (fun i=>Q.bit (cons (List.replicate i true) v)) := bit_singleton _ _ _ (all_value B Q v)
@[simp] theorem collect_value (B : Expr n) (Q : Expr (n+1)) (v : Env n) :
(collect B Q).value v=(List.range (B.number v)).map (fun i=>Q.bit (cons (List.replicate i true) v)) := Recipe.collect_value ..
@[simp] theorem count_number (B : Expr n) (Q : Expr (n+1)) (v : Env n) :
(count B Q).number v=(List.range (B.number v)).countP (fun i=>Q.bit (cons (List.replicate i true) v)) := by
simp only [Expr.number,Expr.value,count,countTrue_value,List.length_replicate]
rfl
end PolyRecipe
end VariableWL.Computation.Stack
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_NumericProgram
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.NumericProgram
open Computation.Stack Computation.Stack.Recipe Computation.Stack.PolyRecipe
variable {n m : ℕ}
@[simp] theorem cons_one (w z : Word) (v : Env n) : cons z (cons w v) (1 : Fin (n+2))=w := rfl
structure Data (n : ℕ) where
leftOrder : Expr n
rightOrder : Expr n
dimension : Expr n
leftMatrix : Expr n
rightMatrix : Expr n
capacity : Expr n
def Data.reindex (D : Data n) (φ : Fin n → Fin m) : Data m :=
⟨D.leftOrder.reindex φ,D.rightOrder.reindex φ,D.dimension.reindex φ,
D.leftMatrix.reindex φ,D.rightMatrix.reindex φ,D.capacity.reindex φ⟩
def Data.up (D : Data n) : Data (n+1) := D.reindex Fin.succ
def Data.up₂ (D : Data n) : Data (n+2) := D.reindex (fun i=>i.succ.succ)
def Data.eval (D : Data n) (v : Env n) : NumericRefinement.Data :=
⟨D.leftOrder.number v,D.rightOrder.number v,D.dimension.number v,D.leftMatrix.value v,D.rightMatrix.value v⟩
@[simp] theorem eval_reindex (D : Data n) (φ : Fin n → Fin m) (v : Env m) :
(D.reindex φ).eval v=D.eval (v ∘ φ) := rfl
@[simp] theorem eval_up (D : Data n) (v : Env n) (w : Word) : D.up.eval (cons w v)=D.eval v := rfl
@[simp] theorem eval_up₂ (D : Data n) (v : Env n) (w z : Word) : D.up₂.eval (cons z (cons w v))=D.eval v := rfl
@[simp] theorem choose_number (B P Q : Expr n) (v : Env n) :
(PolyRecipe.choose B P Q).number v=if B.bit v then P.number v else Q.number v := by
unfold Expr.number
rw [PolyRecipe.choose_value]
split <;> rfl
@[simp] theorem up_bit (P : Expr n) (v : Env n) (w : Word) : P.up.bit (cons w v)=P.bit v := rfl
@[simp] theorem up₂_bit (P : Expr n) (v : Env n) (w z : Word) : P.up₂.bit (cons z (cons w v))=P.bit v := rfl
def Data.leftCount (D : Data n) : Expr n := capPow D.leftOrder D.dimension D.capacity
def Data.rightCount (D : Data n) : Expr n := capPow D.rightOrder D.dimension D.capacity
def Data.count (D : Data n) : Expr n := add D.leftCount D.rightCount
def Data.isLeft (D : Data n) (a : Expr n) : Expr n := lt a D.leftCount
def Data.order (D : Data n) (a : Expr n) : Expr n := PolyRecipe.choose (D.isLeft a) D.leftOrder D.rightOrder
def Data.offset (D : Data n) (a : Expr n) : Expr n := PolyRecipe.choose (D.isLeft a) (numeral 0) D.leftCount
def Data.power (D : Data n) (a i : Expr n) : Expr n := capPow (D.order a) i D.capacity
def Data.coordinate (D : Data n) (a i : Expr n) : Expr n := mod (div (sub a (D.offset a)) (D.power a i)) (D.order a)
def Data.replacement (D : Data n) (a z i : Expr n) : Expr n :=
add (D.offset a) (add (sub (sub a (D.offset a)) (mul (D.coordinate a i) (D.power a i))) (mul z (D.power a i)))
def Data.edge (D : Data n) (a i j : Expr n) : Expr n :=
PolyRecipe.lookup (PolyRecipe.choose (D.isLeft a) D.leftMatrix D.rightMatrix)
(add (mul (D.coordinate a i) (D.order a)) (D.coordinate a j))
def Data.initial (D : Data n) (a b : Expr n) : Expr n :=
PolyRecipe.all D.dimension (PolyRecipe.all D.up.dimension
(PolyRecipe.conj (bitEq (PolyRecipe.eq (D.up₂.coordinate a.up₂ (PolyRecipe.input 1)) (D.up₂.coordinate a.up₂ (PolyRecipe.input 0)))
(PolyRecipe.eq (D.up₂.coordinate b.up₂ (PolyRecipe.input 1)) (D.up₂.coordinate b.up₂ (PolyRecipe.input 0))))
(bitEq (D.up₂.edge a.up₂ (PolyRecipe.input 1) (PolyRecipe.input 0))
(D.up₂.edge b.up₂ (PolyRecipe.input 1) (PolyRecipe.input 0)))))
end VariableWL.NumericProgram
namespace VariableWL.NumericProgram
open Computation.Stack Computation.Stack.Recipe Computation.Stack.PolyRecipe
variable {n : ℕ}
def sameRanges (A B : Expr n) (AA AB BA BB : Expr (n+2)) : Expr n :=
PolyRecipe.conj
(PolyRecipe.all A (PolyRecipe.eq (PolyRecipe.count A.up AA) (PolyRecipe.count B.up AB)))
(PolyRecipe.all B (PolyRecipe.eq (PolyRecipe.count A.up BA) (PolyRecipe.count B.up BB)))
def Data.get (D : Data n) (R a b : Expr n) : Expr n := PolyRecipe.lookup R (add (mul a D.count) b)
def Data.profile (D : Data n) (R a z b w : Expr n) : Expr n :=
PolyRecipe.all D.dimension (D.up.get R.up (D.up.replacement a.up z.up (PolyRecipe.input 0))
(D.up.replacement b.up w.up (PolyRecipe.input 0)))
def Data.comparison (D : Data n) (R a b : Expr n) : Expr n :=
sameRanges (D.order a) (D.order b)
(D.up₂.profile R.up₂ a.up₂ (PolyRecipe.input 1) a.up₂ (PolyRecipe.input 0))
(D.up₂.profile R.up₂ a.up₂ (PolyRecipe.input 1) b.up₂ (PolyRecipe.input 0))
(D.up₂.profile R.up₂ b.up₂ (PolyRecipe.input 1) a.up₂ (PolyRecipe.input 0))
(D.up₂.profile R.up₂ b.up₂ (PolyRecipe.input 1) b.up₂ (PolyRecipe.input 0))
def Data.update (D : Data n) (R a b : Expr n) : Expr n := PolyRecipe.conj (D.get R a b) (D.comparison R a b)
def Data.initialArray (D : Data n) : Expr n :=
PolyRecipe.collect (mul D.count D.count)
(D.up.initial (div (PolyRecipe.input 0) D.up.count) (mod (PolyRecipe.input 0) D.up.count))
def Data.nextArray (D : Data n) (R : Expr n) : Expr n :=
PolyRecipe.collect (mul D.count D.count)
(D.up.update R.up (div (PolyRecipe.input 0) D.up.count) (mod (PolyRecipe.input 0) D.up.count))
end VariableWL.NumericProgram
namespace VariableWL.NumericProgram
open Computation.Stack Computation.Stack.Recipe Computation.Stack.PolyRecipe
variable {n : ℕ}
theorem count_up₂ (D : Data n) (v : Env n) (w z : Word) :
D.up₂.count.number (cons z (cons w v))=D.count.number v := by
simp only [Data.count,add_number,Data.leftCount,Data.rightCount,capPow_number]
rfl
theorem initialArray_length (D : Data n) (v : Env n) :
(D.initialArray.value v).length=D.count.number v^2 := by
rw [Data.initialArray,PolyRecipe.collect_value,List.length_map,List.length_range,mul_number,pow_two]
theorem nextArray_length (D : Data n) (R : Expr n) (v : Env n) :
((D.nextArray R).value v).length=D.count.number v^2 := by
rw [Data.nextArray,PolyRecipe.collect_value,List.length_map,List.length_range,mul_number,pow_two]
def Data.arrayBody (D : Data n) : Expr (n+2) := D.up₂.nextArray (PolyRecipe.input 0)
def Data.arrayProgram (D : Data n) : Certified n :=
Recipe.iterate (mul D.count D.count).program D.initialArray.program D.arrayBody.program
theorem arrayPrefix_length (D : Data n) (v : Env n) (j : ℕ) :
(Recipe.foldValue D.arrayBody.program v (D.initialArray.value v) j).length=D.count.number v^2 := by
cases j with
| zero => exact initialArray_length D v
| succ j =>
change ((D.up₂.nextArray (PolyRecipe.input 0)).value _).length=_
rw [nextArray_length,count_up₂]
theorem arrayProgram_poly (D : Data n) : Poly D.arrayProgram := by
obtain ⟨f,hf,h⟩ := D.count.polynomial
apply Recipe.poly_iterate (mul D.count D.count).polynomial D.initialArray.polynomial D.arrayBody.polynomial
(fun C=>(f C)^2) (hf.pow 2)
intro C v hv j hj
change (Recipe.foldValue D.arrayBody.program v (D.initialArray.value v) j).length≤(f C)^2
rw [arrayPrefix_length]
have hb := h C v hv
exact Nat.pow_le_pow_left (show D.count.number v≤f C by exact (Nat.le_add_left _ _).trans hb) 2
def Data.array (D : Data n) : Expr n := ⟨D.arrayProgram,arrayProgram_poly D⟩
def Data.histogram (D : Data n) (R : Expr n) : Expr n :=
sameRanges D.leftCount D.rightCount
(D.up₂.get R.up₂ (PolyRecipe.input 1) (PolyRecipe.input 0))
(D.up₂.get R.up₂ (PolyRecipe.input 1) (add D.up₂.leftCount (PolyRecipe.input 0)))
(D.up₂.get R.up₂ (add D.up₂.leftCount (PolyRecipe.input 1)) (PolyRecipe.input 0))
(D.up₂.get R.up₂ (add D.up₂.leftCount (PolyRecipe.input 1)) (add D.up₂.leftCount (PolyRecipe.input 0)))
def Data.accepts (D : Data n) : Expr n := D.histogram D.array
end VariableWL.NumericProgram
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def Expr.bind (P : Expr n) (Q : Expr (n+1)) : Expr n :=
⟨P.program.bind Q.program,poly_bind P.polynomial Q.polynomial⟩
@[simp] theorem bind_value (P : Expr n) (Q : Expr (n+1)) (v : Env n) :
(P.bind Q).value v=Q.value (cons (P.value v) v) := rfl
def length (P : Expr n) : Expr n := ⟨Recipe.len P.program,poly_len P.polynomial⟩
def reverse (P : Expr n) : Expr n := ⟨Recipe.rev P.program,poly_rev P.polynomial⟩
def drop (P Q : Expr n) : Expr n := ⟨tailAt P.program Q.program,poly_tailAt P.polynomial Q.polynomial⟩
def minimum (P Q : Expr n) : Expr n := ⟨Recipe.minimum P.program Q.program,poly_minimum P.polynomial Q.polynomial⟩
def append (P Q : Expr n) : Expr n := ⟨cat P.program Q.program,poly_cat P.polynomial Q.polynomial⟩
@[simp] theorem length_number (P : Expr n) (v : Env n) : (length P).number v=(P.value v).length := by
simp only [Expr.number,Expr.value,length,len_value,List.length_replicate]
@[simp] theorem reverse_value (P : Expr n) (v : Env n) : (reverse P).value v=(P.value v).reverse := Recipe.rev_value ..
@[simp] theorem drop_value (P Q : Expr n) (v : Env n) : (drop P Q).value v=(P.value v).drop (Q.number v) := tailAt_value ..
@[simp] theorem minimum_value (P Q : Expr n) (v : Env n) :
(minimum P Q).value v=List.replicate (min (P.number v) (Q.number v)) true := Recipe.minimum_value ..
@[simp] theorem minimum_number (P Q : Expr n) (v : Env n) : (minimum P Q).number v=min (P.number v) (Q.number v) := by
unfold Expr.number
rw [minimum_value,List.length_replicate]
rfl
@[simp] theorem append_value (P Q : Expr n) (v : Env n) : (append P Q).value v=P.value v++Q.value v := cat_value ..
def foldWordIndices (n : ℕ) : Fin (n+2) → Fin (n+3) :=
Fin.cons 1 (Fin.cons 0 (fun i=>i.succ.succ.succ))
theorem foldWord_env (v : Env n) (acc bit index : Word) :
cons bit (cons acc (cons index v)) ∘ foldWordIndices n=cons acc (cons bit v) := by
funext i
refine Fin.cases ?_ (fun i=>Fin.cases ?_ (fun i=>?_) i) i <;> rfl
def foldWordBody (W : Expr n) (Q : Expr (n+2)) : Expr (n+2) :=
(lookup W.up₂ (input 1)).bind (Q.reindex (foldWordIndices n))
theorem foldWordBody_value (W : Expr n) (Q : Expr (n+2)) (v : Env n) (acc : Word) (i : ℕ) :
(foldWordBody W Q).value (cons acc (cons (List.replicate i true) v))=
Q.value (cons acc (cons [(W.value v).getD i false] v)) := by
rw [foldWordBody,bind_value,reindex_value,lookup_value,up₂_value,input_number]
change Q.value (cons [(W.value v).getD (List.replicate i true).length false]
(cons acc (cons (List.replicate i true) v)) ∘ foldWordIndices n)=_
rw [List.length_replicate,foldWord_env]
def foldWordStep (Q : Expr (n+2)) (v : Env n) (a : Word) (b : Bool) : Word := Q.value (cons a (cons [b] v))
theorem foldWord_prefix (W Z : Expr n) (Q : Expr (n+2)) (v : Env n) (j : ℕ) (hj : j≤(W.value v).length) :
foldValue (foldWordBody W Q).program v (Z.value v) j=
((W.value v).take j).foldl (foldWordStep Q v) (Z.value v) := by
induction j with
| zero => rfl
| succ j ih =>
have hj' : j<(W.value v).length := by omega
change (foldWordBody W Q).value (cons (foldValue (foldWordBody W Q).program v (Z.value v) j)
(cons (List.replicate j true) v))=_
rw [foldWordBody_value,ih (by omega),List.take_succ_eq_append_getElem hj',List.foldl_append,List.foldl_cons,List.foldl_nil]
unfold foldWordStep
rw [List.getD_eq_getElem _ _ hj']
def foldWordProgram (W Z : Expr n) (Q : Expr (n+2)) : Certified n :=
Recipe.iterate (length W).program Z.program (foldWordBody W Q).program
theorem foldWordProgram_poly (W Z : Expr n) (Q : Expr (n+2)) (F : ℕ → ℕ) (hF : Growth F)
(hacc : ∀C v,EnvBound C v → ∀j≤(W.value v).length,
(((W.value v).take j).foldl (foldWordStep Q v) (Z.value v)).length≤F C) :
Poly (foldWordProgram W Z Q) := by
apply poly_iterate (length W).polynomial Z.polynomial (foldWordBody W Q).polynomial F hF
intro C v hv j hj
change j≤(length W).number v at hj
rw [length_number] at hj
change (foldValue (foldWordBody W Q).program v (Z.value v) j).length≤F C
rw [foldWord_prefix _ _ _ _ _ hj]
exact hacc C v hv j hj
end VariableWL.Computation.Stack.PolyRecipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_MatrixOutput
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
@[simp] theorem input_one_bit (a : Word) (b : Bool) (v : Env n) :
(input (1 : Fin (n+2))).bit (cons a (cons [b] v))=b := by cases b <;> rfl
def binaryStep (C : Expr n) : Expr (n+2) :=
minimum (add (mul (numeral 2) (input 0)) (choose (input 1) (numeral 1) (numeral 0))) C.up₂
theorem binaryStep_value (C : Expr n) (v : Env n) (a : Word) (b : Bool) :
(binaryStep C).value (cons a (cons [b] v))=List.replicate (min (2*a.length+b.toNat) (C.number v)) true := by
rw [binaryStep,minimum_value,add_number,mul_number,numeral_number,input_number,cons_zero,
NumericProgram.choose_number,input_one_bit,numeral_number,numeral_number,up₂_number]
cases b <;> rfl
theorem min_double (q C b : ℕ) : min (2*min q C+b) C=min (2*q+b) C := by
by_cases h : q≤C
· rw [min_eq_left h]
· have hq : C≤q := by omega
rw [min_eq_right hq,min_eq_right (by omega),min_eq_right (by omega)]
theorem binary_fold (C : Expr n) (v : Env n) (w : Word) (q : ℕ) :
w.foldl (foldWordStep (binaryStep C) v) (List.replicate (min q (C.number v)) true)=
List.replicate (min (BinaryMachine.value w q) (C.number v)) true := by
induction w generalizing q with
| nil => rfl
| cons b w ih =>
rw [List.foldl_cons]
unfold foldWordStep
rw [binaryStep_value,List.length_replicate,min_double]
exact ih (2*q+b.toNat)
theorem binary_poly (W C : Expr n) : Poly (foldWordProgram (reverse W) (numeral 0) (binaryStep C)) := by
obtain ⟨f,hf,h⟩ := C.polynomial
apply foldWordProgram_poly _ _ _ f hf
intro N v hv j hj
have h0 : (numeral (0 : ℕ) : Expr n).value v=List.replicate (min 0 (C.number v)) true := by simp [numeral]
rw [h0,binary_fold,List.length_replicate]
have hc := h N v hv
exact (min_le_right _ _).trans (by exact (Nat.le_add_left _ _).trans hc)
def binary (W C : Expr n) : Expr n := ⟨foldWordProgram (reverse W) (numeral 0) (binaryStep C),binary_poly W C⟩
def prefixStep : Expr (n+2) := choose (input 1) (add (input 0) (numeral 1)) (numeral 0)
def prefixValue : Word → ℕ → ℕ
| [],q => q
| false::w,_q => prefixValue w 0
| true::w,q => prefixValue w (q+1)
def headCount : Word → ℕ
| [] => 0
| false::_ => 0
| true::w => headCount w+1
theorem prefixValue_bound (w : Word) (q : ℕ) : prefixValue w q≤w.length+q := by
induction w generalizing q with
| nil => simp [prefixValue]
| cons b w ih => cases b <;> simp only [prefixValue,List.length_cons] <;> have h := ih (q+1) <;> have h' := ih 0 <;> omega
theorem prefixStep_value (v : Env n) (q : ℕ) (b : Bool) :
(prefixStep : Expr (n+2)).value (cons (List.replicate q true) (cons [b] v))=
List.replicate (if b then q+1 else 0) true := by
rw [prefixStep,choose_value,input_one_bit]
cases b with
| false => rfl
| true =>
change (Recipe.plus (Recipe.input 0) (Recipe.literal [true])).value (cons (List.replicate q true) (cons [true] v))=_
rw [Recipe.plus_value]
simp only [Recipe.input_value,cons_zero,Recipe.literal_value,List.length_replicate,List.length_cons,List.length_nil,Nat.zero_add,ite_true]
theorem prefix_fold (v : Env n) (w : Word) (q : ℕ) :
w.foldl (foldWordStep (prefixStep : Expr (n+2)) v) (List.replicate q true)=List.replicate (prefixValue w q) true := by
induction w generalizing q with
| nil => rfl
| cons b w ih =>
rw [List.foldl_cons]
unfold foldWordStep
rw [prefixStep_value]
cases b <;> exact ih _
theorem prefix_poly (W : Expr n) : Poly (foldWordProgram (reverse W) (numeral 0) prefixStep) := by
obtain ⟨f,hf,h⟩ := W.polynomial
apply foldWordProgram_poly _ _ _ f hf
intro N v hv j hj
change ((((reverse W).value v).take j).foldl (foldWordStep prefixStep v) (List.replicate 0 true)).length≤f N
rw [prefix_fold,List.length_replicate]
have hh := prefixValue_bound (((reverse W).value v).take j) 0
have hw := h N v hv
rw [Nat.add_zero,List.length_take,reverse_value,List.length_reverse] at hh
exact hh.trans ((min_le_right _ _).trans ((Nat.le_add_left _ _).trans hw))
def prefixLength (W : Expr n) : Expr n := ⟨foldWordProgram (reverse W) (numeral 0) prefixStep,prefix_poly W⟩
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def take (W C : Expr n) : Expr n := reverse (drop (reverse W) (sub (length W) C))
@[simp] theorem take_value (W C : Expr n) (v : Env n) : (take W C).value v=(W.value v).take (C.number v) := by
rw [take,reverse_value,drop_value,reverse_value,sub_number,length_number,← List.reverse_take,List.reverse_reverse]
def disj (P Q : Expr n) : Expr n := choose P (literal [true]) Q
@[simp] theorem disj_bit (P Q : Expr n) (v : Env n) : (disj P Q).bit v=(P.bit v || Q.bit v) := by
rw [disj,choose_bit]
have ht : (literal [true] : Expr n).bit v=true := rfl
rw [ht]
cases P.bit v <;> rfl
def canonical (W : Expr n) : Expr n := disj (eq (length W) (numeral 0)) (reverse W)
def afterHeader (W : Expr n) : Expr n := drop W (add (prefixLength W) (numeral 1))
def integerBits (W : Expr n) : Expr n := take (afterHeader W) (prefixLength W)
def afterInteger (W : Expr n) : Expr n := drop (afterHeader W) (prefixLength W)
def integerNumber (W C : Expr n) : Expr n := binary (integerBits W) C
def integerValid (W : Expr n) : Expr n := conj (lt (prefixLength W) (length W))
(conj (le (prefixLength W) (length (afterHeader W))) (canonical (integerBits W)))
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def matrixEntry (A N I J : Expr n) : Expr n := lookup A (add (mul I N) J)
def matrixValid (A N : Expr n) : Expr n :=
conj (eq (length A) (mul N N))
(conj (all N (all N.up (bitEq (matrixEntry A.up₂ N.up₂ (input 1) (input 0))
(matrixEntry A.up₂ N.up₂ (input 0) (input 1)))))
(all N (neg (matrixEntry A.up N.up (input 0) (input 0)))))
@[simp] theorem matrixEntry_bit (A N I J : Expr n) (v : Env n) :
(matrixEntry A N I J).bit v=(A.value v).getD (I.number v*N.number v+J.number v) false := by
rw [matrixEntry,lookup_bit,add_number,mul_number]
def graphMatrix (W C : Expr n) : Expr n := take (afterInteger W) (mul (integerNumber W C) (integerNumber W C))
def afterGraph (W C : Expr n) : Expr n := drop (afterInteger W) (mul (integerNumber W C) (integerNumber W C))
def graphValid (W C : Expr n) : Expr n := conj (integerValid W) (matrixValid (graphMatrix W C) (integerNumber W C))
@[simp] theorem graphMatrix_value (W C : Expr n) (v : Env n) :
(graphMatrix W C).value v=((afterInteger W).value v).take ((integerNumber W C).number v*(integerNumber W C).number v) := by
rw [graphMatrix,take_value,mul_number]
@[simp] theorem afterGraph_value (W C : Expr n) (v : Env n) :
(afterGraph W C).value v=((afterInteger W).value v).drop ((integerNumber W C).number v*(integerNumber W C).number v) := by
rw [afterGraph,drop_value,mul_number]
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def Enough (W C : Expr n) (v : Env n) : Prop := 2^(W.value v).length≤C.number v
def secondWord (W C : Expr n) : Expr n := afterGraph W C
def dimensionWord (W C : Expr n) : Expr n := afterGraph (secondWord W C) C
def pairValid (W C : Expr n) : Expr n :=
conj (graphValid W C) (conj (graphValid (secondWord W C) C)
(conj (integerValid (dimensionWord W C)) (eq (length (afterInteger (dimensionWord W C))) (numeral 0))))
end VariableWL.Computation.Stack.PolyRecipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_ExponentialRecipe
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def maximum (P Q : Expr n) : Expr n := choose (le P Q) Q P
@[simp] theorem maximum_number (P Q : Expr n) (v : Env n) : (maximum P Q).number v=max (P.number v) (Q.number v) := by
rw [maximum,NumericProgram.choose_number,le_bit]
by_cases h : P.number v≤Q.number v
· simp only [decide_eq_true h,ite_true,max_eq_right h]
· simp only [decide_eq_false h,Bool.false_eq_true,ite_false,max_eq_left (Nat.le_of_not_ge h)]
def rawDimension (W C : Expr n) : Expr n := integerNumber (dimensionWord W C) C
def parsedData (W C : Expr n) : NumericProgram.Data n := {
leftOrder := integerNumber W C
rightOrder := integerNumber (secondWord W C) C
dimension := minimum (rawDimension W C) (maximum (numeral 2) (integerNumber W C))
leftMatrix := graphMatrix W C
rightMatrix := graphMatrix (secondWord W C) C
capacity := C }
def StrongEnough (W C : Expr n) (v : Env n) : Prop := 2^(((W.value v).length+2)^2+1)≤C.number v
def generalProgram (W C : Expr n) : Expr n :=
conj (pairValid W C) (conj (le (numeral 2) (rawDimension W C)) (parsedData W C).accepts)
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.ExponentialRecipe
open Recipe PolyRecipe
def exponent : Expr 1 :=
add (mul (add (length (PolyRecipe.input 0)) (numeral 2)) (add (length (PolyRecipe.input 0)) (numeral 2))) (numeral 1)
def size (v : Env 1) : ℕ := 2^(((v 0).length+2)^2+1)
def capacity : Certified 1 := Recipe.power (Recipe.literal [true,true]) exponent.program
def full (Q : Expr 2) : Certified 1 := capacity.bind Q.program
def environment (w : Word) : Env 2 := cons (List.replicate (2^((w.length+2)^2+1)) true) (fun _=>w.reverse)
end VariableWL.Computation.Stack.ExponentialRecipe
namespace VariableWL.Computation.Stack.ExponentialRecipe
open Recipe PolyRecipe
def general : Expr 2 := generalProgram (PolyRecipe.reverse (PolyRecipe.input 1)) (PolyRecipe.input 0)
end VariableWL.Computation.Stack.ExponentialRecipe
namespace VariableWL.NumericPromise
attribute [local instance] Classical.propDecidable
def get (n : ℕ) (R : Word) (a b : ℕ) : Bool := R.getD (a*n+b) false
def pack (n : ℕ) (f : ℕ → ℕ → Bool) : Word :=
(List.range (n*n)).map fun p=>f (p/n) (p%n)
def update (n : ℕ) (A R : Word) (a b : ℕ) : Bool :=
get n R a b || (List.range n).any fun z=>get n A a z && get n R z b
def array (n : ℕ) (A : Word) : ℕ → Word
| 0 => pack n (fun a b=>decide (a=b))
| j+1 => pack n (update n A (array n A j))
end VariableWL.NumericPromise
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Descriptor
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def any (N : Expr n) (B : Expr (n+1)) : Expr n := neg (all N (neg B))
@[simp] theorem any_bit (N : Expr n) (B : Expr (n+1)) (v : Env n) :
(any N B).bit v=(List.range (N.number v)).any fun j=>B.bit (cons (List.replicate j true) v) := by
simp only [any,neg_bit,all_bit,List.any_eq_not_all_not]
def reachInitial (N : Expr n) : Expr n :=
collect (mul N N) (eq (div (input 0) N.up) (mod (input 0) N.up))
def reachUpdate (N A R I J : Expr n) : Expr n :=
disj (matrixEntry R N I J) (any N (conj (matrixEntry A.up N.up I.up (input 0))
(matrixEntry R.up N.up (input 0) J.up)))
def reachNext (N A R : Expr n) : Expr n :=
collect (mul N N) (reachUpdate N.up A.up R.up (div (input 0) N.up) (mod (input 0) N.up))
theorem reachInitial_value (N : Expr n) (v : Env n) :
(reachInitial N).value v=NumericPromise.array (N.number v) [] 0 := by
simp only [reachInitial,collect_value,mul_number,eq_bit,div_number,mod_number,input_number,
cons_zero,List.length_replicate,up_number]
rfl
theorem reachUpdate_bit (N A R I J : Expr n) (v : Env n) :
(reachUpdate N A R I J).bit v=NumericPromise.update (N.number v) (A.value v) (R.value v) (I.number v) (J.number v) := by
simp only [reachUpdate,disj_bit,matrixEntry_bit,any_bit,conj_bit,up_value,up_number,input_number,cons_zero,List.length_replicate]
rfl
theorem reachNext_value (N A R : Expr n) (v : Env n) :
(reachNext N A R).value v=NumericPromise.pack (N.number v)
(NumericPromise.update (N.number v) (A.value v) (R.value v)) := by
simp only [reachNext,collect_value,mul_number,reachUpdate_bit,up_number,up_value,div_number,mod_number,
input_number,cons_zero,List.length_replicate]
rfl
theorem reachInitial_length (N : Expr n) (v : Env n) : ((reachInitial N).value v).length=N.number v^2 := by
rw [reachInitial_value]
simp only [NumericPromise.array,NumericPromise.pack,List.length_map,List.length_range,pow_two]
theorem reachNext_length (N A R : Expr n) (v : Env n) : ((reachNext N A R).value v).length=N.number v^2 := by
rw [reachNext_value]
simp only [NumericPromise.pack,List.length_map,List.length_range,pow_two]
def reachBody (N A : Expr n) : Expr (n+2) := reachNext N.up₂ A.up₂ (input 0)
def reachProgram (N A : Expr n) : Certified n :=
Recipe.iterate N.program (reachInitial N).program (reachBody N A).program
theorem reachPrefix_length (N A : Expr n) (v : Env n) (j : ℕ) :
(Recipe.foldValue (reachBody N A).program v ((reachInitial N).value v) j).length=N.number v^2 := by
cases j with
| zero => exact reachInitial_length N v
| succ j =>
change ((reachNext N.up₂ A.up₂ (input 0)).value _).length=_
rw [reachNext_length,up₂_number]
theorem reachProgram_poly (N A : Expr n) : Poly (reachProgram N A) := by
obtain ⟨f,hf,h⟩ := N.polynomial
apply Recipe.poly_iterate N.polynomial (reachInitial N).polynomial (reachBody N A).polynomial
(fun C=>(f C)^2) (hf.pow 2)
intro C v hv j hj
change (Recipe.foldValue (reachBody N A).program v ((reachInitial N).value v) j).length≤(f C)^2
rw [reachPrefix_length]
have hb := h C v hv
exact Nat.pow_le_pow_left (show N.number v≤f C by exact (Nat.le_add_left _ _).trans hb) 2
def reachArray (N A : Expr n) : Expr n := ⟨reachProgram N A,reachProgram_poly N A⟩
def connectedProgram (N A : Expr n) : Expr n :=
conj (lt (numeral 0) N) (all N (all N.up (matrixEntry (reachArray N A).up₂ N.up₂ (input 1) (input 0))))
def subcubicProgram (N A : Expr n) : Expr n :=
all N (le (count N.up (matrixEntry A.up₂ N.up₂ (input 1) (input 0))) (numeral 3))
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def promiseProgram (N M A B : Expr n) : Expr n :=
conj (lt (numeral 0) N) (conj (eq N M) (conj (connectedProgram N A)
(conj (connectedProgram M B) (conj (subcubicProgram N A) (subcubicProgram M B)))))
def subProgram (W C : Expr n) : Expr n :=
conj (generalProgram W C) (promiseProgram (integerNumber W C) (integerNumber (secondWord W C) C)
(graphMatrix W C) (graphMatrix (secondWord W C) C))
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.ExponentialRecipe
open Recipe PolyRecipe
def subcubic : Expr 2 := subProgram (PolyRecipe.reverse (PolyRecipe.input 1)) (PolyRecipe.input 0)
end VariableWL.Computation.Stack.ExponentialRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def binaryLength (N : Expr n) : Expr n :=
count N (le (capPow (numeral 2) (input 0) (add N.up (numeral 1))) N.up)
def binaryDigit (N I : Expr n) : Expr n :=
eq (mod (div N (capPow (numeral 2) I (add N (numeral 1)))) (numeral 2)) (numeral 1)
def binaryEncode (N : Expr n) : Expr n := collect (binaryLength N) (binaryDigit N.up (input 0))
def integerEncode (N : Expr n) : Expr n :=
append (length (binaryEncode N)) (append (literal [false]) (binaryEncode N))
def graphEncode (N A : Expr n) : Expr n := append (integerEncode N) A
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Descriptor
def rank (P : ℕ → Bool) (a : ℕ) : ℕ := (List.range a).countP P
theorem rank_succ (P : ℕ → Bool) (a : ℕ) :
rank P (a+1)=rank P a+(if P a then 1 else 0) := by
simp only [rank,List.range_succ,List.countP_append,List.countP_cons,List.countP_nil,Nat.zero_add]
theorem rank_mono (P : ℕ → Bool) : Monotone (rank P) := by
intro a b h
exact List.Sublist.countP_le (List.range_sublist.mpr h)
theorem rank_lt (P : ℕ → Bool) {a b : ℕ} (h : a<b) (ha : P a=true) : rank P a<rank P b := by
have hm := rank_mono P (Nat.succ_le_of_lt h)
simp only [rank_succ,ha,ite_true] at hm
omega
theorem rank_exists (P : ℕ → Bool) (N i : ℕ) (hi : i<rank P N) :
∃a,a<N ∧ P a=true ∧ rank P a=i := by
induction N with
| zero => simp [rank] at hi
| succ N ih =>
by_cases h : i<rank P N
· obtain ⟨a,ha,hp,hr⟩ := ih h
exact ⟨a,by omega,hp,hr⟩
· rw [rank_succ] at hi
cases hp : P N <;> simp only [hp,Bool.false_eq_true,ite_false,ite_true,Nat.add_zero] at hi
· omega
· exact ⟨N,by omega,hp,by omega⟩
def pick (N : ℕ) (P : ℕ → Bool) (i : ℕ) : ℕ :=
(List.range N).countP fun j=>decide (rank P (j+1)≤ i)
theorem pick_rank (N : ℕ) (P : ℕ → Bool) (a : ℕ) (ha : a<N) (hp : P a=true) :
pick N P (rank P a)=a := by
have he (j : ℕ) : decide (rank P (j+1)≤rank P a)=decide (j<a) := by
apply Bool.eq_iff_iff.mpr
simp only [decide_eq_true_eq]
constructor
· intro h
by_contra hj
have hm := rank_lt P (show a<j+1 by omega) hp
omega
· exact fun h=>rank_mono P (Nat.succ_le_of_lt h)
simp only [pick,he]
rw [Computation.Stack.Recipe.count_range_lt,Nat.min_eq_right (Nat.le_of_lt ha)]
theorem pick_spec (N : ℕ) (P : ℕ → Bool) (i : ℕ) (hi : i<rank P N) :
pick N P i<N ∧ P (pick N P i)=true ∧ rank P (pick N P i)=i := by
obtain ⟨a,ha,hp,hr⟩ := rank_exists P N i hi
rw [←hr,pick_rank N P a ha hp]
exact ⟨ha,hp,rfl⟩
abbrev Valid (N : ℕ) (P : ℕ → Bool) := {a : Fin N // P a.val=true}
def rankEquiv (N : ℕ) (P : ℕ → Bool) : Valid N P ≃ Fin (rank P N) where
toFun a := ⟨rank P a.val.val,rank_lt P a.val.isLt a.property⟩
invFun i := ⟨⟨pick N P i.val,(pick_spec N P i.val i.isLt).1⟩,(pick_spec N P i.val i.isLt).2.1⟩
left_inv a := by apply Subtype.ext; apply Fin.ext; exact pick_rank N P a.val.val a.val.isLt a.property
right_inv i := by apply Fin.ext; exact (pick_spec N P i.val i.isLt).2.2
end VariableWL.Descriptor
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def underOne (P : Expr (n+1)) : Expr (n+2) := P.reindex (Fin.cons 0 (fun i=>i.succ.succ))
def select (N : Expr n) (P : Expr (n+1)) (I : Expr n) : Expr n :=
count N (le (count (add (input 0) (numeral 1)) (underOne P)) I.up)
def apply₂ (F : Expr (n+2)) (A B : Expr n) : Expr n := B.bind (A.up.bind F)
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Descriptor
attribute [local instance] Classical.propDecidable
structure Data where
bound : ℕ
valid : ℕ → Bool
edge : ℕ → ℕ → Bool
def Data.Sound (D : Data) : Prop :=
(∀a b,a<D.bound → b<D.bound → D.valid a=true → D.valid b=true → D.edge a b=D.edge b a) ∧
(∀a,a<D.bound → D.valid a=true → D.edge a a=false)
noncomputable def Data.graph (D : Data) (h : D.Sound) : Graph where
order := rank D.valid D.bound
graph := {
Adj := fun i j=>D.edge (pick D.bound D.valid i.val) (pick D.bound D.valid j.val)=true
symm := ⟨by
intro i j hij
have hi := pick_spec D.bound D.valid i.val i.isLt
have hj := pick_spec D.bound D.valid j.val j.isLt
rw [h.1 _ _ hj.1 hi.1 hj.2.1 hi.2.1]
exact hij⟩
loopless := ⟨by
intro i he
have hi := pick_spec D.bound D.valid i.val i.isLt
rw [h.2 _ hi.1 hi.2.1] at he
contradiction⟩ }
end VariableWL.Descriptor
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PortListing
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def underTwo (P : Expr (n+2)) : Expr (n+3) :=
P.reindex (Fin.cons 0 (Fin.cons 1 (fun i=>i.succ.succ.succ)))
structure GraphListing (n : ℕ) where
bound : Expr n
valid : Expr (n+1)
edge : Expr (n+2)
def GraphListing.eval (D : GraphListing n) (v : Env n) : Descriptor.Data where
bound := D.bound.number v
valid := fun j=>D.valid.bit (cons (List.replicate j true) v)
edge := fun i j=>D.edge.bit (cons (List.replicate i true) (cons (List.replicate j true) v))
def GraphListing.order (D : GraphListing n) : Expr n := count D.bound D.valid
def GraphListing.matrix (D : GraphListing n) : Expr n :=
collect (mul D.order D.order) (apply₂ (underTwo D.edge)
(select D.bound.up (underOne D.valid) (div (input 0) D.order.up))
(select D.bound.up (underOne D.valid) (mod (input 0) D.order.up)))
def GraphListing.code (D : GraphListing n) : Expr n := graphEncode D.order D.matrix
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Descriptor
open SubcubicRealization
attribute [local instance] Classical.propDecidable
structure Presentation (A : Type uVariable1) where
bound : ℕ
valid : ℕ → Bool
equiv : Valid bound valid ≃ A
namespace Presentation
variable {A : Type uVariable2} (D : Presentation A)
def encode (a : A) : ℕ := (D.equiv.symm a).val.val
theorem encode_lt (a : A) : D.encode a<D.bound := (D.equiv.symm a).val.isLt
theorem encode_valid (a : A) : D.valid (D.encode a)=true := (D.equiv.symm a).property
theorem encode_injective : Function.Injective D.encode := by
intro a b h
apply D.equiv.symm.injective
apply Subtype.ext
exact Fin.ext h
@[instance_reducible] noncomputable def numbering [Fintype A] : FiniteNumbering A :=
⟨D.equiv.symm.trans ((rankEquiv D.bound D.valid).trans (finCongr (by
simpa only [Fintype.card_fin] using (Fintype.card_congr (rankEquiv D.bound D.valid)).symm.trans
(Fintype.card_congr D.equiv))))⟩
end Presentation
@[ext] structure PortData where
bound : ℕ
valid : ℕ → Bool
color : ℕ → ℕ
colorBound : ℕ
incidence : ℕ → ℕ → Bool
namespace PortData
abbrev Owners (D : PortData) := Valid D.bound D.valid
def Sound (D : PortData) : Prop :=
(∀a : D.Owners,D.color a.val.val≤D.colorBound) ∧
(∀a b : D.Owners,∀i j : Fin 3,
D.incidence (3*a.val.val+i.val) (3*b.val.val+j.val)=
D.incidence (3*b.val.val+j.val) (3*a.val.val+i.val)) ∧
(∀a b c : D.Owners,∀i j k : Fin 3,
D.incidence (3*a.val.val+i.val) (3*b.val.val+j.val)=true →
D.incidence (3*a.val.val+i.val) (3*c.val.val+k.val)=true → b=c ∧ j=k) ∧
(∀a b : D.Owners,∀i j : Fin 3,
D.incidence (3*a.val.val+i.val) (3*b.val.val+j.val)=true → a≠b)
noncomputable def ports (D : PortData) (h : D.Sound) : PortGraph D.Owners where
edge x y := D.incidence (3*x.1.val.val+x.2.val) (3*y.1.val.val+y.2.val)=true
symm := by intro x y he; rw [h.2.1]; exact he
unique := by intro x y z hy hz; obtain ⟨ha,hb⟩ := h.2.2.1 _ _ _ _ _ _ hy hz; exact Prod.ext ha hb
different := by intro x y he; exact h.2.2.2 _ _ _ _ he
abbrev Vertices (D : PortData) := Vertex (fun a : D.Owners=>D.color a.val.val)
def stride (D : PortData) : ℕ := D.colorBound+2
def owner (D : PortData) (i : ℕ) : ℕ := i/D.stride/3
def port (D : PortData) (i : ℕ) : ℕ := i/D.stride%3
def level (D : PortData) (i : ℕ) : ℕ := i%D.stride
def code (D : PortData) (x : D.Vertices) : ℕ := (3*x.owner.val.val+x.port.val)*D.stride+x.level
def expanded (D : PortData) : Data where
bound := (3*D.bound)*D.stride
valid i := D.valid (D.owner i) && decide (D.level i<D.color (D.owner i)+2)
edge i j :=
(decide (D.owner i=D.owner j) &&
((decide (D.level i=0) && decide (D.level j=0) && decide (D.port i≠D.port j)) ||
(decide (D.port i=D.port j) &&
(decide (D.level i+1=D.level j) || decide (D.level j+1=D.level i))))) ||
(decide (D.level i=1) && decide (D.level j=1) &&
D.incidence (3*D.owner i+D.port i) (3*D.owner j+D.port j))
theorem stride_pos (D : PortData) : 0<D.stride := by unfold stride; omega
theorem owner_lt (D : PortData) {i : ℕ} (hi : i<D.expanded.bound) : D.owner i<D.bound := by
have h : i/D.stride<3*D.bound := (Nat.div_lt_iff_lt_mul D.stride_pos).mpr hi
unfold owner
apply (Nat.div_lt_iff_lt_mul (by omega : 0<3)).mpr
simpa only [Nat.mul_comm] using h
theorem code_parts (D : PortData) (h : D.Sound) (x : D.Vertices) :
D.owner (D.code x)=x.owner.val.val ∧ D.port (D.code x)=x.port.val ∧ D.level (D.code x)=x.level := by
have hx : x.level<D.stride := lt_of_lt_of_le x.bound (Nat.add_le_add_right (h.1 x.owner) 2)
have hp : x.port.val<3 := x.port.isLt
have hd : D.code x/D.stride=3*x.owner.val.val+x.port.val := by
rw [code,Nat.mul_comm _ D.stride,Nat.mul_add_div D.stride_pos,Nat.div_eq_of_lt hx,Nat.add_zero]
constructor
· change (D.code x/D.stride)/3=_
rw [hd,Nat.mul_add_div (by omega : 0<3),Nat.div_eq_of_lt hp,Nat.add_zero]
constructor
· change (D.code x/D.stride)%3=_
rw [hd,Nat.mul_add_mod,Nat.mod_eq_of_lt hp]
· change D.code x%D.stride=_
rw [code,Nat.mul_comm _ D.stride,Nat.mul_add_mod,Nat.mod_eq_of_lt hx]
theorem code_lt (D : PortData) (h : D.Sound) (x : D.Vertices) : D.code x<D.expanded.bound := by
have hx : x.level<D.stride := lt_of_lt_of_le x.bound (Nat.add_le_add_right (h.1 x.owner) 2)
have hp : 3*x.owner.val.val+x.port.val<3*D.bound := by
have := x.owner.val.isLt
have := x.port.isLt
omega
exact (Nat.add_lt_add_left hx _).trans_le (by
change (3*x.owner.val.val+x.port.val)*D.stride+D.stride≤(3*D.bound)*D.stride
rw [←Nat.succ_mul]
exact Nat.mul_le_mul_right _ hp)
noncomputable def presentation (D : PortData) (h : D.Sound) : Presentation D.Vertices where
bound := D.expanded.bound
valid := D.expanded.valid
equiv := {
toFun a := ⟨⟨⟨D.owner a.val.val,D.owner_lt a.val.isLt⟩,(Bool.and_eq_true_iff.mp a.property).1⟩,
⟨D.port a.val.val,Nat.mod_lt _ (by omega)⟩,D.level a.val.val,
of_decide_eq_true (Bool.and_eq_true_iff.mp a.property).2⟩
invFun x := ⟨⟨D.code x,D.code_lt h x⟩,by
simp only [expanded,code_parts D h x |>.1,code_parts D h x |>.2.2,x.owner.property,
x.bound,decide_true,Bool.and_self]⟩
left_inv a := by
apply Subtype.ext
apply Fin.ext
change (3*(a.val.val/D.stride/3)+(a.val.val/D.stride%3))*D.stride+a.val.val%D.stride=a.val.val
rw [Nat.div_add_mod,Nat.mul_comm,Nat.div_add_mod]
right_inv x := by
apply Vertex.ext
· apply Subtype.ext; apply Fin.ext; exact (code_parts D h x).1
· apply Fin.ext; exact (code_parts D h x).2.1
· exact (code_parts D h x).2.2 }
end PortData
end VariableWL.Descriptor
namespace VariableWL.Descriptor
@[ext] theorem data_ext {D E : Data} (hb : D.bound=E.bound) (hv : D.valid=E.valid)
(he : D.edge=E.edge) : D=E := by cases D; cases E; cases hb; cases hv; cases he; rfl
end VariableWL.Descriptor
namespace VariableWL.Descriptor.PortData
open SubcubicRealization
attribute [local instance] Classical.propDecidable
theorem edge_correct (D : PortData) (h : D.Sound) (a b : Valid D.expanded.bound D.expanded.valid) :
D.expanded.edge a.val.val b.val.val=true ↔
(graph (D.ports h) (fun x=>D.color x.val.val)).Adj
((D.presentation h).equiv a) ((D.presentation h).equiv b) := by
change D.expanded.edge a.val.val b.val.val=true ↔
((⟨⟨D.owner a.val.val,D.owner_lt a.val.isLt⟩,
(Bool.and_eq_true_iff.mp a.property).1⟩ : D.Owners)=
⟨⟨D.owner b.val.val,D.owner_lt b.val.isLt⟩,(Bool.and_eq_true_iff.mp b.property).1⟩ ∧
((D.level a.val.val=0 ∧ D.level b.val.val=0 ∧
(⟨D.port a.val.val,Nat.mod_lt _ (by omega)⟩ : Fin 3)≠⟨D.port b.val.val,Nat.mod_lt _ (by omega)⟩) ∨
((⟨D.port a.val.val,Nat.mod_lt _ (by omega)⟩ : Fin 3)=⟨D.port b.val.val,Nat.mod_lt _ (by omega)⟩ ∧
(D.level a.val.val+1=D.level b.val.val ∨ D.level b.val.val+1=D.level a.val.val)))) ∨
(D.level a.val.val=1 ∧ D.level b.val.val=1 ∧
D.incidence (3*D.owner a.val.val+D.port a.val.val) (3*D.owner b.val.val+D.port b.val.val)=true)
simp only [expanded,Bool.or_eq_true,Bool.and_eq_true,decide_eq_true_eq,
Subtype.mk.injEq,ne_eq,Fin.ext_iff,and_assoc]
theorem sound_expanded (D : PortData) (h : D.Sound) : D.expanded.Sound := by
constructor
· intro a b ha hb hva hvb
let x : Valid D.expanded.bound D.expanded.valid := ⟨⟨a,ha⟩,hva⟩
let y : Valid D.expanded.bound D.expanded.valid := ⟨⟨b,hb⟩,hvb⟩
apply Bool.eq_iff_iff.mpr
exact (D.edge_correct h x y).trans ((graph (D.ports h) (fun x=>D.color x.val.val)).adj_comm _ _ |>.trans
(D.edge_correct h y x).symm)
· intro a ha hva
apply Bool.eq_false_iff.mpr
intro he
exact (graph (D.ports h) (fun x=>D.color x.val.val)).loopless.irrefl _
((D.edge_correct h ⟨⟨a,ha⟩,hva⟩ ⟨⟨a,ha⟩,hva⟩).mp he)
noncomputable def graphIso (D : PortData) (h : D.Sound) :
(D.expanded.graph (D.sound_expanded h)).graph ≃g
graph (D.ports h) (fun x=>D.color x.val.val) where
toEquiv := (rankEquiv D.expanded.bound D.expanded.valid).symm.trans (D.presentation h).equiv
map_rel_iff' := by
intro x y
exact (D.edge_correct h ((rankEquiv D.expanded.bound D.expanded.valid).symm x)
((rankEquiv D.expanded.bound D.expanded.valid).symm y)).symm
end VariableWL.Descriptor.PortData
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n m : ℕ}
def applyNat (P : Expr (n+1)) (I : Expr n) : Expr n := (length I).bind P
def applyNat₂ (P : Expr (n+2)) (I J : Expr n) : Expr n := applyNat (applyNat P I.up) J
structure PortListing (n : ℕ) where
bound : Expr n
valid : Expr (n+1)
color : Expr (n+1)
colorBound : Expr n
incidence : Expr (n+2)
namespace PortListing
def eval (D : PortListing n) (v : Env n) : Descriptor.PortData where
bound := D.bound.number v
valid i := D.valid.bit (cons (List.replicate i true) v)
color i := D.color.number (cons (List.replicate i true) v)
colorBound := D.colorBound.number v
incidence i j := D.incidence.bit (cons (List.replicate i true) (cons (List.replicate j true) v))
def up (D : PortListing n) : PortListing (n+1) where
bound := D.bound.up
valid := underOne D.valid
color := underOne D.color
colorBound := D.colorBound.up
incidence := underTwo D.incidence
def stride (D : PortListing n) : Expr n := add D.colorBound (numeral 2)
def owner (D : PortListing n) (I : Expr n) : Expr n := div (div I D.stride) (numeral 3)
def port (D : PortListing n) (I : Expr n) : Expr n := mod (div I D.stride) (numeral 3)
def level (D : PortListing n) (I : Expr n) : Expr n := mod I D.stride
def expandedValid (D : PortListing n) (I : Expr n) : Expr n :=
conj (applyNat D.valid (D.owner I))
(lt (D.level I) (add (applyNat D.color (D.owner I)) (numeral 2)))
def expandedEdge (D : PortListing n) (I J : Expr n) : Expr n :=
disj (conj (eq (D.owner I) (D.owner J))
(disj (conj (conj (eq (D.level I) (numeral 0)) (eq (D.level J) (numeral 0)))
(neg (eq (D.port I) (D.port J))))
(conj (eq (D.port I) (D.port J))
(disj (eq (add (D.level I) (numeral 1)) (D.level J))
(eq (add (D.level J) (numeral 1)) (D.level I))))))
(conj (conj (eq (D.level I) (numeral 1)) (eq (D.level J) (numeral 1)))
(applyNat₂ D.incidence (add (mul (numeral 3) (D.owner I)) (D.port I))
(add (mul (numeral 3) (D.owner J)) (D.port J))))
def expanded (D : PortListing n) : GraphListing n where
bound := mul (mul (numeral 3) D.bound) D.stride
valid := D.up.expandedValid (input 0)
edge := D.up.up.expandedEdge (input 0) (input 1)
end PortListing
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def fixedNat : (N : ℕ) → (Fin N → ℕ) → Expr n → Expr n
| 0,_,_ => numeral 0
| N+1,f,I => choose (eq I (numeral 0)) (numeral (f 0))
(fixedNat N (fun i=>f i.succ) (sub I (numeral 1)))
def fixedBool (N : ℕ) (f : Fin N → Bool) (I : Expr n) : Expr n :=
eq (fixedNat N (fun i=>if f i then 1 else 0) I) (numeral 1)
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Computation.Stack.Recipe
@[simp] theorem cons_two {n : ℕ} (a b c : Word) (v : Env n) : cons a (cons b (cons c v)) (2 : Fin (n+3))=c := rfl
end VariableWL.Computation.Stack.Recipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PrefixAlphabet
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def applyNat₃ (P : Expr (n+3)) (I J K : Expr n) : Expr n :=
applyNat (applyNat₂ P I.up J.up) K
def tableLookup {N : ℕ} (f : Fin N → ℕ) (i : ℕ) : ℕ := if h : i<N then f ⟨i,h⟩ else 0
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.Descriptor.Presentation
variable {A : Type uVariable1}
noncomputable def ofEncoding (N : ℕ) (P : ℕ → Bool) (f : A → ℕ)
(hf : ∀a,f a<N) (hp : ∀a,P (f a)=true) (hi : Function.Injective f)
(hs : ∀i,i<N → P i=true → ∃a,f a=i) : Presentation A where
bound := N
valid := P
equiv := (Equiv.ofBijective (fun a=> (⟨⟨f a,hf a⟩,hp a⟩ : Valid N P)) (by
constructor
· intro a b he; exact hi (congrArg (fun a : Valid N P=>a.val.val) he)
· intro i; obtain ⟨a,ha⟩ := hs i.val.val i.val.isLt i.property
exact ⟨a,Subtype.ext (Fin.ext ha)⟩)).symm
end VariableWL.Descriptor.Presentation
namespace VariableWL.Descriptor.PortData
open SubcubicRealization
variable {A : Type uVariable3}
theorem sound_of_encoding (D : PortData) (f : A → D.Owners) (hf : Function.Bijective f) (Y : PortGraph A)
(hc : ∀a,D.color (f a).val.val≤D.colorBound)
(he : ∀a b i j,D.incidence (3*(f a).val.val+i.val) (3*(f b).val.val+j.val)=true ↔
Y.edge (a,i) (b,j)) : D.Sound := by
refine ⟨?_,?_,?_,?_⟩
· intro x; obtain ⟨a,rfl⟩ := hf.2 x; exact hc a
· intro x y i j
obtain ⟨a,rfl⟩ := hf.2 x
obtain ⟨b,rfl⟩ := hf.2 y
apply Bool.eq_iff_iff.mpr
exact (he a b i j).trans ⟨fun h=>(he b a j i).mpr (Y.symm h),fun h=>Y.symm ((he b a j i).mp h)⟩
· intro x y z i j k hxy hxz
obtain ⟨a,rfl⟩ := hf.2 x
obtain ⟨b,rfl⟩ := hf.2 y
obtain ⟨c,rfl⟩ := hf.2 z
have ht := Y.unique ((he a b i j).mp hxy) ((he a c i k).mp hxz)
exact ⟨congrArg f (congrArg Prod.fst ht),congrArg Prod.snd ht⟩
· intro x y i j hxy hx
obtain ⟨a,rfl⟩ := hf.2 x
obtain ⟨b,rfl⟩ := hf.2 y
exact Y.different ((he a b i j).mp hxy) (hf.1 hx)
end VariableWL.Descriptor.PortData
namespace VariableWL.PrefixAlphabet
open VariableWL.Affine
attribute [local instance] Classical.propDecidable
abbrev Vector := Σa : Fin 7, Vec a.val
abbrev Order := Σa : Fin 7, Equiv.Perm (Fin a.val)
noncomputable instance vectorFintype : Fintype Vector := inferInstance
noncomputable instance orderFintype : Fintype Order := Fintype.ofFinite _
noncomputable def vectorNumber : Vector ≃ Fin (Fintype.card Vector) := Fintype.equivFin _
noncomputable def orderNumber : Order ≃ Fin (Fintype.card Order) := Fintype.equivFin _
noncomputable def vectorCount : ℕ := Fintype.card Vector
noncomputable def orderCount : ℕ := Fintype.card Order
noncomputable def encode {a : ℕ} (h : a≤6) (z : Vec a) : ℕ :=
(vectorNumber ⟨⟨a,by omega⟩,z⟩).val
noncomputable def encodeOrder {a : ℕ} (h : a≤6) (p : Equiv.Perm (Fin a)) : ℕ :=
(orderNumber ⟨⟨a,by omega⟩,p⟩).val
theorem encode_lt {a : ℕ} (h : a≤6) (z : Vec a) : encode h z<vectorCount :=
(vectorNumber ⟨⟨a,by omega⟩,z⟩).isLt
theorem order_lt {a : ℕ} (h : a≤6) (p : Equiv.Perm (Fin a)) : encodeOrder h p<orderCount :=
(orderNumber ⟨⟨a,by omega⟩,p⟩).isLt
theorem encode_injective {a : ℕ} (h : a≤6) : Function.Injective (@encode a h) := by
intro z w he
have hv := vectorNumber.injective (Fin.ext he)
exact eq_of_heq (Sigma.mk.inj_iff.mp hv).2
noncomputable def truncated (h : ℕ) (v : Vector) : Vector :=
⟨v.1,PrefixParts.Data.truncate h v.2⟩
noncomputable def permuted (p : Order) (v : Vector) : Vector :=
if h : p.1=v.1 then ⟨v.1,v.2 ∘ (h ▸ p.2)⟩ else v
noncomputable def prefixCode (p h i : ℕ) : ℕ :=
if hp : p<orderCount then if hi : i<vectorCount then
(vectorNumber (truncated h (permuted (orderNumber.symm ⟨p,hp⟩) (vectorNumber.symm ⟨i,hi⟩)))).val
else 0 else 0
noncomputable def bit (i h : ℕ) : ℕ :=
if hi : i<vectorCount then
let v := vectorNumber.symm ⟨i,hi⟩
if hh : h<v.1.val then (v.2 ⟨h,hh⟩).val else 0
else 0
noncomputable def paddedEqual (i j : ℕ) : Bool :=
if hi : i<vectorCount then if hj : j<vectorCount then
decide (PrefixParts.Wiring.pad (vectorNumber.symm ⟨i,hi⟩).2=
PrefixParts.Wiring.pad (vectorNumber.symm ⟨j,hj⟩).2)
else false else false
@[simp] theorem prefix_encode {a : ℕ} (ha : a≤6) (p : Equiv.Perm (Fin a)) (h : ℕ) (z : Vec a) :
prefixCode (encodeOrder ha p) h (encode ha z)=encode ha (PrefixParts.Data.truncate h (z ∘ p)) := by
simp only [prefixCode,dite_eq_left (order_lt ha p),dite_eq_left (encode_lt ha z)]
change (vectorNumber (truncated h (permuted (orderNumber.symm (orderNumber ⟨⟨a,by omega⟩,p⟩))
(vectorNumber.symm (vectorNumber ⟨⟨a,by omega⟩,z⟩))))).val=_
rw [Equiv.symm_apply_apply,Equiv.symm_apply_apply]
unfold permuted
rw [dite_eq_left rfl]
rfl
@[simp] theorem bit_encode {a : ℕ} (ha : a≤6) (z : Vec a) (i : Fin a) :
bit (encode ha z) i.val=(z i).val := by
simp only [bit,dite_eq_left (encode_lt ha z)]
change (if h : i.val<(vectorNumber.symm (vectorNumber ⟨⟨a,by omega⟩,z⟩)).1.val then
((vectorNumber.symm (vectorNumber ⟨⟨a,by omega⟩,z⟩)).2 ⟨i.val,h⟩).val else 0)=_
rw [Equiv.symm_apply_apply]
exact dite_eq_left i.isLt
@[simp] theorem paddedEqual_encode {a b : ℕ} (ha : a≤6) (hb : b≤6) (z : Vec a) (w : Vec b) :
paddedEqual (encode ha z) (encode hb w)=decide (PrefixParts.Wiring.pad z=PrefixParts.Wiring.pad w) := by
simp only [paddedEqual,dite_eq_left (encode_lt ha z),dite_eq_left (encode_lt hb w)]
change decide (PrefixParts.Wiring.pad (vectorNumber.symm (vectorNumber ⟨⟨a,by omega⟩,z⟩)).2=
PrefixParts.Wiring.pad (vectorNumber.symm (vectorNumber ⟨⟨b,by omega⟩,w⟩)).2)=_
rw [Equiv.symm_apply_apply,Equiv.symm_apply_apply]
end VariableWL.PrefixAlphabet
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def fixedNat₂ (N M : ℕ) (f : ℕ → ℕ → ℕ) (I J : Expr n) : Expr n :=
fixedNat (N*M) (fun q=>f (q.val/M) (q.val%M)) (add (mul I (numeral M)) J)
def fixedNat₃ (N M K : ℕ) (f : ℕ → ℕ → ℕ → ℕ) (I J L : Expr n) : Expr n :=
fixedNat₂ N (M*K) (fun i q=>f i (q/K) (q%K)) I (add (mul J (numeral K)) L)
def fixedBool₂ (N M : ℕ) (f : ℕ → ℕ → Bool) (I J : Expr n) : Expr n :=
eq (fixedNat₂ N M (fun i j=>if f i j then 1 else 0) I J) (numeral 1)
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.PrefixAlphabet.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
noncomputable def paddedEqual (I J : Expr n) : Expr n :=
fixedBool₂ vectorCount vectorCount PrefixAlphabet.paddedEqual I J
end VariableWL.PrefixAlphabet.Program
namespace VariableWL.PrefixAlphabet
theorem vectorCount_pos : 0<vectorCount := by
let : Nonempty Vector := ⟨⟨0,0⟩⟩
exact Fintype.card_pos
end VariableWL.PrefixAlphabet
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
@[ext] structure Raw where
block : ℕ
kind : ℕ
channel : ℕ
height : ℕ
vector : ℕ
deriving DecidableEq
structure Data where
blocks : ℕ
validBlock : ℕ → Bool
channelBound : ℕ
dimension : ℕ → ℕ
channels : ℕ → ℕ
root : ℕ → ℕ → ℕ
order : ℕ → ℕ → ℕ
legal : ℕ → ℕ → Bool
matching : ℕ → ℕ → Bool
namespace Data
variable (D : Data)
def sortBound : ℕ := D.blocks*3*D.channelBound*7
noncomputable def bound : ℕ := D.sortBound*PrefixAlphabet.vectorCount
def tag (x : Raw) : ℕ := ((x.block*3+x.kind)*D.channelBound+x.channel)*7+x.height
noncomputable def pack (x : Raw) : ℕ := D.tag x*PrefixAlphabet.vectorCount+x.vector
noncomputable def unpack (i : ℕ) : Raw :=
⟨i/PrefixAlphabet.vectorCount/7/D.channelBound/3,
i/PrefixAlphabet.vectorCount/7/D.channelBound%3,
i/PrefixAlphabet.vectorCount/7%D.channelBound,
i/PrefixAlphabet.vectorCount%7,i%PrefixAlphabet.vectorCount⟩
theorem join_div (x y m : ℕ) (hm : 0 < m) (hy : y < m) : (x*m+y)/m=x := by
rw [Nat.mul_comm x m,Nat.mul_add_div hm,Nat.div_eq_of_lt hy,Nat.add_zero]
theorem join_mod (x y m : ℕ) (hy : y < m) : (x*m+y)%m=y := by
rw [Nat.mul_comm x m,Nat.mul_add_mod,Nat.mod_eq_of_lt hy]
theorem unpack_pack (x : Raw) (hk : x.kind<3) (hc : x.channel<D.channelBound)
(hh : x.height<7) (hu : x.vector<PrefixAlphabet.vectorCount) : D.unpack (D.pack x)=x := by
have hC : 0<D.channelBound := by omega
simp only [unpack,pack,tag,join_div _ _ _ PrefixAlphabet.vectorCount_pos hu,
join_mod _ _ _ hu,join_div _ _ _ (by omega : 0<7) hh,join_mod _ _ _ hh,
join_div _ _ _ hC hc,join_mod _ _ _ hc,join_div _ _ _ (by omega : 0<3) hk,join_mod _ _ _ hk]
theorem pack_unpack (i : ℕ) : D.pack (D.unpack i)=i := by
simp only [pack,tag,unpack]
rw [Nat.mul_comm (i/PrefixAlphabet.vectorCount/7/D.channelBound/3) 3,Nat.div_add_mod,
Nat.mul_comm (i/PrefixAlphabet.vectorCount/7/D.channelBound) D.channelBound,Nat.div_add_mod,
Nat.mul_comm (i/PrefixAlphabet.vectorCount/7) 7,Nat.div_add_mod,
Nat.mul_comm (i/PrefixAlphabet.vectorCount) PrefixAlphabet.vectorCount,Nat.div_add_mod]
theorem tag_lt (x : Raw) (hb : x.block<D.blocks) (hk : x.kind<3)
(hc : x.channel<D.channelBound) (hh : x.height<7) : D.tag x<D.sortBound := by
have h1 : x.block*3+x.kind<D.blocks*3 := by omega
have h2 : (x.block*3+x.kind)*D.channelBound+x.channel<(D.blocks*3)*D.channelBound :=
(Nat.add_lt_add_left hc _).trans_le (by rw [←Nat.succ_mul]; exact Nat.mul_le_mul_right _ h1)
exact (Nat.add_lt_add_left hh _).trans_le (by rw [←Nat.succ_mul]; exact Nat.mul_le_mul_right _ h2)
theorem pack_lt (x : Raw) (hb : x.block<D.blocks) (hk : x.kind<3)
(hc : x.channel<D.channelBound) (hh : x.height<7) (hu : x.vector<PrefixAlphabet.vectorCount) :
D.pack x<D.bound :=
(Nat.add_lt_add_left hu _).trans_le (by
change D.tag x*PrefixAlphabet.vectorCount+PrefixAlphabet.vectorCount≤D.sortBound*PrefixAlphabet.vectorCount
rw [←Nat.succ_mul]
exact Nat.mul_le_mul_right _ (D.tag_lt x hb hk hc hh))
theorem unpack_bounds (hC : 0<D.channelBound) {i : ℕ} (hi : i<D.bound) :
(D.unpack i).block<D.blocks ∧ (D.unpack i).kind<3 ∧
(D.unpack i).channel<D.channelBound ∧ (D.unpack i).height<7 ∧
(D.unpack i).vector<PrefixAlphabet.vectorCount := by
refine ⟨?_,Nat.mod_lt _ (by omega),Nat.mod_lt _ hC,Nat.mod_lt _ (by omega),
Nat.mod_lt _ PrefixAlphabet.vectorCount_pos⟩
have h1 : i/PrefixAlphabet.vectorCount<D.sortBound :=
(Nat.div_lt_iff_lt_mul PrefixAlphabet.vectorCount_pos).mpr hi
have h2 : i/PrefixAlphabet.vectorCount/7<D.blocks*3*D.channelBound :=
(Nat.div_lt_iff_lt_mul (by omega : 0<7)).mpr h1
have h3 : i/PrefixAlphabet.vectorCount/7/D.channelBound<D.blocks*3 :=
(Nat.div_lt_iff_lt_mul hC).mpr h2
exact (Nat.div_lt_iff_lt_mul (by omega : 0<3)).mpr h3
noncomputable def treeValid (x : Raw) : Bool :=
decide (D.root x.block x.channel≤x.height ∧ x.height≤D.dimension x.block) &&
(List.range PrefixAlphabet.vectorCount).any (fun j=>D.legal x.block j &&
decide (PrefixAlphabet.prefixCode (D.order x.block x.channel) x.height j=x.vector))
noncomputable def validRaw (x : Raw) : Bool := D.validBlock x.block &&
((decide (x.kind=0 ∧ x.channel=0 ∧ x.height=0 ∧ x.vector=0)) ||
(decide (x.kind=1 ∧ x.channel<D.channels x.block ∧ x.height=0) && D.legal x.block x.vector) ||
(decide (x.kind=2 ∧ x.channel<D.channels x.block) && D.treeValid x))
noncomputable def valid (i : ℕ) : Bool := D.validRaw (D.unpack i)
def sortValid (x : Raw) : Bool := D.validBlock x.block &&
decide ((x.kind=0 ∧ x.channel=0 ∧ x.height=0) ∨
(x.kind=1 ∧ x.channel<D.channels x.block ∧ x.height=0) ∨
(x.kind=2 ∧ x.channel<D.channels x.block ∧ D.root x.block x.channel≤x.height ∧
x.height≤D.dimension x.block))
end Data
variable {B : Type uVariable4} (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
structure Good (D : Data) : Prop where
blocks : D.blocks=P.bound
validBlock : D.validBlock=P.valid
positive : 0<D.channelBound
channelBound : ∀b,(F b).channels≤D.channelBound
dimension : ∀b,D.dimension (P.encode b)=(F b).dimension
channels : ∀b,D.channels (P.encode b)=(F b).channels
root : ∀b (c : Fin (F b).channels),D.root (P.encode b) c.val=(F b).root c
order : ∀b (c : Fin (F b).channels),D.order (P.encode b) c.val=PrefixAlphabet.encodeOrder (hDim b) ((F b).order c)
legal : ∀b i,D.legal (P.encode b) i=true ↔
∃z : (F b).Valuation ε,PrefixAlphabet.encode (hDim b) z.val=i
noncomputable def raw (x : PrefixParts.Wiring.Vertex F ε) : Raw :=
match x.2 with
| .inl _ => ⟨P.encode x.1,0,0,0,0⟩
| .inr (.inl (c,z)) => ⟨P.encode x.1,1,c.val,0,PrefixAlphabet.encode (hDim x.1) z.val⟩
| .inr (.inr t) => ⟨P.encode x.1,2,t.channel.val,t.height,PrefixAlphabet.encode (hDim x.1) t.bits⟩
@[simp] theorem raw_block (x : PrefixParts.Wiring.Vertex F ε) : (raw P F hDim ε x).block=P.encode x.1 := by
rcases x with ⟨b,x | (x | x)⟩ <;> rfl
theorem raw_bounds {D : Data} (h : Good P F hDim ε D) (x : PrefixParts.Wiring.Vertex F ε) :
(raw P F hDim ε x).block<D.blocks ∧ (raw P F hDim ε x).kind<3 ∧
(raw P F hDim ε x).channel<D.channelBound ∧ (raw P F hDim ε x).height<7 ∧
(raw P F hDim ε x).vector<PrefixAlphabet.vectorCount := by
have hb := P.encode_lt x.1
rw [←h.blocks] at hb
rcases x with ⟨b,x | (⟨c,z⟩ | t)⟩
· exact ⟨hb,by change 0<3; omega,h.positive,by change 0<7; omega,PrefixAlphabet.vectorCount_pos⟩
· exact ⟨hb,by change 1<3; omega,c.isLt.trans_le (h.channelBound b),by change 0<7; omega,PrefixAlphabet.encode_lt (hDim b) z.val⟩
· have ht := t.val.2.1.isLt
have hd := hDim b
exact ⟨hb,by change 2<3; omega,t.channel.isLt.trans_le (h.channelBound b),by dsimp [raw,PrefixParts.Data.Tree.height]; omega,
PrefixAlphabet.encode_lt (hDim b) t.bits⟩
theorem raw_valid {D : Data} (h : Good P F hDim ε D) (x : PrefixParts.Wiring.Vertex F ε) :
D.validRaw (raw P F hDim ε x)=true := by
have hb : D.validBlock (P.encode x.1)=true := h.validBlock ▸ P.encode_valid x.1
rcases x with ⟨b,x | (⟨c,z⟩ | t)⟩
· simp only [raw,Data.validRaw,hb,Bool.true_and,and_self,decide_true,Bool.true_or]
· have hz := (h.legal b (PrefixAlphabet.encode (hDim b) z.val)).mpr ⟨z,rfl⟩
simp only [raw,Data.validRaw,hb,Bool.true_and,h.channels,one_ne_zero,false_and,
decide_false,Bool.false_or,true_and,c.isLt,and_true,decide_true,Bool.true_and,hz,Bool.true_or]
· apply Bool.and_eq_true_iff.mpr ⟨hb,?_⟩
apply Bool.or_eq_true_iff.mpr
right
apply Bool.and_eq_true_iff.mpr
refine ⟨by simp only [raw,h.channels,t.channel.isLt,and_self,decide_true],?_⟩
change D.treeValid ⟨P.encode b,2,t.channel.val,t.height,PrefixAlphabet.encode (hDim b) t.bits⟩=true
apply Bool.and_eq_true_iff.mpr
refine ⟨by exact decide_eq_true (show D.root (P.encode b) t.channel.val≤t.height ∧
t.height≤D.dimension (P.encode b) from ⟨(h.root b t.channel) ▸ t.property.1,
(h.dimension b) ▸ Nat.le_of_lt_succ t.val.2.1.isLt⟩),?_⟩
obtain ⟨z,hz⟩ := t.property.2
apply List.any_eq_true.mpr
refine ⟨PrefixAlphabet.encode (hDim b) z.val,List.mem_range.mpr (PrefixAlphabet.encode_lt _ _),?_⟩
apply Bool.and_eq_true_iff.mpr
refine ⟨(h.legal b _).mpr ⟨z,rfl⟩,?_⟩
rw [h.order,PrefixAlphabet.prefix_encode,hz]
exact decide_eq_true rfl
end VariableWL.PrefixDescriptor
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PrefixDescriptor
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable1} (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
theorem raw_injective : Function.Injective (raw P F hDim ε) := by
rintro ⟨b,x⟩ ⟨d,y⟩ he
have hb : b=d := P.encode_injective (by simpa only [raw_block] using congrArg Raw.block he)
subst d
apply congrArg (Sigma.mk b)
cases x with
| inl x =>
cases y with
| inl y => congr
| inr y => cases y <;> have hk := congrArg Raw.kind he <;> cases hk
| inr x =>
cases y with
| inl y => cases x <;> have hk := congrArg Raw.kind he <;> cases hk
| inr y =>
congr 1
cases x with
| inl x =>
cases y with
| inr y => have hk := congrArg Raw.kind he; cases hk
| inl y =>
congr 1
apply Prod.ext
· exact Fin.ext (congrArg Raw.channel he)
· exact Subtype.ext (PrefixAlphabet.encode_injective (hDim b) (congrArg Raw.vector he))
| inr x =>
cases y with
| inl y => have hk := congrArg Raw.kind he; cases hk
| inr y =>
congr 1
exact Data.Tree.ext (Fin.ext (congrArg Raw.channel he)) (congrArg Raw.height he)
(PrefixAlphabet.encode_injective (hDim b) (congrArg Raw.vector he))
theorem raw_surjective {D : Data} (h : Good P F hDim ε D) (x : Raw)
(hb : x.block<D.blocks) (hv : D.validRaw x=true) :
∃v : Wiring.Vertex F ε,raw P F hDim ε v=x := by
obtain ⟨hbv,hv⟩ := Bool.and_eq_true_iff.mp hv
let u : Valid P.bound P.valid := ⟨⟨x.block,h.blocks ▸ hb⟩,h.validBlock ▸ hbv⟩
let b := P.equiv u
have eb : P.encode b=x.block := by
change (P.equiv.symm (P.equiv u)).val.val=_
rw [Equiv.symm_apply_apply]
rcases Bool.or_eq_true_iff.mp hv with hv | hv
· rcases Bool.or_eq_true_iff.mp hv with hv | hv
· obtain ⟨hk,hc,hh,hu⟩ := of_decide_eq_true hv
refine ⟨⟨b,.inl ()⟩,?_⟩
apply Raw.ext <;> simp only [raw,eb,hk,hc,hh,hu]
· obtain ⟨hv,hl⟩ := Bool.and_eq_true_iff.mp hv
obtain ⟨hk,hc,hh⟩ := of_decide_eq_true hv
rw [←eb,h.channels] at hc
rw [←eb] at hl
obtain ⟨z,hz⟩ := (h.legal b x.vector).mp hl
refine ⟨⟨b,.inr (.inl (⟨x.channel,hc⟩,z))⟩,?_⟩
apply Raw.ext <;> simp only [raw,eb,hk,hh,hz]
· obtain ⟨hv,ht⟩ := Bool.and_eq_true_iff.mp hv
obtain ⟨hk,hc⟩ := of_decide_eq_true hv
rw [←eb,h.channels] at hc
let c : Fin (F b).channels := ⟨x.channel,hc⟩
obtain ⟨ht,hz⟩ := Bool.and_eq_true_iff.mp ht
obtain ⟨hr,hd⟩ := of_decide_eq_true ht
rw [←eb,h.dimension] at hd
have hr' : (F b).root c≤x.height := by
rw [←eb] at hr
change D.root (P.encode b) c.val≤x.height at hr
rwa [h.root] at hr
obtain ⟨j,_,hj⟩ := List.any_eq_true.mp hz
obtain ⟨hl,hp⟩ := Bool.and_eq_true_iff.mp hj
rw [←eb] at hl
obtain ⟨z,ez⟩ := (h.legal b j).mp hl
have hp' : PrefixAlphabet.encode (hDim b) (PrefixParts.Data.truncate x.height (z.val ∘ (F b).order c))=x.vector := by
have hop := h.order b c
rw [←ez,←eb,hop,PrefixAlphabet.prefix_encode] at hp
exact of_decide_eq_true hp
refine ⟨⟨b,.inr (.inr (PrefixParts.Data.Tree.ofValuation c x.height hr' hd z))⟩,?_⟩
apply Raw.ext <;> simp only [raw,PrefixParts.Data.Tree.ofValuation,eb,hk,hp',c]
noncomputable def presentation {D : Data} (h : Good P F hDim ε D) : Presentation (Wiring.Vertex F ε) :=
Presentation.ofEncoding D.bound D.valid (fun x=>D.pack (raw P F hDim ε x))
(fun x=>D.pack_lt _ (raw_bounds P F hDim ε h x).1 (raw_bounds P F hDim ε h x).2.1
(raw_bounds P F hDim ε h x).2.2.1 (raw_bounds P F hDim ε h x).2.2.2.1
(raw_bounds P F hDim ε h x).2.2.2.2)
(fun x=>by
rw [Data.valid,D.unpack_pack _ (raw_bounds P F hDim ε h x).2.1
(raw_bounds P F hDim ε h x).2.2.1 (raw_bounds P F hDim ε h x).2.2.2.1
(raw_bounds P F hDim ε h x).2.2.2.2]
exact raw_valid P F hDim ε h x)
(by
intro x y he
have hb := raw_bounds P F hDim ε h x
have hc := raw_bounds P F hDim ε h y
have he' := congrArg D.unpack he
rw [D.unpack_pack _ hb.2.1 hb.2.2.1 hb.2.2.2.1 hb.2.2.2.2,
D.unpack_pack _ hc.2.1 hc.2.2.1 hc.2.2.2.1 hc.2.2.2.2] at he'
exact raw_injective P F hDim ε he')
(by
intro i hi hv
obtain ⟨x,hx⟩ := raw_surjective P F hDim ε h (D.unpack i) (D.unpack_bounds h.positive hi).1 hv
exact ⟨x,by rw [hx,D.pack_unpack]⟩)
@[simp] theorem presentation_encode {D : Data} (h : Good P F hDim ε D) (x : Wiring.Vertex F ε) :
(presentation P F hDim ε h).encode x=D.pack (raw P F hDim ε x) := rfl
end VariableWL.PrefixDescriptor
namespace VariableWL.PrefixAlphabet
open VariableWL.Affine
noncomputable def trim (h i : ℕ) : ℕ :=
if hi : i<vectorCount then (vectorNumber (truncated h (vectorNumber.symm ⟨i,hi⟩))).val else 0
@[simp] theorem trim_encode {a : ℕ} (ha : a≤6) (z : Vec a) (h : ℕ) :
trim h (encode ha z)=encode ha (PrefixParts.Data.truncate h z) := by
simp only [trim,dite_eq_left (encode_lt ha z)]
change (vectorNumber (truncated h (vectorNumber.symm (vectorNumber ⟨⟨a,by omega⟩,z⟩)))).val=_
rw [Equiv.symm_apply_apply]
rfl
end VariableWL.PrefixAlphabet
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
namespace Data
variable (D : Data)
noncomputable def forward (x y : Raw) : Bool :=
(decide (x.kind=0 ∧ y.kind=2 ∧ y.channel=0 ∧ y.height=0)) ||
(decide (x.kind=1 ∧ y.kind=1 ∧ x.channel+1=y.channel ∧ x.vector=y.vector)) ||
(decide (x.kind=2 ∧ y.kind=2 ∧ x.channel=y.channel ∧ x.height+1=y.height ∧
PrefixAlphabet.trim x.height y.vector=x.vector)) ||
(decide (x.kind=2 ∧ y.kind=1 ∧ x.channel=y.channel ∧ x.height=D.dimension x.block ∧
x.vector=PrefixAlphabet.prefixCode (D.order x.block y.channel) (D.dimension x.block) y.vector))
noncomputable def slot (x y : Raw) : ℕ :=
if x.kind=0 then 0 else if x.kind=1 then
if y.kind=1 then if y.channel<x.channel then 0 else 1 else 2
else if y.kind=0 then 0 else if y.kind=1 then 1 else
if y.height<x.height then 0 else
if x.height<D.dimension x.block then PrefixAlphabet.bit y.vector x.height+1 else 1
noncomputable def internal (x y : Raw) (i j : ℕ) : Bool :=
decide (x.block=y.block) && (D.forward x y || D.forward y x) &&
decide (i=D.slot x y ∧ j=D.slot y x)
end Data
variable {B : Type uVariable2} (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
theorem raw_forward {D : Data} (h : Good P F hDim ε D) (b : B) (x y : (F b).Vertex ε) :
D.forward (raw P F hDim ε ⟨b,x⟩) (raw P F hDim ε ⟨b,y⟩)=true ↔ PrefixParts.Data.Forward x y := by
have hinj (z w : Vec (F b).dimension) : PrefixAlphabet.encode (hDim b) z=PrefixAlphabet.encode (hDim b) w ↔ z=w :=
(PrefixAlphabet.encode_injective (hDim b)).eq_iff
rcases x with x | (⟨c,z⟩ | t) <;> rcases y with y | (⟨d,w⟩ | u) <;>
simp only [raw,Data.forward,PrefixParts.Data.Forward,PrefixParts.Data.TreeStep,
h.dimension,h.order,PrefixAlphabet.prefix_encode,PrefixAlphabet.trim_encode,
PrefixParts.Data.truncate_full,Bool.or_eq_true,decide_eq_true_eq,hinj,
Fin.ext_iff,Subtype.ext_iff]
all_goals norm_num only
all_goals simp only [true_and,false_and,and_true,and_false,false_or,or_false,decide_false,Bool.false_eq_true]
theorem fin_val_ite (p : Prop) [Decidable p] (a b : Fin 3) :
(if p then a else b).val=if p then a.val else b.val := by split_ifs <;> rfl
theorem fin_val_dite (p : Prop) [Decidable p] (a : p → Fin 3) (b : ¬p → Fin 3) :
(dite p a b).val=dite p (fun h => (a h).val) (fun h => (b h).val) := by split_ifs <;> rfl
theorem raw_slot {D : Data} (h : Good P F hDim ε D) (b : B) (x y : (F b).Vertex ε) :
D.slot (raw P F hDim ε ⟨b,x⟩) (raw P F hDim ε ⟨b,y⟩)=(PrefixParts.Data.slot x y).val := by
rcases x with x | (⟨c,z⟩ | t) <;> rcases y with y | (⟨d,w⟩ | u) <;>
simp only [Data.slot,raw,PrefixParts.Data.slot,h.dimension,one_ne_zero,show (2:ℕ)≠0 by omega,show (2:ℕ)≠1 by omega,
ite_true,ite_false,show (0:ℕ)≠1 by omega,Fin.val_zero,Fin.val_one,fin_val_ite,fin_val_dite,PrefixParts.Data.bitPort]
· rfl
· rfl
· rfl
· split_ifs with h1 h2
· rfl
· rw [PrefixAlphabet.bit_encode (hDim b) u.bits ⟨t.height,h2⟩]
· rfl
theorem raw_internal [Fintype B] {D : Data} (h : Good P F hDim ε D)
(x y : Wiring.Vertex F ε) (i j : Fin 3) :
D.internal (raw P F hDim ε x) (raw P F hDim ε y) i.val j.val=true ↔
(Wiring.internal F ε).edge (x,i) (y,j) := by
rcases x with ⟨b,x⟩
rcases y with ⟨d,y⟩
by_cases hbd : b=d
· subst d
simp only [Data.internal,raw_block,Bool.and_eq_true,Bool.or_eq_true,decide_eq_true_eq,
true_and,raw_forward P F hDim ε h,raw_slot P F hDim ε h]
simp only [Wiring.internal,SubcubicRealization.PortGraph.sigma,PrefixParts.Data.ports,
PrefixParts.Data.graph,SubcubicRealization.PortGraph.ofSlots,exists_true_left,Fin.ext_iff]
· have he : P.encode b≠P.encode d := P.encode_injective.ne hbd
simp only [Data.internal,raw_block,he,decide_false,Bool.false_and,Bool.false_eq_true,
Wiring.internal,SubcubicRealization.PortGraph.sigma,hbd]
exact ⟨False.elim,fun ⟨h,_⟩=>h⟩
end VariableWL.PrefixDescriptor
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable3} (P : Presentation B) (F : B → PrefixParts.Data)
noncomputable def sortRaw (s : Wiring.SortTag F) : Raw := match s.2 with
| .inl _ => ⟨P.encode s.1,0,0,0,0⟩
| .inr (.inl c) => ⟨P.encode s.1,1,c.val,0,0⟩
| .inr (.inr ⟨c,h⟩) => ⟨P.encode s.1,2,c.val,h.val.val,0⟩
@[simp] theorem sortRaw_block (s : Wiring.SortTag F) : (sortRaw P F s).block=P.encode s.1 := by
rcases s with ⟨b,x| (x|x)⟩ <;> rfl
theorem sortRaw_injective : Function.Injective (sortRaw P F) := by
rintro ⟨b,x⟩ ⟨d,y⟩ he
have hb := P.encode_injective (by simpa only [sortRaw_block] using congrArg Raw.block he)
subst d
apply congrArg (Sigma.mk b)
cases x with
| inl x =>
cases y with
| inl y => congr
| inr y => cases y <;> have hk := congrArg Raw.kind he <;> cases hk
| inr x =>
cases y with
| inl y => cases x <;> have hk := congrArg Raw.kind he <;> cases hk
| inr y =>
congr 1
cases x with
| inl x =>
cases y with
| inr y => have hk := congrArg Raw.kind he; cases hk
| inl y => exact congrArg Sum.inl (Fin.ext (congrArg Raw.channel he))
| inr x =>
cases y with
| inl y => have hk := congrArg Raw.kind he; cases hk
| inr y =>
congr 1
rcases x with ⟨c,u⟩
rcases y with ⟨d,v⟩
have hc : c=d := Fin.ext (congrArg Raw.channel he)
subst d
apply congrArg (Sigma.mk c)
exact Subtype.ext (Fin.ext (congrArg Raw.height he))
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
theorem sortRaw_bounds {D : Data} (h : Good P F hDim ε D) (x : Wiring.SortTag F) :
(sortRaw P F x).block<D.blocks ∧ (sortRaw P F x).kind<3 ∧
(sortRaw P F x).channel<D.channelBound ∧ (sortRaw P F x).height<7 ∧
(sortRaw P F x).vector<PrefixAlphabet.vectorCount := by
have hb := P.encode_lt x.1
rw [←h.blocks] at hb
rcases x with ⟨b,x | (c | ⟨c,t⟩)⟩
· exact ⟨hb,by change 0<3; omega,h.positive,by change 0<7; omega,PrefixAlphabet.vectorCount_pos⟩
· exact ⟨hb,by change 1<3; omega,c.isLt.trans_le (h.channelBound b),by change 0<7; omega,PrefixAlphabet.vectorCount_pos⟩
· have ht := t.val.isLt
have hd := hDim b
exact ⟨hb,by change 2<3; omega,c.isLt.trans_le (h.channelBound b),by dsimp [sortRaw]; omega,
PrefixAlphabet.vectorCount_pos⟩
theorem sortRaw_valid {D : Data} (h : Good P F hDim ε D) (x : Wiring.SortTag F) :
D.sortValid (sortRaw P F x)=true := by
have hb : D.validBlock (P.encode x.1)=true := h.validBlock ▸ P.encode_valid x.1
rcases x with ⟨b,x | (c | ⟨c,t⟩)⟩
· simp only [sortRaw,Data.sortValid,hb,Bool.true_and,and_self,true_or,decide_true]
· have hc := c.isLt
simp only [sortRaw,Data.sortValid,hb,Bool.true_and,h.channels,decide_eq_true_eq]
exact Or.inr (Or.inl ⟨True.intro,hc,True.intro⟩)
· simp only [sortRaw,Data.sortValid,hb,Bool.true_and,h.channels,h.root,h.dimension,decide_eq_true_eq]
exact Or.inr (Or.inr ⟨True.intro,c.isLt,t.property,Nat.le_of_lt_succ t.val.isLt⟩)
namespace Data
variable (D : Data)
noncomputable def sortPredicate (i : ℕ) : Bool := D.sortValid (D.unpack (i*PrefixAlphabet.vectorCount))
noncomputable def color (i : ℕ) : ℕ := 1+Descriptor.rank D.sortPredicate (D.tag (D.unpack i))
noncomputable def colorBound : ℕ := 1+Descriptor.rank D.sortPredicate D.sortBound
end Data
theorem sortPresentation {D : Data} (h : Good P F hDim ε D) :
∃Q : Presentation (Wiring.SortTag F),Q.bound=D.sortBound ∧ Q.valid=D.sortPredicate ∧
∀s,Q.encode s=D.tag (sortRaw P F s) := by
let f := fun s : Wiring.SortTag F=>D.tag (sortRaw P F s)
have hf (s) : f s<D.sortBound := by
have hb := sortRaw_bounds P F hDim ε h s
exact D.tag_lt _ hb.1 hb.2.1 hb.2.2.1 hb.2.2.2.1
have helper (s) : D.unpack (f s*PrefixAlphabet.vectorCount)=sortRaw P F s := by
have hb := sortRaw_bounds P F hDim ε h s
have hv : (sortRaw P F s).vector=0 := by rcases s with ⟨b,x | (x|x)⟩ <;> rfl
have he : f s*PrefixAlphabet.vectorCount=D.pack (sortRaw P F s) := by simp only [Data.pack,hv,Nat.add_zero]; rfl
rw [he,D.unpack_pack _ hb.2.1 hb.2.2.1 hb.2.2.2.1 hb.2.2.2.2]
have hp (s) : D.sortPredicate (f s)=true := by
rw [Data.sortPredicate,helper]
exact sortRaw_valid P F hDim ε h s
have hi : Function.Injective f := by
intro s t he
apply sortRaw_injective P F
rw [←helper s,←helper t,he]
have hs (i : ℕ) (hi : i<D.sortBound) (hv : D.sortPredicate i=true) : ∃s,f s=i := by
let x := D.unpack (i*PrefixAlphabet.vectorCount)
have hx : i*PrefixAlphabet.vectorCount<D.bound := Nat.mul_lt_mul_of_pos_right hi PrefixAlphabet.vectorCount_pos
have hb := (D.unpack_bounds h.positive hx).1
obtain ⟨hbv,hv⟩ := Bool.and_eq_true_iff.mp hv
let u : Valid P.bound P.valid := ⟨⟨x.block,h.blocks ▸ hb⟩,h.validBlock ▸ hbv⟩
let b := P.equiv u
have eb : P.encode b=x.block := by
change (P.equiv.symm (P.equiv u)).val.val=_
rw [Equiv.symm_apply_apply]
have hxv : x.vector=0 := by simp [x,Data.unpack]
have target (s : Wiring.SortTag F) (hh : sortRaw P F s=x) : f s=i := by
have he := congrArg D.pack hh
rw [D.pack_unpack] at he
have hv : (sortRaw P F s).vector=0 := by rcases s with ⟨b,x | (x|x)⟩ <;> rfl
simp only [Data.pack,hv,Nat.add_zero] at he
exact Nat.eq_of_mul_eq_mul_right PrefixAlphabet.vectorCount_pos he
change decide ((x.kind=0 ∧ x.channel=0 ∧ x.height=0) ∨
(x.kind=1 ∧ x.channel<D.channels x.block ∧ x.height=0) ∨
(x.kind=2 ∧ x.channel<D.channels x.block ∧ D.root x.block x.channel≤x.height ∧
x.height≤D.dimension x.block))=true at hv
rcases of_decide_eq_true hv with hh | hh | hh
· obtain ⟨hk,hc,hh⟩ := hh
exact ⟨⟨b,.inl ()⟩,target _ (by apply Raw.ext <;> simp only [sortRaw,eb,hk,hc,hh,hxv])⟩
· obtain ⟨hk,hc,hh⟩ := hh
rw [←eb,h.channels] at hc
exact ⟨⟨b,.inr (.inl ⟨x.channel,hc⟩)⟩,target _ (by apply Raw.ext <;> simp only [sortRaw,eb,hk,hh,hxv])⟩
· obtain ⟨hk,hc,hr,hd⟩ := hh
rw [←eb,h.channels] at hc
rw [←eb,h.dimension] at hd
let c : Fin (F b).channels := ⟨x.channel,hc⟩
have hr' : (F b).root c≤x.height := by
rw [←eb] at hr
change D.root (P.encode b) c.val≤x.height at hr
rwa [h.root] at hr
exact ⟨⟨b,.inr (.inr ⟨c,⟨x.height,by omega⟩,hr'⟩)⟩,
target _ (by apply Raw.ext <;> simp only [sortRaw,eb,hk,hxv,c])⟩
exact ⟨Presentation.ofEncoding _ _ f hf hp hi hs,rfl,rfl,fun s=>rfl⟩
end VariableWL.PrefixDescriptor
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def table₂ (N M : ℕ) (f : ℕ → ℕ → ℕ) (I J : Expr n) : Expr n :=
choose (conj (lt I (numeral N)) (lt J (numeral M))) (fixedNat₂ N M f I J) (numeral 0)
def table₃ (N M K : ℕ) (f : ℕ → ℕ → ℕ → ℕ) (I J L : Expr n) : Expr n :=
choose (conj (conj (lt I (numeral N)) (lt J (numeral M))) (lt L (numeral K)))
(fixedNat₃ N M K f I J L) (numeral 0)
end VariableWL.Computation.Stack.PolyRecipe
namespace VariableWL.PrefixAlphabet
open VariableWL.Affine
namespace TotalProgram
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
noncomputable def prefixCode (P H I : Expr n) : Expr n :=
table₃ orderCount 8 vectorCount PrefixAlphabet.prefixCode P (minimum H (numeral 7)) I
noncomputable def trim (H I : Expr n) : Expr n :=
table₂ 8 vectorCount PrefixAlphabet.trim (minimum H (numeral 7)) I
noncomputable def bit (I H : Expr n) : Expr n :=
table₂ vectorCount 7 PrefixAlphabet.bit I H
end TotalProgram
end VariableWL.PrefixAlphabet
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
namespace Data
variable (D : Data)
noncomputable def roots (x y : Raw) (i j : ℕ) : Bool :=
decide (x.kind=2 ∧ y.kind=2 ∧ i=0 ∧ j=0 ∧ x.channel≠0 ∧ y.channel≠0 ∧
x.height=D.root x.block x.channel ∧ y.height=D.root y.block y.channel) &&
D.matching (x.block*D.channelBound+x.channel) (y.block*D.channelBound+y.channel) &&
PrefixAlphabet.paddedEqual x.vector y.vector
noncomputable def anchors (x y : Raw) (i j : ℕ) : Bool :=
decide (x.kind=0 ∧ y.kind=0 ∧
((i=2 ∧ j=1 ∧ Descriptor.rank D.validBlock x.block+1=Descriptor.rank D.validBlock y.block) ∨
(i=1 ∧ j=2 ∧ Descriptor.rank D.validBlock y.block+1=Descriptor.rank D.validBlock x.block)))
noncomputable def incidence (a b : ℕ) : Bool :=
let x := D.unpack (a/3)
let y := D.unpack (b/3)
D.internal x y (a%3) (b%3) || D.roots x y (a%3) (b%3) || D.anchors x y (a%3) (b%3)
noncomputable def portData : Descriptor.PortData where
bound := D.bound
valid := D.valid
color := D.color
colorBound := D.colorBound
incidence := D.incidence
end Data
variable {B : Type uVariable4} (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
def MatchingGood (D : Data) (W : Wiring F) : Prop :=
∀c d : Channel F,D.matching (P.encode c.1*D.channelBound+c.2.val.val)
(P.encode d.1*D.channelBound+d.2.val.val)=true ↔ W.mate c=d
theorem rootPorts_tree [Fintype B] (W : Wiring F) (b d : B) (t : (F b).Tree ε) (u : (F d).Tree ε)
(i j : Fin 3) :
(W.rootPorts F ε).edge ((⟨b,.inr (.inr t)⟩ : Wiring.Vertex F ε),i) (⟨d,.inr (.inr u)⟩,j) ↔
i=0 ∧ j=0 ∧ ∃hc : t.channel.val≠0,∃hd : u.channel.val≠0,
t.height=(F b).root t.channel ∧ u.height=(F d).root u.channel ∧
W.mate ⟨b,t.channel,hc⟩=⟨d,u.channel,hd⟩ ∧ Wiring.pad t.bits=Wiring.pad u.bits := by
constructor
· rintro ⟨⟨⟨b',c⟩,t'⟩,⟨⟨d',e⟩,u'⟩,hx,hy,hm,hp⟩
have hi := congrArg Prod.snd hx
have hj := congrArg Prod.snd hy
have hb := congrArg (fun a : Wiring.Vertex F ε × Fin 3=>a.1.1) hx
have hd := congrArg (fun a : Wiring.Vertex F ε × Fin 3=>a.1.1) hy
dsimp only [Wiring.rootVertex] at hb hd
subst b'; subst d'
have ht : t=t'.val := Sum.inr_injective (Sum.inr_injective
(eq_of_heq (Sigma.mk.inj_iff.mp (congrArg Prod.fst hx)).2))
have hu : u=u'.val := Sum.inr_injective (Sum.inr_injective
(eq_of_heq (Sigma.mk.inj_iff.mp (congrArg Prod.fst hy)).2))
subst t; subst u
have hc := t'.property.1
have he := u'.property.1
refine ⟨hi,hj,by rw [hc]; exact c.property,by rw [he]; exact e.property,?_,?_,?_,hp⟩
· rw [hc]; exact t'.property.2
· rw [he]; exact u'.property.2
· simpa only [hc,he] using hm
· rintro ⟨rfl,rfl,hc,hd,ht,hu,hm,hp⟩
exact ⟨⟨⟨b,t.channel,hc⟩,t,rfl,ht⟩,⟨⟨d,u.channel,hd⟩,u,rfl,hu⟩,rfl,rfl,hm,hp⟩
theorem raw_roots [Fintype B] {D : Data} (h : Good P F hDim ε D) (W : Wiring F)
(hm : MatchingGood P F D W) (x y : Wiring.Vertex F ε) (i j : Fin 3) :
D.roots (raw P F hDim ε x) (raw P F hDim ε y) i.val j.val=true ↔
(W.rootPorts F ε).edge (x,i) (y,j) := by
rcases x with ⟨b,x | (x | t)⟩ <;> rcases y with ⟨d,y | (y | u)⟩
all_goals try {
simp only [Data.roots,raw,show (0:ℕ)≠2 by omega,show (1:ℕ)≠2 by omega,false_and,and_false,
decide_false,Bool.false_and,Bool.false_eq_true]
constructor
· exact False.elim
· rintro ⟨a,b,ha,hb,_,_⟩
first
| have hx := congrArg (fun z : Wiring.Vertex F ε => (raw P F hDim ε z).kind) (congrArg Prod.fst ha)
simp only [Wiring.rootVertex,raw] at hx
omega
| have hy := congrArg (fun z : Wiring.Vertex F ε => (raw P F hDim ε z).kind) (congrArg Prod.fst hb)
simp only [Wiring.rootVertex,raw] at hy
omega }
rw [rootPorts_tree F ε W]
simp only [Data.roots,raw,h.root,Bool.and_eq_true,decide_eq_true_eq,
PrefixAlphabet.paddedEqual_encode,true_and]
constructor
· rintro ⟨⟨⟨hi,hj,hc,hd,ht,hu⟩,hmatch⟩,hp⟩
exact ⟨Fin.ext hi,Fin.ext hj,hc,hd,ht,hu,(hm ⟨b,t.channel,hc⟩ ⟨d,u.channel,hd⟩).mp hmatch,hp⟩
· rintro ⟨hi,hj,hc,hd,ht,hu,hmatch,hp⟩
exact ⟨⟨⟨congrArg Fin.val hi,congrArg Fin.val hj,hc,hd,ht,hu⟩,
(hm ⟨b,t.channel,hc⟩ ⟨d,u.channel,hd⟩).mpr hmatch⟩,hp⟩
end VariableWL.PrefixDescriptor
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_PrefixListing
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1
namespace VariableWL.PrefixAlphabet.TotalProgram
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
noncomputable def paddedEqual (I J : Expr n) : Expr n :=
choose (conj (lt I (numeral vectorCount)) (lt J (numeral vectorCount)))
(Program.paddedEqual I J) (literal [false])
end VariableWL.PrefixAlphabet.TotalProgram
namespace VariableWL.PrefixDescriptor.Program
attribute [local instance] Classical.propDecidable
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
structure RawExpr (n : ℕ) where
block : Expr n
kind : Expr n
channel : Expr n
height : Expr n
vector : Expr n
def RawExpr.up (x : RawExpr n) : RawExpr (n+1) :=
⟨x.block.up,x.kind.up,x.channel.up,x.height.up,x.vector.up⟩
structure Listing (n : ℕ) where
blocks : Expr n
validBlock : Expr (n+1)
channelBound : Expr n
dimension : Expr (n+1)
channels : Expr (n+1)
root : Expr (n+2)
order : Expr (n+2)
legal : Expr (n+2)
matching : Expr (n+2)
namespace Listing
variable (D : Listing n)
def up : Listing (n+1) where
blocks := D.blocks.up
validBlock := underOne D.validBlock
channelBound := D.channelBound.up
dimension := underOne D.dimension
channels := underOne D.channels
root := underTwo D.root
order := underTwo D.order
legal := underTwo D.legal
matching := underTwo D.matching
noncomputable def sortBound : Expr n := mul (mul (mul D.blocks (numeral 3)) D.channelBound) (numeral 7)
noncomputable def bound : Expr n := mul D.sortBound (numeral PrefixAlphabet.vectorCount)
noncomputable def tag (x : RawExpr n) : Expr n :=
add (mul (add (mul (add (mul x.block (numeral 3)) x.kind) D.channelBound) x.channel) (numeral 7)) x.height
noncomputable def unpack (I : Expr n) : RawExpr n :=
let a := div I (numeral PrefixAlphabet.vectorCount)
let b := div a (numeral 7)
let c := div b D.channelBound
⟨div c (numeral 3),mod c (numeral 3),mod b D.channelBound,mod a (numeral 7),
mod I (numeral PrefixAlphabet.vectorCount)⟩
noncomputable def treePossible (x : RawExpr n) (J : Expr n) : Expr n :=
conj (applyNat₂ D.legal x.block J)
(eq (PrefixAlphabet.TotalProgram.prefixCode (applyNat₂ D.order x.block x.channel) x.height J) x.vector)
noncomputable def treeValid (x : RawExpr n) : Expr n :=
conj (conj (le (applyNat₂ D.root x.block x.channel) x.height) (le x.height (applyNat D.dimension x.block)))
(any (numeral PrefixAlphabet.vectorCount) (D.up.treePossible x.up (input 0)))
noncomputable def validRaw (x : RawExpr n) : Expr n :=
conj (applyNat D.validBlock x.block)
(disj (conj (conj (eq x.kind (numeral 0)) (eq x.channel (numeral 0)))
(conj (eq x.height (numeral 0)) (eq x.vector (numeral 0))))
(disj (conj (conj (conj (eq x.kind (numeral 1)) (lt x.channel (applyNat D.channels x.block)))
(eq x.height (numeral 0))) (applyNat₂ D.legal x.block x.vector))
(conj (conj (eq x.kind (numeral 2)) (lt x.channel (applyNat D.channels x.block))) (D.treeValid x))))
noncomputable def valid (I : Expr n) : Expr n := D.validRaw (D.unpack I)
noncomputable def sortValid (x : RawExpr n) : Expr n :=
conj (applyNat D.validBlock x.block)
(disj (conj (eq x.kind (numeral 0)) (conj (eq x.channel (numeral 0)) (eq x.height (numeral 0))))
(disj (conj (eq x.kind (numeral 1)) (conj (lt x.channel (applyNat D.channels x.block)) (eq x.height (numeral 0))))
(conj (eq x.kind (numeral 2)) (conj (lt x.channel (applyNat D.channels x.block))
(conj (le (applyNat₂ D.root x.block x.channel) x.height) (le x.height (applyNat D.dimension x.block)))))))
noncomputable def sortPredicate (I : Expr n) : Expr n := D.sortValid (D.unpack (mul I (numeral PrefixAlphabet.vectorCount)))
noncomputable def color (I : Expr n) : Expr n := add (numeral 1)
(count (D.tag (D.unpack I)) (D.up.sortPredicate (input 0)))
noncomputable def colorBound : Expr n := add (numeral 1) (count D.sortBound (D.up.sortPredicate (input 0)))
noncomputable def forward (x y : RawExpr n) : Expr n :=
disj (disj (disj
(conj (conj (eq x.kind (numeral 0)) (eq y.kind (numeral 2)))
(conj (eq y.channel (numeral 0)) (eq y.height (numeral 0))))
(conj (conj (eq x.kind (numeral 1)) (eq y.kind (numeral 1)))
(conj (eq (add x.channel (numeral 1)) y.channel) (eq x.vector y.vector))))
(conj (conj (eq x.kind (numeral 2)) (eq y.kind (numeral 2)))
(conj (eq x.channel y.channel) (conj (eq (add x.height (numeral 1)) y.height)
(eq (PrefixAlphabet.TotalProgram.trim x.height y.vector) x.vector)))))
(conj (conj (eq x.kind (numeral 2)) (eq y.kind (numeral 1)))
(conj (eq x.channel y.channel) (conj (eq x.height (applyNat D.dimension x.block))
(eq x.vector (PrefixAlphabet.TotalProgram.prefixCode (applyNat₂ D.order x.block y.channel)
(applyNat D.dimension x.block) y.vector)))))
noncomputable def slot (x y : RawExpr n) : Expr n :=
choose (eq x.kind (numeral 0)) (numeral 0)
(choose (eq x.kind (numeral 1))
(choose (eq y.kind (numeral 1)) (choose (lt y.channel x.channel) (numeral 0) (numeral 1)) (numeral 2))
(choose (eq y.kind (numeral 0)) (numeral 0)
(choose (eq y.kind (numeral 1)) (numeral 1)
(choose (lt y.height x.height) (numeral 0)
(choose (lt x.height (applyNat D.dimension x.block))
(add (PrefixAlphabet.TotalProgram.bit y.vector x.height) (numeral 1)) (numeral 1))))))
noncomputable def internal (x y : RawExpr n) (I J : Expr n) : Expr n :=
conj (conj (eq x.block y.block) (disj (D.forward x y) (D.forward y x)))
(conj (eq I (D.slot x y)) (eq J (D.slot y x)))
noncomputable def roots (x y : RawExpr n) (I J : Expr n) : Expr n :=
conj (conj (conj (conj (eq x.kind (numeral 2)) (eq y.kind (numeral 2)))
(conj (conj (eq I (numeral 0)) (eq J (numeral 0)))
(conj (conj (neg (eq x.channel (numeral 0))) (neg (eq y.channel (numeral 0))))
(conj (eq x.height (applyNat₂ D.root x.block x.channel)) (eq y.height (applyNat₂ D.root y.block y.channel))))))
(applyNat₂ D.matching (add (mul x.block D.channelBound) x.channel) (add (mul y.block D.channelBound) y.channel)))
(PrefixAlphabet.TotalProgram.paddedEqual x.vector y.vector)
noncomputable def anchors (x y : RawExpr n) (I J : Expr n) : Expr n :=
conj (conj (eq x.kind (numeral 0)) (eq y.kind (numeral 0)))
(disj (conj (conj (eq I (numeral 2)) (eq J (numeral 1)))
(eq (add (count x.block D.validBlock) (numeral 1)) (count y.block D.validBlock)))
(conj (conj (eq I (numeral 1)) (eq J (numeral 2)))
(eq (add (count y.block D.validBlock) (numeral 1)) (count x.block D.validBlock))))
noncomputable def incidence (I J : Expr n) : Expr n :=
let x := D.unpack (div I (numeral 3))
let y := D.unpack (div J (numeral 3))
let i := mod I (numeral 3)
let j := mod J (numeral 3)
disj (disj (D.internal x y i j) (D.roots x y i j)) (D.anchors x y i j)
noncomputable def portListing : PortListing n where
bound := D.bound
valid := D.up.valid (input 0)
color := D.up.color (input 0)
colorBound := D.colorBound
incidence := D.up.up.incidence (input 0) (input 1)
end Listing
end VariableWL.PrefixDescriptor.Program
namespace VariableWL.Descriptor.Presentation
variable {A : Type uVariable1} [Fintype A] (P : Presentation A)
theorem enumeration_val (x : A) :
((@VariableWL.enumeration A _ P.numbering) x).val=Descriptor.rank P.valid (P.encode x) := rfl
end VariableWL.Descriptor.Presentation
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockDescriptor
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable1} [Fintype B] (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
theorem raw_anchors {D : Data} (h : Good P F hDim ε D) (x y : Wiring.Vertex F ε) (i j : Fin 3) :
let _ : FiniteNumbering B := P.numbering
D.anchors (raw P F hDim ε x) (raw P F hDim ε y) i.val j.val=true ↔
(Wiring.anchorPorts F ε).edge (x,i) (y,j) := by
let _ : FiniteNumbering B := P.numbering
rcases x with ⟨b,x | (x | t)⟩ <;> rcases y with ⟨d,y | (y | u)⟩
all_goals try {
simp only [Data.anchors,raw,one_ne_zero,show (2:ℕ)≠0 by omega,false_and,and_false,decide_false,Bool.false_eq_true]
constructor
· exact False.elim
· rintro (⟨a,b,ha,hb,_⟩ | ⟨a,b,hb,ha,_⟩)
all_goals first
| have hx := congrArg (fun z : Wiring.Vertex F ε => (raw P F hDim ε z).kind) (congrArg Prod.fst ha)
simp only [Wiring.anchor,raw] at hx
omega
| have hy := congrArg (fun z : Wiring.Vertex F ε => (raw P F hDim ε z).kind) (congrArg Prod.fst hb)
simp only [Wiring.anchor,raw] at hy
omega }
cases x; cases y
simp only [Data.anchors,raw,h.validBlock,true_and,decide_eq_true_eq]
constructor
· rintro (⟨hi,hj,he⟩ | ⟨hi,hj,he⟩)
· left; exact ⟨b,d,by congr; exact Fin.ext hi,by congr; exact Fin.ext hj,by simpa only [Presentation.enumeration_val] using he⟩
· right; exact ⟨d,b,by congr; exact Fin.ext hj,by congr; exact Fin.ext hi,by simpa only [Presentation.enumeration_val] using he⟩
· rintro (⟨a,c,ha,hc,he⟩ | ⟨a,c,hc,ha,he⟩)
· have hb : b=a := congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.1.1) ha
have hd : d=c := congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.1.1) hc
subst a; subst c
exact Or.inl ⟨congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.2.val) ha,
congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.2.val) hc,by simpa only [Presentation.enumeration_val] using he⟩
· have hb : b=c := congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.1.1) ha
have hd : d=a := congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.1.1) hc
subst a; subst c
exact Or.inr ⟨congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.2.val) ha,
congrArg (fun z : Wiring.Vertex F ε × Fin 3=>z.2.val) hc,by simpa only [Presentation.enumeration_val] using he⟩
theorem raw_incidence {D : Data} (h : Good P F hDim ε D) (W : Wiring F) (hm : MatchingGood P F D W)
(x y : Wiring.Vertex F ε) (i j : Fin 3) :
let _ : FiniteNumbering B := P.numbering
D.incidence (3*D.pack (raw P F hDim ε x)+i.val) (3*D.pack (raw P F hDim ε y)+j.val)=true ↔
(W.ports F ε).edge (x,i) (y,j) := by
let _ : FiniteNumbering B := P.numbering
have hi : i.val<3 := i.isLt
have hj : j.val<3 := j.isLt
have hx := raw_bounds P F hDim ε h x
have hy := raw_bounds P F hDim ε h y
simp only [Data.incidence,Nat.mul_add_div (by omega : 0<3),Nat.mul_add_mod,Nat.mod_eq_of_lt hi,
Nat.mod_eq_of_lt hj,Nat.div_eq_of_lt hi,Nat.div_eq_of_lt hj,Nat.add_zero,
D.unpack_pack _ hx.2.1 hx.2.2.1 hx.2.2.2.1 hx.2.2.2.2,
D.unpack_pack _ hy.2.1 hy.2.2.1 hy.2.2.2.1 hy.2.2.2.2,
Bool.or_eq_true,raw_internal P F hDim ε h,raw_roots P F hDim ε h W hm,raw_anchors P F hDim ε h,
Wiring.ports,SubcubicRealization.PortGraph.union,or_assoc]
omit [Fintype B] in
theorem tag_sort {D : Data} (x : Wiring.Vertex F ε) :
D.tag (raw P F hDim ε x)=D.tag (sortRaw P F (Wiring.sort F x)) := by
rcases x with ⟨b,x | (x | x)⟩ <;> rfl
theorem raw_color {D : Data} (h : Good P F hDim ε D) (Q : Presentation (Wiring.SortTag F))
(hq : Q.valid=D.sortPredicate) (he : ∀s,Q.encode s=D.tag (sortRaw P F s))
(x : Wiring.Vertex F ε) :
let _ : FiniteNumbering (Wiring.SortTag F) := Q.numbering
D.color (D.pack (raw P F hDim ε x))=Wiring.color F x := by
let _ : FiniteNumbering (Wiring.SortTag F) := Q.numbering
have hx := raw_bounds P F hDim ε h x
rw [Data.color,D.unpack_pack _ hx.2.1 hx.2.2.1 hx.2.2.2.1 hx.2.2.2.2,tag_sort P F hDim ε]
simp only [Wiring.color,Presentation.enumeration_val,hq,he,Nat.add_comm]
omit [Fintype B] in
theorem color_le {D : Data} (h : Good P F hDim ε D) (x : Wiring.Vertex F ε) :
D.color (D.pack (raw P F hDim ε x))≤D.colorBound := by
have hx := raw_bounds P F hDim ε h x
rw [Data.color,D.unpack_pack _ hx.2.1 hx.2.2.1 hx.2.2.2.1 hx.2.2.2.2,Data.colorBound]
apply Nat.add_le_add_left
exact Descriptor.rank_mono D.sortPredicate (D.tag_lt _ hx.1 hx.2.1 hx.2.2.1 hx.2.2.2.1).le
end VariableWL.PrefixDescriptor
namespace VariableWL.Descriptor.Presentation
attribute [local instance] Classical.propDecidable
variable {A : Type uVariable2} {B : Type uVariable3}
noncomputable def product (P : Presentation A) (Q : Presentation B) : Presentation (A × B) :=
ofEncoding (P.bound*Q.bound) (fun i=>P.valid (i/Q.bound) && Q.valid (i%Q.bound))
(fun x=>P.encode x.1*Q.bound+Q.encode x.2)
(fun x=>by have hp := P.encode_lt x.1; have hq := Q.encode_lt x.2; nlinarith)
(fun x=>by
have hq := Q.encode_lt x.2
simp only [PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<Q.bound) hq,
PrefixDescriptor.Data.join_mod _ _ _ hq,P.encode_valid,Q.encode_valid,Bool.and_self])
(by
intro x y he
have hx := Q.encode_lt x.2
have hy := Q.encode_lt y.2
have hm := congrArg (fun i=>i%Q.bound) he
have hd := congrArg (fun i=>i/Q.bound) he
dsimp only at hm hd
rw [PrefixDescriptor.Data.join_mod _ _ _ hx,PrefixDescriptor.Data.join_mod _ _ _ hy] at hm
rw [PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<Q.bound) hx,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<Q.bound) hy] at hd
exact Prod.ext (P.encode_injective hd) (Q.encode_injective hm))
(by
intro i hi hv
have hq : 0<Q.bound := by nlinarith
obtain ⟨hpv,hqv⟩ := Bool.and_eq_true_iff.mp hv
let a : Valid P.bound P.valid := ⟨⟨i/Q.bound,(Nat.div_lt_iff_lt_mul hq).mpr hi⟩,hpv⟩
let b : Valid Q.bound Q.valid := ⟨⟨i%Q.bound,Nat.mod_lt _ hq⟩,hqv⟩
refine ⟨(P.equiv a,Q.equiv b),?_⟩
simp only [encode,Equiv.symm_apply_apply]
change (i/Q.bound)*Q.bound+i%Q.bound=i
rw [Nat.mul_comm,Nat.div_add_mod])
@[simp] theorem product_encode (P : Presentation A) (Q : Presentation B) (x : A × B) :
(P.product Q).encode x=P.encode x.1*Q.bound+Q.encode x.2 := rfl
noncomputable def sum (P : Presentation A) (Q : Presentation B) : Presentation (A ⊕ B) :=
ofEncoding (P.bound+Q.bound) (fun i=>if i<P.bound then P.valid i else Q.valid (i-P.bound))
(Sum.elim P.encode (fun b=>P.bound+Q.encode b))
(fun x=>by cases x with
| inl a => exact (P.encode_lt a).trans_le (Nat.le_add_right _ _)
| inr b => have := Q.encode_lt b; dsimp; omega)
(fun x=>by cases x with
| inl a => exact (ite_eq_left (P.encode_lt a)).trans (P.encode_valid a)
| inr b => simpa only [Sum.elim_inr,not_lt.mpr (Nat.le_add_right _ _),ite_false,Nat.add_sub_cancel_left] using Q.encode_valid b)
(by
rintro (a|a) (b|b) he
· exact congrArg Sum.inl (P.encode_injective he)
· have := P.encode_lt a; dsimp at he; omega
· have := P.encode_lt b; dsimp at he; omega
· exact congrArg Sum.inr (Q.encode_injective (Nat.add_left_cancel he)))
(by
intro i hi hv
by_cases h : i<P.bound
· rw [ite_eq_left h] at hv
let a : Valid P.bound P.valid := ⟨⟨i,h⟩,hv⟩
exact ⟨.inl (P.equiv a),by simp only [Sum.elim_inl,encode,Equiv.symm_apply_apply]; rfl⟩
· rw [ite_eq_right h] at hv
let b : Valid Q.bound Q.valid := ⟨⟨i-P.bound,by omega⟩,hv⟩
exact ⟨.inr (Q.equiv b),by simp only [Sum.elim_inr,encode,Equiv.symm_apply_apply]; change P.bound+(i-P.bound)=i; omega⟩)
@[simp] theorem sum_inl (P : Presentation A) (Q : Presentation B) (a : A) :
(P.sum Q).encode (.inl a)=P.encode a := rfl
@[simp] theorem sum_inr (P : Presentation A) (Q : Presentation B) (b : B) :
(P.sum Q).encode (.inr b)=P.bound+Q.encode b := rfl
noncomputable def filter (P : Presentation A) (Q : ℕ → Bool) (T : A → Prop)
(h : ∀a,Q (P.encode a)=true ↔ T a) : Presentation {a // T a} :=
ofEncoding P.bound (fun i=>P.valid i && Q i) (fun a=>P.encode a.val)
(fun a=>P.encode_lt a.val)
(fun a=>Bool.and_eq_true_iff.mpr ⟨P.encode_valid a.val,(h a.val).mpr a.property⟩)
(by intro a b he; exact Subtype.ext (P.encode_injective he))
(by
intro i hi hv
obtain ⟨hp,hq⟩ := Bool.and_eq_true_iff.mp hv
let a : Valid P.bound P.valid := ⟨⟨i,hi⟩,hp⟩
have ha : P.encode (P.equiv a)=i := by simp only [encode,Equiv.symm_apply_apply]; rfl
exact ⟨⟨P.equiv a,(h _).mp (ha ▸ hq)⟩,ha⟩)
@[simp] theorem filter_encode (P : Presentation A) (Q : ℕ → Bool) (T : A → Prop) (h) (a : {a // T a}) :
(P.filter Q T h).encode a=P.encode a.val := rfl
end VariableWL.Descriptor.Presentation
namespace VariableWL.PrefixDescriptor
open VariableWL.Affine Descriptor PrefixParts SubcubicRealization
attribute [local instance] Classical.propDecidable
variable {B : Type uVariable4} [Fintype B] (P : Presentation B) (F : B → PrefixParts.Data)
variable (hDim : ∀b,(F b).dimension≤6) (ε : Bit)
omit [Fintype B] in
theorem presentation_inverse_val {D : Data} (h : Good P F hDim ε D) (x : Wiring.Vertex F ε) :
((presentation P F hDim ε h).equiv.symm x).val.val=D.pack (raw P F hDim ε x) := rfl
theorem port_sound {D : Data} (h : Good P F hDim ε D) (W : Wiring F) (hm : MatchingGood P F D W) :
D.portData.Sound := by
let _ : FiniteNumbering B := P.numbering
let Q := presentation P F hDim ε h
apply PortData.sound_of_encoding D.portData Q.equiv.symm Q.equiv.symm.bijective (W.ports F ε)
· intro x
exact color_le P F hDim ε h x
· intro x y i j
exact raw_incidence P F hDim ε h W hm x y i j
noncomputable def uncoloredIso {D : Data} (h : Good P F hDim ε D) (W : Wiring F)
(hm : MatchingGood P F D W) (S : Presentation (Wiring.SortTag F))
(hs : S.valid=D.sortPredicate) (he : ∀s,S.encode s=D.tag (sortRaw P F s)) :
let _ : FiniteNumbering B := P.numbering
let _ : FiniteNumbering (Wiring.SortTag F) := S.numbering
(D.portData.expanded.graph (D.portData.sound_expanded (port_sound P F hDim ε h W hm))).graph ≃g
Wiring.uncolored F W ε := by
let _ : FiniteNumbering B := P.numbering
let _ : FiniteNumbering (Wiring.SortTag F) := S.numbering
let Q := presentation P F hDim ε h
have hc (a : D.portData.Owners) : Wiring.color F (Q.equiv a)=D.color a.val.val := by
obtain ⟨x,rfl⟩ := Q.equiv.symm.surjective a
simpa only [Equiv.apply_symm_apply,Q,presentation_inverse_val] using (raw_color P F hDim ε h S hs he x).symm
let E := vertexEquiv Q.equiv (fun _=>Equiv.refl (Fin 3)) hc
let T : SubcubicRealization.graph (D.portData.ports (port_sound P F hDim ε h W hm))
(fun a=>D.color a.val.val) ≃g Wiring.uncolored F W ε := {
toEquiv := E
map_rel_iff' := by
intro x y
apply vertexEquiv_adj
obtain ⟨a,ha⟩ := Q.equiv.symm.surjective x.owner
obtain ⟨b,hb⟩ := Q.equiv.symm.surjective y.owner
change D.incidence (3*x.owner.val.val+x.port.val) (3*y.owner.val.val+y.port.val)=true ↔ _
rw [←ha,←hb]
simpa only [Equiv.apply_symm_apply,Equiv.refl_apply,Q,presentation_inverse_val] using raw_incidence P F hDim ε h W hm a b x.port y.port }
exact (D.portData.graphIso (port_sound P F hDim ε h W hm)).trans T
end VariableWL.PrefixDescriptor
namespace VariableWL.Descriptor.Presentation
variable {A : Type uVariable5} {B : Type uVariable6}
def transport (P : Presentation A) (e : A ≃ B) : Presentation B := ⟨P.bound,P.valid,P.equiv.trans e⟩
@[simp] theorem transport_encode (P : Presentation A) (e : A ≃ B) (a : A) :
(P.transport e).encode (e a)=P.encode a := by
change ((P.equiv.symm (e.symm (e a))).val.val)=_
rw [Equiv.symm_apply_apply]
rfl
def fin (n : ℕ) : Presentation (Fin n) where
bound := n
valid _ := true
equiv := { toFun a:=a.val, invFun a:=⟨a,rfl⟩,left_inv _:=rfl,right_inv _:=rfl }
@[simp] theorem fin_encode (n : ℕ) (a : Fin n) : (fin n).encode a=a.val := rfl
theorem count_eq_card [Fintype A] (P : Presentation A) : Descriptor.rank P.valid P.bound=Fintype.card A := by
simpa only [Fintype.card_fin] using (Fintype.card_congr (Descriptor.rankEquiv P.bound P.valid)).symm.trans
(Fintype.card_congr P.equiv)
end VariableWL.Descriptor.Presentation
namespace VariableWL.BlockDescriptor
open Blocks BlockCoordinates Descriptor
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable7} {E : Type uVariable8} [Fintype P] [Fintype E]
variable (J : ProductImages.Instance r P E)
variable (PB : Presentation (Block (n := n) J)) (PR : Presentation (Readout r n P E))
variable (H : ℕ → ℕ → Bool)
variable (hH : ∀b : Block (n := n) J,∀a,H (PB.encode b) (PR.encode a)=true ↔ HasReadout J b.val a)
noncomputable def properEquiv (b : Block (n := n) J) : Proper J b ≃
{x : Block (n := n) J × Readout r n P E // x.1≠b ∧ HasReadout J b.val x.2 ∧ HasReadout J x.1.val x.2} where
toFun p := ⟨(p.1.val,p.2.val),p.1.property,p.2.property⟩
invFun x := ⟨⟨x.val.1,x.property.1⟩,x.val.2,x.property.2⟩
left_inv _ := rfl
right_inv _ := rfl
def ProperPredicate (b i : ℕ) : Bool :=
decide (i/PR.bound≠b) && (H b (i%PR.bound) && H (i/PR.bound) (i%PR.bound))
omit [Fintype P] [Fintype E] in
include hH in
theorem properPredicate_code (b c : Block (n := n) J) (a : Readout r n P E) :
ProperPredicate PR H (PB.encode b) (PB.encode c*PR.bound+PR.encode a)=true ↔
c≠b ∧ HasReadout J b.val a ∧ HasReadout J c.val a := by
have ha := PR.encode_lt a
simp only [ProperPredicate,PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<PR.bound) ha,
PrefixDescriptor.Data.join_mod _ _ _ ha,Bool.and_eq_true,decide_eq_true_eq,
hH]
exact and_congr_left (fun _=>not_congr PB.encode_injective.eq_iff)
noncomputable def properPresentation (b : Block (n := n) J) : Presentation (Proper J b) :=
((PB.product PR).filter (ProperPredicate PR H (PB.encode b))
(fun x=>x.1≠b ∧ HasReadout J b.val x.2 ∧ HasReadout J x.1.val x.2)
(fun x=>properPredicate_code J PB PR H hH b x.1 x.2)).transport (properEquiv J b).symm
omit [Fintype P] [Fintype E] in
theorem properPresentation_valid (b : Block (n := n) J) (i : ℕ) :
(properPresentation J PB PR H hH b).valid i=
((PB.valid (i/PR.bound) && PR.valid (i%PR.bound)) && ProperPredicate PR H (PB.encode b) i) := rfl
theorem properNumber_pick (b : Block (n := n) J) (p : Proper J b) :
let _ : ∀b : Block (n := n) J, FiniteNumbering (Proper J b) := fun b=>(properPresentation J PB PR H hH b).numbering
Descriptor.pick (PB.bound*PR.bound) (properPresentation J PB PR H hH b).valid
((properNumber J b p).val.val-1)=PB.encode p.1.val*PR.bound+PR.encode p.2.val := by
let _ : ∀b : Block (n := n) J, FiniteNumbering (Proper J b) := fun b=>(properPresentation J PB PR H hH b).numbering
dsimp only
change Descriptor.pick _ _ (Descriptor.rank _ _ + 1 - 1)=_
rw [Nat.add_sub_cancel]
exact Descriptor.pick_rank _ _ _ ((properPresentation J PB PR H hH b).encode_lt p)
((properPresentation J PB PR H hH b).encode_valid p)
end VariableWL.BlockDescriptor
namespace VariableWL.BlockDescriptor
structure Core where
blocks : ℕ
validBlock : ℕ → Bool
reads : ℕ
validRead : ℕ → Bool
has : ℕ → ℕ → Bool
dimension : ℕ → ℕ
readDimension : ℕ → ℕ
zeroOrder : ℕ → ℕ
readOrder : ℕ → ℕ → ℕ
legal : ℕ → ℕ → Bool
namespace Core
variable (D : Core)
def properBound : ℕ := D.blocks*D.reads
def channelBound : ℕ := D.properBound+1
def proper (b i : ℕ) : Bool :=
(D.validBlock (i/D.reads) && D.validRead (i%D.reads)) &&
(decide (i/D.reads≠b) && (D.has b (i%D.reads) && D.has (i/D.reads) (i%D.reads)))
def channels (b : ℕ) : ℕ := Descriptor.rank (D.proper b) D.properBound+1
def select (b c : ℕ) : ℕ := Descriptor.pick D.properBound (D.proper b) (c-1)
def other (b c : ℕ) : ℕ := D.select b c/D.reads
def readout (b c : ℕ) : ℕ := D.select b c%D.reads
def root (b c : ℕ) : ℕ := if c=0 then 0 else D.readDimension (D.readout b c)
def order (b c : ℕ) : ℕ := if c=0 then D.zeroOrder b else D.readOrder b (D.readout b c)
def matching (i j : ℕ) : Bool :=
decide (D.other (i/D.channelBound) (i%D.channelBound)=j/D.channelBound ∧
D.other (j/D.channelBound) (j%D.channelBound)=i/D.channelBound ∧
D.readout (i/D.channelBound) (i%D.channelBound)=D.readout (j/D.channelBound) (j%D.channelBound))
def toPrefix : PrefixDescriptor.Data where
blocks := D.blocks
validBlock := D.validBlock
channelBound := D.channelBound
dimension := D.dimension
channels := D.channels
root := D.root
order := D.order
legal := D.legal
matching := D.matching
theorem channelBound_pos : 0<D.channelBound := Nat.zero_lt_succ _
theorem channels_le (b : ℕ) : D.channels b≤D.channelBound := by
apply Nat.add_le_add_right
exact List.countP_le_length.trans_eq List.length_range
end Core
end VariableWL.BlockDescriptor
namespace VariableWL.BlockDescriptor.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
structure Listing (n : ℕ) where
blocks : Expr n
validBlock : Expr (n+1)
reads : Expr n
validRead : Expr (n+1)
has : Expr (n+2)
dimension : Expr (n+1)
readDimension : Expr (n+1)
zeroOrder : Expr (n+1)
readOrder : Expr (n+2)
legal : Expr (n+2)
namespace Listing
variable (D : Listing n)
def eval (v : Env n) : Core where
blocks := D.blocks.number v
validBlock i := D.validBlock.bit (cons (List.replicate i true) v)
reads := D.reads.number v
validRead i := D.validRead.bit (cons (List.replicate i true) v)
has i j := D.has.bit (cons (List.replicate i true) (cons (List.replicate j true) v))
dimension i := D.dimension.number (cons (List.replicate i true) v)
readDimension i := D.readDimension.number (cons (List.replicate i true) v)
zeroOrder i := D.zeroOrder.number (cons (List.replicate i true) v)
readOrder i j := D.readOrder.number (cons (List.replicate i true) (cons (List.replicate j true) v))
legal i j := D.legal.bit (cons (List.replicate i true) (cons (List.replicate j true) v))
def up : Listing (n+1) where
blocks := D.blocks.up
validBlock := underOne D.validBlock
reads := D.reads.up
validRead := underOne D.validRead
has := underTwo D.has
dimension := underOne D.dimension
readDimension := underOne D.readDimension
zeroOrder := underOne D.zeroOrder
readOrder := underTwo D.readOrder
legal := underTwo D.legal
def properBound : Expr n := mul D.blocks D.reads
def channelBound : Expr n := add D.properBound (numeral 1)
def proper (B I : Expr n) : Expr n :=
conj (conj (applyNat D.validBlock (div I D.reads)) (applyNat D.validRead (mod I D.reads)))
(conj (neg (eq (div I D.reads) B))
(conj (applyNat₂ D.has B (mod I D.reads)) (applyNat₂ D.has (div I D.reads) (mod I D.reads))))
def channels (B : Expr n) : Expr n := add (count D.properBound (D.up.proper B.up (input 0))) (numeral 1)
def select (B C : Expr n) : Expr n := Computation.Stack.PolyRecipe.select D.properBound (D.up.proper B.up (input 0)) (sub C (numeral 1))
def other (B C : Expr n) : Expr n := div (D.select B C) D.reads
def readout (B C : Expr n) : Expr n := mod (D.select B C) D.reads
def root (B C : Expr n) : Expr n := choose (eq C (numeral 0)) (numeral 0) (applyNat D.readDimension (D.readout B C))
def order (B C : Expr n) : Expr n := choose (eq C (numeral 0)) (applyNat D.zeroOrder B) (applyNat₂ D.readOrder B (D.readout B C))
def matching (I J : Expr n) : Expr n :=
conj (eq (D.other (div I D.channelBound) (mod I D.channelBound)) (div J D.channelBound))
(conj (eq (D.other (div J D.channelBound) (mod J D.channelBound)) (div I D.channelBound))
(eq (D.readout (div I D.channelBound) (mod I D.channelBound)) (D.readout (div J D.channelBound) (mod J D.channelBound))))
def toPrefix : PrefixDescriptor.Program.Listing n where
blocks := D.blocks
validBlock := D.validBlock
channelBound := D.channelBound
dimension := D.dimension
channels := D.up.channels (input 0)
root := D.up.up.root (input 0) (input 1)
order := D.up.up.order (input 0) (input 1)
legal := D.legal
matching := D.up.up.matching (input 0) (input 1)
end Listing
end VariableWL.BlockDescriptor.Program
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockCatalog
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6
namespace VariableWL.BlockDescriptor
open Blocks BlockCoordinates Descriptor VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} [Fintype P] [Fintype E]
variable (J : ProductImages.Instance r P E) (hr : 2≤r) (hn : 0<n) (marked : Fin r)
variable (PB : Presentation (Block (n := n) J)) (PR : Presentation (Readout r n P E))
variable (hDim : ∀b : Block (n := n) J,Fintype.card (Coordinate J b.val)≤6) (ε : Bit)
structure Good (D : Core) : Prop where
blocks : D.blocks=PB.bound
reads : D.reads=PR.bound
validBlock : D.validBlock=PB.valid
validRead : D.validRead=PR.valid
has : ∀b a,D.has (PB.encode b) (PR.encode a)=true ↔ HasReadout J b.val a
dimension : ∀b,D.dimension (PB.encode b)=Fintype.card (Coordinate J b.val)
readDimension : ∀a,D.readDimension (PR.encode a)=readoutDimension J a
zeroOrder : ∀b,D.zeroOrder (PB.encode b)=PrefixAlphabet.encodeOrder (hDim b) (Equiv.refl _)
readOrder : ∀b a (ha : HasReadout J b.val a),D.readOrder (PB.encode b) (PR.encode a)=
PrefixAlphabet.encodeOrder (hDim b) (exists_readout_order J hr hn ha).choose
legal : ∀b i,D.legal (PB.encode b) i=true ↔ ∃z : Valuation J marked ε b,
PrefixAlphabet.encode (hDim b) (BlockCoordinates.encode J b.val z.val)=i
variable {D : Core} (h : Good J hr hn marked PB PR hDim ε D)
@[instance_reducible] noncomputable def properNumberings : (b : Block (n := n) J) → FiniteNumbering (Proper J b) :=
fun b=>(properPresentation J PB PR D.has h.has b).numbering
omit [Fintype P] [Fintype E] in
theorem proper_eq (b : Block (n := n) J) :
D.proper (PB.encode b)=(properPresentation J PB PR D.has h.has b).valid := by
funext i
simp only [Core.proper,h.reads,h.validBlock,h.validRead,properPresentation_valid,ProperPredicate]
include h in
theorem channels_eq (b : Block (n := n) J) : D.channels (PB.encode b)=Fintype.card (Proper J b)+1 := by
rw [Core.channels,proper_eq J hr hn marked PB PR hDim ε h]
have he : D.properBound=(properPresentation J PB PR D.has h.has b).bound := by
change D.blocks*D.reads=PB.bound*PR.bound
rw [h.blocks,h.reads]
rw [he,Presentation.count_eq_card]
theorem select_number (b : Block (n := n) J) (p : Proper J b) :
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
D.select (PB.encode b) (properNumber J b p).val.val=PB.encode p.1.val*PR.bound+PR.encode p.2.val := by
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
dsimp only
rw [Core.select,proper_eq J hr hn marked PB PR hDim ε h]
change Descriptor.pick (D.blocks*D.reads) _ _=_
rw [h.blocks,h.reads]
exact properNumber_pick J PB PR D.has h.has b p
theorem other_number (b : Block (n := n) J) (p : Proper J b) :
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
D.other (PB.encode b) (properNumber J b p).val.val=PB.encode p.1.val := by
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
dsimp only
rw [Core.other,select_number J hr hn marked PB PR hDim ε h,h.reads]
have ha := PR.encode_lt p.2.val
exact PrefixDescriptor.Data.join_div _ _ _ (by omega) ha
theorem readout_number (b : Block (n := n) J) (p : Proper J b) :
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
D.readout (PB.encode b) (properNumber J b p).val.val=PR.encode p.2.val := by
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
dsimp only
rw [Core.readout,select_number J hr hn marked PB PR hDim ε h,h.reads]
exact PrefixDescriptor.Data.join_mod _ _ _ (PR.encode_lt p.2.val)
theorem prefix_good :
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
PrefixDescriptor.Good PB (data J hr hn marked) hDim ε D.toPrefix := by
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
dsimp only
refine ⟨h.blocks,h.validBlock,D.channelBound_pos,?_,h.dimension,channels_eq J hr hn marked PB PR hDim ε h,?_,?_,?_⟩
· intro b
change Fintype.card (Proper J b)+1≤D.channelBound
rw [←channels_eq J hr hn marked PB PR hDim ε h]
exact D.channels_le _
· intro b c
change D.root (PB.encode b) c.val=channelRoot J b c
by_cases hc : c.val=0
· simp only [Core.root,ite_eq_left hc,channelRoot,dite_eq_left hc]
· obtain ⟨p,hp⟩ := (properNumber J b).surjective ⟨c,hc⟩
have hc' : (properNumber J b p).val=c := congrArg Subtype.val hp
rw [←hc']
change D.root (PB.encode b) (properNumber J b p).val.val=channelRoot J b (properNumber J b p).val
rw [channelRoot_number,Core.root,ite_eq_right (properNumber J b p).property,
readout_number J hr hn marked PB PR hDim ε h,h.readDimension]
· intro b c
change D.order (PB.encode b) c.val=PrefixAlphabet.encodeOrder (hDim b) (channelOrder J hr hn b c)
by_cases hc : c.val=0
· simp only [Core.order,ite_eq_left hc,channelOrder,dite_eq_left hc,h.zeroOrder]
· obtain ⟨p,hp⟩ := (properNumber J b).surjective ⟨c,hc⟩
have hc' : (properNumber J b p).val=c := congrArg Subtype.val hp
rw [←hc']
change D.order (PB.encode b) (properNumber J b p).val.val=
PrefixAlphabet.encodeOrder (hDim b) (channelOrder J hr hn b (properNumber J b p).val)
rw [channelOrder_number,Core.order,ite_eq_right (properNumber J b p).property,
readout_number J hr hn marked PB PR hDim ε h,h.readOrder b p.2.val p.2.property.1]
· intro b i
constructor
· intro hi
obtain ⟨z,hz⟩ := (h.legal b i).mp hi
exact ⟨valuationEquiv J hr hn marked b ε z,hz⟩
· rintro ⟨z,hz⟩
obtain ⟨y,rfl⟩ := (valuationEquiv J hr hn marked b ε).surjective z
exact (h.legal b i).mpr ⟨y,hz⟩
theorem matching_good :
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
PrefixDescriptor.MatchingGood PB (data J hr hn marked) D.toPrefix (wiring J hr hn marked) := by
let _ : (b : Block (n := n) J) → FiniteNumbering (Proper J b) := properNumberings J hr hn marked PB PR hDim ε h
dsimp only
intro c d
obtain ⟨⟨b,p⟩,rfl⟩ := (channelEquiv J hr hn marked).surjective c
obtain ⟨⟨e,q⟩,rfl⟩ := (channelEquiv J hr hn marked).surjective d
rw [mate_channel]
have hp : (properNumber J b p).val.val<D.channelBound :=
(properNumber J b p).val.isLt.trans_le (by rw [←channels_eq J hr hn marked PB PR hDim ε h]; exact D.channels_le _)
have hq : (properNumber J e q).val.val<D.channelBound :=
(properNumber J e q).val.isLt.trans_le (by rw [←channels_eq J hr hn marked PB PR hDim ε h]; exact D.channels_le _)
change D.matching (PB.encode b*D.channelBound+(properNumber J b p).val.val)
(PB.encode e*D.channelBound+(properNumber J e q).val.val)=true ↔ _
simp only [Core.matching,PrefixDescriptor.Data.join_div _ _ _ D.channelBound_pos hp,
PrefixDescriptor.Data.join_div _ _ _ D.channelBound_pos hq,
PrefixDescriptor.Data.join_mod _ _ _ hp,PrefixDescriptor.Data.join_mod _ _ _ hq,
other_number J hr hn marked PB PR hDim ε h,readout_number J hr hn marked PB PR hDim ε h,decide_eq_true_eq]
rw [PB.encode_injective.eq_iff,PB.encode_injective.eq_iff,PR.encode_injective.eq_iff]
rw [(channelEquiv J hr hn marked).injective.eq_iff]
constructor
· rintro ⟨he,hb,ha⟩
subst e
rcases q with ⟨⟨c,hc⟩,⟨a,haq⟩⟩
dsimp only at hb ha
subst c
subst a
rfl
· intro he
have he' := congrArg Sigma.fst he
have hb' := congrArg (fun x : Σ b : Block (n := n) J,Proper J b=>x.2.1.val) he
have ha' := congrArg (fun x : Σ b : Block (n := n) J,Proper J b=>x.2.2.val) he
exact ⟨he',hb'.symm,ha'⟩
end VariableWL.BlockDescriptor
namespace VariableWL.Descriptor.Presentation
attribute [local instance] Classical.propDecidable
noncomputable def boolean : Presentation Bool :=
ofEncoding 2 (fun _=>true) Bool.toNat (by intro b; cases b <;> decide) (fun _=>rfl)
(by intro a b h; cases a <;> cases b <;> simp_all)
(by intro i hi _; interval_cases i; exact ⟨false,rfl⟩; exact ⟨true,rfl⟩)
@[simp] theorem boolean_encode (b : Bool) : boolean.encode b=b.toNat := rfl
end VariableWL.Descriptor.Presentation
namespace VariableWL.BlockCatalog
open Blocks Subdivision Descriptor
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4}
variable (PP : Presentation P) (PE : Presentation E)
noncomputable def vertex : Presentation (Vertex P E n) := PP.sum (PE.product (Presentation.fin n))
noncomputable def link : Presentation (Link E n) := PE.product (Presentation.fin (n+1))
def horizontalEquiv : ((Fin r × Vertex P E n) × (Bool × Bool)) ≃ Horizontal r n P E where
toFun a := ⟨a.1.1,a.1.2,a.2.1,a.2.2⟩
invFun h := ((h.row,h.type),(h.first,h.last))
left_inv _ := rfl
right_inv _ := rfl
def squareEquiv : ((Fin r × Link E n) × (Bool × Bool)) ≃ Square r n E where
toFun a := ⟨a.1.1,a.1.2,a.2.1,a.2.2⟩
invFun h := ((h.row,h.link),(h.first,h.last))
left_inv _ := rfl
right_inv _ := rfl
def verticalEquiv : ((Fin r × Link E n) × Bool) ≃ Vertical r n E where
toFun a := ⟨a.1.1,a.1.2,a.2⟩
invFun h := ((h.row,h.link),h.label)
left_inv _ := rfl
right_inv _ := rfl
noncomputable def horizontal : Presentation (Horizontal r n P E) :=
(((Presentation.fin r).product (vertex (n := n) PP PE)).product
(Presentation.boolean.product Presentation.boolean)).transport horizontalEquiv
noncomputable def square : Presentation (Square r n E) :=
(((Presentation.fin r).product (link (n := n) PE)).product
(Presentation.boolean.product Presentation.boolean)).transport squareEquiv
noncomputable def vertical : Presentation (Vertical r n E) :=
(((Presentation.fin r).product (link (n := n) PE)).product Presentation.boolean).transport verticalEquiv
noncomputable def raw : Presentation (RawBlock r n P E) := (horizontal PP PE).sum (square PE)
noncomputable def readout : Presentation (Readout r n P E) := (horizontal PP PE).sum (vertical PE)
theorem horizontal_encode (h : Horizontal r n P E) :
(horizontal PP PE).encode h=(h.row.val*(PP.bound+PE.bound*n)+(vertex PP PE).encode h.type)*4+
h.first.toNat*2+h.last.toNat := by
change (h.row.val*(PP.bound+PE.bound*n)+(vertex PP PE).encode h.type)*(2*2)+
(h.first.toNat*2+h.last.toNat)=_
omega
theorem square_encode (s : Square r n E) :
(square PE).encode s=(s.row.val*(PE.bound*(n+1))+(link PE).encode s.link)*4+
s.first.toNat*2+s.last.toNat := by
change (s.row.val*(PE.bound*(n+1))+(link PE).encode s.link)*(2*2)+
(s.first.toNat*2+s.last.toNat)=_
omega
theorem vertex_inl (p : P) : (vertex (n := n) PP PE).encode (.inl p)=PP.encode p := rfl
theorem vertex_inr (e : E) (j : Fin n) :
(vertex PP PE).encode (.inr (e,j))=PP.bound+PE.encode e*n+j.val := by
change PP.bound+(PE.encode e*n+j.val)=_; omega
theorem link_encode (e : E) (j : Fin (n+1)) : (link PE).encode (e,j)=PE.encode e*(n+1)+j.val := rfl
structure Data where
rows : ℕ
internal : ℕ
reals : ℕ
comparisons : ℕ
validReal : ℕ → Bool
validComparison : ℕ → Bool
source : ℕ → ℕ
target : ℕ → ℕ
domain : ℕ → ℕ → ℕ → Bool
map : ℕ → ℕ → ℕ → ℕ
namespace Data
variable (D : Data)
def vertices : ℕ := D.reals+D.comparisons*D.internal
def links : ℕ := D.comparisons*(D.internal+1)
def horizontals : ℕ := D.rows*D.vertices*4
def squares : ℕ := D.rows*D.links*4
def verticals : ℕ := D.rows*D.links*2
def blocks : ℕ := D.horizontals+D.squares
def reads : ℕ := D.horizontals+D.verticals
def validVertex (i : ℕ) : Bool := if i<D.reals then D.validReal i else D.validComparison ((i-D.reals)/D.internal)
def validLink (i : ℕ) : Bool := D.validComparison (i/(D.internal+1))
def validH (i : ℕ) : Bool := D.validVertex (i/4%D.vertices)
def validS (i : ℕ) : Bool := D.validLink (i/4%D.links)
def validV (i : ℕ) : Bool := D.validLink (i/2%D.links)
def rawValid (i : ℕ) : Bool := if i<D.horizontals then D.validH i else D.validS (i-D.horizontals)
def readValid (i : ℕ) : Bool := if i<D.horizontals then D.validH i else D.validV (i-D.horizontals)
def hrow (i : ℕ) : ℕ := i/4/D.vertices
def htype (i : ℕ) : ℕ := i/4%D.vertices
def srow (i : ℕ) : ℕ := i/4/D.links
def slink (i : ℕ) : ℕ := i/4%D.links
def first (i : ℕ) : ℕ := i%4/2
def last (i : ℕ) : ℕ := i%2
def next (i : ℕ) : ℕ := (i+1)%D.rows
def labels (t i a : ℕ) : Bool := if t<D.reals then true else D.domain ((t-D.reals)/D.internal) i a
def horizontalValid (i : ℕ) : Bool := D.labels (D.htype i) (D.hrow i) (first i) && D.labels (D.htype i) (D.next (D.hrow i)) (last i)
def squareValid (i : ℕ) : Bool := D.domain (D.slink i/(D.internal+1)) (D.srow i) (first i) &&
D.domain (D.slink i/(D.internal+1)) (D.next (D.srow i)) (last i)
def validBlock (i : ℕ) : Bool := D.rawValid i &&
(if i<D.horizontals then D.horizontalValid i else D.squareValid (i-D.horizontals))
def left (l : ℕ) : ℕ := if l%(D.internal+1)=0 then D.source (l/(D.internal+1)) else
D.reals+(l/(D.internal+1))*D.internal+(l%(D.internal+1)-1)
def right (l : ℕ) : ℕ := if l%(D.internal+1)=D.internal then D.target (l/(D.internal+1)) else
D.reals+(l/(D.internal+1))*D.internal+l%(D.internal+1)
def output (l i a : ℕ) : ℕ := if l%(D.internal+1)=D.internal then D.map (l/(D.internal+1)) i a else a
def horizontalCode (i t a b : ℕ) : ℕ := (i*D.vertices+t)*4+a*2+b
def verticalCode (i l a : ℕ) : ℕ := D.horizontals+(i*D.links+l)*2+a
def squareLeft (s : ℕ) : ℕ := D.horizontalCode (D.srow s) (D.left (D.slink s)) (first s) (last s)
def squareRight (s : ℕ) : ℕ := D.horizontalCode (D.srow s) (D.right (D.slink s))
(D.output (D.slink s) (D.srow s) (first s)) (D.output (D.slink s) (D.next (D.srow s)) (last s))
def squareBottom (s : ℕ) : ℕ := D.verticalCode (D.srow s) (D.slink s) (first s)
def squareTop (s : ℕ) : ℕ := D.verticalCode (D.next (D.srow s)) (D.slink s) (last s)
def has (b a : ℕ) : Bool := if b<D.horizontals then decide (a=b) else
let s:=b-D.horizontals
decide (a=D.squareLeft s ∨ a=D.squareRight s ∨ a=D.squareBottom s ∨ a=D.squareTop s)
end Data
structure Good (J : ProductImages.Instance r P E) (D : Data) : Prop where
rows : D.rows=r
internal : D.internal=n
reals : D.reals=PP.bound
comparisons : D.comparisons=PE.bound
validReal : D.validReal=PP.valid
validComparison : D.validComparison=PE.valid
source : ∀e,D.source (PE.encode e)=PP.encode (J.source e)
target : ∀e,D.target (PE.encode e)=PP.encode (J.target e)
domain : ∀e i a,D.domain (PE.encode e) i.val a.toNat=true ↔ a ∈ J.domain e i
map : ∀e i a,D.map (PE.encode e) i.val a.toNat=(J.map e i a).toNat
end VariableWL.BlockCatalog
namespace VariableWL.BlockCatalog
open Blocks Subdivision Descriptor
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable5} {E : Type uVariable6}
variable (PP : Presentation P) (PE : Presentation E) (J : ProductImages.Instance r P E)
variable {D : Data} (h : Good (n := n) PP PE J D)
include h
theorem vertices_eq : D.vertices=(vertex (n := n) PP PE).bound := by
change D.reals+D.comparisons*D.internal=PP.bound+PE.bound*n
rw [h.reals,h.comparisons,h.internal]
theorem links_eq : D.links=(link (n := n) PE).bound := by
change D.comparisons*(D.internal+1)=PE.bound*(n+1)
rw [h.comparisons,h.internal]
theorem horizontals_eq : D.horizontals=(horizontal (r := r) (n := n) PP PE).bound := by
change D.rows*D.vertices*4=r*(PP.bound+PE.bound*n)*(2*2)
rw [h.rows,vertices_eq PP PE J h]
rfl
theorem squares_eq : D.squares=(square (r := r) (n := n) PE).bound := by
change D.rows*D.links*4=r*(PE.bound*(n+1))*(2*2)
rw [h.rows,links_eq PP PE J h]
rfl
theorem verticals_eq : D.verticals=(vertical (r := r) (n := n) PE).bound := by
change D.rows*D.links*2=r*(PE.bound*(n+1))*2
rw [h.rows,links_eq PP PE J h]
rfl
theorem blocks_eq : D.blocks=(raw (r := r) (n := n) PP PE).bound := by
change D.horizontals+D.squares=_
rw [horizontals_eq PP PE J h,squares_eq PP PE J h]
rfl
theorem reads_eq : D.reads=(readout (r := r) (n := n) PP PE).bound := by
change D.horizontals+D.verticals=_
rw [horizontals_eq PP PE J h,verticals_eq PP PE J h]
rfl
theorem validVertex_eq : D.validVertex=(vertex (n := n) PP PE).valid := by
funext i
change (if i<D.reals then D.validReal i else D.validComparison ((i-D.reals)/D.internal))=
(if i<PP.bound then PP.valid i else (PE.valid ((i-PP.bound)/n) && true))
simp only [h.reals,h.validReal,h.validComparison,h.internal,Bool.and_true]
theorem validLink_eq : D.validLink=(link (n := n) PE).valid := by
funext i
change D.validComparison (i/(D.internal+1))= (PE.valid (i/(n+1)) && true)
simp only [h.validComparison,h.internal,Bool.and_true]
theorem validH_eq : D.validH=(horizontal (r := r) (n := n) PP PE).valid := by
funext i
change D.validVertex (i/4%D.vertices)=
((true && (vertex PP PE).valid (i/4%(vertex (n := n) PP PE).bound)) && (true && true))
simp only [validVertex_eq PP PE J h,vertices_eq PP PE J h,Bool.true_and,Bool.and_true]
theorem validS_eq : D.validS=(square (r := r) (n := n) PE).valid := by
funext i
change D.validLink (i/4%D.links)=
((true && (link PE).valid (i/4%(link (n := n) PE).bound)) && (true && true))
simp only [validLink_eq PP PE J h,links_eq PP PE J h,Bool.true_and,Bool.and_true]
theorem validV_eq : D.validV=(vertical (r := r) (n := n) PE).valid := by
funext i
change D.validLink (i/2%D.links)=
((true && (link PE).valid (i/2%(link (n := n) PE).bound)) && true)
simp only [validLink_eq PP PE J h,links_eq PP PE J h,Bool.true_and,Bool.and_true]
theorem rawValid_eq : D.rawValid=(raw (r := r) (n := n) PP PE).valid := by
funext i
change (if i<D.horizontals then D.validH i else D.validS (i-D.horizontals))=_
simp only [horizontals_eq PP PE J h,validH_eq PP PE J h,validS_eq PP PE J h]
rfl
theorem readValid_eq : D.readValid=(readout (r := r) (n := n) PP PE).valid := by
funext i
change (if i<D.horizontals then D.validH i else D.validV (i-D.horizontals))=_
simp only [horizontals_eq PP PE J h,validH_eq PP PE J h,validV_eq PP PE J h]
rfl
omit h in
theorem boolPair_lt (a b : Bool) : a.toNat*2+b.toNat<4 := by cases a <;> cases b <;> decide
omit h in
theorem boolPair_first (a b : Bool) : (a.toNat*2+b.toNat)/2=a.toNat := by cases a <;> cases b <;> decide
omit h in
theorem packed_div (q : ℕ) (a b : Bool) : (q*4+a.toNat*2+b.toNat)/4=q := by
rw [Nat.add_assoc]
exact PrefixDescriptor.Data.join_div _ _ _ (by decide) (boolPair_lt a b)
omit h in
theorem packed_first (q : ℕ) (a b : Bool) : Data.first (q*4+a.toNat*2+b.toNat)=a.toNat := by
unfold Data.first
rw [Nat.add_assoc,PrefixDescriptor.Data.join_mod _ _ _ (boolPair_lt a b),boolPair_first]
omit h in
theorem packed_last (q : ℕ) (a b : Bool) : Data.last (q*4+a.toNat*2+b.toNat)=b.toNat := by
unfold Data.last
cases a <;> cases b <;> simp only [Bool.toNat_false,Bool.toNat_true] <;> omega
theorem horizontal_parts (x : Horizontal r n P E) :
D.hrow ((horizontal PP PE).encode x)=x.row.val ∧
D.htype ((horizontal PP PE).encode x)=(vertex PP PE).encode x.type ∧
Data.first ((horizontal PP PE).encode x)=x.first.toNat ∧
Data.last ((horizontal PP PE).encode x)=x.last.toNat := by
have hx := (vertex (n := n) PP PE).encode_lt x.type
have hv := vertices_eq PP PE J h
have hp : 0<(vertex (n := n) PP PE).bound := by omega
simp only [horizontal_encode,Data.hrow,Data.htype,packed_div,packed_first,packed_last,hv]
change (x.row.val*(vertex (n := n) PP PE).bound+(vertex PP PE).encode x.type)/(vertex PP PE).bound=x.row.val ∧
(x.row.val*(vertex (n := n) PP PE).bound+(vertex PP PE).encode x.type)%(vertex PP PE).bound=_ ∧ _
simp only [PrefixDescriptor.Data.join_div _ _ _ hp hx,PrefixDescriptor.Data.join_mod _ _ _ hx,and_self]
theorem square_parts (x : Square r n E) :
D.srow ((square PE).encode x)=x.row.val ∧ D.slink ((square PE).encode x)=(link PE).encode x.link ∧
Data.first ((square PE).encode x)=x.first.toNat ∧ Data.last ((square PE).encode x)=x.last.toNat := by
have hx := (link (n := n) PE).encode_lt x.link
have hv := links_eq PP PE J h
have hp : 0<(link (n := n) PE).bound := by omega
simp only [square_encode,Data.srow,Data.slink,packed_div,packed_first,packed_last,hv]
change (x.row.val*(link (n := n) PE).bound+(link PE).encode x.link)/(link PE).bound=x.row.val ∧
(x.row.val*(link (n := n) PE).bound+(link PE).encode x.link)%(link PE).bound=_ ∧ _
simp only [PrefixDescriptor.Data.join_div _ _ _ hp hx,PrefixDescriptor.Data.join_mod _ _ _ hx,and_self]
theorem next_eq (i : Fin r) : D.next i.val=(finRotate r i).val := by
have : NeZero r := i.neZero
rw [Data.next,h.rows,finRotate_apply,Fin.val_add]
simp only [Fin.val_one',Nat.add_mod_mod]
theorem labels_code (t : Vertex P E n) (i : Fin r) (a : Bool) :
D.labels ((vertex PP PE).encode t) i.val a.toNat=true ↔ a ∈ J.labels t i := by
cases t with
| inl p => simp only [Data.labels,vertex_inl,h.reals,ite_eq_left (PP.encode_lt p),ProductImages.Instance.labels,Finset.mem_univ]
| inr q =>
rcases q with ⟨e,j⟩
simp only [Data.labels,vertex_inr,h.reals,not_lt.mpr (by omega : PP.bound≤PP.bound+PE.encode e*n+j.val),ite_false]
have he : PP.bound+PE.encode e*n+j.val-PP.bound=PE.encode e*n+j.val := by omega
rw [he,h.internal,PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n) j.isLt]
exact h.domain e i a
theorem horizontal_valid (x : Horizontal r n P E) :
D.horizontalValid ((horizontal PP PE).encode x)=true ↔ ValidHorizontal J x := by
obtain ⟨hrw,ht,hf,hl⟩ := horizontal_parts PP PE J h x
rw [Data.horizontalValid,hrw,ht,hf,hl,next_eq PP PE J h,Bool.and_eq_true]
exact and_congr (labels_code PP PE J h x.type x.row x.first)
(labels_code PP PE J h x.type (finRotate r x.row) x.last)
theorem square_valid (x : Square r n E) :
D.squareValid ((square PE).encode x)=true ↔ ValidSquare J x := by
obtain ⟨hrw,ht,hf,hl⟩ := square_parts PP PE J h x
rw [Data.squareValid,hrw,ht,hf,hl,next_eq PP PE J h,h.internal,link_encode,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) x.link.2.isLt,Bool.and_eq_true]
exact and_congr (h.domain x.link.1 x.row x.first) (h.domain x.link.1 (finRotate r x.row) x.last)
theorem block_predicate (b : RawBlock r n P E) :
(if (raw PP PE).encode b<D.horizontals then D.horizontalValid ((raw PP PE).encode b)
else D.squareValid ((raw PP PE).encode b-D.horizontals))=true ↔ Valid J b := by
cases b with
| inl x =>
change (if (horizontal PP PE).encode x<D.horizontals then _ else _)=true ↔ _
rw [ite_eq_left (by rw [horizontals_eq PP PE J h]; exact (horizontal PP PE).encode_lt x)]
exact horizontal_valid PP PE J h x
| inr x =>
change (if (horizontal PP PE).bound+(square PE).encode x<D.horizontals then _ else _)=true ↔ _
rw [horizontals_eq PP PE J h,ite_eq_right (by omega)]
change D.squareValid ((horizontal PP PE).bound+(square PE).encode x-(horizontal PP PE).bound)=true ↔ _
rw [Nat.add_sub_cancel_left]
exact square_valid PP PE J h x
noncomputable def block : Presentation (Block (n := n) J) :=
(raw PP PE).filter (fun i=>if i<D.horizontals then D.horizontalValid i else D.squareValid (i-D.horizontals))
(Valid J) (block_predicate PP PE J h)
theorem block_encode (b : Block (n := n) J) : (block PP PE J h).encode b=(raw PP PE).encode b.val := rfl
theorem block_bound : (block PP PE J h).bound=D.blocks := (blocks_eq PP PE J h).symm
theorem block_valid : (block PP PE J h).valid=D.validBlock := by
funext i
change ((raw PP PE).valid i && _) = (D.rawValid i && _)
rw [rawValid_eq PP PE J h]
theorem left_code (l : Link E n) : D.left ((link PE).encode l)=(vertex PP PE).encode (Subdivision.left J.source l) := by
rcases l with ⟨e,j⟩
have hj := j.isLt
simp only [Data.left,h.internal,link_encode,PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) hj,
PrefixDescriptor.Data.join_mod _ _ _ hj]
by_cases hz : j.val=0
· rw [ite_eq_left hz,Subdivision.left,dite_eq_left hz,vertex_inl,h.source]
· rw [ite_eq_right hz,Subdivision.left,dite_eq_right hz,vertex_inr,h.reals]
theorem right_code (l : Link E n) : D.right ((link PE).encode l)=(vertex PP PE).encode (Subdivision.right J.target l) := by
rcases l with ⟨e,j⟩
have hj := j.isLt
simp only [Data.right,h.internal,link_encode,PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) hj,
PrefixDescriptor.Data.join_mod _ _ _ hj]
by_cases hz : j.val=n
· rw [ite_eq_left hz,Subdivision.right,dite_eq_left hz,vertex_inl,h.target]
· rw [ite_eq_right hz,Subdivision.right,dite_eq_right hz,vertex_inr,h.reals]
theorem output_code (l : Link E n) (i : Fin r) (a : Bool) :
D.output ((link PE).encode l) i.val a.toNat=(matchOutput J l i a).toNat := by
rcases l with ⟨e,j⟩
have hj := j.isLt
simp only [Data.output,h.internal,link_encode,PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) hj,
PrefixDescriptor.Data.join_mod _ _ _ hj,matchOutput]
split_ifs <;> first | exact h.map e i a | rfl
theorem horizontalCode_eq (x : Horizontal r n P E) :
D.horizontalCode x.row.val ((vertex PP PE).encode x.type) x.first.toNat x.last.toNat=(horizontal PP PE).encode x := by
rw [Data.horizontalCode,horizontal_encode,vertices_eq PP PE J h]
rfl
theorem verticalCode_eq (x : Vertical r n E) :
D.verticalCode x.row.val ((link PE).encode x.link) x.label.toNat=(readout PP PE).encode (.inr x) := by
rw [Data.verticalCode,links_eq PP PE J h,horizontals_eq PP PE J h]
change _=(horizontal PP PE).bound+((x.row.val*(link (n := n) PE).bound+(link PE).encode x.link)*2+x.label.toNat)
omega
theorem square_faces (s : Square r n E) :
D.squareLeft ((square PE).encode s)=(readout PP PE).encode (.inl (Blocks.squareLeft J s)) ∧
D.squareRight ((square PE).encode s)=(readout PP PE).encode (.inl (Blocks.squareRight J s)) ∧
D.squareBottom ((square PE).encode s)=(readout PP PE).encode (.inr (Blocks.squareBottom s)) ∧
D.squareTop ((square PE).encode s)=(readout PP PE).encode (.inr (Blocks.squareTop s)) := by
obtain ⟨hrw,ht,hf,hl⟩ := square_parts PP PE J h s
simp only [Data.squareLeft,Data.squareRight,Data.squareBottom,Data.squareTop,hrw,ht,hf,hl,
next_eq PP PE J h,left_code PP PE J h,right_code PP PE J h,output_code PP PE J h]
exact ⟨horizontalCode_eq PP PE J h (Blocks.squareLeft J s),
horizontalCode_eq PP PE J h (Blocks.squareRight J s),
verticalCode_eq PP PE J h (Blocks.squareBottom s),verticalCode_eq PP PE J h (Blocks.squareTop s)⟩
theorem has_code (b : Block (n := n) J) (a : Readout r n P E) :
D.has ((block PP PE J h).encode b) ((readout PP PE).encode a)=true ↔ HasReadout J b.val a := by
rw [block_encode,Data.has]
cases he : b.val with
| inl x =>
change (if (horizontal PP PE).encode x<D.horizontals then _ else _)=true ↔ _
rw [ite_eq_left (by rw [horizontals_eq PP PE J h]; exact (horizontal PP PE).encode_lt x),decide_eq_true_eq]
change (readout PP PE).encode a=(readout PP PE).encode (.inl x) ↔ a=.inl x
exact (readout PP PE).encode_injective.eq_iff
| inr s =>
change (if (horizontal PP PE).bound+(square PE).encode s<D.horizontals then _ else _)=true ↔ _
rw [horizontals_eq PP PE J h,ite_eq_right (by omega)]
have hs : (raw PP PE).encode (.inr s)-(horizontal (r := r) (n := n) PP PE).bound=(square PE).encode s := by
change (horizontal PP PE).bound+(square PE).encode s-(horizontal PP PE).bound=_
omega
dsimp only
rw [hs]
obtain ⟨hl,hr,hb,ht⟩ := square_faces PP PE J h s
simp only [hl,hr,hb,ht,decide_eq_true_eq,(readout PP PE).encode_injective.eq_iff,HasReadout]
end VariableWL.BlockCatalog
namespace VariableWL.Computation.Stack.PolyRecipe
open Recipe
variable {n : ℕ}
def underThree (P : Expr (n+3)) : Expr (n+4) :=
P.reindex (Fin.cons 0 (Fin.cons 1 (Fin.cons 2 (fun i=>i.succ.succ.succ.succ))))
end VariableWL.Computation.Stack.PolyRecipe
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_BlockListing
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4
namespace VariableWL.BlockCatalog.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
structure Listing (n : ℕ) where
rows : Expr n
internal : Expr n
reals : Expr n
comparisons : Expr n
validReal : Expr (n+1)
validComparison : Expr (n+1)
source : Expr (n+1)
target : Expr (n+1)
domain : Expr (n+3)
map : Expr (n+3)
namespace Listing
variable (D : Listing n)
def eval (v : Env n) : Data where
rows := D.rows.number v
internal := D.internal.number v
reals := D.reals.number v
comparisons := D.comparisons.number v
validReal i := D.validReal.bit (cons (List.replicate i true) v)
validComparison i := D.validComparison.bit (cons (List.replicate i true) v)
source i := D.source.number (cons (List.replicate i true) v)
target i := D.target.number (cons (List.replicate i true) v)
domain i j a := D.domain.bit (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
map i j a := D.map.number (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
def up : Listing (n+1) where
rows := D.rows.up
internal := D.internal.up
reals := D.reals.up
comparisons := D.comparisons.up
validReal := underOne D.validReal
validComparison := underOne D.validComparison
source := underOne D.source
target := underOne D.target
domain := underThree D.domain
map := underThree D.map
def vertices : Expr n := add D.reals (mul D.comparisons D.internal)
def links : Expr n := mul D.comparisons (add D.internal (numeral 1))
def horizontals : Expr n := mul (mul D.rows D.vertices) (numeral 4)
def squares : Expr n := mul (mul D.rows D.links) (numeral 4)
def verticals : Expr n := mul (mul D.rows D.links) (numeral 2)
def blocks : Expr n := add D.horizontals D.squares
def reads : Expr n := add D.horizontals D.verticals
def validVertex (I : Expr n) : Expr n := choose (lt I D.reals) (applyNat D.validReal I) (applyNat D.validComparison (div (sub I D.reals) D.internal))
def validLink (I : Expr n) : Expr n := applyNat D.validComparison (div I (add D.internal (numeral 1)))
def validH (I : Expr n) : Expr n := D.validVertex (mod (div I (numeral 4)) D.vertices)
def validS (I : Expr n) : Expr n := D.validLink (mod (div I (numeral 4)) D.links)
def validV (I : Expr n) : Expr n := D.validLink (mod (div I (numeral 2)) D.links)
def rawValid (I : Expr n) : Expr n := choose (lt I D.horizontals) (D.validH I) (D.validS (sub I D.horizontals))
def readValid (I : Expr n) : Expr n := choose (lt I D.horizontals) (D.validH I) (D.validV (sub I D.horizontals))
def hrow (I : Expr n) : Expr n := div (div I (numeral 4)) D.vertices
def htype (I : Expr n) : Expr n := mod (div I (numeral 4)) D.vertices
def srow (I : Expr n) : Expr n := div (div I (numeral 4)) D.links
def slink (I : Expr n) : Expr n := mod (div I (numeral 4)) D.links
def first (I : Expr n) : Expr n := div (mod I (numeral 4)) (numeral 2)
def last (I : Expr n) : Expr n := mod I (numeral 2)
def next (I : Expr n) : Expr n := mod (add I (numeral 1)) D.rows
def labels (T I A : Expr n) : Expr n := choose (lt T D.reals) (literal [true]) (applyNat₃ D.domain (div (sub T D.reals) D.internal) I A)
def horizontalValid (I : Expr n) : Expr n := conj (D.labels (D.htype I) (D.hrow I) (first I)) (D.labels (D.htype I) (D.next (D.hrow I)) (last I))
def squareValid (I : Expr n) : Expr n := conj (applyNat₃ D.domain (div (D.slink I) (add D.internal (numeral 1))) (D.srow I) (first I))
(applyNat₃ D.domain (div (D.slink I) (add D.internal (numeral 1))) (D.next (D.srow I)) (last I))
def validBlock (I : Expr n) : Expr n := conj (D.rawValid I) (choose (lt I D.horizontals) (D.horizontalValid I) (D.squareValid (sub I D.horizontals)))
def left (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) (numeral 0)) (applyNat D.source (div L (add D.internal (numeral 1))))
(add (add D.reals (mul (div L (add D.internal (numeral 1))) D.internal)) (sub (mod L (add D.internal (numeral 1))) (numeral 1)))
def right (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) D.internal) (applyNat D.target (div L (add D.internal (numeral 1))))
(add (add D.reals (mul (div L (add D.internal (numeral 1))) D.internal)) (mod L (add D.internal (numeral 1))))
def output (L I A : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) D.internal)
(applyNat₃ D.map (div L (add D.internal (numeral 1))) I A) A
def horizontalCode (I T A B : Expr n) : Expr n := add (add (mul (add (mul I D.vertices) T) (numeral 4)) (mul A (numeral 2))) B
def verticalCode (I L A : Expr n) : Expr n := add (add D.horizontals (mul (add (mul I D.links) L) (numeral 2))) A
def squareLeft (S : Expr n) : Expr n := D.horizontalCode (D.srow S) (D.left (D.slink S)) (first S) (last S)
def squareRight (S : Expr n) : Expr n := D.horizontalCode (D.srow S) (D.right (D.slink S))
(D.output (D.slink S) (D.srow S) (first S)) (D.output (D.slink S) (D.next (D.srow S)) (last S))
def squareBottom (S : Expr n) : Expr n := D.verticalCode (D.srow S) (D.slink S) (first S)
def squareTop (S : Expr n) : Expr n := D.verticalCode (D.next (D.srow S)) (D.slink S) (last S)
def has (B A : Expr n) : Expr n := choose (lt B D.horizontals) (eq A B)
(disj (eq A (D.squareLeft (sub B D.horizontals)))
(disj (eq A (D.squareRight (sub B D.horizontals)))
(disj (eq A (D.squareBottom (sub B D.horizontals))) (eq A (D.squareTop (sub B D.horizontals))))))
end Listing
end VariableWL.BlockCatalog.Program
namespace VariableWL.AffineAlphabet
open VariableWL.Affine
attribute [local instance] Classical.propDecidable
abbrev SquareCoordinate (d e : ℕ) := (Fin d ⊕ Fin e) ⊕ Bool
def squareCoordinate (d e : ℕ) : SquareVal d e ≃+ (SquareCoordinate d e → Bit) where
toFun z := Sum.elim (Sum.elim z.1.1 z.1.2) (fun t=>if t then z.2.2 else z.2.1)
invFun f := ((fun i=>f (.inl (.inl i)),fun i=>f (.inl (.inr i))),(f (.inr false),f (.inr true)))
left_inv z := by cases z; rfl
right_inv f := by
funext i
rcases i with (i|i)|t
· rfl
· rfl
· cases t <;> rfl
map_add' z w := by
funext i
rcases i with (i|i)|t
· rfl
· rfl
· cases t <;> rfl
noncomputable def horizontalEncode (d : ℕ) : Vec d ≃+ Vec (Fintype.card (Fin d)) where
toFun z := z ∘ (Fintype.equivFin (Fin d)).symm
invFun f := f ∘ Fintype.equivFin (Fin d)
left_inv z := by funext i; simp only [Function.comp_apply,Equiv.symm_apply_apply]
right_inv f := by funext i; simp only [Function.comp_apply,Equiv.apply_symm_apply]
map_add' _ _ := rfl
noncomputable def squareEncode (d e : ℕ) : SquareVal d e ≃+ Vec (Fintype.card (SquareCoordinate d e)) where
toFun z := squareCoordinate d e z ∘ (Fintype.equivFin (SquareCoordinate d e)).symm
invFun f := (squareCoordinate d e).symm (f ∘ Fintype.equivFin (SquareCoordinate d e))
left_inv z := by
simp only [Function.comp_def,Equiv.symm_apply_apply]
exact (squareCoordinate d e).symm_apply_apply z
right_inv f := by funext i; simp
map_add' z w := by funext i; exact congrFun ((squareCoordinate d e).map_add z w) _
theorem horizontal_count_le (d : Fin 3) : Fintype.card (Fin d.val)≤6 := by simp only [Fintype.card_fin]; omega
theorem square_count_le (d e : Fin 3) : Fintype.card (SquareCoordinate d.val e.val)≤6 := by
simp only [SquareCoordinate,Fintype.card_sum,Fintype.card_fin,Fintype.card_bool]
omega
noncomputable instance linearFintype (d : ℕ) : Fintype (Vec d →ₗ[Bit] Bit) :=
Fintype.ofInjective (fun L : Vec d →ₗ[Bit] Bit => (L : Vec d → Bit)) DFunLike.coe_injective
abbrev Form := Σd : Fin 3, Vec d.val →ₗ[Bit] Bit
noncomputable instance formFintype : Fintype Form := Fintype.ofFinite _
noncomputable def formNumber : Form ≃ Fin (Fintype.card Form) := Fintype.equivFin _
noncomputable def formCount : ℕ := Fintype.card Form
noncomputable def encodeForm {d : ℕ} (hd : d≤2) (L : Vec d →ₗ[Bit] Bit) : ℕ :=
(formNumber ⟨⟨d,by omega⟩,L⟩).val
theorem encodeForm_lt {d : ℕ} (hd : d≤2) (L : Vec d →ₗ[Bit] Bit) : encodeForm hd L<formCount :=
(formNumber ⟨⟨d,by omega⟩,L⟩).isLt
noncomputable def horizontalLegal (d i : ℕ) : Bool :=
decide (∃ hd : d≤2,∃z : Vec d,PrefixAlphabet.encode (by simp only [Fintype.card_fin]; omega)
(horizontalEncode d z)=i)
noncomputable def squareLegal (l r c i : ℕ) : Bool :=
if hl : l<formCount then if hr : r<formCount then
let L:=formNumber.symm ⟨l,hl⟩
let R:=formNumber.symm ⟨r,hr⟩
decide (∃z : SquareVal L.1.val R.1.val,boundary L.2 R.2 z=(c : Bit) ∧
PrefixAlphabet.encode (square_count_le L.1 R.1) (squareEncode L.1.val R.1.val z)=i)
else false else false
theorem horizontalLegal_eq {d : ℕ} (hd : d≤2) (i : ℕ) :
horizontalLegal d i=true ↔ ∃z : Vec d,PrefixAlphabet.encode (by simp only [Fintype.card_fin]; omega)
(horizontalEncode d z)=i := by
simp only [horizontalLegal,decide_eq_true_eq]
exact ⟨fun ⟨_,z,hz⟩=>⟨z,hz⟩,fun ⟨z,hz⟩=>⟨hd,z,hz⟩⟩
theorem encodeForm_heq {d e : ℕ} (hd : d≤2) (he : e≤2)
(L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit) (h : d=e) (hLR : HEq L R) : encodeForm hd L=encodeForm he R := by
subst e
cases hLR
rfl
theorem decodeForm {d : ℕ} (hd : d≤2) (L : Vec d →ₗ[Bit] Bit) :
formNumber.symm ⟨encodeForm hd L,encodeForm_lt hd L⟩=⟨⟨d,by omega⟩,L⟩ := by
apply formNumber.injective
rw [Equiv.apply_symm_apply]
apply Fin.ext
rfl
theorem squareLegal_eq {d e : ℕ} (hd : d≤2) (he : e≤2) (L : Vec d →ₗ[Bit] Bit) (R : Vec e →ₗ[Bit] Bit)
(c : Bit) (i : ℕ) : squareLegal (encodeForm hd L) (encodeForm he R) c.val i=true ↔
∃z : SquareVal d e,boundary L R z=c ∧
PrefixAlphabet.encode (square_count_le ⟨d,by omega⟩ ⟨e,by omega⟩) (squareEncode d e z)=i := by
rw [squareLegal,dite_eq_left (encodeForm_lt hd L),dite_eq_left (encodeForm_lt he R)]
dsimp only
simp only [ZMod.natCast_zmod_val,decide_eq_true_eq]
let F (X Y : Form) : Prop := ∃z : SquareVal X.1.val Y.1.val,boundary X.2 Y.2 z=c ∧
PrefixAlphabet.encode (square_count_le X.1 Y.1) (squareEncode X.1.val Y.1.val z)=i
exact Iff.of_eq (congrArg₂ F (decodeForm hd L) (decodeForm he R))
end VariableWL.AffineAlphabet
namespace VariableWL.AffineAlphabet
open VariableWL.Affine
attribute [local instance] Classical.propDecidable
theorem embedding_le {m d : ℕ} (e : Fin m ↪ Fin d) : m≤d := by
simpa only [Fintype.card_fin] using Fintype.card_le_of_injective e e.injective
noncomputable def extend {m d : ℕ} (e : Fin m ↪ Fin d) : Equiv.Perm (Fin d) :=
(Equiv.Perm.exists_extending_pair
(fun i : Fin m=>(⟨i.val,lt_of_lt_of_le i.isLt (embedding_le e)⟩ : Fin d)) e
(fun a b h=>Fin.ext (show a.val=b.val from congrArg (fun x : Fin d=>x.val) h)) e.injective).choose
noncomputable def horizontalEmbedding (d : ℕ) : Fin d ↪ Fin (Fintype.card (Fin d)) :=
(Function.Embedding.refl (Fin d)).trans (Fintype.equivFin (Fin d)).toEmbedding
noncomputable def leftEmbedding (d e : ℕ) : Fin d ↪ Fin (Fintype.card (SquareCoordinate d e)) :=
(⟨fun i=>Sum.inl (Sum.inl i),fun _ _ h=>Sum.inl.inj (Sum.inl.inj h)⟩ : Fin d ↪ SquareCoordinate d e).trans
(Fintype.equivFin (SquareCoordinate d e)).toEmbedding
noncomputable def rightEmbedding (d e : ℕ) : Fin e ↪ Fin (Fintype.card (SquareCoordinate d e)) :=
(⟨fun i=>Sum.inl (Sum.inr i),fun _ _ h=>Sum.inr.inj (Sum.inl.inj h)⟩ : Fin e ↪ SquareCoordinate d e).trans
(Fintype.equivFin (SquareCoordinate d e)).toEmbedding
noncomputable def scalarEmbedding (d e : ℕ) (a : Bool) : Fin 1 ↪ Fin (Fintype.card (SquareCoordinate d e)) :=
(⟨fun _=>Sum.inr a,fun _ _ _=>Subsingleton.elim _ _⟩ : Fin 1 ↪ SquareCoordinate d e).trans
(Fintype.equivFin (SquareCoordinate d e)).toEmbedding
noncomputable def horizontalOrder (d : ℕ) : ℕ := if hd : d≤2 then
PrefixAlphabet.encodeOrder (horizontal_count_le ⟨d,by omega⟩) (extend (horizontalEmbedding d)) else 0
noncomputable def squareOrder (d e a : ℕ) : ℕ := if hd : d≤2 then if he : e≤2 then
PrefixAlphabet.encodeOrder (square_count_le ⟨d,by omega⟩ ⟨e,by omega⟩)
(if a=0 then extend (leftEmbedding d e) else if a=1 then extend (rightEmbedding d e) else
extend (scalarEmbedding d e (decide (a≠2)))) else 0 else 0
noncomputable def zeroOrder (d : ℕ) : ℕ := if hd : d≤6 then PrefixAlphabet.encodeOrder hd (Equiv.refl _) else 0
end VariableWL.AffineAlphabet
namespace VariableWL.BlockCoordinates
open Blocks Subdivision VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4} (J : ProductImages.Instance r P E) (hr : 2≤r) (hn : 0<n)
theorem coordinate_lift_unique {b : RawBlock r n P E} {a : Readout r n P E}
(ha : HasReadout J b a) (e : Fin (readoutDimension J a) ↪ Coordinate J b)
(he : ∀z i,coordinateEquiv J b z (e i)=readoutEquiv J a (readout J z ha) i) :
(coordinate_lift J hr hn ha).choose=e := by
ext i
have hh : ∀f : Coordinate J b → Bit,f ((coordinate_lift J hr hn ha).choose i)=f (e i) := by
intro f
obtain ⟨z,rfl⟩ := (coordinateEquiv J b).surjective f
exact ((coordinate_lift J hr hn ha).choose_spec z i).trans (he z i).symm
by_contra hne
have h := hh (fun j=>if j=e i then 1 else 0)
simp only [ite_eq_right hne] at h
exact zero_ne_one h
theorem order_eq_extend {b : RawBlock r n P E} {a : Readout r n P E} (ha : HasReadout J b a) :
(exists_readout_order J hr hn ha).choose=AffineAlphabet.extend (readoutEmbedding J hr hn ha) := rfl
theorem embedding_horizontal (h : Horizontal r n P E) :
readoutEmbedding J hr hn (b := .inl h) (a := .inl h) rfl=
AffineAlphabet.horizontalEmbedding (dimension J h.type) := by
unfold readoutEmbedding
have he := coordinate_lift_unique J hr hn (b := .inl h) (a := .inl h) rfl (Function.Embedding.refl _) (by
intro z i
rw [readout_eq J hr hn (b := .inl h) (z := z) (a := .inl h) rfl ⟨rfl,HEq.rfl⟩]
rfl)
rw [he]
rfl
theorem embedding_left (s : Square r n E) :
readoutEmbedding J hr hn (b := .inr s) (a := .inl (squareLeft J s)) (Or.inl rfl)=
AffineAlphabet.leftEmbedding (dimension J (left J.source s.link)) (dimension J (right J.target s.link)) := by
unfold readoutEmbedding
have he := coordinate_lift_unique J hr hn (b := .inr s) (a := .inl (squareLeft J s)) (Or.inl rfl)
⟨fun i=>.inl (.inl i),fun _ _ h=>Sum.inl.inj (Sum.inl.inj h)⟩ (by
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := .inl (squareLeft J s)) (Or.inl rfl) (Or.inl ⟨rfl,HEq.rfl⟩)]
rfl)
rw [he]
rfl
theorem embedding_right (s : Square r n E) :
readoutEmbedding J hr hn (b := .inr s) (a := .inl (squareRight J s)) (Or.inr (Or.inl rfl))=
AffineAlphabet.rightEmbedding (dimension J (left J.source s.link)) (dimension J (right J.target s.link)) := by
unfold readoutEmbedding
have he := coordinate_lift_unique J hr hn (b := .inr s) (a := .inl (squareRight J s)) (Or.inr (Or.inl rfl))
⟨fun i=>.inl (.inr i),fun _ _ h=>Sum.inr.inj (Sum.inl.inj h)⟩ (by
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := .inl (squareRight J s)) (Or.inr (Or.inl rfl)) (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩))]
rfl)
rw [he]
rfl
theorem embedding_bottom (s : Square r n E) :
readoutEmbedding J hr hn (b := .inr s) (a := .inr (squareBottom s)) (Or.inr (Or.inr (Or.inl rfl)))=
AffineAlphabet.scalarEmbedding (dimension J (left J.source s.link)) (dimension J (right J.target s.link)) false := by
unfold readoutEmbedding
have he := coordinate_lift_unique J hr hn (b := .inr s) (a := .inr (squareBottom s)) (Or.inr (Or.inr (Or.inl rfl)))
⟨fun _=>.inr false,fun i j _=>Fin.ext (by have hi := i.isLt; have hj := j.isLt; change i.val<1 at hi; change j.val<1 at hj; omega)⟩ (by
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := .inr (squareBottom s)) (Or.inr (Or.inr (Or.inl rfl))) (Or.inr (Or.inr (Or.inl ⟨rfl,HEq.rfl⟩)))]
rfl)
rw [he]
rfl
theorem embedding_top (s : Square r n E) :
readoutEmbedding J hr hn (b := .inr s) (a := .inr (squareTop s)) (Or.inr (Or.inr (Or.inr rfl)))=
AffineAlphabet.scalarEmbedding (dimension J (left J.source s.link)) (dimension J (right J.target s.link)) true := by
unfold readoutEmbedding
have he := coordinate_lift_unique J hr hn (b := .inr s) (a := .inr (squareTop s)) (Or.inr (Or.inr (Or.inr rfl)))
⟨fun _=>.inr true,fun i j _=>Fin.ext (by have hi := i.isLt; have hj := j.isLt; change i.val<1 at hi; change j.val<1 at hj; omega)⟩ (by
intro z i
rw [readout_eq J hr hn (b := .inr s) (z := z) (a := .inr (squareTop s)) (Or.inr (Or.inr (Or.inr rfl))) (Or.inr (Or.inr (Or.inr ⟨rfl,HEq.rfl⟩)))]
rfl)
rw [he]
rfl
end VariableWL.BlockCoordinates
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_AffineCatalog
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4
namespace VariableWL.AffineCatalog
open Blocks Subdivision Descriptor VariableWL.Affine
attribute [local instance] Classical.propDecidable
structure Data extends BlockCatalog.Data where
realDimension : ℕ → ℕ
leftForm : ℕ → ℕ
rightForm : ℕ → ℕ
leftConstant : ℕ → ℕ
rightConstant : ℕ → ℕ
marked : ℕ
epsilon : ℕ
namespace Data
variable (D : Data)
def vertexDimension (t : ℕ) : ℕ := if t<D.reals then D.realDimension t else 1
def horizontalDimension (h : ℕ) : ℕ := D.vertexDimension (D.htype h)
def squareLeftDimension (s : ℕ) : ℕ := D.vertexDimension (D.left (D.slink s))
def squareRightDimension (s : ℕ) : ℕ := D.vertexDimension (D.right (D.slink s))
def dimension (b : ℕ) : ℕ := if b<D.horizontals then D.horizontalDimension b else
D.squareLeftDimension (b-D.horizontals)+D.squareRightDimension (b-D.horizontals)+2
def readDimension (a : ℕ) : ℕ := if a<D.horizontals then D.horizontalDimension a else 1
noncomputable def linkLeft (l : ℕ) : ℕ := if l%(D.internal+1)=0 then D.leftForm (l/(D.internal+1)) else
AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj (0 : Fin 1))
noncomputable def linkRight (l : ℕ) : ℕ := if l%(D.internal+1)=D.internal then D.rightForm (l/(D.internal+1)) else
AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj (0 : Fin 1))
def linkLeftConstant (l : ℕ) : ℕ := if l%(D.internal+1)=0 then D.leftConstant (l/(D.internal+1)) else 0
def linkRightConstant (l : ℕ) : ℕ := if l%(D.internal+1)=D.internal then D.rightConstant (l/(D.internal+1)) else 0
def constant (s : ℕ) : ℕ := (D.epsilon*(if D.srow s=D.marked then
D.linkLeftConstant (D.slink s)+D.linkRightConstant (D.slink s) else 0))%2
noncomputable def zeroOrder (b : ℕ) : ℕ := AffineAlphabet.zeroOrder (D.dimension b)
noncomputable def readOrder (b a : ℕ) : ℕ := if b<D.horizontals then AffineAlphabet.horizontalOrder (D.horizontalDimension b) else
let s:=b-D.horizontals
AffineAlphabet.squareOrder (D.squareLeftDimension s) (D.squareRightDimension s)
(if a=D.squareLeft s then 0 else if a=D.squareRight s then 1 else if a=D.squareBottom s then 2 else 3)
noncomputable def legal (b i : ℕ) : Bool := if b<D.horizontals then AffineAlphabet.horizontalLegal (D.horizontalDimension b) i else
let s:=b-D.horizontals
AffineAlphabet.squareLegal (D.linkLeft (D.slink s)) (D.linkRight (D.slink s)) (D.constant s) i
noncomputable def core : BlockDescriptor.Core where
blocks := D.blocks
validBlock := D.validBlock
reads := D.reads
validRead := D.readValid
has := D.has
dimension := D.dimension
readDimension := D.readDimension
zeroOrder := D.zeroOrder
readOrder := D.readOrder
legal := D.legal
end Data
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} (PP : Presentation P) (PE : Presentation E)
variable (J : ProductImages.Instance r P E) (marked : Fin r) (ε : Bit)
structure Good (D : Data) : Prop extends BlockCatalog.Good (n := n) PP PE J D.toData where
realDimension : ∀p,D.realDimension (PP.encode p)=J.dimension p
leftForm : ∀e,D.leftForm (PE.encode e)=AffineAlphabet.encodeForm
(RealizationSize.dimension_le_two J (n := n) (.inl (J.source e))) (J.linearLeft e)
rightForm : ∀e,D.rightForm (PE.encode e)=AffineAlphabet.encodeForm
(RealizationSize.dimension_le_two J (n := n) (.inl (J.target e))) (J.linearRight e)
leftConstant : ∀e,D.leftConstant (PE.encode e)=(J.constantLeft e).val
rightConstant : ∀e,D.rightConstant (PE.encode e)=(J.constantRight e).val
marked : D.marked=marked.val
epsilon : D.epsilon=ε.val
variable {D : Data} (h : Good (n := n) PP PE J marked ε D)
include h
theorem vertex_dimension (t : Vertex P E n) : D.vertexDimension ((BlockCatalog.vertex PP PE).encode t)=Blocks.dimension J t := by
cases t with
| inl p =>
rw [Data.vertexDimension,BlockCatalog.vertex_inl,h.reals,ite_eq_left (PP.encode_lt p),h.realDimension]
rfl
| inr q =>
rcases q with ⟨e,j⟩
rw [Data.vertexDimension,BlockCatalog.vertex_inr,h.reals,ite_eq_right (by omega)]
rfl
theorem horizontal_dimension (x : Horizontal r n P E) : D.horizontalDimension ((BlockCatalog.horizontal PP PE).encode x)=dimension J x.type := by
rw [Data.horizontalDimension,(BlockCatalog.horizontal_parts PP PE J h.toGood x).2.1]
exact vertex_dimension PP PE J marked ε h x.type
theorem square_dimensions (s : Square r n E) :
D.squareLeftDimension ((BlockCatalog.square PE).encode s)=dimension J (left J.source s.link) ∧
D.squareRightDimension ((BlockCatalog.square PE).encode s)=dimension J (right J.target s.link) := by
obtain ⟨_,hl,_,_⟩ := BlockCatalog.square_parts PP PE J h.toGood s
simp only [Data.squareLeftDimension,Data.squareRightDimension,hl,
BlockCatalog.left_code PP PE J h.toGood,BlockCatalog.right_code PP PE J h.toGood,
vertex_dimension PP PE J marked ε h]
exact ⟨trivial,trivial⟩
theorem dimension_code (b : RawBlock r n P E) : D.dimension ((BlockCatalog.raw PP PE).encode b)=Fintype.card (BlockCoordinates.Coordinate J b) := by
cases b with
| inl x =>
change (if (BlockCatalog.horizontal PP PE).encode x<D.horizontals then _ else _)=_
rw [ite_eq_left (by rw [BlockCatalog.horizontals_eq PP PE J h.toGood]; exact (BlockCatalog.horizontal PP PE).encode_lt x)]
change D.horizontalDimension ((BlockCatalog.horizontal PP PE).encode x)=_
rw [horizontal_dimension PP PE J marked ε h]
simp only [BlockCoordinates.Coordinate,Fintype.card_fin]
| inr s =>
change (if (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s<D.horizontals then _ else _)=_
rw [BlockCatalog.horizontals_eq PP PE J h.toGood,ite_eq_right (by omega)]
have hs : (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square (r := r) (n := n) PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s := by omega
change (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s at hs
simp only [BlockCatalog.raw,Presentation.sum_inr,Nat.add_sub_cancel_left] at *
obtain ⟨hl,hr⟩ := square_dimensions PP PE J marked ε h s
rw [hl,hr]
simp only [BlockCoordinates.Coordinate,Fintype.card_sum,Fintype.card_fin,Fintype.card_bool]
theorem read_dimension (a : Readout r n P E) : D.readDimension ((BlockCatalog.readout PP PE).encode a)=BlockCoordinates.readoutDimension J a := by
cases a with
| inl x =>
change (if (BlockCatalog.horizontal PP PE).encode x<D.horizontals then _ else _)=_
rw [ite_eq_left (by rw [BlockCatalog.horizontals_eq PP PE J h.toGood]; exact (BlockCatalog.horizontal PP PE).encode_lt x)]
change D.horizontalDimension ((BlockCatalog.horizontal PP PE).encode x)=_
rw [horizontal_dimension PP PE J marked ε h]
rfl
| inr x =>
change (if (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.vertical PE).encode x<D.horizontals then _ else _)=_
rw [BlockCatalog.horizontals_eq PP PE J h.toGood,ite_eq_right (by omega)]
rfl
theorem link_left (l : Link E n) : D.linkLeft ((BlockCatalog.link PE).encode l)=AffineAlphabet.encodeForm
(RealizationSize.dimension_le_two J (left J.source l)) (Blocks.linkLeft J l) := by
rcases l with ⟨e,j⟩
simp only [Data.linkLeft,h.internal,BlockCatalog.link_encode,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) j.isLt,PrefixDescriptor.Data.join_mod _ _ _ j.isLt]
by_cases hz : j.val=0
· simp only [ite_eq_left hz,h.leftForm,Blocks.linkLeft,Subdivision.left,dite_eq_left hz]
apply AffineAlphabet.encodeForm_heq
· simp [dimension,hz]
· exact (cast_heq _ _).symm
· simp only [ite_eq_right hz,Blocks.linkLeft,Subdivision.left,dite_eq_right hz,Blocks.dimension]
apply AffineAlphabet.encodeForm_heq
· simp [hz]
· exact (cast_heq _ _).symm
theorem link_right (l : Link E n) : D.linkRight ((BlockCatalog.link PE).encode l)=AffineAlphabet.encodeForm
(RealizationSize.dimension_le_two J (right J.target l)) (Blocks.linkRight J l) := by
rcases l with ⟨e,j⟩
simp only [Data.linkRight,h.internal,BlockCatalog.link_encode,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) j.isLt,PrefixDescriptor.Data.join_mod _ _ _ j.isLt]
by_cases hz : j.val=n
· simp only [ite_eq_left hz,h.rightForm,Blocks.linkRight,Subdivision.right,dite_eq_left hz]
apply AffineAlphabet.encodeForm_heq
· simp [dimension,hz]
· exact (cast_heq _ _).symm
· simp only [ite_eq_right hz,Blocks.linkRight,Subdivision.right,dite_eq_right hz,Blocks.dimension]
apply AffineAlphabet.encodeForm_heq
· simp [hz]
· exact (cast_heq _ _).symm
theorem link_left_constant (l : Link E n) : (D.linkLeftConstant ((BlockCatalog.link PE).encode l) : Bit)=Blocks.leftConstant J l := by
rcases l with ⟨e,j⟩
simp only [Data.linkLeftConstant,h.internal,BlockCatalog.link_encode,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) j.isLt,PrefixDescriptor.Data.join_mod _ _ _ j.isLt,
Blocks.leftConstant,h.leftConstant]
split_ifs <;> simp only [ZMod.natCast_zmod_val,Nat.cast_zero]
theorem link_right_constant (l : Link E n) : (D.linkRightConstant ((BlockCatalog.link PE).encode l) : Bit)=Blocks.rightConstant J l := by
rcases l with ⟨e,j⟩
simp only [Data.linkRightConstant,h.internal,BlockCatalog.link_encode,
PrefixDescriptor.Data.join_div _ _ _ (by omega : 0<n+1) j.isLt,PrefixDescriptor.Data.join_mod _ _ _ j.isLt,
Blocks.rightConstant,h.rightConstant]
split_ifs <;> simp only [ZMod.natCast_zmod_val,Nat.cast_zero]
theorem constant_code (s : Square r n E) : (D.constant ((BlockCatalog.square PE).encode s) : Bit)=ε*inhomogeneity J marked (.inr s) := by
obtain ⟨hrw,hl,_,_⟩ := BlockCatalog.square_parts PP PE J h.toGood s
rw [Data.constant]
simp only [hrw,hl,h.marked,h.epsilon,Blocks.inhomogeneity,Blocks.linkConstant]
rw [ZMod.natCast_mod, Nat.cast_mul,ZMod.natCast_zmod_val]
by_cases hi : s.row=marked
· subst marked
rw [ite_eq_left rfl,Nat.cast_add,link_left_constant PP PE J _ ε h,link_right_constant PP PE J _ ε h]
simp only [marker,ite_true,one_mul]
· rw [ite_eq_right (fun he=>hi (Fin.ext he)),Nat.cast_zero,mul_zero]
simp only [marker,ite_eq_right hi,zero_mul,mul_zero]
end VariableWL.AffineCatalog
namespace VariableWL.AffineCatalog
open Blocks Subdivision Descriptor VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {r n : ℕ} {P : Type uVariable3} {E : Type uVariable4} (PP : Presentation P) (PE : Presentation E)
variable (J : ProductImages.Instance r P E) (marked : Fin r) (ε : Bit)
variable {D : Data} (h : Good (n := n) PP PE J marked ε D)
include h
theorem zero_order (b : RawBlock r n P E) : D.zeroOrder ((BlockCatalog.raw PP PE).encode b)=
PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J b) (Equiv.refl _) := by
rw [Data.zeroOrder,dimension_code PP PE J marked ε h,AffineAlphabet.zeroOrder,
dite_eq_left (RealizationSize.coordinate_card J b)]
theorem read_order (hr : 2≤r) (hn : 0<n) (b : RawBlock r n P E) (a : Readout r n P E)
(ha : HasReadout J b a) : D.readOrder ((BlockCatalog.raw PP PE).encode b) ((BlockCatalog.readout PP PE).encode a)=
PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J b) (BlockCoordinates.exists_readout_order J hr hn ha).choose := by
cases b with
| inl x =>
have he : a=.inl x := ha
subst a
change (if (BlockCatalog.horizontal PP PE).encode x<D.horizontals then _ else _)=_
rw [ite_eq_left (by rw [BlockCatalog.horizontals_eq PP PE J h.toGood]; exact (BlockCatalog.horizontal PP PE).encode_lt x)]
change AffineAlphabet.horizontalOrder (D.horizontalDimension ((BlockCatalog.horizontal PP PE).encode x))=_
rw [horizontal_dimension PP PE J marked ε h]
have ho := BlockCoordinates.order_eq_extend J hr hn (b := .inl x) (a := .inl x) rfl
have hb := BlockCoordinates.embedding_horizontal J hr hn x
rw [ho,hb]
rw [AffineAlphabet.horizontalOrder,dite_eq_left (RealizationSize.dimension_le_two J x.type)]
rfl
| inr s =>
change (if (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s<D.horizontals then _ else _)=_
rw [BlockCatalog.horizontals_eq PP PE J h.toGood,ite_eq_right (by omega)]
have hs : (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square (r := r) (n := n) PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s := by omega
dsimp only
change (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s at hs
simp only [BlockCatalog.raw,Presentation.sum_inr,Nat.add_sub_cancel_left] at *
obtain ⟨hl,he⟩ := square_dimensions PP PE J marked ε h s
obtain ⟨fl,fr,fb,ft⟩ := BlockCatalog.square_faces PP PE J h.toGood s
rw [hl,he,fl,fr,fb]
have hi := (BlockCatalog.readout (r := r) (n := n) PP PE).encode_injective
change a=.inl (squareLeft J s) ∨ a=.inl (squareRight J s) ∨ a=.inr (squareBottom s) ∨ a=.inr (squareTop s) at ha
rcases ha with ha | ha | ha | ha
all_goals subst a
· simp only [ite_true]
rw [AffineAlphabet.squareOrder,dite_eq_left (RealizationSize.dimension_le_two J (left J.source s.link)),
dite_eq_left (RealizationSize.dimension_le_two J (right J.target s.link)),ite_eq_left rfl]
have hh := (BlockCoordinates.order_eq_extend J hr hn (b := .inr s) (a := .inl (squareLeft J s)) (Or.inl rfl)).trans
(congrArg AffineAlphabet.extend (BlockCoordinates.embedding_left J hr hn s))
exact (congrArg (PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J (.inr s))) hh).symm
· have hnL : (BlockCatalog.readout PP PE).encode (.inl (squareRight J s)) ≠ (BlockCatalog.readout PP PE).encode (.inl (squareLeft J s)) :=
fun hh=>squareLeft_ne_right J hn s (Sum.inl.inj (hi hh)).symm
simp only [hnL,ite_false,ite_true]
rw [AffineAlphabet.squareOrder,dite_eq_left (RealizationSize.dimension_le_two J (left J.source s.link)),
dite_eq_left (RealizationSize.dimension_le_two J (right J.target s.link)),ite_eq_right (by decide : ¬(1 : ℕ)=0),ite_eq_left rfl]
have hh := (BlockCoordinates.order_eq_extend J hr hn (b := .inr s) (a := .inl (squareRight J s)) (Or.inr (Or.inl rfl))).trans
(congrArg AffineAlphabet.extend (BlockCoordinates.embedding_right J hr hn s))
exact (congrArg (PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J (.inr s))) hh).symm
· have hnL : (BlockCatalog.readout PP PE).encode (.inr (squareBottom s)) ≠ (BlockCatalog.readout PP PE).encode (.inl (squareLeft J s)) := fun hh=>Sum.inr_ne_inl (hi hh)
have hnR : (BlockCatalog.readout PP PE).encode (.inr (squareBottom s)) ≠ (BlockCatalog.readout PP PE).encode (.inl (squareRight J s)) := fun hh=>Sum.inr_ne_inl (hi hh)
simp only [hnL,hnR,ite_false,ite_true]
rw [AffineAlphabet.squareOrder,dite_eq_left (RealizationSize.dimension_le_two J (left J.source s.link)),
dite_eq_left (RealizationSize.dimension_le_two J (right J.target s.link)),ite_eq_right (by decide : ¬(2 : ℕ)=0),ite_eq_right (by decide : ¬(2 : ℕ)=1)]
have hh := (BlockCoordinates.order_eq_extend J hr hn (b := .inr s) (a := .inr (squareBottom s)) (Or.inr (Or.inr (Or.inl rfl)))).trans
(congrArg AffineAlphabet.extend (BlockCoordinates.embedding_bottom J hr hn s))
exact (congrArg (PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J (.inr s))) hh).symm
· have hnL : (BlockCatalog.readout PP PE).encode (.inr (squareTop s)) ≠ (BlockCatalog.readout PP PE).encode (.inl (squareLeft J s)) := fun hh=>Sum.inr_ne_inl (hi hh)
have hnR : (BlockCatalog.readout PP PE).encode (.inr (squareTop s)) ≠ (BlockCatalog.readout PP PE).encode (.inl (squareRight J s)) := fun hh=>Sum.inr_ne_inl (hi hh)
have hnB : (BlockCatalog.readout PP PE).encode (.inr (squareTop s)) ≠ (BlockCatalog.readout PP PE).encode (.inr (squareBottom s)) := fun hh=>squareBottom_ne_top hr s (Sum.inr.inj (hi hh)).symm
simp only [hnL,hnR,hnB,ite_false]
rw [AffineAlphabet.squareOrder,dite_eq_left (RealizationSize.dimension_le_two J (left J.source s.link)),
dite_eq_left (RealizationSize.dimension_le_two J (right J.target s.link)),ite_eq_right (by decide : ¬(3 : ℕ)=0),ite_eq_right (by decide : ¬(3 : ℕ)=1)]
have hh := (BlockCoordinates.order_eq_extend J hr hn (b := .inr s) (a := .inr (squareTop s)) (Or.inr (Or.inr (Or.inr rfl)))).trans
(congrArg AffineAlphabet.extend (BlockCoordinates.embedding_top J hr hn s))
exact (congrArg (PrefixAlphabet.encodeOrder (RealizationSize.coordinate_card J (.inr s))) hh).symm
theorem legal_code (b : RawBlock r n P E) (i : ℕ) : D.legal ((BlockCatalog.raw PP PE).encode b) i=true ↔
∃z : RawValue J b,LegalValue J marked ε b z ∧
PrefixAlphabet.encode (RealizationSize.coordinate_card J b) (BlockCoordinates.encode J b z)=i := by
cases b with
| inl x =>
change (if (BlockCatalog.horizontal PP PE).encode x<D.horizontals then _ else _)=true ↔ _
rw [ite_eq_left (by rw [BlockCatalog.horizontals_eq PP PE J h.toGood]; exact (BlockCatalog.horizontal PP PE).encode_lt x)]
change AffineAlphabet.horizontalLegal (D.horizontalDimension ((BlockCatalog.horizontal PP PE).encode x)) i=true ↔ _
rw [horizontal_dimension PP PE J marked ε h,
AffineAlphabet.horizontalLegal_eq (RealizationSize.dimension_le_two J x.type)]
simp only [LegalValue,boundaryMap,inhomogeneity,mul_zero,AddMonoidHom.zero_apply,true_and]
rfl
| inr s =>
change (if (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s<D.horizontals then _ else _)=true ↔ _
rw [BlockCatalog.horizontals_eq PP PE J h.toGood,ite_eq_right (by omega)]
have hs : (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square (r := r) (n := n) PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s := by omega
dsimp only
change (BlockCatalog.horizontal (r := r) (n := n) PP PE).bound+(BlockCatalog.square PE).encode s-
(BlockCatalog.horizontal (r := r) (n := n) PP PE).bound=(BlockCatalog.square PE).encode s at hs
simp only [BlockCatalog.raw,Presentation.sum_inr,Nat.add_sub_cancel_left] at *
rw [(BlockCatalog.square_parts PP PE J h.toGood s).2.1,link_left PP PE J marked ε h,link_right PP PE J marked ε h]
have hc : D.constant ((BlockCatalog.square PE).encode s)=(ε*inhomogeneity J marked (.inr s)).val := by
have hh := congrArg ZMod.val (constant_code PP PE J marked ε h s)
rw [ZMod.val_natCast] at hh
have hm : D.constant ((BlockCatalog.square PE).encode s)<2 := Nat.mod_lt _ (by decide)
rwa [Nat.mod_eq_of_lt hm] at hh
rw [hc,AffineAlphabet.squareLegal_eq]
rfl
theorem core_good (hr : 2≤r) (hn : 0<n) : BlockDescriptor.Good J hr hn marked
(BlockCatalog.block PP PE J h.toGood) (BlockCatalog.readout PP PE)
(fun b=>RealizationSize.coordinate_card J b.val) ε D.core := by
refine ⟨(BlockCatalog.block_bound PP PE J h.toGood).symm,BlockCatalog.reads_eq PP PE J h.toGood,
(BlockCatalog.block_valid PP PE J h.toGood).symm,BlockCatalog.readValid_eq PP PE J h.toGood,
BlockCatalog.has_code PP PE J h.toGood,?_,read_dimension PP PE J marked ε h,?_,?_,?_⟩
· intro b; exact dimension_code PP PE J marked ε h b.val
· intro b; exact zero_order PP PE J marked ε h b.val
· intro b a ha; exact read_order PP PE J marked ε h hr hn b.val a ha
· intro b i
rw [show D.core.legal (BlockCatalog.block PP PE J h.toGood |>.encode b) i=D.legal ((BlockCatalog.raw PP PE).encode b.val) i from rfl,
legal_code PP PE J marked ε h]
exact ⟨fun ⟨z,hz,he⟩=>⟨⟨z,hz⟩,he⟩,fun ⟨z,he⟩=>⟨z.val,z.property,he⟩⟩
end VariableWL.AffineCatalog
namespace VariableWL.AffineAlphabet.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
variable {n : ℕ}
noncomputable def horizontalLegal (D I : Expr n) : Expr n :=
eq (table₂ 3 PrefixAlphabet.vectorCount (fun d i=>if AffineAlphabet.horizontalLegal d i then 1 else 0) D I) (numeral 1)
noncomputable def squareLegalBody (L R C I : Expr n) : Expr n :=
eq (table₃ formCount formCount (2*PrefixAlphabet.vectorCount)
(fun l r q=>if AffineAlphabet.squareLegal l r (q/PrefixAlphabet.vectorCount) (q%PrefixAlphabet.vectorCount) then 1 else 0)
L R (add (mul (mod C (numeral 2)) (numeral PrefixAlphabet.vectorCount)) I)) (numeral 1)
noncomputable def horizontalOrder (D : Expr n) : Expr n := fixedNat 3 (fun d=>AffineAlphabet.horizontalOrder d.val) D
noncomputable def squareOrder (D E A : Expr n) : Expr n := table₃ 3 3 4 AffineAlphabet.squareOrder D E (minimum A (numeral 3))
noncomputable def zeroOrder (D : Expr n) : Expr n := fixedNat 7 (fun d=>AffineAlphabet.zeroOrder d.val) D
noncomputable def squareLegal (L R C I : Expr n) : Expr n :=
choose (lt I (numeral PrefixAlphabet.vectorCount)) (squareLegalBody L R C I) (literal [false])
end VariableWL.AffineAlphabet.Program
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_CircuitCatalog
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5 uVariable6 uVariable7 uVariable8 uVariable9 uVariable10 uVariable11
namespace VariableWL.AffineCatalog.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe
open VariableWL.NumericProgram
variable {n : ℕ}
structure Listing (n : ℕ) extends BlockCatalog.Program.Listing n where
realDimension : Expr (n+1)
leftForm : Expr (n+1)
rightForm : Expr (n+1)
leftConstant : Expr (n+1)
rightConstant : Expr (n+1)
marked : Expr n
epsilon : Expr n
namespace Listing
variable (D : Listing n)
def eval (v : Env n) : Data where
toData := D.toListing.eval v
realDimension i := D.realDimension.number (cons (List.replicate i true) v)
leftForm i := D.leftForm.number (cons (List.replicate i true) v)
rightForm i := D.rightForm.number (cons (List.replicate i true) v)
leftConstant i := D.leftConstant.number (cons (List.replicate i true) v)
rightConstant i := D.rightConstant.number (cons (List.replicate i true) v)
marked := D.marked.number v
epsilon := D.epsilon.number v
def up : Listing (n+1) where
toListing := D.toListing.up
realDimension := underOne D.realDimension
leftForm := underOne D.leftForm
rightForm := underOne D.rightForm
leftConstant := underOne D.leftConstant
rightConstant := underOne D.rightConstant
marked := D.marked.up
epsilon := D.epsilon.up
def vertexDimension (T : Expr n) : Expr n := choose (lt T D.reals) (applyNat D.realDimension T) (numeral 1)
def horizontalDimension (H : Expr n) : Expr n := D.vertexDimension (D.toListing.htype H)
def squareLeftDimension (S : Expr n) : Expr n := D.vertexDimension (D.toListing.left (D.toListing.slink S))
def squareRightDimension (S : Expr n) : Expr n := D.vertexDimension (D.toListing.right (D.toListing.slink S))
def dimension (B : Expr n) : Expr n := choose (lt B D.toListing.horizontals) (D.horizontalDimension B)
(add (add (D.squareLeftDimension (sub B D.toListing.horizontals)) (D.squareRightDimension (sub B D.toListing.horizontals))) (numeral 2))
def readDimension (A : Expr n) : Expr n := choose (lt A D.toListing.horizontals) (D.horizontalDimension A) (numeral 1)
noncomputable def linkLeft (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) (numeral 0))
(applyNat D.leftForm (div L (add D.internal (numeral 1))))
(numeral (AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj (0 : Fin 1))))
noncomputable def linkRight (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) D.internal)
(applyNat D.rightForm (div L (add D.internal (numeral 1))))
(numeral (AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj (0 : Fin 1))))
def linkLeftConstant (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) (numeral 0))
(applyNat D.leftConstant (div L (add D.internal (numeral 1)))) (numeral 0)
def linkRightConstant (L : Expr n) : Expr n := choose (eq (mod L (add D.internal (numeral 1))) D.internal)
(applyNat D.rightConstant (div L (add D.internal (numeral 1)))) (numeral 0)
def constant (S : Expr n) : Expr n := mod (mul D.epsilon (choose (eq (D.toListing.srow S) D.marked)
(add (D.linkLeftConstant (D.toListing.slink S)) (D.linkRightConstant (D.toListing.slink S))) (numeral 0))) (numeral 2)
noncomputable def zeroOrder (B : Expr n) : Expr n := AffineAlphabet.Program.zeroOrder (D.dimension B)
noncomputable def readOrder (B A : Expr n) : Expr n := choose (lt B D.toListing.horizontals)
(AffineAlphabet.Program.horizontalOrder (D.horizontalDimension B))
(AffineAlphabet.Program.squareOrder (D.squareLeftDimension (sub B D.toListing.horizontals))
(D.squareRightDimension (sub B D.toListing.horizontals))
(choose (eq A (D.toListing.squareLeft (sub B D.toListing.horizontals))) (numeral 0)
(choose (eq A (D.toListing.squareRight (sub B D.toListing.horizontals))) (numeral 1)
(choose (eq A (D.toListing.squareBottom (sub B D.toListing.horizontals))) (numeral 2) (numeral 3)))))
noncomputable def legal (B I : Expr n) : Expr n := choose (lt B D.toListing.horizontals)
(AffineAlphabet.Program.horizontalLegal (D.horizontalDimension B) I)
(AffineAlphabet.Program.squareLegal (D.linkLeft (D.toListing.slink (sub B D.toListing.horizontals)))
(D.linkRight (D.toListing.slink (sub B D.toListing.horizontals))) (D.constant (sub B D.toListing.horizontals)) I)
noncomputable def core : BlockDescriptor.Program.Listing n where
blocks := D.toListing.blocks
validBlock := D.toListing.up.validBlock (input 0)
reads := D.toListing.reads
validRead := D.toListing.up.readValid (input 0)
has := D.toListing.up.up.has (input 0) (input 1)
dimension := D.up.dimension (input 0)
readDimension := D.up.readDimension (input 0)
zeroOrder := D.up.zeroOrder (input 0)
readOrder := D.up.up.readOrder (input 0) (input 1)
legal := D.up.up.legal (input 0) (input 1)
end Listing
end VariableWL.AffineCatalog.Program
namespace VariableWL.Descriptor.Presentation
attribute [local instance] Classical.propDecidable
@[simp] theorem sum_bound {A : Type uVariable1} {B : Type uVariable2} (P : Presentation A) (Q : Presentation B) : (P.sum Q).bound=P.bound+Q.bound := rfl
noncomputable def unit : Presentation Unit := ofEncoding 1 (fun _=>true) (fun _=>0)
(by intro; decide) (by intro; rfl) (by intro a b _; exact Subsingleton.elim a b)
(by intro i hi _; exact ⟨(),by omega⟩)
@[simp] theorem unit_encode (u : Unit) : unit.encode u=0 := rfl
def optionEquiv (A : Type uVariable4) : Unit ⊕ A ≃ Option A where
toFun := Sum.elim (fun _=>none) some
invFun := Option.elim' (.inl ()) Sum.inr
left_inv a := by rcases a with u|a; cases u; rfl; rfl
right_inv a := by cases a <;> rfl
noncomputable def option {A : Type uVariable5} (P : Presentation A) : Presentation (Option A) :=
(unit.sum P).transport (optionEquiv A)
@[simp] theorem option_none {A : Type uVariable6} (P : Presentation A) : P.option.encode none=0 := rfl
@[simp] theorem option_some {A : Type uVariable7} (P : Presentation A) (a : A) : P.option.encode (some a)=1+P.encode a := rfl
end VariableWL.Descriptor.Presentation
namespace VariableWL.CircuitCatalog
open Descriptor Circuit VariableWL.Affine
attribute [local instance] Classical.propDecidable
structure Data where
rows : ℕ
internal : ℕ
scalars : ℕ
ands : ℕ
edges : ℕ
requests : ℕ
validScalar : ℕ → Bool
validAnd : ℕ → Bool
validEdge : ℕ → Bool
validRequest : ℕ → Bool
source : ℕ → ℕ
destination : ℕ → ℕ
destinationForm : ℕ → ℕ
domain : ℕ → ℕ → ℕ → Bool
map : ℕ → ℕ → ℕ → ℕ
requestGate : ℕ → ℕ
requestTest : ℕ → ℕ
requestDomain : ℕ → ℕ → ℕ → Bool
marked : ℕ
epsilon : ℕ
namespace Data
variable (D : Data)
def gates : ℕ := D.scalars+D.ands
def edgeCode (c : ℕ) : ℕ := if c<D.edges then c else if c<2*D.edges then c-D.edges else c-2*D.edges
noncomputable def affine : AffineCatalog.Data where
rows := D.rows
internal := D.internal
reals := D.gates+(D.edges+1)
comparisons := D.edges+(D.edges+D.edges)+D.requests
validReal i := if i<D.gates then (if i<D.scalars then D.validScalar i else D.validAnd (i-D.scalars))
else if i-D.gates<D.edges then D.validEdge (i-D.gates) else true
validComparison c := if c<D.edges+(D.edges+D.edges) then
(if c<D.edges then D.validEdge c else if c-D.edges<D.edges then D.validEdge (c-D.edges)
else D.validEdge (c-D.edges-D.edges)) else D.validRequest (c-(D.edges+(D.edges+D.edges)))
source c := if c<2*D.edges then D.source (D.edgeCode c) else
if c<3*D.edges then D.gates+D.edgeCode c else D.requestGate (c-3*D.edges)
target c := if c<2*D.edges then D.gates+D.edgeCode c else
if c<3*D.edges then D.destination (D.edgeCode c) else D.gates+D.edges
domain c i a := if c<3*D.edges then D.domain (D.edgeCode c) i a else D.requestDomain (c-3*D.edges) i a
map c i a := if 2*D.edges≤c ∧ c<3*D.edges then D.map (D.edgeCode c) i a else a
realDimension p := if p<D.scalars then 1 else if p<D.gates+D.edges then 2 else 1
leftForm c := if c<2*D.edges then
(if D.source (D.edgeCode c)<D.scalars then AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0)
else AffineAlphabet.encodeForm (by decide : 2≤2) ((LinearMap.proj (0 : Fin 2) : Vec 2 →ₗ[Bit] Bit)+LinearMap.proj 1))
else if c<3*D.edges then AffineAlphabet.encodeForm (by decide : 2≤2)
((LinearMap.proj (0 : Fin 2) : Vec 2 →ₗ[Bit] Bit)+LinearMap.proj 1)
else AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0)
rightForm c := if c<D.edges then AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0)
else if c<2*D.edges then AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 1)
else if c<3*D.edges then D.destinationForm (D.edgeCode c)
else AffineAlphabet.encodeForm (by decide : 1≤2) 0
leftConstant _ := 0
rightConstant c := if c<3*D.edges then 0 else D.requestTest (c-3*D.edges)
marked := D.marked
epsilon := D.epsilon
end Data
variable {r n : ℕ} {S : Type uVariable8} {A : Type uVariable9} {E : Type uVariable10} {R : Type uVariable11}
variable (PS : Presentation S) (PA : Presentation A) (PE : Presentation E) (PR : Presentation R)
noncomputable def real : Presentation (Description.Real (S := S) (A := A) (E := E)) :=
(PS.sum PA).sum (PE.sum Presentation.unit)
noncomputable def comparison : Presentation (Description.Comparison (E := E) (R := R)) :=
(PE.sum (PE.sum PE)).sum PR
structure Good (C : Description r S A E R) (marked : Fin r) (ε : Bit) (D : Data) : Prop where
rows : D.rows=r
internal : D.internal=n
scalars : D.scalars=PS.bound
ands : D.ands=PA.bound
edges : D.edges=PE.bound
requests : D.requests=PR.bound
validScalar : D.validScalar=PS.valid
validAnd : D.validAnd=PA.valid
validEdge : D.validEdge=PE.valid
validRequest : D.validRequest=PR.valid
source : ∀e,D.source (PE.encode e)=(PS.sum PA).encode (C.source e)
destination : ∀e,D.destination (PE.encode e)=(PS.sum PA).encode (target S A (C.destination e))
destinationForm : ∀e,D.destinationForm (PE.encode e)=AffineAlphabet.encodeForm
(by cases C.destination e <;> simp only [dimension] <;> decide) (inputLinear (C.destination e))
domain : ∀e i a,D.domain (PE.encode e) i.val a.toNat=true ↔ a ∈ C.domain e i
map : ∀e i a,D.map (PE.encode e) i.val a.toNat=(C.map e i a).toNat
requestGate : ∀b,D.requestGate (PR.encode b)=PS.encode (C.requestGate b)
requestTest : ∀b,D.requestTest (PR.encode b)=(if C.requestTest b then 1 else 0)
requestDomain : ∀b i a,D.requestDomain (PR.encode b) i.val a.toNat=true ↔ a ∈ C.requestDomain b i
marked : D.marked=marked.val
epsilon : D.epsilon=ε.val
end VariableWL.CircuitCatalog
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_CellularCatalog
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4 uVariable5
namespace VariableWL.CircuitCatalog.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe VariableWL.NumericProgram
variable {n : ℕ}
structure Listing (n : ℕ) where
rows : Expr n
internal : Expr n
scalars : Expr n
ands : Expr n
edges : Expr n
requests : Expr n
validScalar : Expr (n+1)
validAnd : Expr (n+1)
validEdge : Expr (n+1)
validRequest : Expr (n+1)
source : Expr (n+1)
destination : Expr (n+1)
destinationForm : Expr (n+1)
domain : Expr (n+3)
map : Expr (n+3)
requestGate : Expr (n+1)
requestTest : Expr (n+1)
requestDomain : Expr (n+3)
marked : Expr n
epsilon : Expr n
namespace Listing
variable (D : Listing n)
def eval (v : Env n) : Data where
rows := D.rows.number v
internal := D.internal.number v
scalars := D.scalars.number v
ands := D.ands.number v
edges := D.edges.number v
requests := D.requests.number v
validScalar i := D.validScalar.bit (cons (List.replicate i true) v)
validAnd i := D.validAnd.bit (cons (List.replicate i true) v)
validEdge i := D.validEdge.bit (cons (List.replicate i true) v)
validRequest i := D.validRequest.bit (cons (List.replicate i true) v)
source i := D.source.number (cons (List.replicate i true) v)
destination i := D.destination.number (cons (List.replicate i true) v)
destinationForm i := D.destinationForm.number (cons (List.replicate i true) v)
domain i j a := D.domain.bit (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
map i j a := D.map.number (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
requestGate i := D.requestGate.number (cons (List.replicate i true) v)
requestTest i := D.requestTest.number (cons (List.replicate i true) v)
requestDomain i j a := D.requestDomain.bit (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
marked := D.marked.number v
epsilon := D.epsilon.number v
def up : Listing (n+1) where
rows := D.rows.up
internal := D.internal.up
scalars := D.scalars.up
ands := D.ands.up
edges := D.edges.up
requests := D.requests.up
validScalar := underOne D.validScalar
validAnd := underOne D.validAnd
validEdge := underOne D.validEdge
validRequest := underOne D.validRequest
source := underOne D.source
destination := underOne D.destination
destinationForm := underOne D.destinationForm
domain := underThree D.domain
map := underThree D.map
requestGate := underOne D.requestGate
requestTest := underOne D.requestTest
requestDomain := underThree D.requestDomain
marked := D.marked.up
epsilon := D.epsilon.up
def gates : Expr n := add D.scalars D.ands
def edgeCode (C : Expr n) : Expr n := choose (lt C D.edges) C
(choose (lt C (mul (numeral 2) D.edges)) (sub C D.edges) (sub C (mul (numeral 2) D.edges)))
noncomputable def affineSource (C : Expr n) : Expr n := choose (lt C (mul (numeral 2) D.edges))
(applyNat D.source (D.edgeCode C)) (choose (lt C (mul (numeral 3) D.edges))
(add D.gates (D.edgeCode C)) (applyNat D.requestGate (sub C (mul (numeral 3) D.edges))))
noncomputable def affineTarget (C : Expr n) : Expr n := choose (lt C (mul (numeral 2) D.edges))
(add D.gates (D.edgeCode C)) (choose (lt C (mul (numeral 3) D.edges))
(applyNat D.destination (D.edgeCode C)) (add D.gates D.edges))
noncomputable def affineDomain (C I A : Expr n) : Expr n := choose (lt C (mul (numeral 3) D.edges))
(applyNat₃ D.domain (D.edgeCode C) I A) (applyNat₃ D.requestDomain (sub C (mul (numeral 3) D.edges)) I A)
noncomputable def affineMap (C I A : Expr n) : Expr n := choose
(conj (le (mul (numeral 2) D.edges) C) (lt C (mul (numeral 3) D.edges)))
(applyNat₃ D.map (D.edgeCode C) I A) A
noncomputable def affineDimension (P : Expr n) : Expr n := choose (lt P D.scalars) (numeral 1)
(choose (lt P (add D.gates D.edges)) (numeral 2) (numeral 1))
noncomputable def affineLeft (C : Expr n) : Expr n := choose (lt C (mul (numeral 2) D.edges))
(choose (lt (applyNat D.source (D.edgeCode C)) D.scalars)
(numeral (AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0)))
(numeral (AffineAlphabet.encodeForm (by decide : 2≤2) ((LinearMap.proj (0 : Fin 2) : Affine.Vec 2 →ₗ[Affine.Bit] Affine.Bit)+LinearMap.proj 1))))
(choose (lt C (mul (numeral 3) D.edges))
(numeral (AffineAlphabet.encodeForm (by decide : 2≤2) ((LinearMap.proj (0 : Fin 2) : Affine.Vec 2 →ₗ[Affine.Bit] Affine.Bit)+LinearMap.proj 1)))
(numeral (AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0))))
noncomputable def affineRight (C : Expr n) : Expr n := choose (lt C D.edges)
(numeral (AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0)))
(choose (lt C (mul (numeral 2) D.edges)) (numeral (AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 1)))
(choose (lt C (mul (numeral 3) D.edges)) (applyNat D.destinationForm (D.edgeCode C))
(numeral (AffineAlphabet.encodeForm (by decide : 1≤2) 0))))
noncomputable def affineConstant (C : Expr n) : Expr n := choose (lt C (mul (numeral 3) D.edges))
(numeral 0) (applyNat D.requestTest (sub C (mul (numeral 3) D.edges)))
noncomputable def affineValidReal (I : Expr n) : Expr n := choose (lt I D.gates)
(choose (lt I D.scalars) (applyNat D.validScalar I) (applyNat D.validAnd (sub I D.scalars)))
(choose (lt (sub I D.gates) D.edges) (applyNat D.validEdge (sub I D.gates)) (literal [true]))
noncomputable def affineValidComparison (C : Expr n) : Expr n := choose (lt C (add D.edges (add D.edges D.edges)))
(choose (lt C D.edges) (applyNat D.validEdge C) (choose (lt (sub C D.edges) D.edges)
(applyNat D.validEdge (sub C D.edges)) (applyNat D.validEdge (sub (sub C D.edges) D.edges))))
(applyNat D.validRequest (sub C (add D.edges (add D.edges D.edges))))
noncomputable def affine : AffineCatalog.Program.Listing n where
rows := D.rows
internal := D.internal
reals := add D.gates (add D.edges (numeral 1))
comparisons := add (add D.edges (add D.edges D.edges)) D.requests
validReal := D.up.affineValidReal (input 0)
validComparison := D.up.affineValidComparison (input 0)
source := D.up.affineSource (input 0)
target := D.up.affineTarget (input 0)
domain := D.up.up.up.affineDomain (input 0) (input 1) (input 2)
map := D.up.up.up.affineMap (input 0) (input 1) (input 2)
realDimension := D.up.affineDimension (input 0)
leftForm := D.up.affineLeft (input 0)
rightForm := D.up.affineRight (input 0)
leftConstant := numeral 0
rightConstant := D.up.affineConstant (input 0)
marked := D.marked
epsilon := D.epsilon
end Listing
end VariableWL.CircuitCatalog.Program
namespace VariableWL.Binary
theorem number_bit {d : ℕ} (x : Digits d) : ∀i : Fin d,(number x).testBit i.val=x i := by
induction d with
| zero => intro i; exact Fin.elim0 i
| succ d ih =>
intro i
have he : number x=Nat.bit (x 0) (number (fun j : Fin d=>x j.succ)) := by
cases hb : x 0 <;> simp [number,hb,Nat.bit,Nat.add_comm]
rw [he]
refine Fin.cases ?_ (fun j=>?_) i
· cases hb : x 0 <;> simp [Nat.bit,Nat.testBit_eq_decide_div_mod_eq]
· rw [Fin.val_succ,Nat.testBit_bit_succ]
exact ih (fun j : Fin d=>x j.succ) j
end VariableWL.Binary
namespace VariableWL.Circuit.ProductCellular.Data
theorem threshold_bit {L : Type uVariable1} {d m : ℕ} (D : Data L d m) (i : Fin d) : m.testBit i.val=D.threshold i := by
simpa only [D.number_threshold] using (Binary.number_bit D.threshold i)
end VariableWL.Circuit.ProductCellular.Data
namespace VariableWL.CellularCatalog
open Descriptor Circuit VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {L : Type uVariable3} {d m : ℕ} (P : Presentation L)
noncomputable def triple : Presentation (Cellular.Triple L) := P.product (P.product P)
noncomputable def ands : Presentation (Cellular.Triple L × Bool) := (triple P).product Presentation.boolean
noncomputable def kind (d : ℕ) : Presentation (ProductCellular.Kind d) :=
((Presentation.fin d).product (Presentation.fin d).option).sum
((Presentation.fin d).sum (((Presentation.fin d).product (Presentation.fin d).option).sum Presentation.boolean))
noncomputable def edge : Presentation (ProductCellular.Edge L d) := (triple P).product (kind d)
noncomputable def zeroBit (D : ProductCellular.Data L d m) : Presentation {h : Fin d // D.threshold h=false} :=
(Presentation.fin d).filter (fun i=>!(m.testBit i)) (fun h=>D.threshold h=false)
(by intro i; simp only [Presentation.fin_encode,←D.threshold_bit i,Bool.not_eq_true'])
noncomputable def accepting (D : ProductCellular.Data L d m) : Presentation {f : L // f∈D.accepting} :=
P.filter (fun i=>decide (∃f,P.encode f=i ∧ f∈D.accepting)) (fun f=>f∈D.accepting)
(by intro f; simp only [decide_eq_true_eq,P.encode_injective.eq_iff]; simp)
noncomputable def request (D : ProductCellular.Data L d m) : Presentation D.Request :=
((Presentation.fin m).sum (zeroBit D).option).sum (accepting P D)
structure Data where
bits : ℕ
inputLength : ℕ
letters : ℕ
internal : ℕ
rule : ℕ → ℕ → ℕ → ℕ
input : ℕ → ℕ
blank : ℕ
accepting : ℕ → Bool
marked : ℕ
epsilon : ℕ
namespace Data
variable (D : Data)
def leftEnd : ℕ := D.bits*(1+D.bits)
def centerEnd : ℕ := D.leftEnd+D.bits
def rightEnd : ℕ := D.centerEnd+D.leftEnd
def kinds : ℕ := D.rightEnd+2
def triples : ℕ := D.letters*(D.letters*D.letters)
def tripleCode (e : ℕ) : ℕ := e/D.kinds
def kindCode (e : ℕ) : ℕ := e%D.kinds
def first (t : ℕ) : ℕ := t/(D.letters*D.letters)
def second (t : ℕ) : ℕ := (t/D.letters)%D.letters
def third (t : ℕ) : ℕ := t%D.letters
def kindTime (k : ℕ) : ℕ := if k<D.leftEnd then k/(1+D.bits) else
if k<D.centerEnd then k-D.leftEnd else (k-D.centerEnd)/(1+D.bits)
def kindPosition (k : ℕ) : ℕ := if k<D.leftEnd then k%(1+D.bits) else (k-D.centerEnd)%(1+D.bits)
def source (e : ℕ) : ℕ := let k:=D.kindCode e; let t:=D.tripleCode e
if k<D.leftEnd then D.first t else if k<D.centerEnd then D.second t else
if k<D.rightEnd then D.third t else D.letters+(t*2+(k-D.rightEnd))
def destination (e : ℕ) : ℕ := let k:=D.kindCode e; let t:=D.tripleCode e
if k<D.centerEnd then D.letters+t*2 else if k<D.rightEnd+1 then D.letters+(t*2+1)
else D.rule (D.first t) (D.second t) (D.third t)
noncomputable def destinationForm (e : ℕ) : ℕ := let k:=D.kindCode e
if k<D.leftEnd then AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0)
else if k<D.rightEnd then AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 1)
else if k<D.rightEnd+1 then AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0)
else AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0)
def carryDomain (bit : ℕ) (h i a : ℕ) : Bool := if i<h then decide (a=bit) else if i=h then decide (a=1-bit) else true
def cyclicDomain (bit : ℕ) (h i a : ℕ) : Bool := if h=0 then decide (a=bit) else carryDomain bit (h-1) i a
def domain (e i a : ℕ) : Bool := let k:=D.kindCode e
if k<D.rightEnd then if i<D.bits then carryDomain 1 (D.kindTime k) i a
else if k<D.leftEnd then cyclicDomain 1 (D.kindPosition k) (i-D.bits) a
else if k<D.centerEnd then true else cyclicDomain 0 (D.kindPosition k) (i-D.bits) a
else true
def map (e i a : ℕ) : ℕ := let k:=D.kindCode e
if k<D.rightEnd then if i<D.bits then (if i≤D.kindTime k then 1-a else a)
else if k<D.leftEnd ∨ D.centerEnd≤k then
(if D.kindPosition k=0 ∨ i-D.bits<D.kindPosition k then 1-a else a) else a
else a
def initialEnd : ℕ := D.inputLength+(1+D.bits)
def validRequest (b : ℕ) : Bool := if b<D.inputLength then true else if b=D.inputLength then true
else if b<D.initialEnd then !(D.inputLength.testBit (b-D.inputLength-1)) else D.accepting (b-D.initialEnd)
def requestGate (b : ℕ) : ℕ := if b<D.inputLength then D.input b else if b<D.initialEnd then D.blank else b-D.initialEnd
def requestTest (b : ℕ) : ℕ := if b<D.initialEnd then 0 else 1
def requestPositionDomain (b i a : ℕ) : Bool := if b<D.inputLength then decide (a=(b.testBit i).toNat)
else if b<D.initialEnd then
(if b=D.inputLength ∨ b - D.inputLength - 1 < i then decide (a=(D.inputLength.testBit i).toNat)
else if i=b-D.inputLength-1 then decide (a=1) else true) else true
def requestDomain (b i a : ℕ) : Bool := if i<D.bits then decide (a=D.requestTest b)
else D.requestPositionDomain b (i-D.bits) a
noncomputable def catalog : CircuitCatalog.Data where
rows := D.bits+D.bits
internal := D.internal
scalars := D.letters
ands := D.triples*2
edges := D.triples*D.kinds
requests := D.initialEnd+D.letters
validScalar _ := true
validAnd _ := true
validEdge _ := true
validRequest := D.validRequest
source := D.source
destination := D.destination
destinationForm := D.destinationForm
domain := D.domain
map := D.map
requestGate := D.requestGate
requestTest := D.requestTest
requestDomain := D.requestDomain
marked := D.marked
epsilon := D.epsilon
end Data
end VariableWL.CellularCatalog
namespace VariableWL.Descriptor.Presentation
variable {A : Type uVariable4} {B : Type uVariable5}
@[simp] theorem product_bound (P : Presentation A) (Q : Presentation B) : (P.product Q).bound=P.bound*Q.bound := rfl
@[simp] theorem product_valid (P : Presentation A) (Q : Presentation B) (i : ℕ) : (P.product Q).valid i=(P.valid (i/Q.bound) && Q.valid (i%Q.bound)) := rfl
@[simp] theorem sum_valid (P : Presentation A) (Q : Presentation B) (i : ℕ) : (P.sum Q).valid i=(if i<P.bound then P.valid i else Q.valid (i-P.bound)) := rfl
@[simp] theorem filter_bound (P : Presentation A) (Q : ℕ → Bool) (T : A → Prop) (h) : (P.filter Q T h).bound=P.bound := rfl
@[simp] theorem filter_valid (P : Presentation A) (Q : ℕ → Bool) (T : A → Prop) (h) (i : ℕ) : (P.filter Q T h).valid i=(P.valid i && Q i) := rfl
@[simp] theorem option_bound (P : Presentation A) : P.option.bound=1+P.bound := rfl
@[simp] theorem option_valid (P : Presentation A) (i : ℕ) : P.option.valid i=(if i<1 then true else P.valid (i-1)) := rfl
@[simp] theorem fin_bound (d : ℕ) : (fin d).bound=d := rfl
@[simp] theorem fin_valid (d i : ℕ) : (fin d).valid i=true := rfl
end VariableWL.Descriptor.Presentation
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_CellularListing
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2 uVariable3 uVariable4
namespace VariableWL.CellularCatalog
open Descriptor Circuit VariableWL.Affine
attribute [local instance] Classical.propDecidable
variable {L : Type uVariable1} {d m n : ℕ} (P : Presentation L) (C : ProductCellular.Data L d m)
variable (marked : Fin (d+d)) (ε : Bit)
structure Good (D : Data) : Prop where
bits : D.bits=d
inputLength : D.inputLength=m
letters : D.letters=P.bound
valid : P.valid=fun _=>true
internal : D.internal=n
rule : ∀a b c,D.rule (P.encode a) (P.encode b) (P.encode c)=P.encode (C.rule a b c)
input : ∀j : Fin m,D.input j.val=P.encode (C.input j)
blank : D.blank=P.encode C.blank
accepting : ∀i,D.accepting i=decide (∃f,P.encode f=i ∧ f∈C.accepting)
marked : D.marked=marked.val
epsilon : D.epsilon=ε.val
end VariableWL.CellularCatalog
namespace VariableWL.CellularCatalog.Program
open Computation.Stack.PolyRecipe Computation.Stack.Recipe VariableWL.NumericProgram
variable {n : ℕ}
structure Listing (n : ℕ) where
bits : Expr n
inputLength : Expr n
letters : Expr n
internal : Expr n
rule : Expr (n+3)
input : Expr (n+1)
blank : Expr n
accepting : Expr (n+1)
marked : Expr n
epsilon : Expr n
namespace Listing
variable (D : Listing n)
def eval (v : Env n) : Data where
bits := D.bits.number v
inputLength := D.inputLength.number v
letters := D.letters.number v
internal := D.internal.number v
rule i j a := D.rule.number (cons (List.replicate i true) (cons (List.replicate j true) (cons (List.replicate a true) v)))
input i := D.input.number (cons (List.replicate i true) v)
blank := D.blank.number v
accepting i := D.accepting.bit (cons (List.replicate i true) v)
marked := D.marked.number v
epsilon := D.epsilon.number v
def up : Listing (n+1) where
bits := D.bits.up
inputLength := D.inputLength.up
letters := D.letters.up
internal := D.internal.up
rule := underThree D.rule
input := underOne D.input
blank := D.blank.up
accepting := underOne D.accepting
marked := D.marked.up
epsilon := D.epsilon.up
noncomputable def leftEnd : Expr n := (mul D.bits (add (numeral 1) D.bits))
noncomputable def centerEnd : Expr n := (add D.leftEnd D.bits)
noncomputable def rightEnd : Expr n := (add D.centerEnd D.leftEnd)
noncomputable def kinds : Expr n := (add D.rightEnd (numeral 2))
noncomputable def triples : Expr n := (mul D.letters (mul D.letters D.letters))
noncomputable def tripleCode (E : Expr n) : Expr n := (div E D.kinds)
noncomputable def kindCode (E : Expr n) : Expr n := (mod E D.kinds)
noncomputable def first (T : Expr n) : Expr n := (div T (mul D.letters D.letters))
noncomputable def second (T : Expr n) : Expr n := (mod (div T D.letters) D.letters)
noncomputable def third (T : Expr n) : Expr n := (mod T D.letters)
noncomputable def kindTime (K : Expr n) : Expr n := (choose (lt K D.leftEnd) (div K (add (numeral 1) D.bits)) (choose (lt K D.centerEnd) (sub K D.leftEnd) (div (sub K D.centerEnd) (add (numeral 1) D.bits))))
noncomputable def kindPosition (K : Expr n) : Expr n := (choose (lt K D.leftEnd) (mod K (add (numeral 1) D.bits)) (mod (sub K D.centerEnd) (add (numeral 1) D.bits)))
noncomputable def source (E : Expr n) : Expr n := (choose (lt (D.kindCode E) D.leftEnd) (D.first (D.tripleCode E)) (choose (lt (D.kindCode E) D.centerEnd) (D.second (D.tripleCode E)) (choose (lt (D.kindCode E) D.rightEnd) (D.third (D.tripleCode E)) (add D.letters (add (mul (D.tripleCode E) (numeral 2)) (sub (D.kindCode E) D.rightEnd))))))
noncomputable def destination (E : Expr n) : Expr n := (choose (lt (D.kindCode E) D.centerEnd) (add D.letters (mul (D.tripleCode E) (numeral 2))) (choose (lt (D.kindCode E) (add D.rightEnd (numeral 1))) (add D.letters (add (mul (D.tripleCode E) (numeral 2)) (numeral 1))) (applyNat₃ D.rule (D.first (D.tripleCode E)) (D.second (D.tripleCode E)) (D.third (D.tripleCode E)))))
noncomputable def destinationForm (E : Expr n) : Expr n := (choose (lt (D.kindCode E) D.leftEnd) (numeral (AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0))) (choose (lt (D.kindCode E) D.rightEnd) (numeral (AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 1))) (choose (lt (D.kindCode E) (add D.rightEnd (numeral 1))) (numeral (AffineAlphabet.encodeForm (by decide : 2≤2) (LinearMap.proj 0))) (numeral (AffineAlphabet.encodeForm (by decide : 1≤2) (LinearMap.proj 0))))))
def carryDomain (_D : Listing n) (B H I A : Expr n) : Expr n := (choose (lt I H) (eq A B) (choose (eq I H) (eq A (sub (numeral 1) B)) (literal [true])))
def cyclicDomain (D : Listing n) (B H I A : Expr n) : Expr n := (choose (eq H (numeral 0)) (eq A B) (D.carryDomain B (sub H (numeral 1)) I A))
noncomputable def domain (E I A : Expr n) : Expr n := (choose (lt (D.kindCode E) D.rightEnd) (choose (lt I D.bits) (D.carryDomain (numeral 1) (D.kindTime (D.kindCode E)) I A) (choose (lt (D.kindCode E) D.leftEnd) (D.cyclicDomain (numeral 1) (D.kindPosition (D.kindCode E)) (sub I D.bits) A) (choose (lt (D.kindCode E) D.centerEnd) (literal [true]) (D.cyclicDomain (numeral 0) (D.kindPosition (D.kindCode E)) (sub I D.bits) A)))) (literal [true]))
noncomputable def map (E I A : Expr n) : Expr n := (choose (lt (D.kindCode E) D.rightEnd) (choose (lt I D.bits) (choose (le I (D.kindTime (D.kindCode E))) (sub (numeral 1) A) A) (choose (disj (lt (D.kindCode E) D.leftEnd) (le D.centerEnd (D.kindCode E))) (choose (disj (eq (D.kindPosition (D.kindCode E)) (numeral 0)) (lt (sub I D.bits) (D.kindPosition (D.kindCode E)))) (sub (numeral 1) A) A) A)) A)
noncomputable def initialEnd : Expr n := (add D.inputLength (add (numeral 1) D.bits))
noncomputable def validRequest (B : Expr n) : Expr n := (choose (lt B D.inputLength) (literal [true]) (choose (eq B D.inputLength) (literal [true]) (choose (lt B D.initialEnd) (neg (binaryDigit D.inputLength (sub (sub B D.inputLength) (numeral 1)))) (applyNat D.accepting (sub B D.initialEnd)))))
noncomputable def requestGate (B : Expr n) : Expr n := (choose (lt B D.inputLength) (applyNat D.input B) (choose (lt B D.initialEnd) D.blank (sub B D.initialEnd)))
noncomputable def requestTest (B : Expr n) : Expr n := (choose (lt B D.initialEnd) (numeral 0) (numeral 1))
noncomputable def requestPositionDomain (B I A : Expr n) : Expr n := (choose (lt B D.inputLength) (eq A (choose (binaryDigit B I) (numeral 1) (numeral 0))) (choose (lt B D.initialEnd) (choose (disj (eq B D.inputLength) (lt (sub (sub B D.inputLength) (numeral 1)) I)) (eq A (choose (binaryDigit D.inputLength I) (numeral 1) (numeral 0))) (choose (eq I (sub (sub B D.inputLength) (numeral 1))) (eq A (numeral 1)) (literal [true]))) (literal [true])))
noncomputable def requestDomain (B I A : Expr n) : Expr n := (choose (lt I D.bits) (eq A (D.requestTest B)) (D.requestPositionDomain B (sub I D.bits) A))
noncomputable def catalog : CircuitCatalog.Program.Listing n where
rows := add D.bits D.bits
internal := D.internal
scalars := D.letters
ands := mul D.triples (numeral 2)
edges := mul D.triples D.kinds
requests := add D.initialEnd D.letters
validScalar := literal [true]
validAnd := literal [true]
validEdge := literal [true]
validRequest := D.up.validRequest (Computation.Stack.PolyRecipe.input 0)
source := D.up.source (Computation.Stack.PolyRecipe.input 0)
destination := D.up.destination (Computation.Stack.PolyRecipe.input 0)
destinationForm := D.up.destinationForm (Computation.Stack.PolyRecipe.input 0)
domain := D.up.up.up.domain (Computation.Stack.PolyRecipe.input 0) (Computation.Stack.PolyRecipe.input 1) (Computation.Stack.PolyRecipe.input 2)
map := D.up.up.up.map (Computation.Stack.PolyRecipe.input 0) (Computation.Stack.PolyRecipe.input 1) (Computation.Stack.PolyRecipe.input 2)
requestGate := D.up.requestGate (Computation.Stack.PolyRecipe.input 0)
requestTest := D.up.requestTest (Computation.Stack.PolyRecipe.input 0)
requestDomain := D.up.up.up.requestDomain (Computation.Stack.PolyRecipe.input 0) (Computation.Stack.PolyRecipe.input 1) (Computation.Stack.PolyRecipe.input 2)
marked := D.marked
epsilon := D.epsilon
end Listing
end VariableWL.CellularCatalog.Program
end OAI
end
section
-- module Solutions.OAIQ6_WL.VariableWL_Completeness
set_option linter.all false
set_option linter.unusedVariables false
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace OAI
universe uVariable1 uVariable2
namespace VariableWL.AffineCatalog
open Blocks BlockCoordinates Descriptor VariableWL.Affine
attribute [local instance] Classical.propDecidable
namespace Data
def resign (D : Data) (ε : Bit) : Data := {D with epsilon:=ε.val}
noncomputable def descriptor (D : Data) (ε : Bit) : Descriptor.Data :=
(D.resign ε).core.toPrefix.portData.expanded
end Data
theorem sortPredicate_congr {X Y : PrefixDescriptor.Data}
(hv : X.validBlock=Y.validBlock) (hc : X.channelBound=Y.channelBound)
(hd : X.dimension=Y.dimension) (hch : X.channels=Y.channels)
(hr : X.root=Y.root) : X.sortPredicate=Y.sortPredicate := by
cases X
cases Y
dsimp only at hv hc hd hch hr
cases hv
cases hc
cases hd
cases hch
cases hr
rfl
variable {r n : ℕ} {P : Type uVariable1} {E : Type uVariable2} [Fintype P] [Fintype E]
variable (PP : Presentation P) (PE : Presentation E) (J : ProductImages.Instance r P E)
variable (hr : 2≤r) (hn : 0<n) (marked : Fin r) {D : Data} {ε₀ : Bit}
variable (h : Good (n := n) PP PE J marked ε₀ D)
omit [Fintype P] [Fintype E] in
include h in
theorem resign_good (ε : Bit) : Good (n := n) PP PE J marked ε (D.resign ε) := by
exact ⟨h.toGood,h.realDimension,h.leftForm,h.rightForm,h.leftConstant,h.rightConstant,h.marked,rfl⟩
noncomputable def blockPresentation := BlockCatalog.block PP PE J h.toGood
noncomputable def readPresentation := BlockCatalog.readout (r := r) (n := n) PP PE
omit [Fintype P] [Fintype E] in
theorem coordinateBound : ∀b : Block (n := n) J,
Fintype.card (BlockCoordinates.Coordinate J b.val)≤6 :=
fun b => RealizationSize.coordinate_card J b.val
omit [Fintype P] [Fintype E] in
include h in
theorem core_resign_good (ε : Bit) :
BlockDescriptor.Good J hr hn marked (blockPresentation PP PE J marked h)
(readPresentation (r := r) (n := n) PP PE) (coordinateBound (n := n) J) ε (D.resign ε).core :=
core_good PP PE J marked ε (resign_good PP PE J marked h ε) hr hn
@[instance_reducible] noncomputable def properNumbering : ∀b : Block (n := n) J, FiniteNumbering (Proper J b) :=
BlockDescriptor.properNumberings J hr hn marked (blockPresentation PP PE J marked h)
(readPresentation (r := r) (n := n) PP PE) (coordinateBound (n := n) J) 0
(core_resign_good PP PE J hr hn marked h 0)
include h in
theorem properNumbering_eq (ε : Bit) :
BlockDescriptor.properNumberings J hr hn marked (blockPresentation PP PE J marked h)
(readPresentation (r := r) (n := n) PP PE) (coordinateBound (n := n) J) ε
(core_resign_good PP PE J hr hn marked h ε)=properNumbering PP PE J hr hn marked h := rfl
include h in
theorem prefix_resign_good (ε : Bit) :
let _ := properNumbering PP PE J hr hn marked h
PrefixDescriptor.Good (blockPresentation PP PE J marked h) (data J hr hn marked)
(coordinateBound (n := n) J) ε (D.resign ε).core.toPrefix := by
have ht := BlockDescriptor.prefix_good J hr hn marked (blockPresentation PP PE J marked h)
(readPresentation (r := r) (n := n) PP PE) (coordinateBound (n := n) J) ε
(core_resign_good PP PE J hr hn marked h ε)
rw [properNumbering_eq PP PE J hr hn marked h ε] at ht
exact ht
include h in
theorem matching_resign_good (ε : Bit) :
let _ := properNumbering PP PE J hr hn marked h
PrefixDescriptor.MatchingGood (blockPresentation PP PE J marked h) (data J hr hn marked)
(D.resign ε).core.toPrefix (wiring J hr hn marked) := by
have ht := BlockDescriptor.matching_good J hr hn marked (blockPresentation PP PE J marked h)
(readPresentation (r := r) (n := n) PP PE) (coordinateBound (n := n) J) ε
(core_resign_good PP PE J hr hn marked h ε)
rw [properNumbering_eq PP PE J hr hn marked h ε] at ht
exact ht
include hr hn h in
theorem descriptor_sound (ε : Bit) : (D.descriptor ε).Sound := by
let : ∀b : Block (n := n) J,FiniteNumbering (Proper J b) := properNumbering PP PE J hr hn marked h
exact Descriptor.PortData.sound_expanded _
(PrefixDescriptor.port_sound (blockPresentation PP PE J marked h) (data J hr hn marked)
(coordinateBound (n := n) J) ε (prefix_resign_good PP PE J hr hn marked h ε)
(wiring J hr hn marked) (matching_resign_good PP PE J hr hn marked h ε))
noncomputable def sortPresentation :
let _ := properNumbering PP PE J hr hn marked h
Presentation (PrefixParts.Wiring.SortTag (data J hr hn marked)) := by
letI : ∀b : Block (n := n) J,FiniteNumbering (Proper J b) := properNumbering PP PE J hr hn marked h
exact Classical.choose (PrefixDescriptor.sortPresentation (blockPresentation PP PE J marked h)
(data J hr hn marked) (coordinateBound (n := n) J) 0 (prefix_resign_good PP PE J hr hn marked h 0))
theorem core_proper_resign (ε : Bit) :
(D.resign ε).core.proper=(D.resign 0).core.proper := by
funext b i
rfl
theorem core_channels_resign (ε : Bit) :
(D.resign ε).core.channels=(D.resign 0).core.channels := by
funext b
simp only [BlockDescriptor.Core.channels,core_proper_resign]
rfl
theorem core_dimension_resign (ε : Bit) :
(D.resign ε).core.dimension=(D.resign 0).core.dimension := by
funext b
rfl
theorem core_readDimension_resign (ε : Bit) :
(D.resign ε).core.readDimension=(D.resign 0).core.readDimension := by
funext b
rfl
theorem core_root_resign (ε : Bit) :
(D.resign ε).core.root=(D.resign 0).core.root := by
funext b c
simp only [BlockDescriptor.Core.root,BlockDescriptor.Core.readout,
BlockDescriptor.Core.select,core_readDimension_resign,core_proper_resign]
rfl
theorem prefix_channelBound_resign (ε : Bit) :
(D.resign ε).core.toPrefix.channelBound=(D.resign 0).core.toPrefix.channelBound := by
simp only [BlockDescriptor.Core.toPrefix,BlockDescriptor.Core.channelBound,
BlockDescriptor.Core.properBound,Data.core,Data.resign]
theorem prefix_sortPredicate_resign (ε : Bit) :
(D.resign ε).core.toPrefix.sortPredicate=(D.resign 0).core.toPrefix.sortPredicate := by
exact sortPredicate_congr (X := (D.resign ε).core.toPrefix)
(Y := (D.resign 0).core.toPrefix) rfl (prefix_channelBound_resign (D := D) ε)
(core_dimension_resign (D := D) ε)
(core_channels_resign (D := D) ε) (core_root_resign (D := D) ε)
theorem prefix_tag_resign (ε : Bit) :
(D.resign ε).core.toPrefix.tag=(D.resign 0).core.toPrefix.tag := by
funext x
simp only [PrefixDescriptor.Data.tag,BlockDescriptor.Core.toPrefix,
BlockDescriptor.Core.channelBound,BlockDescriptor.Core.properBound,Data.core,Data.resign]
include h in
theorem sort_spec :
let _ := properNumbering PP PE J hr hn marked h
let S := sortPresentation PP PE J hr hn marked h
let X := (D.resign 0).core.toPrefix
S.bound=X.sortBound ∧ S.valid=X.sortPredicate ∧
∀s,S.encode s=X.tag (PrefixDescriptor.sortRaw (blockPresentation PP PE J marked h) (data J hr hn marked) s) := by
let : ∀b : Block (n := n) J,FiniteNumbering (Proper J b) := properNumbering PP PE J hr hn marked h
exact Classical.choose_spec (PrefixDescriptor.sortPresentation (blockPresentation PP PE J marked h)
(data J hr hn marked) (coordinateBound (n := n) J) 0 (prefix_resign_good PP PE J hr hn marked h 0))
include h in
theorem sort_valid (ε : Bit) :
(sortPresentation PP PE J hr hn marked h).valid=(D.resign ε).core.toPrefix.sortPredicate := by
rw [prefix_sortPredicate_resign]
exact (sort_spec PP PE J hr hn marked h).2.1
include h in
theorem sort_encode (ε : Bit) :
let _ := properNumbering PP PE J hr hn marked h
∀s,(sortPresentation PP PE J hr hn marked h).encode s=
(D.resign ε).core.toPrefix.tag (PrefixDescriptor.sortRaw (blockPresentation PP PE J marked h) (data J hr hn marked) s) := by
intro _ s
rw [prefix_tag_resign]
exact (sort_spec PP PE J hr hn marked h).2.2 s
noncomputable def descriptor_iso (ε : Bit) :
let _ := properNumbering PP PE J hr hn marked h
let _ : FiniteNumbering (Block (n := n) J) := (blockPresentation PP PE J marked h).numbering
let _ : FiniteNumbering (PrefixParts.Wiring.SortTag (data J hr hn marked)) := (sortPresentation PP PE J hr hn marked h).numbering
((D.descriptor ε).graph (descriptor_sound PP PE J hr hn marked h ε)).graph ≃g
(Subcubic.finiteGraph J hr hn marked ε).graph := by
letI : ∀b : Block (n := n) J,FiniteNumbering (Proper J b) := properNumbering PP PE J hr hn marked h
letI : FiniteNumbering (Block (n := n) J) := (blockPresentation PP PE J marked h).numbering
letI : FiniteNumbering (PrefixParts.Wiring.SortTag (data J hr hn marked)) := (sortPresentation PP PE J hr hn marked h).numbering
exact (PrefixDescriptor.uncoloredIso (blockPresentation PP PE J marked h) (data J hr hn marked)
(coordinateBound (n := n) J) ε (prefix_resign_good PP PE J hr hn marked h ε)
(wiring J hr hn marked) (matching_resign_good PP PE J hr hn marked h ε)
(sortPresentation PP PE J hr hn marked h) (sort_valid PP PE J hr hn marked h ε)
(sort_encode PP PE J hr hn marked h ε)).trans (TypedGame.numbering (Subcubic.graph J hr hn marked ε))
end VariableWL.AffineCatalog
namespace VariableWL.AffineCatalog.Program.Listing
open Computation.Stack.PolyRecipe
variable {n : ℕ} (D : Listing n)
noncomputable def graph : GraphListing n := D.core.toPrefix.portListing.expanded
end VariableWL.AffineCatalog.Program.Listing
namespace VariableWL.CellularCatalog.Program.Listing
open Computation.Stack.PolyRecipe
variable {n : ℕ} (D : Listing n)
noncomputable def graph : GraphListing n := D.catalog.affine.graph
end VariableWL.CellularCatalog.Program.Listing
namespace VariableWL.CellularCatalog.Data
def resign (D : Data) (ε : Affine.Bit) : Data := {D with epsilon:=ε.val}
end VariableWL.CellularCatalog.Data
end OAI
end