l3lab/ntp-mathlib huggingface dataset:
/-- Decodes a list of symbols as a list of formulas. -/
@[simp]
def listDecode : ∀ l : List (Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ)),
    (Σn, L.BoundedFormula α n) ×
    { l' : List (Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ)) //
      SizeOf.sizeOf l' ≤ max 1 (SizeOf.sizeOf l) }
  | Sum.inr (Sum.inr (n + 2))::l => ⟨⟨n, falsum⟩, l, le_max_of_le_right le_add_self⟩
  | Sum.inl ⟨n₁, t₁⟩::Sum.inl ⟨n₂, t₂⟩::l =>
    ⟨if h : n₁ = n₂ then ⟨n₁, equal t₁ (Eq.mp (by rw [h]) t₂)⟩ else default, l, by
      simp only [SizeOf.sizeOf, List._sizeOf_1, ← add_assoc]
      exact le_max_of_le_right le_add_self⟩
  | Sum.inr (Sum.inl ⟨n, R⟩)::Sum.inr (Sum.inr k)::l =>
    ⟨if h : ∀ i : Fin n, ((l.map Sum.getLeft?).get? i).join.isSome then
        if h' : ∀ i, (Option.get _ (h i)).1 = k then
          ⟨k, BoundedFormula.rel R fun i => Eq.mp (by rw [h' i]) (Option.get _ (h i)).2⟩
        else default
      else default,
      l.drop n, le_max_of_le_right (le_add_left (le_add_left (List.drop_sizeOf_le _ _)))⟩
  | Sum.inr (Sum.inr 0)::l =>
    have : SizeOf.sizeOf
        (↑(listDecode l).2 : List (Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ))) <
        1 + (1 + 1) + SizeOf.sizeOf l := by
      refine' lt_of_le_of_lt (listDecode l).2.2 (max_lt _ (Nat.lt_add_of_pos_left (by decide)))
      rw [add_assoc, lt_add_iff_pos_right, add_pos_iff]
      

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ 0 < 1 + 1 ∨ 0 < sizeOf l

Next tactic:
exact Or.inl zero_lt_two
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
⊢ (listDecode (List.bind l fun φ => listEncode φ.snd)).1 = headI l

Next tactic:
suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · 

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
h :
  ∀ (φ : (n : ℕ) × BoundedFormula L α n) (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode φ.snd ++ l)).1 = φ ∧ ↑(listDecode (listEncode φ.snd ++ l)).2 = l
⊢ (listDecode (List.bind l fun φ => listEncode φ.snd)).1 = headI l

Next tactic:
induction' l with φ l _
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · 

Proof state:
case nil
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
h :
  ∀ (φ : (n : ℕ) × BoundedFormula L α n) (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode φ.snd ++ l)).1 = φ ∧ ↑(listDecode (listEncode φ.snd ++ l)).2 = l
⊢ (listDecode (List.bind [] fun φ => listEncode φ.snd)).1 = headI []

Next tactic:
rw [List.nil_bind]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      

Proof state:
case nil
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
h :
  ∀ (φ : (n : ℕ) × BoundedFormula L α n) (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode φ.snd ++ l)).1 = φ ∧ ↑(listDecode (listEncode φ.snd ++ l)).2 = l
⊢ (listDecode []).1 = headI []

Next tactic:
simp [listDecode]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · 

Proof state:
case cons
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
h :
  ∀ (φ : (n : ℕ) × BoundedFormula L α n) (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode φ.snd ++ l)).1 = φ ∧ ↑(listDecode (listEncode φ.snd ++ l)).2 = l
φ : (n : ℕ) × BoundedFormula L α n
l : List ((n : ℕ) × BoundedFormula L α n)
tail_ih✝ : (listDecode (List.bind l fun φ => listEncode φ.snd)).1 = headI l
⊢ (listDecode (List.bind (φ :: l) fun φ => listEncode φ.snd)).1 = headI (φ :: l)

Next tactic:
rw [cons_bind, (h φ _).1, headI_cons]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · 

Proof state:
case h
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
⊢ ∀ (φ : (n : ℕ) × BoundedFormula L α n) (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode φ.snd ++ l)).1 = φ ∧ ↑(listDecode (listEncode φ.snd ++ l)).2 = l

Next tactic:
rintro ⟨n, φ⟩
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    

Proof state:
case h.mk
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n : ℕ
φ : BoundedFormula L α n
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n, snd := φ }.snd ++ l)).1 = { fst := n, snd := φ } ∧
      ↑(listDecode (listEncode { fst := n, snd := φ }.snd ++ l)).2 = l

Next tactic:
induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> 

Proof state:
case h.mk.falsum
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := falsum }.snd ++ l)).1 = { fst := n✝, snd := falsum } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := falsum }.snd ++ l)).2 = l

Next tactic:
intro l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> 

Proof state:
case h.mk.equal
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
t₁✝ t₂✝ : Term L (α ⊕ Fin n✝)
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := equal t₁✝ t₂✝ }.snd ++ l)).1 = { fst := n✝, snd := equal t₁✝ t₂✝ } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := equal t₁✝ t₂✝ }.snd ++ l)).2 = l

Next tactic:
intro l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> 

Proof state:
case h.mk.rel
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := φ_n, snd := rel φ_R ts }.snd ++ l)).1 = { fst := φ_n, snd := rel φ_R ts } ∧
      ↑(listDecode (listEncode { fst := φ_n, snd := rel φ_R ts }.snd ++ l)).2 = l

Next tactic:
intro l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> 

Proof state:
case h.mk.imp
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
f₁✝ f₂✝ : BoundedFormula L α n✝
ih1 :
  ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := f₁✝ }.snd ++ l)).1 = { fst := n✝, snd := f₁✝ } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := f₁✝ }.snd ++ l)).2 = l
ih2 :
  ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := f₂✝ }.snd ++ l)).1 = { fst := n✝, snd := f₂✝ } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := f₂✝ }.snd ++ l)).2 = l
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := f₁✝ ⟹ f₂✝ }.snd ++ l)).1 = { fst := n✝, snd := f₁✝ ⟹ f₂✝ } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := f₁✝ ⟹ f₂✝ }.snd ++ l)).2 = l

Next tactic:
intro l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> 

Proof state:
case h.mk.all
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
f✝ : BoundedFormula L α (n✝ + 1)
ih :
  ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝ + 1, snd := f✝ }.snd ++ l)).1 = { fst := n✝ + 1, snd := f✝ } ∧
      ↑(listDecode (listEncode { fst := n✝ + 1, snd := f✝ }.snd ++ l)).2 = l
⊢ ∀ (l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)),
    (listDecode (listEncode { fst := n✝, snd := ∀'f✝ }.snd ++ l)).1 = { fst := n✝, snd := ∀'f✝ } ∧
      ↑(listDecode (listEncode { fst := n✝, snd := ∀'f✝ }.snd ++ l)).2 = l

Next tactic:
intro l
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · 

Proof state:
case h.mk.falsum
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ (listDecode (listEncode { fst := n✝, snd := falsum }.snd ++ l)).1 = { fst := n✝, snd := falsum } ∧
    ↑(listDecode (listEncode { fst := n✝, snd := falsum }.snd ++ l)).2 = l

Next tactic:
rw [listEncode, singleton_append, listDecode]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      

Proof state:
case h.mk.falsum
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ ({ fst := { fst := n✝, snd := falsum }.fst, snd := falsum },
          { val := l,
            property :=
              (_ : sizeOf l ≤ max 1 (sizeOf (Sum.inr (Sum.inr ({ fst := n✝, snd := falsum }.fst + 2)) :: l))) }).1 =
      { fst := n✝, snd := falsum } ∧
    ↑({ fst := { fst := n✝, snd := falsum }.fst, snd := falsum },
            { val := l,
              property :=
                (_ : sizeOf l ≤ max 1 (sizeOf (Sum.inr (Sum.inr ({ fst := n✝, snd := falsum }.fst + 2)) :: l))) }).2 =
      l

Next tactic:
simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · 

Proof state:
case h.mk.equal
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
t₁✝ t₂✝ : Term L (α ⊕ Fin n✝)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ (listDecode (listEncode { fst := n✝, snd := equal t₁✝ t₂✝ }.snd ++ l)).1 = { fst := n✝, snd := equal t₁✝ t₂✝ } ∧
    ↑(listDecode (listEncode { fst := n✝, snd := equal t₁✝ t₂✝ }.snd ++ l)).2 = l

Next tactic:
rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · 

Proof state:
case h.mk.equal
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
t₁✝ t₂✝ : Term L (α ⊕ Fin n✝)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ ({ fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst,
            snd :=
              equal t₁✝
                (Eq.mp
                  (_ :
                    Term L (α ⊕ Fin { fst := n✝, snd := equal t₁✝ t₂✝ }.fst) =
                      Term L (α ⊕ Fin { fst := n✝, snd := equal t₁✝ t₂✝ }.fst))
                  t₂✝) },
          { val := [] ++ l,
            property :=
              (_ :
                sizeOf ([] ++ l) ≤
                  max 1
                    (sizeOf
                      (Sum.inl { fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst, snd := t₁✝ } ::
                        Sum.inl { fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst, snd := t₂✝ } :: ([] ++ l)))) }).1 =
      { fst := n✝, snd := equal t₁✝ t₂✝ } ∧
    ↑({ fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst,
              snd :=
                equal t₁✝
                  (Eq.mp
                    (_ :
                      Term L (α ⊕ Fin { fst := n✝, snd := equal t₁✝ t₂✝ }.fst) =
                        Term L (α ⊕ Fin { fst := n✝, snd := equal t₁✝ t₂✝ }.fst))
                    t₂✝) },
            { val := [] ++ l,
              property :=
                (_ :
                  sizeOf ([] ++ l) ≤
                    max 1
                      (sizeOf
                        (Sum.inl { fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst, snd := t₁✝ } ::
                          Sum.inl { fst := { fst := n✝, snd := equal t₁✝ t₂✝ }.fst, snd := t₂✝ } :: ([] ++ l)))) }).2 =
      l

Next tactic:
simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · 

Proof state:
case h.mk.equal.hc
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n n✝ : ℕ
t₁✝ t₂✝ : Term L (α ⊕ Fin n✝)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ { fst := n✝, snd := equal t₁✝ t₂✝ }.fst = { fst := n✝, snd := equal t₁✝ t₂✝ }.fst

Next tactic:
simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · 

Proof state:
case h.mk.rel
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ (listDecode (listEncode { fst := φ_n, snd := rel φ_R ts }.snd ++ l)).1 = { fst := φ_n, snd := rel φ_R ts } ∧
    ↑(listDecode (listEncode { fst := φ_n, snd := rel φ_R ts }.snd ++ l)).2 = l

Next tactic:
rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]