l3lab/ntp-mathlib huggingface dataset:
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  

Proof state:
case mk.hadd
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x x✝ y✝ : ExteriorAlgebra R M
i✝ : ℕ
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
hy✝ : y✝ ∈ LinearMap.range (ι R) ^ i✝
ihx : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
ihy : (liftι R M) y✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := y✝, property := hy✝ }
⊢ (liftι R M) (x✝ + y✝) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝)
      { val := x✝ + y✝, property := (_ : x✝ + y✝ ∈ LinearMap.range (ι R) ^ i✝) }

Next tactic:
| hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; rfl
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => 

Proof state:
case mk.hadd
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x x✝ y✝ : ExteriorAlgebra R M
i✝ : ℕ
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
hy✝ : y✝ ∈ LinearMap.range (ι R) ^ i✝
ihx : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
ihy : (liftι R M) y✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := y✝, property := hy✝ }
⊢ (liftι R M) (x✝ + y✝) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝)
      { val := x✝ + y✝, property := (_ : x✝ + y✝ ∈ LinearMap.range (ι R) ^ i✝) }

Next tactic:
simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; 

Proof state:
case mk.hadd
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x x✝ y✝ : ExteriorAlgebra R M
i✝ : ℕ
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
hy✝ : y✝ ∈ LinearMap.range (ι R) ^ i✝
ihx : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
ihy : (liftι R M) y✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := y✝, property := hy✝ }
⊢ (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝)
      ({ val := x✝, property := hx✝ } + { val := y✝, property := hy✝ }) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝)
      { val := x✝ + y✝, property := (_ : x✝ + y✝ ∈ LinearMap.range (ι R) ^ i✝) }

Next tactic:
rfl
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; rfl
  

Proof state:
case mk.hmul
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x m✝ : ExteriorAlgebra R M
hm : m✝ ∈ LinearMap.range (ι R)
i✝ : ℕ
x✝ : ExteriorAlgebra R M
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
ih : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
⊢ (liftι R M) (m✝ * x✝) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) (Nat.succ i✝))
      { val := m✝ * x✝, property := (_ : m✝ * x✝ ∈ LinearMap.range (ι R) * npowRec i✝ (LinearMap.range (ι R))) }

Next tactic:
| hmul _ hm _ _ _ ih =>
      obtain ⟨_, rfl⟩ := hm
      simp_rw [AlgHom.map_mul, ih, GradedAlgebra.liftι, lift_ι_apply, GradedAlgebra.ι_apply R M,
        DirectSum.of_mul_of]
      exact DirectSum.of_eq_of_gradedMonoid_eq (Sigma.subtype_ext (add_comm _ _) rfl)
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; rfl
  | hmul _ hm _ _ _ ih =>
      

Proof state:
case mk.hmul
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x m✝ : ExteriorAlgebra R M
hm : m✝ ∈ LinearMap.range (ι R)
i✝ : ℕ
x✝ : ExteriorAlgebra R M
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
ih : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
⊢ (liftι R M) (m✝ * x✝) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) (Nat.succ i✝))
      { val := m✝ * x✝, property := (_ : m✝ * x✝ ∈ LinearMap.range (ι R) * npowRec i✝ (LinearMap.range (ι R))) }

Next tactic:
obtain ⟨_, rfl⟩ := hm
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; rfl
  | hmul _ hm _ _ _ ih =>
      obtain ⟨_, rfl⟩ := hm
      

Proof state:
case mk.hmul.intro
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x : ExteriorAlgebra R M
i✝ : ℕ
x✝ : ExteriorAlgebra R M
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
ih : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
w✝ : M
⊢ (liftι R M) ((ι R) w✝ * x✝) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) (Nat.succ i✝))
      { val := (ι R) w✝ * x✝,
        property := (_ : (ι R) w✝ * x✝ ∈ LinearMap.range (ι R) * npowRec i✝ (LinearMap.range (ι R))) }

Next tactic:
simp_rw [AlgHom.map_mul, ih, GradedAlgebra.liftι, lift_ι_apply, GradedAlgebra.ι_apply R M,
        DirectSum.of_mul_of]
theorem GradedAlgebra.liftι_eq (i : ℕ)
    (x : (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) :
    GradedAlgebra.liftι R M x =
    DirectSum.of (fun i =>
      ↥(LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ i :
      Submodule R (ExteriorAlgebra R M))) i x := by
  cases' x with x hx
  dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of]
  -- Porting note: original statement was
  --  refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_)
  --    (fun m hm i x hx ih => ?_) hx
  -- but it created invalid goals
  induction hx using Submodule.pow_induction_on_left' with
  | hr => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl
  | hadd _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← map_add]; rfl
  | hmul _ hm _ _ _ ih =>
      obtain ⟨_, rfl⟩ := hm
      simp_rw [AlgHom.map_mul, ih, GradedAlgebra.liftι, lift_ι_apply, GradedAlgebra.ι_apply R M,
        DirectSum.of_mul_of]
      

Proof state:
case mk.hmul.intro
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
i : ℕ
x : ExteriorAlgebra R M
i✝ : ℕ
x✝ : ExteriorAlgebra R M
hx✝ : x✝ ∈ LinearMap.range (ι R) ^ i✝
ih : (liftι R M) x✝ = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i✝) { val := x✝, property := hx✝ }
w✝ : M
⊢ (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) (1 + i✝))
      (GradedMonoid.GMul.mul { val := (ι R) w✝, property := (_ : (ι R) w✝ ∈ LinearMap.range (ι R) ^ 1) }
        { val := x✝, property := hx✝ }) =
    (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) (Nat.succ i✝))
      { val := (ι R) w✝ * x✝,
        property := (_ : (ι R) w✝ * x✝ ∈ LinearMap.range (ι R) * npowRec i✝ (LinearMap.range (ι R))) }

Next tactic:
exact DirectSum.of_eq_of_gradedMonoid_eq (Sigma.subtype_ext (add_comm _ _) rfl)
/-- The exterior algebra is graded by the powers of the submodule `(ExteriorAlgebra.ι R).range`. -/
instance gradedAlgebra :
    GradedAlgebra (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ · : ℕ → Submodule R _) :=
  GradedAlgebra.ofAlgHom _
    (-- while not necessary, the `by apply` makes this elaborate faster
    by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
⊢ ExteriorAlgebra R M →ₐ[R] ⨁ (i : ℕ), ↥(LinearMap.range (ι R) ^ i)

Next tactic:
apply GradedAlgebra.liftι R M
/-- The exterior algebra is graded by the powers of the submodule `(ExteriorAlgebra.ι R).range`. -/
instance gradedAlgebra :
    GradedAlgebra (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ · : ℕ → Submodule R _) :=
  GradedAlgebra.ofAlgHom _
    (-- while not necessary, the `by apply` makes this elaborate faster
    by apply GradedAlgebra.liftι R M)
    -- the proof from here onward is identical to the `TensorAlgebra` case
    (by
      

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
⊢ AlgHom.comp (DirectSum.coeAlgHom fun x => LinearMap.range (ι R) ^ x) (GradedAlgebra.liftι R M) =
    AlgHom.id R (ExteriorAlgebra R M)

Next tactic:
ext m
/-- The exterior algebra is graded by the powers of the submodule `(ExteriorAlgebra.ι R).range`. -/
instance gradedAlgebra :
    GradedAlgebra (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ · : ℕ → Submodule R _) :=
  GradedAlgebra.ofAlgHom _
    (-- while not necessary, the `by apply` makes this elaborate faster
    by apply GradedAlgebra.liftι R M)
    -- the proof from here onward is identical to the `TensorAlgebra` case
    (by
      ext m
      

Proof state:
case a.h
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
m : M
⊢ (AlgHom.toLinearMap
          (AlgHom.comp (DirectSum.coeAlgHom fun x => LinearMap.range (ι R) ^ x) (GradedAlgebra.liftι R M)) ∘ₗ
        CliffordAlgebra.ι 0)
      m =
    (AlgHom.toLinearMap (AlgHom.id R (ExteriorAlgebra R M)) ∘ₗ CliffordAlgebra.ι 0) m

Next tactic:
dsimp only [LinearMap.comp_apply, AlgHom.toLinearMap_apply, AlgHom.comp_apply,
        AlgHom.id_apply, GradedAlgebra.liftι]
/-- The exterior algebra is graded by the powers of the submodule `(ExteriorAlgebra.ι R).range`. -/
instance gradedAlgebra :
    GradedAlgebra (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ · : ℕ → Submodule R _) :=
  GradedAlgebra.ofAlgHom _
    (-- while not necessary, the `by apply` makes this elaborate faster
    by apply GradedAlgebra.liftι R M)
    -- the proof from here onward is identical to the `TensorAlgebra` case
    (by
      ext m
      dsimp only [LinearMap.comp_apply, AlgHom.toLinearMap_apply, AlgHom.comp_apply,
        AlgHom.id_apply, GradedAlgebra.liftι]
      

Proof state:
case a.h
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
m : M
⊢ (DirectSum.coeAlgHom fun x => LinearMap.range (ι R) ^ x)
      (((lift R)
          { val := GradedAlgebra.ι R M,
            property := (_ : ∀ (m : M), (GradedAlgebra.ι R M) m * (GradedAlgebra.ι R M) m = 0) })
        ((CliffordAlgebra.ι 0) m)) =
    (CliffordAlgebra.ι 0) m

Next tactic:
rw [lift_ι_apply, GradedAlgebra.ι_apply R M, DirectSum.coeAlgHom_of, Subtype.coe_mk]
/-- The exterior algebra is graded by the powers of the submodule `(ExteriorAlgebra.ι R).range`. -/
instance gradedAlgebra :
    GradedAlgebra (LinearMap.range (ι R : M →ₗ[R] ExteriorAlgebra R M) ^ · : ℕ → Submodule R _) :=
  GradedAlgebra.ofAlgHom _
    (-- while not necessary, the `by apply` makes this elaborate faster
    by apply GradedAlgebra.liftι R M)
    -- the proof from here onward is identical to the `TensorAlgebra` case
    (by
      ext m
      dsimp only [LinearMap.comp_apply, AlgHom.toLinearMap_apply, AlgHom.comp_apply,
        AlgHom.id_apply, GradedAlgebra.liftι]
      rw [lift_ι_apply, GradedAlgebra.ι_apply R M, DirectSum.coeAlgHom_of, Subtype.coe_mk])
    (by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
⊢ ∀ (i : ℕ) (x : ↥(LinearMap.range (ι R) ^ i)),
    (GradedAlgebra.liftι R M) ↑x = (DirectSum.of (fun i => ↥(LinearMap.range (ι R) ^ i)) i) x

Next tactic:
apply GradedAlgebra.liftι_eq R M
instance FreeCommRing.instCommRing : CommRing (FreeCommRing α) := by
  

Proof state:
α : Type u
⊢ CommRing (FreeCommRing α)

Next tactic:
delta FreeCommRing
instance FreeCommRing.instCommRing : CommRing (FreeCommRing α) := by
  delta FreeCommRing; 

Proof state:
α : Type u
⊢ CommRing (FreeAbelianGroup (Multiplicative (Multiset α)))

Next tactic:
infer_instance
instance FreeCommRing.instInhabited : Inhabited (FreeCommRing α) := by
  

Proof state:
α : Type u
⊢ Inhabited (FreeCommRing α)

Next tactic:
delta FreeCommRing
instance FreeCommRing.instInhabited : Inhabited (FreeCommRing α) := by
  delta FreeCommRing; 

Proof state:
α : Type u
⊢ Inhabited (FreeAbelianGroup (Multiplicative (Multiset α)))

Next tactic:
infer_instance
lemma of_cons (a : α) (m : Multiset α) : (FreeAbelianGroup.of (Multiplicative.ofAdd (a ::ₘ m))) =
    @HMul.hMul _ (FreeCommRing α) (FreeCommRing α) _ (of a)
    (FreeAbelianGroup.of (Multiplicative.ofAdd m)) := by
  

Proof state:
α : Type u
a : α
m : Multiset α
⊢ FreeAbelianGroup.of (Multiplicative.ofAdd (a ::ₘ m)) = of a * FreeAbelianGroup.of (Multiplicative.ofAdd m)

Next tactic:
dsimp [FreeCommRing]
lemma of_cons (a : α) (m : Multiset α) : (FreeAbelianGroup.of (Multiplicative.ofAdd (a ::ₘ m))) =
    @HMul.hMul _ (FreeCommRing α) (FreeCommRing α) _ (of a)
    (FreeAbelianGroup.of (Multiplicative.ofAdd m)) := by
  dsimp [FreeCommRing]
  

Proof state:
α : Type u
a : α
m : Multiset α
⊢ FreeAbelianGroup.of (Multiplicative.ofAdd (a ::ₘ m)) = of a * FreeAbelianGroup.of (Multiplicative.ofAdd m)

Next tactic:
rw [← Multiset.singleton_add, ofAdd_add,
    of, FreeAbelianGroup.of_mul_of]
@[elab_as_elim]
protected theorem induction_on {C : FreeCommRing α → Prop} (z : FreeCommRing α) (hn1 : C (-1))
    (hb : ∀ b, C (of b)) (ha : ∀ x y, C x → C y → C (x + y)) (hm : ∀ x y, C x → C y → C (x * y)) :
    C z :=
  have hn : ∀ x, C x → C (-x) := fun x ih => neg_one_mul x ▸ hm _ _ hn1 ih
  have h1 : C 1 := neg_neg (1 : FreeCommRing α) ▸ hn _ hn1
  FreeAbelianGroup.induction_on z (add_left_neg (1 : FreeCommRing α) ▸ ha _ _ hn1 h1)
    (fun m => Multiset.induction_on m h1 fun a m ih => by
      

Proof state:
α : Type u
C : FreeCommRing α → Prop
z : FreeCommRing α
hn1 : C (-1)
hb : ∀ (b : α), C (of b)
ha : ∀ (x y : FreeCommRing α), C x → C y → C (x + y)
hm : ∀ (x y : FreeCommRing α), C x → C y → C (x * y)
hn : ∀ (x : FreeCommRing α), C x → C (-x)
h1 : C 1
m✝ : Multiplicative (Multiset α)
a : α
m : Multiset α
ih : C (FreeAbelianGroup.of m)
⊢ C (FreeAbelianGroup.of (a ::ₘ m))

Next tactic:
convert hm (of a) _ (hb a) ih
@[elab_as_elim]
protected theorem induction_on {C : FreeCommRing α → Prop} (z : FreeCommRing α) (hn1 : C (-1))
    (hb : ∀ b, C (of b)) (ha : ∀ x y, C x → C y → C (x + y)) (hm : ∀ x y, C x → C y → C (x * y)) :
    C z :=
  have hn : ∀ x, C x → C (-x) := fun x ih => neg_one_mul x ▸ hm _ _ hn1 ih
  have h1 : C 1 := neg_neg (1 : FreeCommRing α) ▸ hn _ hn1
  FreeAbelianGroup.induction_on z (add_left_neg (1 : FreeCommRing α) ▸ ha _ _ hn1 h1)
    (fun m => Multiset.induction_on m h1 fun a m ih => by
      convert hm (of a) _ (hb a) ih
      

Proof state:
case h.e'_1
α : Type u
C : FreeCommRing α → Prop
z : FreeCommRing α
hn1 : C (-1)
hb : ∀ (b : α), C (of b)
ha : ∀ (x y : FreeCommRing α), C x → C y → C (x + y)
hm : ∀ (x y : FreeCommRing α), C x → C y → C (x * y)
hn : ∀ (x : FreeCommRing α), C x → C (-x)
h1 : C 1
m✝ : Multiplicative (Multiset α)
a : α
m : Multiset α
ih : C (FreeAbelianGroup.of m)
⊢ FreeAbelianGroup.of (a ::ₘ m) = of a * FreeAbelianGroup.of m

Next tactic:
apply of_cons
/-- A helper to implement `lift`. This is essentially `FreeCommMonoid.lift`, but this does not
currently exist. -/
private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R) where
  toFun f :=
    { toFun := fun s => (s.toAdd.map f).prod
      map_mul' := fun x y =>
        calc
          _ = Multiset.prod (Multiset.map f x + Multiset.map f y) := by
            

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f✝ f : α → R
x y : Multiplicative (Multiset α)
⊢ OneHom.toFun
      { toFun := fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s)),
        map_one' :=
          (_ :
            (fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s))) 1 =
              (fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s))) 1) }
      (x * y) =
    Multiset.prod (Multiset.map f x + Multiset.map f y)

Next tactic:
rw [← Multiset.map_add]
/-- A helper to implement `lift`. This is essentially `FreeCommMonoid.lift`, but this does not
currently exist. -/
private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R) where
  toFun f :=
    { toFun := fun s => (s.toAdd.map f).prod
      map_mul' := fun x y =>
        calc
          _ = Multiset.prod (Multiset.map f x + Multiset.map f y) := by
            rw [← Multiset.map_add]
            

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f✝ f : α → R
x y : Multiplicative (Multiset α)
⊢ OneHom.toFun
      { toFun := fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s)),
        map_one' :=
          (_ :
            (fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s))) 1 =
              (fun s => Multiset.prod (Multiset.map f (Multiplicative.toAdd s))) 1) }
      (x * y) =
    Multiset.prod (Multiset.map f (x + y))

Next tactic:
rfl
/-- A helper to implement `lift`. This is essentially `FreeCommMonoid.lift`, but this does not
currently exist. -/
private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R) where
  toFun f :=
    { toFun := fun s => (s.toAdd.map f).prod
      map_mul' := fun x y =>
        calc
          _ = Multiset.prod (Multiset.map f x + Multiset.map f y) := by
            rw [← Multiset.map_add]
            rfl
          _ = _ := Multiset.prod_add _ _
      map_one' := rfl }
  invFun F x := F (Multiplicative.ofAdd ({x} : Multiset α))
  left_inv f := funext fun x => show (Multiset.map f {x}).prod = _ by 

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f✝ f : α → R
x : α
⊢ Multiset.prod (Multiset.map f {x}) = f x

Next tactic:
simp
/-- A helper to implement `lift`. This is essentially `FreeCommMonoid.lift`, but this does not
currently exist. -/
private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R) where
  toFun f :=
    { toFun := fun s => (s.toAdd.map f).prod
      map_mul' := fun x y =>
        calc
          _ = Multiset.prod (Multiset.map f x + Multiset.map f y) := by
            rw [← Multiset.map_add]
            rfl
          _ = _ := Multiset.prod_add _ _
      map_one' := rfl }
  invFun F x := F (Multiplicative.ofAdd ({x} : Multiset α))
  left_inv f := funext fun x => show (Multiset.map f {x}).prod = _ by simp
  right_inv F := MonoidHom.ext fun x =>
    let F' := MonoidHom.toAdditive'' F
    let x' := Multiplicative.toAdd x
    show (Multiset.map (fun a => F' {a}) x').sum = F' x' by
      

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f : α → R
F : Multiplicative (Multiset α) →* R
x : Multiplicative (Multiset α)
F' : Multiset α →+ Additive R := MonoidHom.toAdditive'' F
x' : Multiset α := Multiplicative.toAdd x
⊢ Multiset.sum (Multiset.map (fun a => F' {a}) x') = F' x'

Next tactic:
erw [← Multiset.map_map (fun x => F' x) (fun x => {x}), ← AddMonoidHom.map_multiset_sum]
/-- A helper to implement `lift`. This is essentially `FreeCommMonoid.lift`, but this does not
currently exist. -/
private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R) where
  toFun f :=
    { toFun := fun s => (s.toAdd.map f).prod
      map_mul' := fun x y =>
        calc
          _ = Multiset.prod (Multiset.map f x + Multiset.map f y) := by
            rw [← Multiset.map_add]
            rfl
          _ = _ := Multiset.prod_add _ _
      map_one' := rfl }
  invFun F x := F (Multiplicative.ofAdd ({x} : Multiset α))
  left_inv f := funext fun x => show (Multiset.map f {x}).prod = _ by simp
  right_inv F := MonoidHom.ext fun x =>
    let F' := MonoidHom.toAdditive'' F
    let x' := Multiplicative.toAdd x
    show (Multiset.map (fun a => F' {a}) x').sum = F' x' by
      erw [← Multiset.map_map (fun x => F' x) (fun x => {x}), ← AddMonoidHom.map_multiset_sum]
      

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f : α → R
F : Multiplicative (Multiset α) →* R
x : Multiplicative (Multiset α)
F' : Multiset α →+ Additive R := MonoidHom.toAdditive'' F
x' : Multiset α := Multiplicative.toAdd x
⊢ F' (Multiset.sum (Multiset.map (fun x => {x}) x')) = F' x'

Next tactic:
exact F.congr_arg (Multiset.sum_map_singleton x')
@[simp]
theorem lift_comp_of (f : FreeCommRing α →+* R) : lift (f ∘ of) = f :=
  RingHom.ext fun x =>
    FreeCommRing.induction_on x (by 

Proof state:
α : Type u
R : Type v
inst✝ : CommRing R
f✝ : α → R
f : FreeCommRing α →+* R
x : FreeCommRing α
⊢ (lift (⇑f ∘ of)) (-1) = f (-1)

Next tactic:
rw [RingHom.map_neg, RingHom.map_one, f.map_neg, f.map_one]