l3lab/ntp-mathlib huggingface dataset:
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  

Proof state:
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
⊢ IsExpansionOn ϕ M

Next tactic:
refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · 

Proof state:
case refine'_1
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
f : Functions L n
xs : Fin n → M
⊢ funMap (LHom.onFunction ϕ f) xs = funMap f xs

Next tactic:
have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
    

Proof state:
case refine'_1
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
f : Functions L n
xs : Fin n → M
hf : LHom.onFunction ϕ f ∈ Set.range fun f => LHom.onFunction ϕ f
⊢ funMap (LHom.onFunction ϕ f) xs = funMap f xs

Next tactic:
refine' (dif_pos hf).trans _
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
    refine' (dif_pos hf).trans _
    

Proof state:
case refine'_1
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
f : Functions L n
xs : Fin n → M
hf : LHom.onFunction ϕ f ∈ Set.range fun f => LHom.onFunction ϕ f
⊢ funMap (Exists.choose hf) xs = funMap f xs

Next tactic:
rw [h.onFunction hf.choose_spec]
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
    refine' (dif_pos hf).trans _
    rw [h.onFunction hf.choose_spec]
  · 

Proof state:
case refine'_2
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
r : Relations L n
xs : Fin n → M
⊢ RelMap (LHom.onRelation ϕ r) xs = RelMap r xs

Next tactic:
have hr : ϕ.onRelation r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r := ⟨r, rfl⟩
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
    refine' (dif_pos hf).trans _
    rw [h.onFunction hf.choose_spec]
  · have hr : ϕ.onRelation r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r := ⟨r, rfl⟩
    

Proof state:
case refine'_2
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
r : Relations L n
xs : Fin n → M
hr : LHom.onRelation ϕ r ∈ Set.range fun r => LHom.onRelation ϕ r
⊢ RelMap (LHom.onRelation ϕ r) xs = RelMap r xs

Next tactic:
refine' (dif_pos hr).trans _
theorem Injective.isExpansionOn_default {ϕ : L →ᴸ L'}
    [∀ (n) (f : L'.Functions n), Decidable (f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f)]
    [∀ (n) (r : L'.Relations n), Decidable (r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r)]
    (h : ϕ.Injective) (M : Type*) [Inhabited M] [L.Structure M] :
    @IsExpansionOn L L' ϕ M _ (ϕ.defaultExpansion M) := by
  letI := ϕ.defaultExpansion M
  refine' ⟨fun {n} f xs => _, fun {n} r xs => _⟩
  · have hf : ϕ.onFunction f ∈ Set.range fun f : L.Functions n => ϕ.onFunction f := ⟨f, rfl⟩
    refine' (dif_pos hf).trans _
    rw [h.onFunction hf.choose_spec]
  · have hr : ϕ.onRelation r ∈ Set.range fun r : L.Relations n => ϕ.onRelation r := ⟨r, rfl⟩
    refine' (dif_pos hr).trans _
    

Proof state:
case refine'_2
L : Language
L' : Language
M✝ : Type w
inst✝⁴ : Structure L M✝
ϕ✝ : L →ᴸ L'
L'' : Language
ϕ : L →ᴸ L'
inst✝³ : (n : ℕ) → (f : Functions L' n) → Decidable (f ∈ Set.range fun f => LHom.onFunction ϕ f)
inst✝² : (n : ℕ) → (r : Relations L' n) → Decidable (r ∈ Set.range fun r => LHom.onRelation ϕ r)
h : LHom.Injective ϕ
M : Type u_1
inst✝¹ : Inhabited M
inst✝ : Structure L M
this : Structure L' M := defaultExpansion ϕ M
n : ℕ
r : Relations L n
xs : Fin n → M
hr : LHom.onRelation ϕ r ∈ Set.range fun r => LHom.onRelation ϕ r
⊢ RelMap (Exists.choose hr) xs = RelMap r xs

Next tactic:
rw [h.onRelation hr.choose_spec]
/-- The composition of equivalences of first-order languages. -/
@[simps, trans]
protected def trans (e : L ≃ᴸ L') (e' : L' ≃ᴸ L'') : L ≃ᴸ L'' :=
  ⟨e'.toLHom.comp e.toLHom, e.invLHom.comp e'.invLHom, by
    

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
L'' : Language
e'✝ : L' ≃ᴸ L''
e✝ e : L ≃ᴸ L'
e' : L' ≃ᴸ L''
⊢ LHom.comp (LHom.comp e.invLHom e'.invLHom) (LHom.comp e'.toLHom e.toLHom) = LHom.id L

Next tactic:
rw [LHom.comp_assoc, ← LHom.comp_assoc e'.invLHom, e'.left_inv, LHom.id_comp, e.left_inv]
/-- The composition of equivalences of first-order languages. -/
@[simps, trans]
protected def trans (e : L ≃ᴸ L') (e' : L' ≃ᴸ L'') : L ≃ᴸ L'' :=
  ⟨e'.toLHom.comp e.toLHom, e.invLHom.comp e'.invLHom, by
    rw [LHom.comp_assoc, ← LHom.comp_assoc e'.invLHom, e'.left_inv, LHom.id_comp, e.left_inv], by
    

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
L'' : Language
e'✝ : L' ≃ᴸ L''
e✝ e : L ≃ᴸ L'
e' : L' ≃ᴸ L''
⊢ LHom.comp (LHom.comp e'.toLHom e.toLHom) (LHom.comp e.invLHom e'.invLHom) = LHom.id L''

Next tactic:
rw [LHom.comp_assoc, ← LHom.comp_assoc e.toLHom, e.right_inv, LHom.id_comp, e'.right_inv]
theorem card_constantsOn : (constantsOn α).card = #α := by 

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type u'
⊢ card (constantsOn α) = #α

Next tactic:
simp
theorem constantsOnMap_isExpansionOn {f : α → β} {fα : α → M} {fβ : β → M} (h : fβ ∘ f = fα) :
    @LHom.IsExpansionOn _ _ (LHom.constantsOnMap f) M (constantsOn.structure fα)
      (constantsOn.structure fβ) := by
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type u'
β : Type v'
f : α → β
fα : α → M
fβ : β → M
h : fβ ∘ f = fα
⊢ LHom.IsExpansionOn (LHom.constantsOnMap f) M

Next tactic:
letI := constantsOn.structure fα
theorem constantsOnMap_isExpansionOn {f : α → β} {fα : α → M} {fβ : β → M} (h : fβ ∘ f = fα) :
    @LHom.IsExpansionOn _ _ (LHom.constantsOnMap f) M (constantsOn.structure fα)
      (constantsOn.structure fβ) := by
  letI := constantsOn.structure fα
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type u'
β : Type v'
f : α → β
fα : α → M
fβ : β → M
h : fβ ∘ f = fα
this : Structure (constantsOn α) M := constantsOn.structure fα
⊢ LHom.IsExpansionOn (LHom.constantsOnMap f) M

Next tactic:
letI := constantsOn.structure fβ
theorem constantsOnMap_isExpansionOn {f : α → β} {fα : α → M} {fβ : β → M} (h : fβ ∘ f = fα) :
    @LHom.IsExpansionOn _ _ (LHom.constantsOnMap f) M (constantsOn.structure fα)
      (constantsOn.structure fβ) := by
  letI := constantsOn.structure fα
  letI := constantsOn.structure fβ
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type u'
β : Type v'
f : α → β
fα : α → M
fβ : β → M
h : fβ ∘ f = fα
this✝ : Structure (constantsOn α) M := constantsOn.structure fα
this : Structure (constantsOn β) M := constantsOn.structure fβ
⊢ LHom.IsExpansionOn (LHom.constantsOnMap f) M

Next tactic:
exact
    ⟨fun {n} => Nat.casesOn n (fun F _x => (congr_fun h F : _)) fun n F => isEmptyElim F, fun R =>
      isEmptyElim R⟩
@[simp]
theorem card_withConstants :
    L[[α]].card = Cardinal.lift.{w'} L.card + Cardinal.lift.{max u v} #α := by
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
⊢ card (L[[α]]) = lift.{w', max u v} (card L) + lift.{max u v, w'} #α

Next tactic:
rw [withConstants, card_sum, card_constantsOn]
/-- The language map removing an empty constant set.  -/
@[simps]
def LEquiv.addEmptyConstants [ie : IsEmpty α] : L ≃ᴸ L[[α]] where
  toLHom := lhomWithConstants L α
  invLHom := LHom.sumElim (LHom.id L) (LHom.ofIsEmpty (constantsOn α) L)
  left_inv := by 

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
ie : IsEmpty α
⊢ LHom.comp (LHom.sumElim (LHom.id L) (LHom.ofIsEmpty (constantsOn α) L)) (lhomWithConstants L α) = LHom.id L

Next tactic:
rw [lhomWithConstants, LHom.sumElim_comp_inl]
/-- The language map removing an empty constant set.  -/
@[simps]
def LEquiv.addEmptyConstants [ie : IsEmpty α] : L ≃ᴸ L[[α]] where
  toLHom := lhomWithConstants L α
  invLHom := LHom.sumElim (LHom.id L) (LHom.ofIsEmpty (constantsOn α) L)
  left_inv := by rw [lhomWithConstants, LHom.sumElim_comp_inl]
  right_inv := by
    

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
ie : IsEmpty α
⊢ LHom.comp (lhomWithConstants L α) (LHom.sumElim (LHom.id L) (LHom.ofIsEmpty (constantsOn α) L)) = LHom.id (L[[α]])

Next tactic:
simp only [LHom.comp_sumElim, lhomWithConstants, LHom.comp_id]
/-- The language map removing an empty constant set.  -/
@[simps]
def LEquiv.addEmptyConstants [ie : IsEmpty α] : L ≃ᴸ L[[α]] where
  toLHom := lhomWithConstants L α
  invLHom := LHom.sumElim (LHom.id L) (LHom.ofIsEmpty (constantsOn α) L)
  left_inv := by rw [lhomWithConstants, LHom.sumElim_comp_inl]
  right_inv := by
    simp only [LHom.comp_sumElim, lhomWithConstants, LHom.comp_id]
    

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
ie : IsEmpty α
⊢ LHom.sumElim LHom.sumInl (LHom.comp LHom.sumInl (LHom.ofIsEmpty (constantsOn α) L)) = LHom.id (L[[α]])

Next tactic:
exact _root_.trans (congr rfl (Subsingleton.elim _ _)) LHom.sumElim_inl_inr
@[simp]
theorem LHom.map_constants_comp_sumInl {f : α → β} :
    (L.lhomWithConstantsMap f).comp LHom.sumInl = L.lhomWithConstants β := by 

Proof state:
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
β : Type u_1
f : α → β
⊢ comp (lhomWithConstantsMap L f) LHom.sumInl = lhomWithConstants L β

Next tactic:
ext
@[simp]
theorem LHom.map_constants_comp_sumInl {f : α → β} :
    (L.lhomWithConstantsMap f).comp LHom.sumInl = L.lhomWithConstants β := by ext <;> 

Proof state:
case h_fun.h.h
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
β : Type u_1
f : α → β
x✝¹ : ℕ
x✝ : Functions L x✝¹
⊢ onFunction (comp (lhomWithConstantsMap L f) LHom.sumInl) x✝ = onFunction (lhomWithConstants L β) x✝

Next tactic:
rfl
@[simp]
theorem LHom.map_constants_comp_sumInl {f : α → β} :
    (L.lhomWithConstantsMap f).comp LHom.sumInl = L.lhomWithConstants β := by ext <;> 

Proof state:
case h_rel.h.h
L : Language
L' : Language
M : Type w
inst✝ : Structure L M
α : Type w'
β : Type u_1
f : α → β
x✝¹ : ℕ
x✝ : Relations L x✝¹
⊢ onRelation (comp (lhomWithConstantsMap L f) LHom.sumInl) x✝ = onRelation (lhomWithConstants L β) x✝

Next tactic:
rfl
@[simp]
theorem withConstants_funMap_sum_inr {a : α} {x : Fin 0 → M} :
    @funMap (L[[α]]) M _ 0 (Sum.inr a : L[[α]].Functions 0) x = L.con a := by
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝¹ : Structure L M
α : Type u_1
inst✝ : Structure (constantsOn α) M
a : α
x : Fin 0 → M
⊢ funMap (Sum.inr a) x = ↑(Language.con L a)

Next tactic:
rw [Unique.eq_default x]
@[simp]
theorem withConstants_funMap_sum_inr {a : α} {x : Fin 0 → M} :
    @funMap (L[[α]]) M _ 0 (Sum.inr a : L[[α]].Functions 0) x = L.con a := by
  rw [Unique.eq_default x]
  

Proof state:
L : Language
L' : Language
M : Type w
inst✝¹ : Structure L M
α : Type u_1
inst✝ : Structure (constantsOn α) M
a : α
x : Fin 0 → M
⊢ funMap (Sum.inr a) default = ↑(Language.con L a)

Next tactic:
exact (LHom.sumInr : constantsOn α →ᴸ L.sum _).map_onFunction _ _
/-- Every finite nontrivial cancel_monoid_with_zero is a group_with_zero. -/
def Fintype.groupWithZeroOfCancel (M : Type*) [CancelMonoidWithZero M] [DecidableEq M] [Fintype M]
    [Nontrivial M] : GroupWithZero M :=
  { ‹Nontrivial M›,
    ‹CancelMonoidWithZero M› with
    inv := fun a => if h : a = 0 then 0 else Fintype.bijInv (mul_right_bijective_of_finite₀ h) 1
    mul_inv_cancel := fun a ha => by
      simp only [Inv.inv, dif_neg ha]
      exact Fintype.rightInverse_bijInv _ _
    inv_zero := by 

Proof state:
M✝ : Type u_1
inst✝⁵ : CancelMonoidWithZero M✝
inst✝⁴ : Finite M✝
M : Type u_2
inst✝³ : CancelMonoidWithZero M
inst✝² : DecidableEq M
inst✝¹ : Fintype M
inst✝ : Nontrivial M
src✝¹ : Nontrivial M := inst✝
src✝ : CancelMonoidWithZero M := inst✝³
⊢ 0⁻¹ = 0

Next tactic:
simp [Inv.inv, dif_pos rfl]
/-- Every finite nontrivial cancel_monoid_with_zero is a group_with_zero. -/
def Fintype.groupWithZeroOfCancel (M : Type*) [CancelMonoidWithZero M] [DecidableEq M] [Fintype M]
    [Nontrivial M] : GroupWithZero M :=
  { ‹Nontrivial M›,
    ‹CancelMonoidWithZero M› with
    inv := fun a => if h : a = 0 then 0 else Fintype.bijInv (mul_right_bijective_of_finite₀ h) 1
    mul_inv_cancel := fun a ha => by
      

Proof state:
M✝ : Type u_1
inst✝⁵ : CancelMonoidWithZero M✝
inst✝⁴ : Finite M✝
M : Type u_2
inst✝³ : CancelMonoidWithZero M
inst✝² : DecidableEq M
inst✝¹ : Fintype M
inst✝ : Nontrivial M
src✝¹ : Nontrivial M := inst✝
src✝ : CancelMonoidWithZero M := inst✝³
a : M
ha : a ≠ 0
⊢ a * a⁻¹ = 1

Next tactic:
simp only [Inv.inv, dif_neg ha]
/-- Every finite nontrivial cancel_monoid_with_zero is a group_with_zero. -/
def Fintype.groupWithZeroOfCancel (M : Type*) [CancelMonoidWithZero M] [DecidableEq M] [Fintype M]
    [Nontrivial M] : GroupWithZero M :=
  { ‹Nontrivial M›,
    ‹CancelMonoidWithZero M› with
    inv := fun a => if h : a = 0 then 0 else Fintype.bijInv (mul_right_bijective_of_finite₀ h) 1
    mul_inv_cancel := fun a ha => by
      simp only [Inv.inv, dif_neg ha]
      

Proof state:
M✝ : Type u_1
inst✝⁵ : CancelMonoidWithZero M✝
inst✝⁴ : Finite M✝
M : Type u_2
inst✝³ : CancelMonoidWithZero M
inst✝² : DecidableEq M
inst✝¹ : Fintype M
inst✝ : Nontrivial M
src✝¹ : Nontrivial M := inst✝
src✝ : CancelMonoidWithZero M := inst✝³
a : M
ha : a ≠ 0
⊢ a * bijInv (_ : Bijective fun b => a * b) 1 = 1

Next tactic:
exact Fintype.rightInverse_bijInv _ _
theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) :
    ∃ d : R, a = d ^ n := by
  

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
R : Type u_2
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
a b c : R
n : ℕ
cp : IsCoprime a b
h : a * b = c ^ n
⊢ ∃ d, a = d ^ n

Next tactic:
refine' exists_eq_pow_of_mul_eq_pow (isUnit_of_dvd_one _) h
theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) :
    ∃ d : R, a = d ^ n := by
  refine' exists_eq_pow_of_mul_eq_pow (isUnit_of_dvd_one _) h
  

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
R : Type u_2
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
a b c : R
n : ℕ
cp : IsCoprime a b
h : a * b = c ^ n
⊢ GCDMonoid.gcd a b ∣ 1

Next tactic:
obtain ⟨x, y, hxy⟩ := cp
theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) :
    ∃ d : R, a = d ^ n := by
  refine' exists_eq_pow_of_mul_eq_pow (isUnit_of_dvd_one _) h
  obtain ⟨x, y, hxy⟩ := cp
  

Proof state:
case intro.intro
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
R : Type u_2
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
a b c : R
n : ℕ
h : a * b = c ^ n
x y : R
hxy : x * a + y * b = 1
⊢ GCDMonoid.gcd a b ∣ 1

Next tactic:
rw [← hxy]
theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) :
    ∃ d : R, a = d ^ n := by
  refine' exists_eq_pow_of_mul_eq_pow (isUnit_of_dvd_one _) h
  obtain ⟨x, y, hxy⟩ := cp
  rw [← hxy]
  

Proof state:
case intro.intro
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
R : Type u_2
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
a b c : R
n : ℕ
h : a * b = c ^ n
x y : R
hxy : x * a + y * b = 1
⊢ GCDMonoid.gcd a b ∣ x * a + y * b

Next tactic:
exact  -- porting note: added `GCDMonoid.` twice
    dvd_add (dvd_mul_of_dvd_right (GCDMonoid.gcd_dvd_left _ _) _)
      (dvd_mul_of_dvd_right (GCDMonoid.gcd_dvd_right _ _) _)
nonrec
theorem Finset.exists_eq_pow_of_mul_eq_pow_of_coprime {ι R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R}
    (h : ∀ (i) (_ : i ∈ s) (j) (_ : j ∈ s), i ≠ j → IsCoprime (f i) (f j))
    (hprod : ∏ i in s, f i = c ^ n) : ∀ i ∈ s, ∃ d : R, f i = d ^ n := by
  

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
ι : Type u_2
R : Type u_3
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
n : ℕ
c : R
s : Finset ι
f : ι → R
h : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → IsCoprime (f i) (f j)
hprod : ∏ i in s, f i = c ^ n
⊢ ∀ i ∈ s, ∃ d, f i = d ^ n

Next tactic:
classical
    intro i hi
    rw [← insert_erase hi, prod_insert (not_mem_erase i s)] at hprod
    refine'
      exists_eq_pow_of_mul_eq_pow_of_coprime
        (IsCoprime.prod_right fun j hj => h i hi j (erase_subset i s hj) fun hij => _) hprod
    rw [hij] at hj
    exact (s.not_mem_erase _) hj
nonrec
theorem Finset.exists_eq_pow_of_mul_eq_pow_of_coprime {ι R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R}
    (h : ∀ (i) (_ : i ∈ s) (j) (_ : j ∈ s), i ≠ j → IsCoprime (f i) (f j))
    (hprod : ∏ i in s, f i = c ^ n) : ∀ i ∈ s, ∃ d : R, f i = d ^ n := by
  classical
    

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
ι : Type u_2
R : Type u_3
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
n : ℕ
c : R
s : Finset ι
f : ι → R
h : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → IsCoprime (f i) (f j)
hprod : ∏ i in s, f i = c ^ n
⊢ ∀ i ∈ s, ∃ d, f i = d ^ n

Next tactic:
intro i hi
nonrec
theorem Finset.exists_eq_pow_of_mul_eq_pow_of_coprime {ι R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R}
    (h : ∀ (i) (_ : i ∈ s) (j) (_ : j ∈ s), i ≠ j → IsCoprime (f i) (f j))
    (hprod : ∏ i in s, f i = c ^ n) : ∀ i ∈ s, ∃ d : R, f i = d ^ n := by
  classical
    intro i hi
    

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
ι : Type u_2
R : Type u_3
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
n : ℕ
c : R
s : Finset ι
f : ι → R
h : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → IsCoprime (f i) (f j)
hprod : ∏ i in s, f i = c ^ n
i : ι
hi : i ∈ s
⊢ ∃ d, f i = d ^ n

Next tactic:
rw [← insert_erase hi, prod_insert (not_mem_erase i s)] at hprod
nonrec
theorem Finset.exists_eq_pow_of_mul_eq_pow_of_coprime {ι R : Type*} [CommSemiring R] [IsDomain R]
    [GCDMonoid R] [Unique Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R}
    (h : ∀ (i) (_ : i ∈ s) (j) (_ : j ∈ s), i ≠ j → IsCoprime (f i) (f j))
    (hprod : ∏ i in s, f i = c ^ n) : ∀ i ∈ s, ∃ d : R, f i = d ^ n := by
  classical
    intro i hi
    rw [← insert_erase hi, prod_insert (not_mem_erase i s)] at hprod
    

Proof state:
M : Type u_1
inst✝⁵ : CancelMonoidWithZero M
inst✝⁴ : Finite M
ι : Type u_2
R : Type u_3
inst✝³ : CommSemiring R
inst✝² : IsDomain R
inst✝¹ : GCDMonoid R
inst✝ : Unique Rˣ
n : ℕ
c : R
s : Finset ι
f : ι → R
h : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → IsCoprime (f i) (f j)
i : ι
hprod : f i * ∏ x in erase s i, f x = c ^ n
hi : i ∈ s
⊢ ∃ d, f i = d ^ n

Next tactic:
refine'
      exists_eq_pow_of_mul_eq_pow_of_coprime
        (IsCoprime.prod_right fun j hj => h i hi j (erase_subset i s hj) fun hij => _) hprod