l3lab/ntp-mathlib huggingface dataset:
theorem mapAccumr_bisim {f₁ : α → σ₁ → σ₁ × β} {f₂ : α → σ₂ → σ₂ × β} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR : ∀ {s q} a, R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2) :
    R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst
    ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd := by
  induction xs using Vector.revInductionOn generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs x ih =>
    

Proof state:
α : Type u_2
n : ℕ
xs✝ : Vector α n
σ₁ : Type
β : Type u_1
σ₂ : Type
f₁ : α → σ₁ → σ₁ × β
f₂ : α → σ₂ → σ₂ × β
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α), R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).1 (mapAccumr f₂ xs s₂).1 ∧ (mapAccumr f₁ xs s₁).2 = (mapAccumr f₂ xs s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ (snoc xs x) s₁).1 (mapAccumr f₂ (snoc xs x) s₂).1 ∧
    (mapAccumr f₁ (snoc xs x) s₁).2 = (mapAccumr f₂ (snoc xs x) s₂).2

Next tactic:
rcases (hR x h₀) with ⟨hR, _⟩
theorem mapAccumr_bisim {f₁ : α → σ₁ → σ₁ × β} {f₂ : α → σ₂ → σ₂ × β} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR : ∀ {s q} a, R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2) :
    R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst
    ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd := by
  induction xs using Vector.revInductionOn generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs x ih =>
    rcases (hR x h₀) with ⟨hR, _⟩
    

Proof state:
case intro
α : Type u_2
n : ℕ
xs✝ : Vector α n
σ₁ : Type
β : Type u_1
σ₂ : Type
f₁ : α → σ₁ → σ₁ × β
f₂ : α → σ₂ → σ₂ × β
R : σ₁ → σ₂ → Prop
hR✝ : ∀ {s : σ₁} {q : σ₂} (a : α), R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).1 (mapAccumr f₂ xs s₂).1 ∧ (mapAccumr f₁ xs s₁).2 = (mapAccumr f₂ xs s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x s₁).1 (f₂ x s₂).1
right✝ : (f₁ x s₁).2 = (f₂ x s₂).2
⊢ R (mapAccumr f₁ (snoc xs x) s₁).1 (mapAccumr f₂ (snoc xs x) s₂).1 ∧
    (mapAccumr f₁ (snoc xs x) s₁).2 = (mapAccumr f₂ (snoc xs x) s₂).2

Next tactic:
simp only [mapAccumr_snoc, ih hR, true_and]
theorem mapAccumr_bisim {f₁ : α → σ₁ → σ₁ × β} {f₂ : α → σ₂ → σ₂ × β} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR : ∀ {s q} a, R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2) :
    R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst
    ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd := by
  induction xs using Vector.revInductionOn generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs x ih =>
    rcases (hR x h₀) with ⟨hR, _⟩
    simp only [mapAccumr_snoc, ih hR, true_and]
    

Proof state:
case intro
α : Type u_2
n : ℕ
xs✝ : Vector α n
σ₁ : Type
β : Type u_1
σ₂ : Type
f₁ : α → σ₁ → σ₁ × β
f₂ : α → σ₂ → σ₂ × β
R : σ₁ → σ₂ → Prop
hR✝ : ∀ {s : σ₁} {q : σ₂} (a : α), R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).1 (mapAccumr f₂ xs s₂).1 ∧ (mapAccumr f₁ xs s₁).2 = (mapAccumr f₂ xs s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x s₁).1 (f₂ x s₂).1
right✝ : (f₁ x s₁).2 = (f₂ x s₂).2
⊢ snoc (mapAccumr f₂ xs (f₂ x s₂).1).2 (f₁ x s₁).2 = snoc (mapAccumr f₂ xs (f₂ x s₂).1).2 (f₂ x s₂).2

Next tactic:
congr 1
theorem mapAccumr_bisim_tail {f₁ : α → σ₁ → σ₁ × β} {f₂ : α → σ₂ → σ₂ × β} {s₁ : σ₁} {s₂ : σ₂}
    (h : ∃ R : σ₁ → σ₂ → Prop, R s₁ s₂ ∧
      ∀ {s q} a, R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2) :
    (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd := by
  

Proof state:
α : Type u_2
n : ℕ
xs : Vector α n
σ₁ : Type
β : Type u_1
σ₂ : Type
f₁ : α → σ₁ → σ₁ × β
f₂ : α → σ₂ → σ₂ × β
s₁ : σ₁
s₂ : σ₂
h : ∃ R, R s₁ s₂ ∧ ∀ {s : σ₁} {q : σ₂} (a : α), R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2
⊢ (mapAccumr f₁ xs s₁).2 = (mapAccumr f₂ xs s₂).2

Next tactic:
rcases h with ⟨R, h₀, hR⟩
theorem mapAccumr_bisim_tail {f₁ : α → σ₁ → σ₁ × β} {f₂ : α → σ₂ → σ₂ × β} {s₁ : σ₁} {s₂ : σ₂}
    (h : ∃ R : σ₁ → σ₂ → Prop, R s₁ s₂ ∧
      ∀ {s q} a, R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2) :
    (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd := by
  rcases h with ⟨R, h₀, hR⟩
  

Proof state:
case intro.intro
α : Type u_2
n : ℕ
xs : Vector α n
σ₁ : Type
β : Type u_1
σ₂ : Type
f₁ : α → σ₁ → σ₁ × β
f₂ : α → σ₂ → σ₂ × β
s₁ : σ₁
s₂ : σ₂
R : σ₁ → σ₂ → Prop
h₀ : R s₁ s₂
hR : ∀ {s : σ₁} {q : σ₂} (a : α), R s q → R (f₁ a s).1 (f₂ a q).1 ∧ (f₁ a s).2 = (f₂ a q).2
⊢ (mapAccumr f₁ xs s₁).2 = (mapAccumr f₂ xs s₂).2

Next tactic:
exact (mapAccumr_bisim R h₀ hR).2
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  

Proof state:
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
ys : Vector β n
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
s₁ : σ₁
s₂ : σ₂
R : σ₁ → σ₂ → Prop
h₀ : R s₁ s₂
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
⊢ R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1 ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2

Next tactic:
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  

Proof state:
case nil
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ nil nil s₁).1 (mapAccumr₂ f₂ nil nil s₂).1 ∧
    (mapAccumr₂ f₁ nil nil s₁).2 = (mapAccumr₂ f₂ nil nil s₂).2
case snoc
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs✝ ys✝ s₁).1 (mapAccumr₂ f₂ xs✝ ys✝ s₂).1 ∧
        (mapAccumr₂ f₁ xs✝ ys✝ s₁).2 = (mapAccumr₂ f₂ xs✝ ys✝ s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).1 (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).1 ∧
    (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).2 = (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).2

Next tactic:
next => exact ⟨h₀, rfl⟩
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  next => 

Proof state:
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ nil nil s₁).1 (mapAccumr₂ f₂ nil nil s₂).1 ∧
    (mapAccumr₂ f₁ nil nil s₁).2 = (mapAccumr₂ f₂ nil nil s₂).2

Next tactic:
exact ⟨h₀, rfl⟩
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  

Proof state:
case snoc
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs✝ ys✝ s₁).1 (mapAccumr₂ f₂ xs✝ ys✝ s₂).1 ∧
        (mapAccumr₂ f₁ xs✝ ys✝ s₁).2 = (mapAccumr₂ f₂ xs✝ ys✝ s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).1 (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).1 ∧
    (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).2 = (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).2

Next tactic:
next xs ys x y ih =>
    rcases (hR x y h₀) with ⟨hR, _⟩
    simp only [mapAccumr₂_snoc, ih hR, true_and]
    congr 1
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs ys x y ih =>
    

Proof state:
α : Type
n : ℕ
xs✝ : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1 ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).1 (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).1 ∧
    (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).2 = (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).2

Next tactic:
rcases (hR x y h₀) with ⟨hR, _⟩
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs ys x y ih =>
    rcases (hR x y h₀) with ⟨hR, _⟩
    

Proof state:
case intro
α : Type
n : ℕ
xs✝ : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR✝ : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1 ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x y s₁).1 (f₂ x y s₂).1
right✝ : (f₁ x y s₁).2 = (f₂ x y s₂).2
⊢ R (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).1 (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).1 ∧
    (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).2 = (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).2

Next tactic:
simp only [mapAccumr₂_snoc, ih hR, true_and]
theorem mapAccumr₂_bisim {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (R : σ₁ → σ₂ → Prop) (h₀ : R s₁ s₂)
    (hR :  ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1
    ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
  next => exact ⟨h₀, rfl⟩
  next xs ys x y ih =>
    rcases (hR x y h₀) with ⟨hR, _⟩
    simp only [mapAccumr₂_snoc, ih hR, true_and]
    

Proof state:
case intro
α : Type
n : ℕ
xs✝ : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR✝ : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).1 (mapAccumr₂ f₂ xs ys s₂).1 ∧ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x y s₁).1 (f₂ x y s₂).1
right✝ : (f₁ x y s₁).2 = (f₂ x y s₂).2
⊢ snoc (mapAccumr₂ f₂ xs ys (f₂ x y s₂).1).2 (f₁ x y s₁).2 = snoc (mapAccumr₂ f₂ xs ys (f₂ x y s₂).1).2 (f₂ x y s₂).2

Next tactic:
congr 1
theorem mapAccumr₂_bisim_tail {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (h : ∃ R : σ₁ → σ₂ → Prop, R s₁ s₂ ∧
      ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  

Proof state:
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
ys : Vector β n
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
s₁ : σ₁
s₂ : σ₂
h :
  ∃ R, R s₁ s₂ ∧ ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
⊢ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2

Next tactic:
rcases h with ⟨R, h₀, hR⟩
theorem mapAccumr₂_bisim_tail {ys : Vector β n} {f₁ : α → β → σ₁ → σ₁ × γ}
    {f₂ : α → β → σ₂ → σ₂ × γ} {s₁ : σ₁} {s₂ : σ₂}
    (h : ∃ R : σ₁ → σ₂ → Prop, R s₁ s₂ ∧
      ∀ {s q} a b, R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2) :
    (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2 := by
  rcases h with ⟨R, h₀, hR⟩
  

Proof state:
case intro.intro
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
ys : Vector β n
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
s₁ : σ₁
s₂ : σ₂
R : σ₁ → σ₂ → Prop
h₀ : R s₁ s₂
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).1 (f₂ a b q).1 ∧ (f₁ a b s).2 = (f₂ a b q).2
⊢ (mapAccumr₂ f₁ xs ys s₁).2 = (mapAccumr₂ f₂ xs ys s₂).2

Next tactic:
exact (mapAccumr₂_bisim R h₀ hR).2
protected theorem map_eq_mapAccumr :
    map f xs = (mapAccumr (fun x (_ : Unit) ↦ ((), f x)) xs ()).snd := by
  

Proof state:
α : Type u_2
n : ℕ
β : Type ?u.33592
xs : Vector α n
ys : Vector β n
α✝ : Type u_1
f : α → α✝
⊢ map f xs = (mapAccumr (fun x x_1 => ((), f x)) xs ()).2

Next tactic:
clear ys
protected theorem map_eq_mapAccumr :
    map f xs = (mapAccumr (fun x (_ : Unit) ↦ ((), f x)) xs ()).snd := by
  clear ys
  

Proof state:
α : Type u_2
n : ℕ
β : Type ?u.33592
xs : Vector α n
α✝ : Type u_1
f : α → α✝
⊢ map f xs = (mapAccumr (fun x x_1 => ((), f x)) xs ()).2

Next tactic:
induction xs using Vector.revInductionOn
protected theorem map_eq_mapAccumr :
    map f xs = (mapAccumr (fun x (_ : Unit) ↦ ((), f x)) xs ()).snd := by
  clear ys
  induction xs using Vector.revInductionOn <;> 

Proof state:
case nil
α : Type u_2
n : ℕ
β : Type ?u.33592
xs : Vector α n
α✝ : Type u_1
f : α → α✝
⊢ map f nil = (mapAccumr (fun x x_1 => ((), f x)) nil ()).2

Next tactic:
simp_all
protected theorem map_eq_mapAccumr :
    map f xs = (mapAccumr (fun x (_ : Unit) ↦ ((), f x)) xs ()).snd := by
  clear ys
  induction xs using Vector.revInductionOn <;> 

Proof state:
case snoc
α : Type u_2
n : ℕ
β : Type ?u.33592
xs : Vector α n
α✝ : Type u_1
f : α → α✝
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ : map f xs✝ = (mapAccumr (fun x x_1 => ((), f x)) xs✝ ()).2
⊢ map f (snoc xs✝ x✝) = (mapAccumr (fun x x_1 => ((), f x)) (snoc xs✝ x✝) ()).2

Next tactic:
simp_all
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr` into just `map`
-/
theorem mapAccumr_eq_map {f : α → σ → σ × β} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a s, s ∈ S → (f a s).1 ∈ S)
    (out : ∀ a s s', s ∈ S → s' ∈ S → (f a s).2 = (f a s').2) :
    (mapAccumr f xs s₀).snd = map (f · s₀ |>.snd) xs := by
  

Proof state:
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
f : α → σ → σ × β
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α), ∀ s ∈ S, (f a s).1 ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).2 = (f a s').2
⊢ (mapAccumr f xs s₀).2 = map (fun x => (f x s₀).2) xs

Next tactic:
rw[Vector.map_eq_mapAccumr]
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr` into just `map`
-/
theorem mapAccumr_eq_map {f : α → σ → σ × β} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a s, s ∈ S → (f a s).1 ∈ S)
    (out : ∀ a s s', s ∈ S → s' ∈ S → (f a s).2 = (f a s').2) :
    (mapAccumr f xs s₀).snd = map (f · s₀ |>.snd) xs := by
  rw[Vector.map_eq_mapAccumr]
  

Proof state:
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
f : α → σ → σ × β
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α), ∀ s ∈ S, (f a s).1 ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).2 = (f a s').2
⊢ (mapAccumr f xs s₀).2 = (mapAccumr (fun x x_1 => ((), (f x s₀).2)) xs ()).2

Next tactic:
apply mapAccumr_bisim_tail
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr` into just `map`
-/
theorem mapAccumr_eq_map {f : α → σ → σ × β} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a s, s ∈ S → (f a s).1 ∈ S)
    (out : ∀ a s s', s ∈ S → s' ∈ S → (f a s).2 = (f a s').2) :
    (mapAccumr f xs s₀).snd = map (f · s₀ |>.snd) xs := by
  rw[Vector.map_eq_mapAccumr]
  apply mapAccumr_bisim_tail
  

Proof state:
case h
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
f : α → σ → σ × β
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α), ∀ s ∈ S, (f a s).1 ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).2 = (f a s').2
⊢ ∃ R, R s₀ () ∧ ∀ {s : σ} {q : Unit} (a : α), R s q → R (f a s).1 ((), (f a s₀).2).1 ∧ (f a s).2 = ((), (f a s₀).2).2

Next tactic:
use fun s _ => s ∈ S, h₀
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr` into just `map`
-/
theorem mapAccumr_eq_map {f : α → σ → σ × β} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a s, s ∈ S → (f a s).1 ∈ S)
    (out : ∀ a s s', s ∈ S → s' ∈ S → (f a s).2 = (f a s').2) :
    (mapAccumr f xs s₀).snd = map (f · s₀ |>.snd) xs := by
  rw[Vector.map_eq_mapAccumr]
  apply mapAccumr_bisim_tail
  use fun s _ => s ∈ S, h₀
  

Proof state:
case right
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
f : α → σ → σ × β
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α), ∀ s ∈ S, (f a s).1 ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).2 = (f a s').2
⊢ ∀ {s : σ} {q : Unit} (a : α), s ∈ S → (f a s).1 ∈ S ∧ (f a s).2 = ((), (f a s₀).2).2

Next tactic:
exact @fun s _q a h => ⟨closure a s h, out a s s₀ h h₀⟩
protected theorem map₂_eq_mapAccumr₂ :
    map₂ f xs ys = (mapAccumr₂ (fun x y (_ : Unit) ↦ ((), f x y)) xs ys ()).snd := by
  

Proof state:
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
α✝ : Type
f : α → β → α✝
⊢ map₂ f xs ys = (mapAccumr₂ (fun x y x_1 => ((), f x y)) xs ys ()).2

Next tactic:
induction xs, ys using Vector.revInductionOn₂
protected theorem map₂_eq_mapAccumr₂ :
    map₂ f xs ys = (mapAccumr₂ (fun x y (_ : Unit) ↦ ((), f x y)) xs ys ()).snd := by
  induction xs, ys using Vector.revInductionOn₂ <;> 

Proof state:
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
α✝ : Type
f : α → β → α✝
⊢ map₂ f nil nil = (mapAccumr₂ (fun x y x_1 => ((), f x y)) nil nil ()).2

Next tactic:
simp_all
protected theorem map₂_eq_mapAccumr₂ :
    map₂ f xs ys = (mapAccumr₂ (fun x y (_ : Unit) ↦ ((), f x y)) xs ys ()).snd := by
  induction xs, ys using Vector.revInductionOn₂ <;> 

Proof state:
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
α✝ : Type
f : α → β → α✝
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : map₂ f xs✝ ys✝ = (mapAccumr₂ (fun x y x_1 => ((), f x y)) xs✝ ys✝ ()).2
⊢ map₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) = (mapAccumr₂ (fun x y x_1 => ((), f x y)) (snoc xs✝ x✝) (snoc ys✝ y✝) ()).2

Next tactic:
simp_all
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr₂` into just `map₂`
-/
theorem mapAccumr₂_eq_map₂ {f : α → β → σ → σ × γ} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a b s, s ∈ S → (f a b s).1 ∈ S)
    (out : ∀ a b s s', s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2) :
    (mapAccumr₂ f xs ys s₀).snd = map₂ (f · · s₀ |>.snd) xs ys := by
  

Proof state:
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β), ∀ s ∈ S, (f a b s).1 ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2
⊢ (mapAccumr₂ f xs ys s₀).2 = map₂ (fun x x_1 => (f x x_1 s₀).2) xs ys

Next tactic:
rw[Vector.map₂_eq_mapAccumr₂]
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr₂` into just `map₂`
-/
theorem mapAccumr₂_eq_map₂ {f : α → β → σ → σ × γ} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a b s, s ∈ S → (f a b s).1 ∈ S)
    (out : ∀ a b s s', s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2) :
    (mapAccumr₂ f xs ys s₀).snd = map₂ (f · · s₀ |>.snd) xs ys := by
  rw[Vector.map₂_eq_mapAccumr₂]
  

Proof state:
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β), ∀ s ∈ S, (f a b s).1 ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2
⊢ (mapAccumr₂ f xs ys s₀).2 = (mapAccumr₂ (fun x y x_1 => ((), (f x y s₀).2)) xs ys ()).2

Next tactic:
apply mapAccumr₂_bisim_tail
/--
  If there is a set of states that is closed under `f`, and such that `f` produces that same output
  for all states in this set, then the state is not actually needed.
  Hence, then we can rewrite `mapAccumr₂` into just `map₂`
-/
theorem mapAccumr₂_eq_map₂ {f : α → β → σ → σ × γ} {s₀ : σ} (S : Set σ) (h₀ : s₀ ∈ S)
    (closure : ∀ a b s, s ∈ S → (f a b s).1 ∈ S)
    (out : ∀ a b s s', s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2) :
    (mapAccumr₂ f xs ys s₀).snd = map₂ (f · · s₀ |>.snd) xs ys := by
  rw[Vector.map₂_eq_mapAccumr₂]
  apply mapAccumr₂_bisim_tail
  

Proof state:
case h
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β), ∀ s ∈ S, (f a b s).1 ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).2 = (f a b s').2
⊢ ∃ R,
    R s₀ () ∧
      ∀ {s : σ} {q : Unit} (a : α) (b : β),
        R s q → R (f a b s).1 ((), (f a b s₀).2).1 ∧ (f a b s).2 = ((), (f a b s₀).2).2

Next tactic:
use fun s _ => s ∈ S, h₀