[GOAL]
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr f₁ (mapAccumr f₂ xs s₂).snd s₁ =
    let m :=
      mapAccumr
        (fun x s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        xs (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs using Vector.revInductionOn generalizing s₁ s₂
[GOAL]
case nil
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr f₁ (mapAccumr f₂ nil s₂).snd s₁ =
    let m :=
      mapAccumr
        (fun x s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr f₁ (mapAccumr f₂ xs✝ s₂).snd s₁ =
      let m :=
        mapAccumr
          (fun x s =>
            let r₂ := f₂ x s.snd;
            let r₁ := f₁ r₂.snd s.fst;
            ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr f₁ (mapAccumr f₂ (snoc xs✝ x✝) s₂).snd s₁ =
    let m :=
      mapAccumr
        (fun x s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type ?u.3222
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
s : σ₁
f₂ : α → β
⊢ mapAccumr f₁ (map f₂ xs) s = mapAccumr (fun x s => f₁ (f₂ x) s) xs s
[PROOFSTEP]
induction xs using Vector.revInductionOn generalizing s
[GOAL]
case nil
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type ?u.3222
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
f₂ : α → β
s : σ₁
⊢ mapAccumr f₁ (map f₂ nil) s = mapAccumr (fun x s => f₁ (f₂ x) s) nil s
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type
γ : Type u_1
σ₂ : Type ?u.3222
xs : Vector α n
f₁ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
f₂ : α → β
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ : ∀ {s : σ₁}, mapAccumr f₁ (map f₂ xs✝) s = mapAccumr (fun x s => f₁ (f₂ x) s) xs✝ s
s : σ₁
⊢ mapAccumr f₁ (map f₂ (snoc xs✝ x✝)) s = mapAccumr (fun x s => f₁ (f₂ x) s) (snoc xs✝ x✝) s
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.4482
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
s : σ₂
f₁ : β → γ
⊢ map f₁ (mapAccumr f₂ xs s).snd =
    (mapAccumr
        (fun x s =>
          let r := f₂ x s;
          (r.fst, f₁ r.snd))
        xs s).snd
[PROOFSTEP]
induction xs using Vector.revInductionOn generalizing s
[GOAL]
case nil
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.4482
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
f₁ : β → γ
s : σ₂
⊢ map f₁ (mapAccumr f₂ nil s).snd =
    (mapAccumr
        (fun x s =>
          let r := f₂ x s;
          (r.fst, f₁ r.snd))
        nil s).snd
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.4482
γ : Type u_1
σ₂ : Type
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂ : α → σ₂ → σ₂ × β
f₁ : β → γ
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ :
  ∀ {s : σ₂},
    map f₁ (mapAccumr f₂ xs✝ s).snd =
      (mapAccumr
          (fun x s =>
            let r := f₂ x s;
            (r.fst, f₁ r.snd))
          xs✝ s).snd
s : σ₂
⊢ map f₁ (mapAccumr f₂ (snoc xs✝ x✝) s).snd =
    (mapAccumr
        (fun x s =>
          let r := f₂ x s;
          (r.fst, f₁ r.snd))
        (snoc xs✝ x✝) s).snd
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.6822
γ : Type u_1
σ₂ : Type ?u.6830
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
f₁ : β → γ
f₂ : α → β
⊢ map f₁ (map f₂ xs) = map (fun x => f₁ (f₂ x)) xs
[PROOFSTEP]
induction xs using Vector.inductionOn
[GOAL]
case h_nil
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.6822
γ : Type u_1
σ₂ : Type ?u.6830
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
f₁ : β → γ
f₂ : α → β
⊢ map f₁ (map f₂ nil) = map (fun x => f₁ (f₂ x)) nil
[PROOFSTEP]
simp_all
[GOAL]
case h_cons
α : Type u_3
n : ℕ
β : Type u_2
σ₁ : Type ?u.6822
γ : Type u_1
σ₂ : Type ?u.6830
xs : Vector α n
f₁✝ : β → σ₁ → σ₁ × γ
f₂✝ : α → σ₂ → σ₂ × β
f₁ : β → γ
f₂ : α → β
n✝ : ℕ
x✝ : α
w✝ : Vector α n✝
a✝ : map f₁ (map f₂ w✝) = map (fun x => f₁ (f₂ x)) w✝
⊢ map f₁ (map f₂ (x✝ ::ᵥ w✝)) = map (fun x => f₁ (f₂ x)) (x✝ ::ᵥ w✝)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : γ → β → σ₁ → σ₁ × ζ
f₂ : α → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ (mapAccumr f₂ xs s₂).snd ys s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd y s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : γ → β → σ₁ → σ₁ × ζ
f₂ : α → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr f₂ nil s₂).snd nil s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd y s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : γ → β → σ₁ → σ₁ × ζ
f₂ : α → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ (mapAccumr f₂ xs✝ s₂).snd ys✝ s₁ =
      let m :=
        mapAccumr₂
          (fun x y s =>
            let r₂ := f₂ x s.snd;
            let r₁ := f₁ r₂.snd y s.fst;
            ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr f₂ (snoc xs✝ x✝) s₂).snd (snoc ys✝ y✝) s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x s.snd;
          let r₁ := f₁ r₂.snd y s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_4
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → β → ζ
f₂ : α → γ
⊢ map₂ f₁ (map f₂ xs) ys = map₂ (fun x y => f₁ (f₂ x) y) xs ys
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂
[GOAL]
case nil
α : Type u_4
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → β → ζ
f₂ : α → γ
⊢ map₂ f₁ (map f₂ nil) nil = map₂ (fun x y => f₁ (f₂ x) y) nil nil
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_4
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → β → ζ
f₂ : α → γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : map₂ f₁ (map f₂ xs✝) ys✝ = map₂ (fun x y => f₁ (f₂ x) y) xs✝ ys✝
⊢ map₂ f₁ (map f₂ (snoc xs✝ x✝)) (snoc ys✝ y✝) = map₂ (fun x y => f₁ (f₂ x) y) (snoc xs✝ x✝) (snoc ys✝ y✝)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : α → γ → σ₁ → σ₁ × ζ
f₂ : β → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ xs (mapAccumr f₂ ys s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ y s.snd;
          let r₁ := f₁ x r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : α → γ → σ₁ → σ₁ × ζ
f₂ : β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ nil (mapAccumr f₂ nil s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ y s.snd;
          let r₁ := f₁ x r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : α → γ → σ₁ → σ₁ × ζ
f₂ : β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ xs✝ (mapAccumr f₂ ys✝ s₂).snd s₁ =
      let m :=
        mapAccumr₂
          (fun x y s =>
            let r₂ := f₂ y s.snd;
            let r₁ := f₁ x r₂.snd s.fst;
            ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (snoc xs✝ x✝) (mapAccumr f₂ (snoc ys✝ y✝) s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ y s.snd;
          let r₁ := f₁ x r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : α → γ → ζ
f₂ : β → γ
⊢ map₂ f₁ xs (map f₂ ys) = map₂ (fun x y => f₁ x (f₂ y)) xs ys
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂
[GOAL]
case nil
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : α → γ → ζ
f₂ : β → γ
⊢ map₂ f₁ nil (map f₂ nil) = map₂ (fun x y => f₁ x (f₂ y)) nil nil
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : α → γ → ζ
f₂ : β → γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : map₂ f₁ xs✝ (map f₂ ys✝) = map₂ (fun x y => f₁ x (f₂ y)) xs✝ ys✝
⊢ map₂ f₁ (snoc xs✝ x✝) (map f₂ (snoc ys✝ y✝)) = map₂ (fun x y => f₁ x (f₂ y)) (snoc xs✝ x✝) (snoc ys✝ y✝)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : γ → σ₁ → σ₁ × ζ
f₂ : α → β → σ₂ → σ₂ × γ
⊢ mapAccumr f₁ (mapAccumr₂ f₂ xs ys s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x y s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : γ → σ₁ → σ₁ × ζ
f₂ : α → β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr f₁ (mapAccumr₂ f₂ nil nil s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x y s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ ζ σ₂ : Type
f₁ : γ → σ₁ → σ₁ × ζ
f₂ : α → β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr f₁ (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd s₁ =
      let m :=
        mapAccumr₂
          (fun x y s =>
            let r₂ := f₂ x y s.snd;
            let r₁ := f₁ r₂.snd s.fst;
            ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr f₁ (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y s =>
          let r₂ := f₂ x y s.snd;
          let r₁ := f₁ r₂.snd s.fst;
          ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → ζ
f₂ : α → β → γ
⊢ map f₁ (map₂ f₂ xs ys) = map₂ (fun x y => f₁ (f₂ x y)) xs ys
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂
[GOAL]
case nil
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → ζ
f₂ : α → β → γ
⊢ map f₁ (map₂ f₂ nil nil) = map₂ (fun x y => f₁ (f₂ x y)) nil nil
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_3
n : ℕ
β : Type u_4
xs : Vector α n
ys : Vector β n
γ : Type u_1
ζ : Type u_2
f₁ : γ → ζ
f₂ : α → β → γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : map f₁ (map₂ f₂ xs✝ ys✝) = map₂ (fun x y => f₁ (f₂ x y)) xs✝ ys✝
⊢ map f₁ (map₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝)) = map₂ (fun x y => f₁ (f₂ x y)) (snoc xs✝ x✝) (snoc ys✝ y✝)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : γ → α → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ xs ys s₂).snd xs s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd x s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : γ → α → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ nil nil s₂).snd nil s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd x s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : γ → α → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd xs✝ s₁ =
      let m :=
        mapAccumr₂
          (fun x y x_1 =>
            match x_1 with
            | (s₁, s₂) =>
              let r₂ := f₂ x y s₂;
              let r₁ := f₁ r₂.snd x s₁;
              ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd (snoc xs✝ x✝) s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd x s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : γ → β → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ xs ys s₂).snd ys s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd y s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : γ → β → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ nil nil s₂).snd nil s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd y s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : γ → β → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd ys✝ s₁ =
      let m :=
        mapAccumr₂
          (fun x y x_1 =>
            match x_1 with
            | (s₁, s₂) =>
              let r₂ := f₂ x y s₂;
              let r₁ := f₁ r₂.snd y s₁;
              ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd (snoc ys✝ y✝) s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ r₂.snd y s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : α → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ xs (mapAccumr₂ f₂ xs ys s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ x r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : α → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ nil (mapAccumr₂ f₂ nil nil s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ x r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : α → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ xs✝ (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd s₁ =
      let m :=
        mapAccumr₂
          (fun x y x_1 =>
            match x_1 with
            | (s₁, s₂) =>
              let r₂ := f₂ x y s₂;
              let r₁ := f₁ x r₂.snd s₁;
              ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (snoc xs✝ x✝) (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ x r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
s₂ : σ₂
s₁ : σ₁
f₁ : β → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
⊢ mapAccumr₂ f₁ ys (mapAccumr₂ f₂ xs ys s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ y r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        xs ys (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : β → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ nil (mapAccumr₂ f₂ nil nil s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ y r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        nil nil (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
γ σ₁ φ σ₂ : Type
f₁ : β → γ → σ₁ → σ₁ × φ
f₂ : α → β → σ₂ → σ₂ × γ
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₂ : σ₂} {s₁ : σ₁},
    mapAccumr₂ f₁ ys✝ (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd s₁ =
      let m :=
        mapAccumr₂
          (fun x y x_1 =>
            match x_1 with
            | (s₁, s₂) =>
              let r₂ := f₂ x y s₂;
              let r₁ := f₁ y r₂.snd s₁;
              ((r₁.fst, r₂.fst), r₁.snd))
          xs✝ ys✝ (s₁, s₂);
      (m.fst.fst, m.snd)
s₂ : σ₂
s₁ : σ₁
⊢ mapAccumr₂ f₁ (snoc ys✝ y✝) (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd s₁ =
    let m :=
      mapAccumr₂
        (fun x y x_1 =>
          match x_1 with
          | (s₁, s₂) =>
            let r₂ := f₂ x y s₂;
            let r₁ := f₁ y r₂.snd s₁;
            ((r₁.fst, r₂.fst), r₁.snd))
        (snoc xs✝ x✝) (snoc ys✝ y✝) (s₁, s₂);
    (m.fst.fst, m.snd)
[PROOFSTEP]
simp_all
[GOAL]
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
⊢ R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
[PROOFSTEP]
induction xs using Vector.revInductionOn generalizing s₁ s₂
[GOAL]
case nil
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ nil s₁).fst (mapAccumr f₂ nil s₂).fst ∧ (mapAccumr f₁ nil s₁).snd = (mapAccumr f₂ nil s₂).snd
case snoc
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr f₁ xs✝ s₁).fst (mapAccumr f₂ xs✝ s₂).fst ∧ (mapAccumr f₁ xs✝ s₁).snd = (mapAccumr f₂ xs✝ s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ (snoc xs✝ x✝) s₁).fst (mapAccumr f₂ (snoc xs✝ x✝) s₂).fst ∧
    (mapAccumr f₁ (snoc xs✝ x✝) s₁).snd = (mapAccumr f₂ (snoc xs✝ x✝) s₂).snd
[PROOFSTEP]
next => exact ⟨h₀, rfl⟩
[GOAL]
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ nil s₁).fst (mapAccumr f₂ nil s₂).fst ∧ (mapAccumr f₁ nil s₁).snd = (mapAccumr f₂ nil s₂).snd
[PROOFSTEP]
exact ⟨h₀, rfl⟩
[GOAL]
case snoc
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr f₁ xs✝ s₁).fst (mapAccumr f₂ xs✝ s₂).fst ∧ (mapAccumr f₁ xs✝ s₁).snd = (mapAccumr f₂ xs✝ s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ (snoc xs✝ x✝) s₁).fst (mapAccumr f₂ (snoc xs✝ x✝) s₂).fst ∧
    (mapAccumr f₁ (snoc xs✝ x✝) s₁).snd = (mapAccumr f₂ (snoc xs✝ x✝) s₂).snd
[PROOFSTEP]
next xs x ih =>
  rcases(hR x h₀) with ⟨hR, _⟩
  simp only [mapAccumr_snoc, ih hR, true_and]
  congr 1
[GOAL]
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr f₁ (snoc xs x) s₁).fst (mapAccumr f₂ (snoc xs x) s₂).fst ∧
    (mapAccumr f₁ (snoc xs x) s₁).snd = (mapAccumr f₂ (snoc xs x) s₂).snd
[PROOFSTEP]
rcases(hR x h₀) with ⟨hR, _⟩
[GOAL]
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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x s₁).fst (f₂ x s₂).fst
right✝ : (f₁ x s₁).snd = (f₂ x s₂).snd
⊢ R (mapAccumr f₁ (snoc xs x) s₁).fst (mapAccumr f₂ (snoc xs x) s₂).fst ∧
    (mapAccumr f₁ (snoc xs x) s₁).snd = (mapAccumr f₂ (snoc xs x) s₂).snd
[PROOFSTEP]
simp only [mapAccumr_snoc, ih hR, true_and]
[GOAL]
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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
n✝ : ℕ
xs : Vector α n✝
x : α
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ → R (mapAccumr f₁ xs s₁).fst (mapAccumr f₂ xs s₂).fst ∧ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x s₁).fst (f₂ x s₂).fst
right✝ : (f₁ x s₁).snd = (f₂ x s₂).snd
⊢ snoc (mapAccumr f₂ xs (f₂ x s₂).fst).snd (f₁ x s₁).snd = snoc (mapAccumr f₂ xs (f₂ x s₂).fst).snd (f₂ x s₂).snd
[PROOFSTEP]
congr 1
[GOAL]
α : 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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
⊢ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
[PROOFSTEP]
rcases h with ⟨R, h₀, hR⟩
[GOAL]
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).fst (f₂ a q).fst ∧ (f₁ a s).snd = (f₂ a q).snd
⊢ (mapAccumr f₁ xs s₁).snd = (mapAccumr f₂ xs s₂).snd
[PROOFSTEP]
exact (mapAccumr_bisim R h₀ hR).2
[GOAL]
α : 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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
⊢ R (mapAccumr₂ f₁ xs ys s₁).fst (mapAccumr₂ f₂ xs ys s₂).fst ∧
    (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s₁ s₂
[GOAL]
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ nil nil s₁).fst (mapAccumr₂ f₂ nil nil s₂).fst ∧
    (mapAccumr₂ f₁ nil nil s₁).snd = (mapAccumr₂ f₂ nil nil s₂).snd
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs✝ ys✝ s₁).fst (mapAccumr₂ f₂ xs✝ ys✝ s₂).fst ∧
        (mapAccumr₂ f₁ xs✝ ys✝ s₁).snd = (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).fst (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).fst ∧
    (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).snd = (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd
[PROOFSTEP]
next => exact ⟨h₀, rfl⟩
[GOAL]
α : Type
n : ℕ
xs : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ nil nil s₁).fst (mapAccumr₂ f₂ nil nil s₂).fst ∧
    (mapAccumr₂ f₁ nil nil s₁).snd = (mapAccumr₂ f₂ nil nil s₂).snd
[PROOFSTEP]
exact ⟨h₀, rfl⟩
[GOAL]
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs✝ ys✝ s₁).fst (mapAccumr₂ f₂ xs✝ ys✝ s₂).fst ∧
        (mapAccumr₂ f₁ xs✝ ys✝ s₁).snd = (mapAccumr₂ f₂ xs✝ ys✝ s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).fst (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).fst ∧
    (mapAccumr₂ f₁ (snoc xs✝ x✝) (snoc ys✝ y✝) s₁).snd = (mapAccumr₂ f₂ (snoc xs✝ x✝) (snoc ys✝ y✝) s₂).snd
[PROOFSTEP]
next xs ys x y ih =>
  rcases(hR x y h₀) with ⟨hR, _⟩
  simp only [mapAccumr₂_snoc, ih hR, true_and]
  congr 1
[GOAL]
α : Type
n : ℕ
xs✝ : Vector α n
β σ₁ γ σ₂ : Type
f₁ : α → β → σ₁ → σ₁ × γ
f₂ : α → β → σ₂ → σ₂ × γ
R : σ₁ → σ₂ → Prop
hR : ∀ {s : σ₁} {q : σ₂} (a : α) (b : β), R s q → R (f₁ a b s).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).fst (mapAccumr₂ f₂ xs ys s₂).fst ∧
        (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
⊢ R (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).fst (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).fst ∧
    (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).snd = (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).snd
[PROOFSTEP]
rcases(hR x y h₀) with ⟨hR, _⟩
[GOAL]
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).fst (mapAccumr₂ f₂ xs ys s₂).fst ∧
        (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x y s₁).fst (f₂ x y s₂).fst
right✝ : (f₁ x y s₁).snd = (f₂ x y s₂).snd
⊢ R (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).fst (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).fst ∧
    (mapAccumr₂ f₁ (snoc xs x) (snoc ys y) s₁).snd = (mapAccumr₂ f₂ (snoc xs x) (snoc ys y) s₂).snd
[PROOFSTEP]
simp only [mapAccumr₂_snoc, ih hR, true_and]
[GOAL]
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih :
  ∀ {s₁ : σ₁} {s₂ : σ₂},
    R s₁ s₂ →
      R (mapAccumr₂ f₁ xs ys s₁).fst (mapAccumr₂ f₂ xs ys s₂).fst ∧
        (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
s₁ : σ₁
s₂ : σ₂
h₀ : R s₁ s₂
hR : R (f₁ x y s₁).fst (f₂ x y s₂).fst
right✝ : (f₁ x y s₁).snd = (f₂ x y s₂).snd
⊢ snoc (mapAccumr₂ f₂ xs ys (f₂ x y s₂).fst).snd (f₁ x y s₁).snd =
    snoc (mapAccumr₂ f₂ xs ys (f₂ x y s₂).fst).snd (f₂ x y s₂).snd
[PROOFSTEP]
congr 1
[GOAL]
α : 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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
⊢ (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
[PROOFSTEP]
rcases h with ⟨R, h₀, hR⟩
[GOAL]
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).fst (f₂ a b q).fst ∧ (f₁ a b s).snd = (f₂ a b q).snd
⊢ (mapAccumr₂ f₁ xs ys s₁).snd = (mapAccumr₂ f₂ xs ys s₂).snd
[PROOFSTEP]
exact (mapAccumr₂_bisim R h₀ hR).2
[GOAL]
α : Type u_2
n : ℕ
β : Type ?u.34261
xs : Vector α n
ys : Vector β n
α✝ : Type u_1
f : α → α✝
⊢ map f xs = (mapAccumr (fun x x_1 => ((), f x)) xs ()).snd
[PROOFSTEP]
clear ys
[GOAL]
α : Type u_2
n : ℕ
β : Type ?u.34261
xs : Vector α n
α✝ : Type u_1
f : α → α✝
⊢ map f xs = (mapAccumr (fun x x_1 => ((), f x)) xs ()).snd
[PROOFSTEP]
induction xs using Vector.revInductionOn
[GOAL]
case nil
α : Type u_2
n : ℕ
β : Type ?u.34261
xs : Vector α n
α✝ : Type u_1
f : α → α✝
⊢ map f nil = (mapAccumr (fun x x_1 => ((), f x)) nil ()).snd
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_2
n : ℕ
β : Type ?u.34261
xs : Vector α n
α✝ : Type u_1
f : α → α✝
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ : map f xs✝ = (mapAccumr (fun x x_1 => ((), f x)) xs✝ ()).snd
⊢ map f (snoc xs✝ x✝) = (mapAccumr (fun x x_1 => ((), f x)) (snoc xs✝ x✝) ()).snd
[PROOFSTEP]
simp_all
[GOAL]
α : 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 ∈ S → (f a s).fst ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).snd = (f a s').snd
⊢ (mapAccumr f xs s₀).snd = map (fun x => (f x s₀).snd) xs
[PROOFSTEP]
rw [Vector.map_eq_mapAccumr]
[GOAL]
α : 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 ∈ S → (f a s).fst ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).snd = (f a s').snd
⊢ (mapAccumr f xs s₀).snd = (mapAccumr (fun x x_1 => ((), (f x s₀).snd)) xs ()).snd
[PROOFSTEP]
apply mapAccumr_bisim_tail
[GOAL]
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 ∈ S → (f a s).fst ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).snd = (f a s').snd
⊢ ∃ R,
    R s₀ () ∧
      ∀ {s : σ} {q : Unit} (a : α), R s q → R (f a s).fst ((), (f a s₀).snd).fst ∧ (f a s).snd = ((), (f a s₀).snd).snd
[PROOFSTEP]
use fun s _ => s ∈ S, h₀
[GOAL]
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 ∈ S → (f a s).fst ∈ S
out : ∀ (a : α) (s s' : σ), s ∈ S → s' ∈ S → (f a s).snd = (f a s').snd
⊢ ∀ {s : σ} {q : Unit} (a : α), s ∈ S → (f a s).fst ∈ S ∧ (f a s).snd = ((), (f a s₀).snd).snd
[PROOFSTEP]
exact @fun s _q a h => ⟨closure a s h, out a s s₀ h h₀⟩
[GOAL]
α : 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 ()).snd
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂
[GOAL]
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 ()).snd
[PROOFSTEP]
simp_all
[GOAL]
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✝ ()).snd
⊢ map₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) = (mapAccumr₂ (fun x y x_1 => ((), f x y)) (snoc xs✝ x✝) (snoc ys✝ y✝) ()).snd
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β) (s : σ), s ∈ S → (f a b s).fst ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).snd = (f a b s').snd
⊢ (mapAccumr₂ f xs ys s₀).snd = map₂ (fun x x_1 => (f x x_1 s₀).snd) xs ys
[PROOFSTEP]
rw [Vector.map₂_eq_mapAccumr₂]
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β) (s : σ), s ∈ S → (f a b s).fst ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).snd = (f a b s').snd
⊢ (mapAccumr₂ f xs ys s₀).snd = (mapAccumr₂ (fun x y x_1 => ((), (f x y s₀).snd)) xs ys ()).snd
[PROOFSTEP]
apply mapAccumr₂_bisim_tail
[GOAL]
case h
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β) (s : σ), s ∈ S → (f a b s).fst ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).snd = (f a b s').snd
⊢ ∃ R,
    R s₀ () ∧
      ∀ {s : σ} {q : Unit} (a : α) (b : β),
        R s q → R (f a b s).fst ((), (f a b s₀).snd).fst ∧ (f a b s).snd = ((), (f a b s₀).snd).snd
[PROOFSTEP]
use fun s _ => s ∈ S, h₀
[GOAL]
case right
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s₀ : σ
S : Set σ
h₀ : s₀ ∈ S
closure : ∀ (a : α) (b : β) (s : σ), s ∈ S → (f a b s).fst ∈ S
out : ∀ (a : α) (b : β) (s s' : σ), s ∈ S → s' ∈ S → (f a b s).snd = (f a b s').snd
⊢ ∀ {s : σ} {q : Unit} (a : α) (b : β), s ∈ S → (f a b s).fst ∈ S ∧ (f a b s).snd = ((), (f a b s₀).snd).snd
[PROOFSTEP]
exact @fun s _q a b h => ⟨closure a b s h, out a b s s₀ h h₀⟩
[GOAL]
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
f : α → σ → σ × β
s : σ
h : ∀ (a : α), (f a s).fst = s
⊢ mapAccumr f xs s = (s, map (fun x => (f x s).snd) xs)
[PROOFSTEP]
clear ys
[GOAL]
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
σ : Type
f : α → σ → σ × β
s : σ
h : ∀ (a : α), (f a s).fst = s
⊢ mapAccumr f xs s = (s, map (fun x => (f x s).snd) xs)
[PROOFSTEP]
induction xs using revInductionOn
[GOAL]
case nil
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
σ : Type
f : α → σ → σ × β
s : σ
h : ∀ (a : α), (f a s).fst = s
⊢ mapAccumr f nil s = (s, map (fun x => (f x s).snd) nil)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
σ : Type
f : α → σ → σ × β
s : σ
h : ∀ (a : α), (f a s).fst = s
n✝ : ℕ
xs✝ : Vector α n✝
x✝ : α
a✝ : mapAccumr f xs✝ s = (s, map (fun x => (f x s).snd) xs✝)
⊢ mapAccumr f (snoc xs✝ x✝) s = (s, map (fun x => (f x s).snd) (snoc xs✝ x✝))
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s : σ
h : ∀ (a : α) (b : β), (f a b s).fst = s
⊢ mapAccumr₂ f xs ys s = (s, map₂ (fun x y => (f x y s).snd) xs ys)
[PROOFSTEP]
induction xs, ys using revInductionOn₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s : σ
h : ∀ (a : α) (b : β), (f a b s).fst = s
⊢ mapAccumr₂ f nil nil s = (s, map₂ (fun x y => (f x y s).snd) nil nil)
[PROOFSTEP]
simp_all
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
f : α → β → σ → σ × γ
s : σ
h : ∀ (a : α) (b : β), (f a b s).fst = s
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : mapAccumr₂ f xs✝ ys✝ s = (s, map₂ (fun x y => (f x y s).snd) xs✝ ys✝)
⊢ mapAccumr₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) s = (s, map₂ (fun x y => (f x y s).snd) (snoc xs✝ x✝) (snoc ys✝ y✝))
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
s : σ
f : α → σ × σ → (σ × σ) × β
h : ∀ (x : α) (s : σ), (f x (s, s)).fst.fst = (f x (s, s)).fst.snd
⊢ ∃ R,
    R (s, s) s ∧
      ∀ {s : σ × σ} {q : σ} (a : α),
        R s q →
          R (f a s).fst ((f a (q, q)).fst.fst, (f a (q, q)).snd).fst ∧
            (f a s).snd = ((f a (q, q)).fst.fst, (f a (q, q)).snd).snd
[PROOFSTEP]
use fun (s₁, s₂) s => s₂ = s ∧ s₁ = s
[GOAL]
case h
α : Type u_2
n : ℕ
β : Type u_1
xs : Vector α n
ys : Vector β n
σ : Type
s : σ
f : α → σ × σ → (σ × σ) × β
h : ∀ (x : α) (s : σ), (f x (s, s)).fst.fst = (f x (s, s)).fst.snd
⊢ (match (s, s) with
    | (s₁, s₂) => s₂ = s ∧ s₁ = s) ∧
    ∀ {s : σ × σ} {q : σ} (a : α),
      (match s with
        | (s₁, s₂) => s₂ = q ∧ s₁ = q) →
        (match (f a s).fst with
          | (s₁, s₂) =>
            s₂ = ((f a (q, q)).fst.fst, (f a (q, q)).snd).fst ∧ s₁ = ((f a (q, q)).fst.fst, (f a (q, q)).snd).fst) ∧
          (f a s).snd = ((f a (q, q)).fst.fst, (f a (q, q)).snd).snd
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
f : α → β → σ × σ → (σ × σ) × γ
h :
  ∀ (x : α) (y : β) (s : σ),
    let s' := (f x y (s, s)).fst;
    s'.fst = s'.snd
⊢ ∃ R,
    R (s, s) s ∧
      ∀ {s : σ × σ} {q : σ} (a : α) (b : β),
        R s q →
          R (f a b s).fst ((f a b (q, q)).fst.fst, (f a b (q, q)).snd).fst ∧
            (f a b s).snd = ((f a b (q, q)).fst.fst, (f a b (q, q)).snd).snd
[PROOFSTEP]
use fun (s₁, s₂) s => s₂ = s ∧ s₁ = s
[GOAL]
case h
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
f : α → β → σ × σ → (σ × σ) × γ
h :
  ∀ (x : α) (y : β) (s : σ),
    let s' := (f x y (s, s)).fst;
    s'.fst = s'.snd
⊢ (match (s, s) with
    | (s₁, s₂) => s₂ = s ∧ s₁ = s) ∧
    ∀ {s : σ × σ} {q : σ} (a : α) (b : β),
      (match s with
        | (s₁, s₂) => s₂ = q ∧ s₁ = q) →
        (match (f a b s).fst with
          | (s₁, s₂) =>
            s₂ = ((f a b (q, q)).fst.fst, (f a b (q, q)).snd).fst ∧
              s₁ = ((f a b (q, q)).fst.fst, (f a b (q, q)).snd).fst) ∧
          (f a b s).snd = ((f a b (q, q)).fst.fst, (f a b (q, q)).snd).snd
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
⊢ mapAccumr₂ f xs ys s = mapAccumr (fun b s => f default b s) ys s
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun b s => f default b s) nil s
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : ∀ {s : σ}, mapAccumr₂ f xs✝ ys✝ s = mapAccumr (fun b s => f default b s) ys✝ s
s : σ
⊢ mapAccumr₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) s = mapAccumr (fun b s => f default b s) (snoc ys✝ y✝) s
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun b s => f default b s) nil s
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun b s => f default b s) nil s
[PROOFSTEP]
rfl
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : ∀ {s : σ}, mapAccumr₂ f xs✝ ys✝ s = mapAccumr (fun b s => f default b s) ys✝ s
s : σ
⊢ mapAccumr₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) s = mapAccumr (fun b s => f default b s) (snoc ys✝ y✝) s
[PROOFSTEP]
case snoc xs ys x y ih => simp [h x y s, ih]
[GOAL]
α : Type
n : ℕ
β : Type
xs✝ : Vector α n
ys✝ : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih : ∀ {s : σ}, mapAccumr₂ f xs ys s = mapAccumr (fun b s => f default b s) ys s
s : σ
⊢ mapAccumr₂ f (snoc xs x) (snoc ys y) s = mapAccumr (fun b s => f default b s) (snoc ys y) s
[PROOFSTEP]
case snoc xs ys x y ih => simp [h x y s, ih]
[GOAL]
α : Type
n : ℕ
β : Type
xs✝ : Vector α n
ys✝ : Vector β n
σ γ : Type
inst✝ : Inhabited α
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f default b s = f a b s
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih : ∀ {s : σ}, mapAccumr₂ f xs ys s = mapAccumr (fun b s => f default b s) ys s
s : σ
⊢ mapAccumr₂ f (snoc xs x) (snoc ys y) s = mapAccumr (fun b s => f default b s) (snoc ys y) s
[PROOFSTEP]
simp [h x y s, ih]
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
⊢ mapAccumr₂ f xs ys s = mapAccumr (fun a s => f a default s) xs s
[PROOFSTEP]
induction xs, ys using Vector.revInductionOn₂ generalizing s
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun a s => f a default s) nil s
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : ∀ {s : σ}, mapAccumr₂ f xs✝ ys✝ s = mapAccumr (fun a s => f a default s) xs✝ s
s : σ
⊢ mapAccumr₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) s = mapAccumr (fun a s => f a default s) (snoc xs✝ x✝) s
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun a s => f a default s) nil s
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr (fun a s => f a default s) nil s
[PROOFSTEP]
rfl
[GOAL]
case snoc
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
n✝ : ℕ
xs✝ : Vector α n✝
ys✝ : Vector β n✝
x✝ : α
y✝ : β
a✝ : ∀ {s : σ}, mapAccumr₂ f xs✝ ys✝ s = mapAccumr (fun a s => f a default s) xs✝ s
s : σ
⊢ mapAccumr₂ f (snoc xs✝ x✝) (snoc ys✝ y✝) s = mapAccumr (fun a s => f a default s) (snoc xs✝ x✝) s
[PROOFSTEP]
case snoc xs ys x y ih => simp [h x y s, ih]
[GOAL]
α : Type
n : ℕ
β : Type
xs✝ : Vector α n
ys✝ : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih : ∀ {s : σ}, mapAccumr₂ f xs ys s = mapAccumr (fun a s => f a default s) xs s
s : σ
⊢ mapAccumr₂ f (snoc xs x) (snoc ys y) s = mapAccumr (fun a s => f a default s) (snoc xs x) s
[PROOFSTEP]
case snoc xs ys x y ih => simp [h x y s, ih]
[GOAL]
α : Type
n : ℕ
β : Type
xs✝ : Vector α n
ys✝ : Vector β n
σ γ : Type
inst✝ : Inhabited β
f : α → β → σ → σ × γ
h : ∀ (a : α) (b : β) (s : σ), f a default s = f a b s
n✝ : ℕ
xs : Vector α n✝
ys : Vector β n✝
x : α
y : β
ih : ∀ {s : σ}, mapAccumr₂ f xs ys s = mapAccumr (fun a s => f a default s) xs s
s : σ
⊢ mapAccumr₂ f (snoc xs x) (snoc ys y) s = mapAccumr (fun a s => f a default s) (snoc xs x) s
[PROOFSTEP]
simp [h x y s, ih]
[GOAL]
α : Type u_2
n : ℕ
xs ys : Vector α n
β : Type u_1
f : α → α → β
comm : ∀ (a₁ a₂ : α), f a₁ a₂ = f a₂ a₁
⊢ map₂ f xs ys = map₂ f ys xs
[PROOFSTEP]
induction xs, ys using Vector.inductionOn₂
[GOAL]
case nil
α : Type u_2
n : ℕ
xs ys : Vector α n
β : Type u_1
f : α → α → β
comm : ∀ (a₁ a₂ : α), f a₁ a₂ = f a₂ a₁
⊢ map₂ f nil nil = map₂ f nil nil
[PROOFSTEP]
simp_all
[GOAL]
case cons
α : Type u_2
n : ℕ
xs ys : Vector α n
β : Type u_1
f : α → α → β
comm : ∀ (a₁ a₂ : α), f a₁ a₂ = f a₂ a₁
n✝ : ℕ
a✝¹ b✝ : α
x✝ y✝ : Vector α n✝
a✝ : map₂ f x✝ y✝ = map₂ f y✝ x✝
⊢ map₂ f (a✝¹ ::ᵥ x✝) (b✝ ::ᵥ y✝) = map₂ f (b✝ ::ᵥ y✝) (a✝¹ ::ᵥ x✝)
[PROOFSTEP]
simp_all
[GOAL]
α : Type
n : ℕ
xs ys : Vector α n
σ γ : Type
s : σ
f : α → α → σ → σ × γ
comm : ∀ (a₁ a₂ : α) (s : σ), f a₁ a₂ s = f a₂ a₁ s
⊢ mapAccumr₂ f xs ys s = mapAccumr₂ f ys xs s
[PROOFSTEP]
induction xs, ys using Vector.inductionOn₂ generalizing s
[GOAL]
case nil
α : Type
n : ℕ
xs ys : Vector α n
σ γ : Type
f : α → α → σ → σ × γ
comm : ∀ (a₁ a₂ : α) (s : σ), f a₁ a₂ s = f a₂ a₁ s
s : σ
⊢ mapAccumr₂ f nil nil s = mapAccumr₂ f nil nil s
[PROOFSTEP]
simp_all
[GOAL]
case cons
α : Type
n : ℕ
xs ys : Vector α n
σ γ : Type
f : α → α → σ → σ × γ
comm : ∀ (a₁ a₂ : α) (s : σ), f a₁ a₂ s = f a₂ a₁ s
n✝ : ℕ
a✝¹ b✝ : α
x✝ y✝ : Vector α n✝
a✝ : ∀ {s : σ}, mapAccumr₂ f x✝ y✝ s = mapAccumr₂ f y✝ x✝ s
s : σ
⊢ mapAccumr₂ f (a✝¹ ::ᵥ x✝) (b✝ ::ᵥ y✝) s = mapAccumr₂ f (b✝ ::ᵥ y✝) (a✝¹ ::ᵥ x✝) s
[PROOFSTEP]
simp_all
[GOAL]
α : Type u_2
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
f : α → β → γ
⊢ map₂ f xs ys = map₂ (flip f) ys xs
[PROOFSTEP]
induction xs, ys using Vector.inductionOn₂
[GOAL]
case nil
α : Type u_2
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
f : α → β → γ
⊢ map₂ f nil nil = map₂ (flip f) nil nil
[PROOFSTEP]
simp_all [flip]
[GOAL]
case cons
α : Type u_2
n : ℕ
β : Type u_3
xs : Vector α n
ys : Vector β n
γ : Type u_1
f : α → β → γ
n✝ : ℕ
a✝¹ : α
b✝ : β
x✝ : Vector α n✝
y✝ : Vector β n✝
a✝ : map₂ f x✝ y✝ = map₂ (flip f) y✝ x✝
⊢ map₂ f (a✝¹ ::ᵥ x✝) (b✝ ::ᵥ y✝) = map₂ (flip f) (b✝ ::ᵥ y✝) (a✝¹ ::ᵥ x✝)
[PROOFSTEP]
simp_all [flip]
[GOAL]
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
f : α → β → σ → σ × γ
⊢ mapAccumr₂ f xs ys s = mapAccumr₂ (flip f) ys xs s
[PROOFSTEP]
induction xs, ys using Vector.inductionOn₂
[GOAL]
case nil
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
f : α → β → σ → σ × γ
⊢ mapAccumr₂ f nil nil s = mapAccumr₂ (flip f) nil nil s
[PROOFSTEP]
simp_all [flip]
[GOAL]
case cons
α : Type
n : ℕ
β : Type
xs : Vector α n
ys : Vector β n
σ γ : Type
s : σ
f : α → β → σ → σ × γ
n✝ : ℕ
a✝¹ : α
b✝ : β
x✝ : Vector α n✝
y✝ : Vector β n✝
a✝ : mapAccumr₂ f x✝ y✝ s = mapAccumr₂ (flip f) y✝ x✝ s
⊢ mapAccumr₂ f (a✝¹ ::ᵥ x✝) (b✝ ::ᵥ y✝) s = mapAccumr₂ (flip f) (b✝ ::ᵥ y✝) (a✝¹ ::ᵥ x✝) s
[PROOFSTEP]
simp_all [flip]


[GOAL]
⊢ ∀ (a : PrimeMultiset), ⊥ ≤ a
[PROOFSTEP]
simp only [bot_le, forall_const]
[GOAL]
⊢ Repr PrimeMultiset
[PROOFSTEP]
delta PrimeMultiset
[GOAL]
⊢ Repr (Multiset Nat.Primes)
[PROOFSTEP]
infer_instance
[GOAL]
v : PrimeMultiset
p : ℕ
h : p ∈ toNatMultiset v
⊢ Nat.Prime p
[PROOFSTEP]
rcases Multiset.mem_map.mp h with ⟨⟨_, hp'⟩, ⟨_, h_eq⟩⟩
[GOAL]
case intro.mk.intro
v : PrimeMultiset
p : ℕ
h : p ∈ toNatMultiset v
val✝ : ℕ
hp' : Nat.Prime val✝
left✝ : { val := val✝, property := hp' } ∈ v
h_eq : Coe.coe { val := val✝, property := hp' } = p
⊢ Nat.Prime p
[PROOFSTEP]
exact h_eq ▸ hp'
[GOAL]
v : PrimeMultiset
p : ℕ+
h : p ∈ toPNatMultiset v
⊢ PNat.Prime p
[PROOFSTEP]
rcases Multiset.mem_map.mp h with ⟨⟨_, hp'⟩, ⟨_, h_eq⟩⟩
[GOAL]
case intro.mk.intro
v : PrimeMultiset
p : ℕ+
h : p ∈ toPNatMultiset v
val✝ : ℕ
hp' : Nat.Prime val✝
left✝ : { val := val✝, property := hp' } ∈ v
h_eq : Coe.coe { val := val✝, property := hp' } = p
⊢ PNat.Prime p
[PROOFSTEP]
exact h_eq ▸ hp'
[GOAL]
v : PrimeMultiset
⊢ Multiset.map PNat.val (toPNatMultiset v) = toNatMultiset v
[PROOFSTEP]
change (v.map (Coe.coe : Nat.Primes → ℕ+)).map Subtype.val = v.map Subtype.val
[GOAL]
v : PrimeMultiset
⊢ Multiset.map Subtype.val (Multiset.map Coe.coe v) = Multiset.map Subtype.val v
[PROOFSTEP]
rw [Multiset.map_map]
[GOAL]
v : PrimeMultiset
⊢ Multiset.map (Subtype.val ∘ Coe.coe) v = Multiset.map Subtype.val v
[PROOFSTEP]
congr
[GOAL]
v : PrimeMultiset
⊢ ↑(prod v) = Multiset.prod (toNatMultiset v)
[PROOFSTEP]
let h : (v.prod : ℕ) = ((v.map Coe.coe).map Coe.coe).prod := PNat.coeMonoidHom.map_multiset_prod v.toPNatMultiset
[GOAL]
v : PrimeMultiset
h : ↑(prod v) = Multiset.prod (Multiset.map Coe.coe (Multiset.map Coe.coe v)) :=
  MonoidHom.map_multiset_prod PNat.coeMonoidHom (toPNatMultiset v)
⊢ ↑(prod v) = Multiset.prod (toNatMultiset v)
[PROOFSTEP]
rw [Multiset.map_map] at h
[GOAL]
v : PrimeMultiset
h : ↑(prod v) = Multiset.prod (Multiset.map (Coe.coe ∘ Coe.coe) v)
⊢ ↑(prod v) = Multiset.prod (toNatMultiset v)
[PROOFSTEP]
have : (Coe.coe : ℕ+ → ℕ) ∘ (Coe.coe : Nat.Primes → ℕ+) = Coe.coe := funext fun p => rfl
[GOAL]
v : PrimeMultiset
h : ↑(prod v) = Multiset.prod (Multiset.map (Coe.coe ∘ Coe.coe) v)
this : Coe.coe ∘ Coe.coe = Coe.coe
⊢ ↑(prod v) = Multiset.prod (toNatMultiset v)
[PROOFSTEP]
rw [this] at h
[GOAL]
v : PrimeMultiset
h : ↑(prod v) = Multiset.prod (Multiset.map Coe.coe v)
this : Coe.coe ∘ Coe.coe = Coe.coe
⊢ ↑(prod v) = Multiset.prod (toNatMultiset v)
[PROOFSTEP]
exact h
[GOAL]
v : Multiset ℕ
h : ∀ (p : ℕ), p ∈ v → Nat.Prime p
⊢ toNatMultiset (ofNatMultiset v h) = v
[PROOFSTEP]
dsimp [ofNatMultiset, toNatMultiset]
[GOAL]
v : Multiset ℕ
h : ∀ (p : ℕ), p ∈ v → Nat.Prime p
⊢ Multiset.map Coe.coe (Multiset.pmap (fun p hp => { val := p, property := hp }) v h) = v
[PROOFSTEP]
have : (fun p h => (Coe.coe : Nat.Primes → ℕ) ⟨p, h⟩) = fun p _ => id p :=
  by
  funext p h
  rfl
[GOAL]
v : Multiset ℕ
h : ∀ (p : ℕ), p ∈ v → Nat.Prime p
⊢ (fun p h => Coe.coe { val := p, property := h }) = fun p x => id p
[PROOFSTEP]
funext p h
[GOAL]
case h.h
v : Multiset ℕ
h✝ : ∀ (p : ℕ), p ∈ v → Nat.Prime p
p : ℕ
h : Nat.Prime p
⊢ Coe.coe { val := p, property := h } = id p
[PROOFSTEP]
rfl
[GOAL]
v : Multiset ℕ
h : ∀ (p : ℕ), p ∈ v → Nat.Prime p
this : (fun p h => Coe.coe { val := p, property := h }) = fun p x => id p
⊢ Multiset.map Coe.coe (Multiset.pmap (fun p hp => { val := p, property := hp }) v h) = v
[PROOFSTEP]
rw [Multiset.map_pmap, this, Multiset.pmap_eq_map, Multiset.map_id]
[GOAL]
v : Multiset ℕ
h : ∀ (p : ℕ), p ∈ v → Nat.Prime p
⊢ ↑(prod (ofNatMultiset v h)) = Multiset.prod v
[PROOFSTEP]
rw [coe_prod, to_ofNatMultiset]
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
⊢ toPNatMultiset (ofPNatMultiset v h) = v
[PROOFSTEP]
dsimp [ofPNatMultiset, toPNatMultiset]
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
⊢ Multiset.map Coe.coe (Multiset.pmap (fun p hp => { val := ↑p, property := hp }) v h) = v
[PROOFSTEP]
have : (fun (p : ℕ+) (h : p.Prime) => (Coe.coe : Nat.Primes → ℕ+) ⟨p, h⟩) = fun p _ => id p :=
  by
  funext p h
  apply Subtype.eq
  rfl
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
⊢ (fun p h => Coe.coe { val := ↑p, property := h }) = fun p x => id p
[PROOFSTEP]
funext p h
[GOAL]
case h.h
v : Multiset ℕ+
h✝ : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
p : ℕ+
h : PNat.Prime p
⊢ Coe.coe { val := ↑p, property := h } = id p
[PROOFSTEP]
apply Subtype.eq
[GOAL]
case h.h.a
v : Multiset ℕ+
h✝ : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
p : ℕ+
h : PNat.Prime p
⊢ ↑(Coe.coe { val := ↑p, property := h }) = ↑(id p)
[PROOFSTEP]
rfl
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
this : (fun p h => Coe.coe { val := ↑p, property := h }) = fun p x => id p
⊢ Multiset.map Coe.coe (Multiset.pmap (fun p hp => { val := ↑p, property := hp }) v h) = v
[PROOFSTEP]
rw [Multiset.map_pmap, this, Multiset.pmap_eq_map, Multiset.map_id]
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
⊢ prod (ofPNatMultiset v h) = Multiset.prod v
[PROOFSTEP]
dsimp [prod]
[GOAL]
v : Multiset ℕ+
h : ∀ (p : ℕ+), p ∈ v → PNat.Prime p
⊢ Multiset.prod (toPNatMultiset (ofPNatMultiset v h)) = Multiset.prod v
[PROOFSTEP]
rw [to_ofPNatMultiset]
[GOAL]
l : List ℕ
h : ∀ (p : ℕ), p ∈ l → Nat.Prime p
⊢ ↑(prod (ofNatList l h)) = List.prod l
[PROOFSTEP]
have := prod_ofNatMultiset (l : Multiset ℕ) h
[GOAL]
l : List ℕ
h : ∀ (p : ℕ), p ∈ l → Nat.Prime p
this : ↑(prod (ofNatMultiset (↑l) h)) = Multiset.prod ↑l
⊢ ↑(prod (ofNatList l h)) = List.prod l
[PROOFSTEP]
rw [Multiset.coe_prod] at this
[GOAL]
l : List ℕ
h : ∀ (p : ℕ), p ∈ l → Nat.Prime p
this : ↑(prod (ofNatMultiset (↑l) h)) = List.prod l
⊢ ↑(prod (ofNatList l h)) = List.prod l
[PROOFSTEP]
exact this
[GOAL]
l : List ℕ+
h : ∀ (p : ℕ+), p ∈ l → PNat.Prime p
⊢ prod (ofPNatList l h) = List.prod l
[PROOFSTEP]
have := prod_ofPNatMultiset (l : Multiset ℕ+) h
[GOAL]
l : List ℕ+
h : ∀ (p : ℕ+), p ∈ l → PNat.Prime p
this : prod (ofPNatMultiset (↑l) h) = Multiset.prod ↑l
⊢ prod (ofPNatList l h) = List.prod l
[PROOFSTEP]
rw [Multiset.coe_prod] at this
[GOAL]
l : List ℕ+
h : ∀ (p : ℕ+), p ∈ l → PNat.Prime p
this : prod (ofPNatMultiset (↑l) h) = List.prod l
⊢ prod (ofPNatList l h) = List.prod l
[PROOFSTEP]
exact this
[GOAL]
⊢ prod 0 = 1
[PROOFSTEP]
exact Multiset.prod_zero
[GOAL]
u v : PrimeMultiset
⊢ prod (u + v) = prod u * prod v
[PROOFSTEP]
change (coePNatMonoidHom (u + v)).prod = _
[GOAL]
u v : PrimeMultiset
⊢ Multiset.prod (↑coePNatMonoidHom (u + v)) = prod u * prod v
[PROOFSTEP]
rw [coePNatMonoidHom.map_add]
[GOAL]
u v : PrimeMultiset
⊢ Multiset.prod (↑coePNatMonoidHom u + ↑coePNatMonoidHom v) = prod u * prod v
[PROOFSTEP]
exact Multiset.prod_add _ _
[GOAL]
d : ℕ
u : PrimeMultiset
⊢ prod (d • u) = Pow.pow (prod u) d
[PROOFSTEP]
induction' d with n ih
[GOAL]
case zero
u : PrimeMultiset
⊢ prod (Nat.zero • u) = Pow.pow (prod u) Nat.zero
[PROOFSTEP]
rfl
[GOAL]
case succ
u : PrimeMultiset
n : ℕ
ih : prod (n • u) = Pow.pow (prod u) n
⊢ prod (Nat.succ n • u) = Pow.pow (prod u) (Nat.succ n)
[PROOFSTEP]
have : ∀ n' : ℕ, Pow.pow (prod u) n' = Monoid.npow n' (prod u) := fun _ ↦ rfl
[GOAL]
case succ
u : PrimeMultiset
n : ℕ
ih : prod (n • u) = Pow.pow (prod u) n
this : ∀ (n' : ℕ), Pow.pow (prod u) n' = Monoid.npow n' (prod u)
⊢ prod (Nat.succ n • u) = Pow.pow (prod u) (Nat.succ n)
[PROOFSTEP]
rw [succ_nsmul, prod_add, ih, this, this, Monoid.npow_succ, mul_comm]
[GOAL]
n : ℕ+
⊢ ↑(PrimeMultiset.prod (factorMultiset n)) = ↑n
[PROOFSTEP]
dsimp [factorMultiset]
[GOAL]
n : ℕ+
⊢ ↑(PrimeMultiset.prod (PrimeMultiset.ofNatList (Nat.factors ↑n) (_ : ∀ {p : ℕ}, p ∈ Nat.factors ↑n → Nat.Prime p))) =
    ↑n
[PROOFSTEP]
rw [PrimeMultiset.prod_ofNatList]
[GOAL]
n : ℕ+
⊢ List.prod (Nat.factors ↑n) = ↑n
[PROOFSTEP]
exact Nat.prod_factors n.ne_zero
[GOAL]
v : PrimeMultiset
⊢ PNat.factorMultiset (prod v) = v
[PROOFSTEP]
apply PrimeMultiset.coeNat_injective
[GOAL]
case a
v : PrimeMultiset
⊢ Coe.coe (PNat.factorMultiset (prod v)) = Coe.coe v
[PROOFSTEP]
suffices toNatMultiset (PNat.factorMultiset (prod v)) = toNatMultiset v by exact this
[GOAL]
v : PrimeMultiset
this : toNatMultiset (PNat.factorMultiset (prod v)) = toNatMultiset v
⊢ Coe.coe (PNat.factorMultiset (prod v)) = Coe.coe v
[PROOFSTEP]
exact this
[GOAL]
case a
v : PrimeMultiset
⊢ toNatMultiset (PNat.factorMultiset (prod v)) = toNatMultiset v
[PROOFSTEP]
rw [v.prod.coeNat_factorMultiset, PrimeMultiset.coe_prod]
[GOAL]
case a
v : PrimeMultiset
⊢ ↑(Nat.factors (Multiset.prod (toNatMultiset v))) = toNatMultiset v
[PROOFSTEP]
rcases v with
  ⟨l⟩
    --unfold_coes
[GOAL]
case a.mk
v : PrimeMultiset
l : List Nat.Primes
⊢ ↑(Nat.factors (Multiset.prod (toNatMultiset (Quot.mk Setoid.r l)))) = toNatMultiset (Quot.mk Setoid.r l)
[PROOFSTEP]
dsimp [PrimeMultiset.toNatMultiset]
[GOAL]
case a.mk
v : PrimeMultiset
l : List Nat.Primes
⊢ ↑(Nat.factors (Multiset.prod ↑(List.map Coe.coe l))) = ↑(List.map Coe.coe l)
[PROOFSTEP]
rw [Multiset.coe_prod]
[GOAL]
case a.mk
v : PrimeMultiset
l : List Nat.Primes
⊢ ↑(Nat.factors (List.prod (List.map Coe.coe l))) = ↑(List.map Coe.coe l)
[PROOFSTEP]
let l' := l.map (Coe.coe : Nat.Primes → ℕ)
[GOAL]
case a.mk
v : PrimeMultiset
l : List Nat.Primes
l' : List ℕ := List.map Coe.coe l
⊢ ↑(Nat.factors (List.prod (List.map Coe.coe l))) = ↑(List.map Coe.coe l)
[PROOFSTEP]
have : ∀ p : ℕ, p ∈ l' → p.Prime := fun p hp =>
  by
  rcases List.mem_map.mp hp with ⟨⟨_, hp'⟩, ⟨_, h_eq⟩⟩
  exact h_eq ▸ hp'
[GOAL]
v : PrimeMultiset
l : List Nat.Primes
l' : List ℕ := List.map Coe.coe l
p : ℕ
hp : p ∈ l'
⊢ Nat.Prime p
[PROOFSTEP]
rcases List.mem_map.mp hp with ⟨⟨_, hp'⟩, ⟨_, h_eq⟩⟩
[GOAL]
case intro.mk.intro
v : PrimeMultiset
l : List Nat.Primes
l' : List ℕ := List.map Coe.coe l
p : ℕ
hp : p ∈ l'
val✝ : ℕ
hp' : Nat.Prime val✝
left✝ : { val := val✝, property := hp' } ∈ l
h_eq : Coe.coe { val := val✝, property := hp' } = p
⊢ Nat.Prime p
[PROOFSTEP]
exact h_eq ▸ hp'
[GOAL]
case a.mk
v : PrimeMultiset
l : List Nat.Primes
l' : List ℕ := List.map Coe.coe l
this : ∀ (p : ℕ), p ∈ l' → Nat.Prime p
⊢ ↑(Nat.factors (List.prod (List.map Coe.coe l))) = ↑(List.map Coe.coe l)
[PROOFSTEP]
exact Multiset.coe_eq_coe.mpr (@Nat.factors_unique _ l' rfl this).symm
[GOAL]
⊢ factorMultiset 1 = 0
[PROOFSTEP]
simp [factorMultiset, PrimeMultiset.ofNatList, PrimeMultiset.ofNatMultiset]
[GOAL]
n m : ℕ+
⊢ factorMultiset (n * m) = factorMultiset n + factorMultiset m
[PROOFSTEP]
let u := factorMultiset n
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
⊢ factorMultiset (n * m) = factorMultiset n + factorMultiset m
[PROOFSTEP]
let v := factorMultiset m
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
⊢ factorMultiset (n * m) = factorMultiset n + factorMultiset m
[PROOFSTEP]
have : n = u.prod := (prod_factorMultiset n).symm
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this : n = PrimeMultiset.prod u
⊢ factorMultiset (n * m) = factorMultiset n + factorMultiset m
[PROOFSTEP]
rw [this]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this : n = PrimeMultiset.prod u
⊢ factorMultiset (PrimeMultiset.prod u * m) = factorMultiset (PrimeMultiset.prod u) + factorMultiset m
[PROOFSTEP]
have : m = v.prod := (prod_factorMultiset m).symm
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ factorMultiset (PrimeMultiset.prod u * m) = factorMultiset (PrimeMultiset.prod u) + factorMultiset m
[PROOFSTEP]
rw [this]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ factorMultiset (PrimeMultiset.prod u * PrimeMultiset.prod v) =
    factorMultiset (PrimeMultiset.prod u) + factorMultiset (PrimeMultiset.prod v)
[PROOFSTEP]
rw [← PrimeMultiset.prod_add]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ factorMultiset (PrimeMultiset.prod (u + v)) =
    factorMultiset (PrimeMultiset.prod u) + factorMultiset (PrimeMultiset.prod v)
[PROOFSTEP]
repeat' rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ factorMultiset (PrimeMultiset.prod (u + v)) =
    factorMultiset (PrimeMultiset.prod u) + factorMultiset (PrimeMultiset.prod v)
[PROOFSTEP]
rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ u + v = factorMultiset (PrimeMultiset.prod u) + factorMultiset (PrimeMultiset.prod v)
[PROOFSTEP]
rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n m : ℕ+
u : PrimeMultiset := factorMultiset n
v : PrimeMultiset := factorMultiset m
this✝ : n = PrimeMultiset.prod u
this : m = PrimeMultiset.prod v
⊢ u + v = u + factorMultiset (PrimeMultiset.prod v)
[PROOFSTEP]
rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n : ℕ+
m : ℕ
⊢ factorMultiset (Pow.pow n m) = m • factorMultiset n
[PROOFSTEP]
let u := factorMultiset n
[GOAL]
n : ℕ+
m : ℕ
u : PrimeMultiset := factorMultiset n
⊢ factorMultiset (Pow.pow n m) = m • factorMultiset n
[PROOFSTEP]
have : n = u.prod := (prod_factorMultiset n).symm
[GOAL]
n : ℕ+
m : ℕ
u : PrimeMultiset := factorMultiset n
this : n = PrimeMultiset.prod u
⊢ factorMultiset (Pow.pow n m) = m • factorMultiset n
[PROOFSTEP]
rw [this, ← PrimeMultiset.prod_smul]
[GOAL]
n : ℕ+
m : ℕ
u : PrimeMultiset := factorMultiset n
this : n = PrimeMultiset.prod u
⊢ factorMultiset (PrimeMultiset.prod (m • u)) = m • factorMultiset (PrimeMultiset.prod u)
[PROOFSTEP]
repeat' rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n : ℕ+
m : ℕ
u : PrimeMultiset := factorMultiset n
this : n = PrimeMultiset.prod u
⊢ factorMultiset (PrimeMultiset.prod (m • u)) = m • factorMultiset (PrimeMultiset.prod u)
[PROOFSTEP]
rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
n : ℕ+
m : ℕ
u : PrimeMultiset := factorMultiset n
this : n = PrimeMultiset.prod u
⊢ m • u = m • factorMultiset (PrimeMultiset.prod u)
[PROOFSTEP]
rw [PrimeMultiset.factorMultiset_prod]
[GOAL]
p : Nat.Primes
⊢ factorMultiset ↑p = PrimeMultiset.ofPrime p
[PROOFSTEP]
apply factorMultisetEquiv.symm.injective
[GOAL]
case a
p : Nat.Primes
⊢ ↑factorMultisetEquiv.symm (factorMultiset ↑p) = ↑factorMultisetEquiv.symm (PrimeMultiset.ofPrime p)
[PROOFSTEP]
change (p : ℕ+).factorMultiset.prod = (PrimeMultiset.ofPrime p).prod
[GOAL]
case a
p : Nat.Primes
⊢ PrimeMultiset.prod (factorMultiset ↑p) = PrimeMultiset.prod (PrimeMultiset.ofPrime p)
[PROOFSTEP]
rw [(p : ℕ+).prod_factorMultiset, PrimeMultiset.prod_ofPrime]
[GOAL]
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset n ↔ m ∣ n
[PROOFSTEP]
constructor
[GOAL]
case mp
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset n → m ∣ n
[PROOFSTEP]
intro h
[GOAL]
case mp
m n : ℕ+
h : factorMultiset m ≤ factorMultiset n
⊢ m ∣ n
[PROOFSTEP]
rw [← prod_factorMultiset m, ← prod_factorMultiset m]
[GOAL]
case mp
m n : ℕ+
h : factorMultiset m ≤ factorMultiset n
⊢ PrimeMultiset.prod (factorMultiset (PrimeMultiset.prod (factorMultiset m))) ∣ n
[PROOFSTEP]
apply Dvd.intro (n.factorMultiset - m.factorMultiset).prod
[GOAL]
case mp
m n : ℕ+
h : factorMultiset m ≤ factorMultiset n
⊢ PrimeMultiset.prod (factorMultiset (PrimeMultiset.prod (factorMultiset m))) *
      PrimeMultiset.prod (factorMultiset n - factorMultiset m) =
    n
[PROOFSTEP]
rw [← PrimeMultiset.prod_add, PrimeMultiset.factorMultiset_prod, add_tsub_cancel_of_le h, prod_factorMultiset]
[GOAL]
case mpr
m n : ℕ+
⊢ m ∣ n → factorMultiset m ≤ factorMultiset n
[PROOFSTEP]
intro h
[GOAL]
case mpr
m n : ℕ+
h : m ∣ n
⊢ factorMultiset m ≤ factorMultiset n
[PROOFSTEP]
rw [← mul_div_exact h, factorMultiset_mul]
[GOAL]
case mpr
m n : ℕ+
h : m ∣ n
⊢ factorMultiset m ≤ factorMultiset m + factorMultiset (divExact n m)
[PROOFSTEP]
exact le_self_add
[GOAL]
m : ℕ+
v : PrimeMultiset
⊢ factorMultiset m ≤ v ↔ m ∣ PrimeMultiset.prod v
[PROOFSTEP]
let h := @factorMultiset_le_iff m v.prod
[GOAL]
m : ℕ+
v : PrimeMultiset
h : factorMultiset m ≤ factorMultiset (PrimeMultiset.prod v) ↔ m ∣ PrimeMultiset.prod v := factorMultiset_le_iff
⊢ factorMultiset m ≤ v ↔ m ∣ PrimeMultiset.prod v
[PROOFSTEP]
rw [v.factorMultiset_prod] at h
[GOAL]
m : ℕ+
v : PrimeMultiset
h : factorMultiset m ≤ v ↔ m ∣ PrimeMultiset.prod v
⊢ factorMultiset m ≤ v ↔ m ∣ PrimeMultiset.prod v
[PROOFSTEP]
exact h
[GOAL]
u v : PrimeMultiset
⊢ prod u ∣ prod v ↔ u ≤ v
[PROOFSTEP]
let h := @PNat.factorMultiset_le_iff' u.prod v
[GOAL]
u v : PrimeMultiset
h : PNat.factorMultiset (prod u) ≤ v ↔ prod u ∣ prod v := PNat.factorMultiset_le_iff'
⊢ prod u ∣ prod v ↔ u ≤ v
[PROOFSTEP]
rw [u.factorMultiset_prod] at h
[GOAL]
u v : PrimeMultiset
h : u ≤ v ↔ prod u ∣ prod v
⊢ prod u ∣ prod v ↔ u ≤ v
[PROOFSTEP]
exact h.symm
[GOAL]
u : PrimeMultiset
n : ℕ+
⊢ prod u ∣ n ↔ u ≤ PNat.factorMultiset n
[PROOFSTEP]
let h := @prod_dvd_iff u n.factorMultiset
[GOAL]
u : PrimeMultiset
n : ℕ+
h : prod u ∣ prod (PNat.factorMultiset n) ↔ u ≤ PNat.factorMultiset n := prod_dvd_iff
⊢ prod u ∣ n ↔ u ≤ PNat.factorMultiset n
[PROOFSTEP]
rw [n.prod_factorMultiset] at h
[GOAL]
u : PrimeMultiset
n : ℕ+
h : prod u ∣ n ↔ u ≤ PNat.factorMultiset n
⊢ prod u ∣ n ↔ u ≤ PNat.factorMultiset n
[PROOFSTEP]
exact h
[GOAL]
m n : ℕ+
⊢ factorMultiset (gcd m n) = factorMultiset m ⊓ factorMultiset n
[PROOFSTEP]
apply le_antisymm
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset (gcd m n) ≤ factorMultiset m ⊓ factorMultiset n
[PROOFSTEP]
apply le_inf_iff.mpr
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset (gcd m n) ≤ factorMultiset m ∧ factorMultiset (gcd m n) ≤ factorMultiset n
[PROOFSTEP]
constructor
[GOAL]
case a.left
m n : ℕ+
⊢ factorMultiset (gcd m n) ≤ factorMultiset m
[PROOFSTEP]
apply factorMultiset_le_iff.mpr
[GOAL]
case a.right
m n : ℕ+
⊢ factorMultiset (gcd m n) ≤ factorMultiset n
[PROOFSTEP]
apply factorMultiset_le_iff.mpr
[GOAL]
case a.left
m n : ℕ+
⊢ gcd m n ∣ m
case a.right m n : ℕ+ ⊢ gcd m n ∣ n
[PROOFSTEP]
exact gcd_dvd_left m n
[GOAL]
case a.right
m n : ℕ+
⊢ gcd m n ∣ n
[PROOFSTEP]
exact gcd_dvd_right m n
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset (gcd m n)
[PROOFSTEP]
rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
[GOAL]
case a
m n : ℕ+
⊢ PrimeMultiset.prod (factorMultiset m ⊓ factorMultiset n) ∣ gcd m n
[PROOFSTEP]
apply dvd_gcd
[GOAL]
case a.hm
m n : ℕ+
⊢ PrimeMultiset.prod (factorMultiset m ⊓ factorMultiset n) ∣ m
[PROOFSTEP]
rw [PrimeMultiset.prod_dvd_iff']
[GOAL]
case a.hn
m n : ℕ+
⊢ PrimeMultiset.prod (factorMultiset m ⊓ factorMultiset n) ∣ n
[PROOFSTEP]
rw [PrimeMultiset.prod_dvd_iff']
[GOAL]
case a.hm
m n : ℕ+
⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset m
case a.hn m n : ℕ+ ⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset n
[PROOFSTEP]
exact inf_le_left
[GOAL]
case a.hn
m n : ℕ+
⊢ factorMultiset m ⊓ factorMultiset n ≤ factorMultiset n
[PROOFSTEP]
exact inf_le_right
[GOAL]
m n : ℕ+
⊢ factorMultiset (lcm m n) = factorMultiset m ⊔ factorMultiset n
[PROOFSTEP]
apply le_antisymm
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset (lcm m n) ≤ factorMultiset m ⊔ factorMultiset n
[PROOFSTEP]
rw [← PrimeMultiset.prod_dvd_iff, prod_factorMultiset]
[GOAL]
case a
m n : ℕ+
⊢ lcm m n ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)
[PROOFSTEP]
apply lcm_dvd
[GOAL]
case a.hm
m n : ℕ+
⊢ m ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)
[PROOFSTEP]
rw [← factorMultiset_le_iff']
[GOAL]
case a.hn
m n : ℕ+
⊢ n ∣ PrimeMultiset.prod (factorMultiset m ⊔ factorMultiset n)
[PROOFSTEP]
rw [← factorMultiset_le_iff']
[GOAL]
case a.hm
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset m ⊔ factorMultiset n
case a.hn m n : ℕ+ ⊢ factorMultiset n ≤ factorMultiset m ⊔ factorMultiset n
[PROOFSTEP]
exact le_sup_left
[GOAL]
case a.hn
m n : ℕ+
⊢ factorMultiset n ≤ factorMultiset m ⊔ factorMultiset n
[PROOFSTEP]
exact le_sup_right
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset m ⊔ factorMultiset n ≤ factorMultiset (lcm m n)
[PROOFSTEP]
apply sup_le_iff.mpr
[GOAL]
case a
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset (lcm m n) ∧ factorMultiset n ≤ factorMultiset (lcm m n)
[PROOFSTEP]
constructor
[GOAL]
case a.left
m n : ℕ+
⊢ factorMultiset m ≤ factorMultiset (lcm m n)
[PROOFSTEP]
apply factorMultiset_le_iff.mpr
[GOAL]
case a.right
m n : ℕ+
⊢ factorMultiset n ≤ factorMultiset (lcm m n)
[PROOFSTEP]
apply factorMultiset_le_iff.mpr
[GOAL]
case a.left
m n : ℕ+
⊢ m ∣ lcm m n
case a.right m n : ℕ+ ⊢ n ∣ lcm m n
[PROOFSTEP]
exact dvd_lcm_left m n
[GOAL]
case a.right
m n : ℕ+
⊢ n ∣ lcm m n
[PROOFSTEP]
exact dvd_lcm_right m n
[GOAL]
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ Pow.pow (↑p) k ∣ m ↔ k ≤ Multiset.count p (factorMultiset m)
[PROOFSTEP]
intros
[GOAL]
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ Pow.pow (↑p) k ∣ m ↔ k ≤ Multiset.count p (factorMultiset m)
[PROOFSTEP]
rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow, factorMultiset_ofPrime]
[GOAL]
m : ℕ+
p : Nat.Primes
k : ℕ
⊢ k • PrimeMultiset.ofPrime p ≤ factorMultiset m ↔ Multiset.replicate k p ≤ factorMultiset m
[PROOFSTEP]
congr! 2
[GOAL]
case a.h.e'_3.h
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ k • PrimeMultiset.ofPrime p = Multiset.replicate k p
[PROOFSTEP]
apply Multiset.eq_replicate.mpr
[GOAL]
case a.h.e'_3.h
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ ↑Multiset.card (k • PrimeMultiset.ofPrime p) = k ∧ ∀ (b : Nat.Primes), b ∈ k • PrimeMultiset.ofPrime p → b = p
[PROOFSTEP]
constructor
[GOAL]
case a.h.e'_3.h.left
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ ↑Multiset.card (k • PrimeMultiset.ofPrime p) = k
[PROOFSTEP]
rw [Multiset.card_nsmul, PrimeMultiset.card_ofPrime, mul_one]
[GOAL]
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
⊢ ∀ (b : Nat.Primes), b ∈ k • PrimeMultiset.ofPrime p → b = p
[PROOFSTEP]
intro q h
[GOAL]
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
q : Nat.Primes
h : q ∈ k • PrimeMultiset.ofPrime p
⊢ q = p
[PROOFSTEP]
rw [PrimeMultiset.ofPrime, Multiset.nsmul_singleton _ k] at h
[GOAL]
case a.h.e'_3.h.right
m : ℕ+
p : Nat.Primes
k : ℕ
e_1✝ : PrimeMultiset = Multiset Nat.Primes
q : Nat.Primes
h : q ∈ Multiset.replicate k p
⊢ q = p
[PROOFSTEP]
exact Multiset.eq_of_mem_replicate h
[GOAL]
u v : PrimeMultiset
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)
[PROOFSTEP]
let n := u.prod
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)
[PROOFSTEP]
let m := v.prod
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊓ v) = PNat.gcd (prod u) (prod v)
[PROOFSTEP]
change (u ⊓ v).prod = PNat.gcd n m
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊓ v) = PNat.gcd n m
[PROOFSTEP]
have : u = n.factorMultiset := u.factorMultiset_prod.symm
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (u ⊓ v) = PNat.gcd n m
[PROOFSTEP]
rw [this]
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (PNat.factorMultiset n ⊓ v) = PNat.gcd n m
[PROOFSTEP]
have : v = m.factorMultiset := v.factorMultiset_prod.symm
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊓ v) = PNat.gcd n m
[PROOFSTEP]
rw [this]
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊓ PNat.factorMultiset m) = PNat.gcd n m
[PROOFSTEP]
rw [← PNat.factorMultiset_gcd n m, PNat.prod_factorMultiset]
[GOAL]
u v : PrimeMultiset
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)
[PROOFSTEP]
let n := u.prod
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)
[PROOFSTEP]
let m := v.prod
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊔ v) = PNat.lcm (prod u) (prod v)
[PROOFSTEP]
change (u ⊔ v).prod = PNat.lcm n m
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
⊢ prod (u ⊔ v) = PNat.lcm n m
[PROOFSTEP]
have : u = n.factorMultiset := u.factorMultiset_prod.symm
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (u ⊔ v) = PNat.lcm n m
[PROOFSTEP]
rw [this]
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this : u = PNat.factorMultiset n
⊢ prod (PNat.factorMultiset n ⊔ v) = PNat.lcm n m
[PROOFSTEP]
have : v = m.factorMultiset := v.factorMultiset_prod.symm
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊔ v) = PNat.lcm n m
[PROOFSTEP]
rw [this]
[GOAL]
u v : PrimeMultiset
n : ℕ+ := prod u
m : ℕ+ := prod v
this✝ : u = PNat.factorMultiset n
this : v = PNat.factorMultiset m
⊢ prod (PNat.factorMultiset n ⊔ PNat.factorMultiset m) = PNat.lcm n m
[PROOFSTEP]
rw [← PNat.factorMultiset_lcm n m, PNat.prod_factorMultiset]


[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
⊢ AntilipschitzWith K f ↔ ∀ (x y : α), nndist x y ≤ K * nndist (f x) (f y)
[PROOFSTEP]
simp only [AntilipschitzWith, edist_nndist]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
⊢ (∀ (x y : α), ↑(nndist x y) ≤ ↑K * ↑(nndist (f x) (f y))) ↔ ∀ (x y : α), nndist x y ≤ K * nndist (f x) (f y)
[PROOFSTEP]
norm_cast
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
⊢ AntilipschitzWith K f ↔ ∀ (x y : α), dist x y ≤ ↑K * dist (f x) (f y)
[PROOFSTEP]
simp only [antilipschitzWith_iff_le_mul_nndist, dist_nndist]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
⊢ (∀ (x y : α), nndist x y ≤ K * nndist (f x) (f y)) ↔ ∀ (x y : α), ↑(nndist x y) ≤ ↑K * ↑(nndist (f x) (f y))
[PROOFSTEP]
norm_cast
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
x y : α
⊢ K⁻¹ * nndist x y ≤ nndist (f x) (f y)
[PROOFSTEP]
simpa only [div_eq_inv_mul] using NNReal.div_le_of_le_mul' (hf.le_mul_nndist x y)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
x y : α
⊢ ↑K⁻¹ * dist x y ≤ dist (f x) (f y)
[PROOFSTEP]
exact_mod_cast hf.mul_le_nndist x y
[GOAL]
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
inst✝⁴ : PseudoEMetricSpace α✝
inst✝³ : PseudoEMetricSpace β✝
inst✝² : PseudoEMetricSpace γ
K✝ : ℝ≥0
f✝ : α✝ → β✝
α : Type u_4
β : Type u_5
inst✝¹ : EMetricSpace α
inst✝ : PseudoEMetricSpace β
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
x y : α
h : f x = f y
⊢ x = y
[PROOFSTEP]
simpa only [h, edist_self, mul_zero, edist_le_zero] using hf x y
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
x y : α
⊢ (↑K)⁻¹ * edist x y ≤ edist (f x) (f y)
[PROOFSTEP]
rw [mul_comm, ← div_eq_mul_inv]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
x y : α
⊢ edist x y / ↑K ≤ edist (f x) (f y)
[PROOFSTEP]
exact ENNReal.div_le_of_le_mul' (hf x y)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
x y : α
⊢ edist x y ≤ ↑1 * edist (id x) (id y)
[PROOFSTEP]
simp only [ENNReal.coe_one, one_mul, id, le_refl]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f✝ : α → β
Kg : ℝ≥0
g : β → γ
hg : AntilipschitzWith Kg g
Kf : ℝ≥0
f : α → β
hf : AntilipschitzWith Kf f
x y : α
⊢ ↑Kf * (↑Kg * edist (g (f x)) (g (f y))) = ↑(Kf * Kg) * edist ((g ∘ f) x) ((g ∘ f) y)
[PROOFSTEP]
rw [ENNReal.coe_mul, mul_assoc]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f✝ : α → β
Kg : ℝ≥0
g : β → γ
hg : AntilipschitzWith Kg g
Kf : ℝ≥0
f : α → β
hf : AntilipschitzWith Kf f
x y : α
⊢ ↑Kf * (↑Kg * edist (g (f x)) (g (f y))) = ↑Kf * (↑Kg * edist ((g ∘ f) x) ((g ∘ f) y))
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
s : Set α
hf : AntilipschitzWith K (Set.restrict s f)
g : β → α
t : Set β
g_maps : MapsTo g t s
g_inv : RightInvOn g f t
x y : ↑t
⊢ edist (Set.restrict t g x) (Set.restrict t g y) ≤ ↑K * edist x y
[PROOFSTEP]
simpa only [restrict_apply, g_inv x.mem, g_inv y.mem, Subtype.edist_eq, Subtype.coe_mk] using
  hf ⟨g x, g_maps x.mem⟩ ⟨g y, g_maps y.mem⟩
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
g : β → α
hg : Function.RightInverse g f
⊢ LipschitzWith K g
[PROOFSTEP]
intro x y
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
g : β → α
hg : Function.RightInverse g f
x y : β
⊢ edist (g x) (g y) ≤ ↑K * edist x y
[PROOFSTEP]
have := hf (g x) (g y)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
g : β → α
hg : Function.RightInverse g f
x y : β
this : edist (g x) (g y) ≤ ↑K * edist (f (g x)) (f (g y))
⊢ edist (g x) (g y) ≤ ↑K * edist x y
[PROOFSTEP]
rwa [hg x, hg y] at this
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
⊢ comap (Prod.map f f) (𝓤 β) ≤ 𝓤 α
[PROOFSTEP]
refine ((uniformity_basis_edist.comap _).le_basis_iff uniformity_basis_edist).2 fun ε h₀ => ?_
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
ε : ℝ≥0∞
h₀ : 0 < ε
⊢ ∃ i, 0 < i ∧ Prod.map f f ⁻¹' {p | edist p.fst p.snd < i} ⊆ {p | edist p.fst p.snd < ε}
[PROOFSTEP]
refine ⟨(↑K)⁻¹ * ε, ENNReal.mul_pos (ENNReal.inv_ne_zero.2 ENNReal.coe_ne_top) h₀.ne', ?_⟩
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
ε : ℝ≥0∞
h₀ : 0 < ε
⊢ Prod.map f f ⁻¹' {p | edist p.fst p.snd < (↑K)⁻¹ * ε} ⊆ {p | edist p.fst p.snd < ε}
[PROOFSTEP]
refine' fun x hx => (hf x.1 x.2).trans_lt _
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
ε : ℝ≥0∞
h₀ : 0 < ε
x : α × α
hx : x ∈ Prod.map f f ⁻¹' {p | edist p.fst p.snd < (↑K)⁻¹ * ε}
⊢ ↑K * edist (f x.fst) (f x.snd) < ε
[PROOFSTEP]
rw [mul_comm, ← div_eq_mul_inv] at hx
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
ε : ℝ≥0∞
h₀ : 0 < ε
x : α × α
hx : x ∈ Prod.map f f ⁻¹' {p | edist p.fst p.snd < ε / ↑K}
⊢ ↑K * edist (f x.fst) (f x.snd) < ε
[PROOFSTEP]
rw [mul_comm]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : PseudoEMetricSpace α
inst✝¹ : PseudoEMetricSpace β
inst✝ : PseudoEMetricSpace γ
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
ε : ℝ≥0∞
h₀ : 0 < ε
x : α × α
hx : x ∈ Prod.map f f ⁻¹' {p | edist p.fst p.snd < ε / ↑K}
⊢ edist (f x.fst) (f x.snd) * ↑K < ε
[PROOFSTEP]
exact ENNReal.mul_lt_of_lt_div hx
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoEMetricSpace α
inst✝² : PseudoEMetricSpace β
inst✝¹ : PseudoEMetricSpace γ
K✝ : ℝ≥0
f : α → β
inst✝ : Subsingleton α
K : ℝ≥0
x y : α
⊢ edist x y ≤ ↑K * edist (f x) (f y)
[PROOFSTEP]
simp only [Subsingleton.elim x y, edist_self, zero_le]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
s : Set β
hs : Metric.Bounded s
x : α
hx : x ∈ f ⁻¹' s
y : α
hy : y ∈ f ⁻¹' s
⊢ ↑K * dist (f x) (f y) ≤ ↑K * diam s
[PROOFSTEP]
gcongr
[GOAL]
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoMetricSpace α
inst✝ : PseudoMetricSpace β
K : ℝ≥0
f : α → β
hf : AntilipschitzWith K f
s : Set β
hs : Metric.Bounded s
x : α
hx : x ∈ f ⁻¹' s
y : α
hy : y ∈ f ⁻¹' s
⊢ dist (f x) (f y) ≤ diam s
[PROOFSTEP]
exact dist_le_diam_of_mem hs hx hy
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K f
f_cont : Continuous f
hf : Function.Surjective f
⊢ ProperSpace β
[PROOFSTEP]
refine ⟨fun x₀ r => ?_⟩
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
⊢ IsCompact (closedBall x₀ r)
[PROOFSTEP]
let K := f ⁻¹' closedBall x₀ r
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝¹ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K✝ : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K✝ f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
K : Set α := f ⁻¹' closedBall x₀ r
⊢ IsCompact (closedBall x₀ r)
[PROOFSTEP]
have A : IsClosed K := isClosed_ball.preimage f_cont
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝¹ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K✝ : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K✝ f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
K : Set α := f ⁻¹' closedBall x₀ r
A : IsClosed K
⊢ IsCompact (closedBall x₀ r)
[PROOFSTEP]
have B : Bounded K := hK.bounded_preimage bounded_closedBall
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝¹ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K✝ : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K✝ f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
K : Set α := f ⁻¹' closedBall x₀ r
A : IsClosed K
B : Metric.Bounded K
⊢ IsCompact (closedBall x₀ r)
[PROOFSTEP]
have : IsCompact K := isCompact_iff_isClosed_bounded.2 ⟨A, B⟩
[GOAL]
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝¹ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K✝ : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K✝ f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
K : Set α := f ⁻¹' closedBall x₀ r
A : IsClosed K
B : Metric.Bounded K
this : IsCompact K
⊢ IsCompact (closedBall x₀ r)
[PROOFSTEP]
convert this.image f_cont
[GOAL]
case h.e'_3
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : PseudoMetricSpace α✝
inst✝² : PseudoMetricSpace β
K✝¹ : ℝ≥0
f✝ : α✝ → β
α : Type u_4
inst✝¹ : MetricSpace α
K✝ : ℝ≥0
f : α → β
inst✝ : ProperSpace α
hK : AntilipschitzWith K✝ f
f_cont : Continuous f
hf : Function.Surjective f
x₀ : β
r : ℝ
K : Set α := f ⁻¹' closedBall x₀ r
A : IsClosed K
B : Metric.Bounded K
this : IsCompact K
⊢ closedBall x₀ r = f '' K
[PROOFSTEP]
exact (hf.image_preimage _).symm
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : PseudoEMetricSpace α
inst✝ : PseudoEMetricSpace β
K : ℝ≥0
f : α → β
hf : LipschitzWith K f
g : β → α
hg : Function.RightInverse g f
x y : β
⊢ edist x y ≤ ↑K * edist (g x) (g y)
[PROOFSTEP]
simpa only [hg _] using hf (g x) (g y)


[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
⊢ ↑p a = 0 ↔ ¬a ∈ support p
[PROOFSTEP]
rw [mem_support_iff, Classical.not_not]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
⊢ ↑p a = 1 ↔ support p = {a}
[PROOFSTEP]
refine'
  ⟨fun h =>
    Set.Subset.antisymm (fun a' ha' => by_contra fun ha => _) fun a' ha' =>
      ha'.symm ▸ (p.mem_support_iff a).2 fun ha => zero_ne_one <| ha.symm.trans h,
    fun h => _root_.trans (symm <| tsum_eq_single a fun a' ha' => (p.apply_eq_zero_iff a').2 (h.symm ▸ ha')) p.tsum_coe⟩
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
⊢ False
[PROOFSTEP]
suffices : 1 < ∑' a, p a
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 1 < ∑' (a : α), ↑p a
⊢ False
case this
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
⊢ 1 < ∑' (a : α), ↑p a
[PROOFSTEP]
exact ne_of_lt this p.tsum_coe.symm
[GOAL]
case this
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
⊢ 1 < ∑' (a : α), ↑p a
[PROOFSTEP]
have : 0 < ∑' b, ite (b = a) 0 (p b) :=
  lt_of_le_of_ne' zero_le'
    ((tsum_ne_zero_iff ENNReal.summable).2 ⟨a', ite_ne_left_iff.2 ⟨ha, Ne.symm <| (p.mem_support_iff a').2 ha'⟩⟩)
[GOAL]
case this
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
⊢ 1 < ∑' (a : α), ↑p a
[PROOFSTEP]
calc
  1 = 1 + 0 := (add_zero 1).symm
  _ < p a + ∑' b, ite (b = a) 0 (p b) := (ENNReal.add_lt_add_of_le_of_lt ENNReal.one_ne_top (le_of_eq h.symm) this)
  _ = ite (a = a) (p a) 0 + ∑' b, ite (b = a) 0 (p b) := by rw [eq_self_iff_true, if_true]
  _ = (∑' b, ite (b = a) (p b) 0) + ∑' b, ite (b = a) 0 (p b) :=
    by
    congr
    exact symm (tsum_eq_single a fun b hb => if_neg hb)
  _ = ∑' b, (ite (b = a) (p b) 0 + ite (b = a) 0 (p b)) := ENNReal.tsum_add.symm
  _ = ∑' b, p b := tsum_congr fun b => by split_ifs <;> simp only [zero_add, add_zero, le_rfl]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
⊢ (↑p a + ∑' (b : α), if b = a then 0 else ↑p b) = (if a = a then ↑p a else 0) + ∑' (b : α), if b = a then 0 else ↑p b
[PROOFSTEP]
rw [eq_self_iff_true, if_true]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
⊢ ((if a = a then ↑p a else 0) + ∑' (b : α), if b = a then 0 else ↑p b) =
    (∑' (b : α), if b = a then ↑p b else 0) + ∑' (b : α), if b = a then 0 else ↑p b
[PROOFSTEP]
congr
[GOAL]
case e_a
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
⊢ (if a = a then ↑p a else 0) = ∑' (b : α), if b = a then ↑p b else 0
[PROOFSTEP]
exact symm (tsum_eq_single a fun b hb => if_neg hb)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
b : α
⊢ ((if b = a then ↑p b else 0) + if b = a then 0 else ↑p b) = ↑p b
[PROOFSTEP]
split_ifs
[GOAL]
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
b : α
h✝ : b = a
⊢ ↑p b + 0 = ↑p b
[PROOFSTEP]
simp only [zero_add, add_zero, le_rfl]
[GOAL]
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
h : ↑p a = 1
a' : α
ha' : a' ∈ support p
ha : ¬a' ∈ {a}
this : 0 < ∑' (b : α), if b = a then 0 else ↑p b
b : α
h✝ : ¬b = a
⊢ 0 + ↑p b = ↑p b
[PROOFSTEP]
simp only [zero_add, add_zero, le_rfl]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a : α
⊢ ↑p a ≤ 1
[PROOFSTEP]
refine' hasSum_le (fun b => _) (hasSum_ite_eq a (p a)) (hasSum_coe_one p)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a b : α
⊢ (if b = a then ↑p a else 0) ≤ ↑p b
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a b : α
h : b = a
⊢ ↑p a ≤ ↑p b
[PROOFSTEP]
simp only [h, zero_le', le_rfl]
[GOAL]
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
a b : α
h : ¬b = a
⊢ 0 ≤ ↑p b
[PROOFSTEP]
simp only [h, zero_le', le_rfl]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
⊢ OuterMeasure.caratheodory (toOuterMeasure p) = ⊤
[PROOFSTEP]
refine' eq_top_iff.2 <| le_trans (le_sInf fun x hx => _) (le_sum_caratheodory _)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
x : MeasurableSpace α
hx : x ∈ Set.range fun i => OuterMeasure.caratheodory (↑p i • dirac i)
⊢ ⊤ ≤ x
[PROOFSTEP]
have ⟨y, hy⟩ := hx
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
x : MeasurableSpace α
hx : x ∈ Set.range fun i => OuterMeasure.caratheodory (↑p i • dirac i)
y : α
hy : (fun i => OuterMeasure.caratheodory (↑p i • dirac i)) y = x
⊢ ⊤ ≤ x
[PROOFSTEP]
exact ((le_of_eq (dirac_caratheodory y).symm).trans (le_smul_caratheodory _ _)).trans (le_of_eq hy)
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s✝ t : Set α
s : Finset α
⊢ ↑(toOuterMeasure p) ↑s = ∑ x in s, ↑p x
[PROOFSTEP]
refine' (toOuterMeasure_apply p s).trans ((tsum_eq_sum (s := s) _).trans _)
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s✝ t : Set α
s : Finset α
⊢ ∀ (b : α), ¬b ∈ s → Set.indicator (↑s) (↑p) b = 0
[PROOFSTEP]
exact fun x hx => Set.indicator_of_not_mem (Finset.mem_coe.not.2 hx) _
[GOAL]
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s✝ t : Set α
s : Finset α
⊢ ∑ b in s, Set.indicator (↑s) (↑p) b = ∑ x in s, ↑p x
[PROOFSTEP]
exact Finset.sum_congr rfl fun x hx => Set.indicator_of_mem (Finset.mem_coe.2 hx) _
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
a : α
⊢ ↑(toOuterMeasure p) {a} = ↑p a
[PROOFSTEP]
refine' (p.toOuterMeasure_apply { a }).trans ((tsum_eq_single a fun b hb => _).trans _)
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
a b : α
hb : b ≠ a
⊢ Set.indicator {a} (↑p) b = 0
[PROOFSTEP]
exact ite_eq_right_iff.2 fun hb' => False.elim <| hb hb'
[GOAL]
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
a : α
⊢ Set.indicator {a} (↑p) a = ↑p a
[PROOFSTEP]
exact ite_eq_left_iff.2 fun ha' => False.elim <| ha' rfl
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
⊢ ↑(toOuterMeasure p) s = 0 ↔ Disjoint (support p) s
[PROOFSTEP]
rw [toOuterMeasure_apply, ENNReal.tsum_eq_zero]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
⊢ (∀ (i : α), Set.indicator s (↑p) i = 0) ↔ Disjoint (support p) s
[PROOFSTEP]
exact Function.funext_iff.symm.trans Set.indicator_eq_zero'
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
⊢ ↑(toOuterMeasure p) s = 1 ↔ support p ⊆ s
[PROOFSTEP]
refine' (p.toOuterMeasure_apply s).symm ▸ ⟨fun h a hap => _, fun h => _⟩
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : ∑' (x : α), Set.indicator s (↑p) x = 1
a : α
hap : a ∈ support p
⊢ a ∈ s
[PROOFSTEP]
refine' by_contra fun hs => ne_of_lt _ (h.trans p.tsum_coe.symm)
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : ∑' (x : α), Set.indicator s (↑p) x = 1
a : α
hap : a ∈ support p
hs : ¬a ∈ s
⊢ ∑' (x : α), Set.indicator s (↑p) x < ∑' (a : α), ↑p a
[PROOFSTEP]
have hs' : s.indicator p a = 0 := Set.indicator_apply_eq_zero.2 fun hs' => False.elim <| hs hs'
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : ∑' (x : α), Set.indicator s (↑p) x = 1
a : α
hap : a ∈ support p
hs : ¬a ∈ s
hs' : Set.indicator s (↑p) a = 0
⊢ ∑' (x : α), Set.indicator s (↑p) x < ∑' (a : α), ↑p a
[PROOFSTEP]
have hsa : s.indicator p a < p a := hs'.symm ▸ (p.apply_pos_iff a).2 hap
[GOAL]
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : ∑' (x : α), Set.indicator s (↑p) x = 1
a : α
hap : a ∈ support p
hs : ¬a ∈ s
hs' : Set.indicator s (↑p) a = 0
hsa : Set.indicator s (↑p) a < ↑p a
⊢ ∑' (x : α), Set.indicator s (↑p) x < ∑' (a : α), ↑p a
[PROOFSTEP]
exact ENNReal.tsum_lt_tsum (p.tsum_coe_indicator_ne_top s) (fun x => Set.indicator_apply_le fun _ => le_rfl) hsa
[GOAL]
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : support p ⊆ s
⊢ ∑' (x : α), Set.indicator s (↑p) x = 1
[PROOFSTEP]
suffices : ∀ (x) (_ : x ∉ s), p x = 0
[GOAL]
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : support p ⊆ s
this : ∀ (x : α), ¬x ∈ s → ↑p x = 0
⊢ ∑' (x : α), Set.indicator s (↑p) x = 1
case this α : Type u_1 β : Type u_2 γ : Type u_3 p : Pmf α s t : Set α h : support p ⊆ s ⊢ ∀ (x : α), ¬x ∈ s → ↑p x = 0
[PROOFSTEP]
exact
  _root_.trans (tsum_congr fun a => (Set.indicator_apply s p a).trans (ite_eq_left_iff.2 <| symm ∘ this a)) p.tsum_coe
[GOAL]
case this
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
h : support p ⊆ s
⊢ ∀ (x : α), ¬x ∈ s → ↑p x = 0
[PROOFSTEP]
exact fun a ha => (p.apply_eq_zero_iff a).2 <| Set.not_mem_subset h ha
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
p : Pmf α
s t : Set α
⊢ ↑(toOuterMeasure p) (s ∩ support p) = ↑(toOuterMeasure p) s
[PROOFSTEP]
simp only [toOuterMeasure_apply, Pmf.support, Set.indicator_inter_support]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
s t : Set α
a : α
h : MeasurableSet {a}
⊢ ↑↑(toMeasure p) {a} = ↑p a
[PROOFSTEP]
simp [toMeasure_apply_eq_toOuterMeasure_apply _ _ h, toOuterMeasure_apply_singleton]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
s t : Set α
hs : MeasurableSet s
⊢ ↑↑(toMeasure p) s = 0 ↔ Disjoint (support p) s
[PROOFSTEP]
rw [toMeasure_apply_eq_toOuterMeasure_apply p s hs, toOuterMeasure_apply_eq_zero_iff]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
s t : Set α
hs : MeasurableSet s
hp : MeasurableSet (support p)
⊢ ↑↑(toMeasure p) (s ∩ support p) = ↑↑(toMeasure p) s
[PROOFSTEP]
simp [p.toMeasure_apply_eq_toOuterMeasure_apply s hs, p.toMeasure_apply_eq_toOuterMeasure_apply _ (hs.inter hp)]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
s✝ t✝ s t : Set α
hs : MeasurableSet s
ht : MeasurableSet t
h : s ∩ support p ⊆ t
⊢ ↑↑(toMeasure p) s ≤ ↑↑(toMeasure p) t
[PROOFSTEP]
simpa only [p.toMeasure_apply_eq_toOuterMeasure_apply, hs, ht] using toOuterMeasure_mono p h
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
s✝ t✝ s t : Set α
hs : MeasurableSet s
ht : MeasurableSet t
h : s ∩ support p = t ∩ support p
⊢ ↑↑(toMeasure p) s = ↑↑(toMeasure p) t
[PROOFSTEP]
simpa only [p.toMeasure_apply_eq_toOuterMeasure_apply, hs, ht] using toOuterMeasure_apply_eq_of_inter_support_eq p h
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : MeasurableSpace α
p : Pmf α
s t : Set α
inst✝ : MeasurableSingletonClass α
⊢ Function.Injective toMeasure
[PROOFSTEP]
intro p q h
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : MeasurableSpace α
p✝ : Pmf α
s t : Set α
inst✝ : MeasurableSingletonClass α
p q : Pmf α
h : toMeasure p = toMeasure q
⊢ p = q
[PROOFSTEP]
ext x
[GOAL]
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : MeasurableSpace α
p✝ : Pmf α
s t : Set α
inst✝ : MeasurableSingletonClass α
p q : Pmf α
h : toMeasure p = toMeasure q
x : α
⊢ ↑p x = ↑q x
[PROOFSTEP]
rw [← p.toMeasure_apply_singleton x <| measurableSet_singleton x, ←
  q.toMeasure_apply_singleton x <| measurableSet_singleton x, h]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : Countable α
inst✝² : MeasurableSpace α
inst✝¹ : MeasurableSingletonClass α
μ : Measure α
inst✝ : IsProbabilityMeasure μ
s : Set α
hs : MeasurableSet s
⊢ ↑↑(toMeasure (toPmf μ)) s = ↑↑μ s
[PROOFSTEP]
rw [μ.toPmf.toMeasure_apply s hs, ← μ.tsum_indicator_apply_singleton s hs]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : Countable α
inst✝² : MeasurableSpace α
inst✝¹ : MeasurableSingletonClass α
μ : Measure α
inst✝ : IsProbabilityMeasure μ
s : Set α
hs : MeasurableSet s
⊢ ∑' (x : α), Set.indicator s (↑(toPmf μ)) x = ∑' (x : α), Set.indicator s (fun x => ↑↑μ {x}) x
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : MeasurableSpace α
p : Pmf α
⊢ ↑↑(toMeasure p) Set.univ = 1
[PROOFSTEP]
simpa only [MeasurableSet.univ, toMeasure_apply_eq_toOuterMeasure_apply, Set.indicator_univ, toOuterMeasure_apply,
  ENNReal.coe_eq_one] using tsum_coe p
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : Countable α
inst✝² : MeasurableSpace α
inst✝¹ : MeasurableSingletonClass α
p : Pmf α
μ : Measure α
inst✝ : IsProbabilityMeasure μ
x : α
⊢ ↑(Measure.toPmf (toMeasure p)) x = ↑p x
[PROOFSTEP]
rw [← p.toMeasure_apply_singleton x (measurableSet_singleton x), p.toMeasure.toPmf_apply]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝⁴ : Countable α
inst✝³ : MeasurableSpace α
inst✝² : MeasurableSingletonClass α
p : Pmf α
μ✝ : Measure α
inst✝¹ : IsProbabilityMeasure μ✝
μ : Measure α
inst✝ : IsProbabilityMeasure μ
⊢ toMeasure p = μ ↔ p = Measure.toPmf μ
[PROOFSTEP]
rw [← toMeasure_inj, Measure.toPmf_toMeasure]
[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝⁴ : Countable α
inst✝³ : MeasurableSpace α
inst✝² : MeasurableSingletonClass α
p : Pmf α
μ✝ : Measure α
inst✝¹ : IsProbabilityMeasure μ✝
μ : Measure α
inst✝ : IsProbabilityMeasure μ
⊢ Measure.toPmf μ = p ↔ μ = toMeasure p
[PROOFSTEP]
rw [← toMeasure_inj, Measure.toPmf_toMeasure]