l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem mem_center_iff {z : M} : z ∈ center M ↔ ∀ g, g * z = z * g := by
  

Proof state:
M : Type u_1
inst✝ : Monoid M
z : M
⊢ z ∈ center M ↔ ∀ (g : M), g * z = z * g

Next tactic:
rw [← Semigroup.mem_center_iff]
@[to_additive]
theorem mem_center_iff {z : M} : z ∈ center M ↔ ∀ g, g * z = z * g := by
  rw [← Semigroup.mem_center_iff]
  

Proof state:
M : Type u_1
inst✝ : Monoid M
z : M
⊢ z ∈ center M ↔ z ∈ Set.center M

Next tactic:
exact Iff.rfl
example : SMulCommClass (center M) (center M) M := by 

Proof state:
M : Type ?u.10308
inst✝ : Monoid M
⊢ SMulCommClass (↥(center M)) (↥(center M)) M

Next tactic:
infer_instance
/-- For a monoid, the units of the center inject into the center of the units. This is not an
equivalence in general; one case when it is is for groups with zero, which is covered in
`centerUnitsEquivUnitsCenter`. -/
@[to_additive (attr := simps! apply_coe_val)
  "For an additive monoid, the units of the center inject into the center of the units."]
def unitsCenterToCenterUnits [Monoid M] : (Submonoid.center M)ˣ →* Submonoid.center (Mˣ) :=
  (Units.map (Submonoid.center M).subtype).codRestrict _ <|
      fun u ↦ Submonoid.mem_center_iff.mpr <|
        fun r ↦ Units.ext <| by
        

Proof state:
M : Type ?u.11981
inst✝ : Monoid M
u : (↥(Submonoid.center M))ˣ
r : Mˣ
⊢ ↑(r * (Units.map (Submonoid.subtype (Submonoid.center M))) u) =
    ↑((Units.map (Submonoid.subtype (Submonoid.center M))) u * r)

Next tactic:
rw [Units.val_mul, Units.coe_map, Submonoid.coe_subtype, Units.val_mul, Units.coe_map,
          Submonoid.coe_subtype, u.1.prop.comm r]
/-- There is (noncomputably) an equivalence between a finite type `α` and `Fin (Nat.card α)`. -/
def Finite.equivFin (α : Type*) [Finite α] : α ≃ Fin (Nat.card α) := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
⊢ α ≃ Fin (Nat.card α)

Next tactic:
have := (Finite.exists_equiv_fin α).choose_spec.some
/-- There is (noncomputably) an equivalence between a finite type `α` and `Fin (Nat.card α)`. -/
def Finite.equivFin (α : Type*) [Finite α] : α ≃ Fin (Nat.card α) := by
  have := (Finite.exists_equiv_fin α).choose_spec.some
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
this : α ≃ Fin (Exists.choose (_ : ∃ n, Nonempty (α ≃ Fin n)))
⊢ α ≃ Fin (Nat.card α)

Next tactic:
rwa [Nat.card_eq_of_equiv_fin this]
/-- Similar to `Finite.equivFin` but with control over the term used for the cardinality. -/
def Finite.equivFinOfCardEq [Finite α] {n : ℕ} (h : Nat.card α = n) : α ≃ Fin n := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
n : ℕ
h : Nat.card α = n
⊢ α ≃ Fin n

Next tactic:
subst h
/-- Similar to `Finite.equivFin` but with control over the term used for the cardinality. -/
def Finite.equivFinOfCardEq [Finite α] {n : ℕ} (h : Nat.card α = n) : α ≃ Fin n := by
  subst h
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ α ≃ Fin (Nat.card α)

Next tactic:
apply Finite.equivFin
theorem Nat.card_eq (α : Type*) :
    Nat.card α = if h : Finite α then @Fintype.card α (Fintype.ofFinite α) else 0 := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
⊢ Nat.card α = if h : Finite α then Fintype.card α else 0

Next tactic:
cases finite_or_infinite α
theorem Nat.card_eq (α : Type*) :
    Nat.card α = if h : Finite α then @Fintype.card α (Fintype.ofFinite α) else 0 := by
  cases finite_or_infinite α
  · 

Proof state:
case inl
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
h✝ : Finite α
⊢ Nat.card α = if h : Finite α then Fintype.card α else 0

Next tactic:
letI := Fintype.ofFinite α
theorem Nat.card_eq (α : Type*) :
    Nat.card α = if h : Finite α then @Fintype.card α (Fintype.ofFinite α) else 0 := by
  cases finite_or_infinite α
  · letI := Fintype.ofFinite α
    

Proof state:
case inl
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
h✝ : Finite α
this : Fintype α := Fintype.ofFinite α
⊢ Nat.card α = if h : Finite α then Fintype.card α else 0

Next tactic:
simp only [*, Nat.card_eq_fintype_card, dif_pos]
theorem Nat.card_eq (α : Type*) :
    Nat.card α = if h : Finite α then @Fintype.card α (Fintype.ofFinite α) else 0 := by
  cases finite_or_infinite α
  · letI := Fintype.ofFinite α
    simp only [*, Nat.card_eq_fintype_card, dif_pos]
  · 

Proof state:
case inr
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
h✝ : Infinite α
⊢ Nat.card α = if h : Finite α then Fintype.card α else 0

Next tactic:
simp only [*, card_eq_zero_of_infinite, not_finite_iff_infinite.mpr, dite_false]
theorem Finite.card_pos_iff [Finite α] : 0 < Nat.card α ↔ Nonempty α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ 0 < Nat.card α ↔ Nonempty α

Next tactic:
haveI := Fintype.ofFinite α
theorem Finite.card_pos_iff [Finite α] : 0 < Nat.card α ↔ Nonempty α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
this : Fintype α
⊢ 0 < Nat.card α ↔ Nonempty α

Next tactic:
rw [Nat.card_eq_fintype_card, Fintype.card_pos_iff]
theorem card_eq [Finite α] [Finite β] : Nat.card α = Nat.card β ↔ Nonempty (α ≃ β) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
⊢ Nat.card α = Nat.card β ↔ Nonempty (α ≃ β)

Next tactic:
haveI := Fintype.ofFinite α
theorem card_eq [Finite α] [Finite β] : Nat.card α = Nat.card β ↔ Nonempty (α ≃ β) := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
this : Fintype α
⊢ Nat.card α = Nat.card β ↔ Nonempty (α ≃ β)

Next tactic:
haveI := Fintype.ofFinite β
theorem card_eq [Finite α] [Finite β] : Nat.card α = Nat.card β ↔ Nonempty (α ≃ β) := by
  haveI := Fintype.ofFinite α
  haveI := Fintype.ofFinite β
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
this✝ : Fintype α
this : Fintype β
⊢ Nat.card α = Nat.card β ↔ Nonempty (α ≃ β)

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.card_eq]
theorem card_le_one_iff_subsingleton [Finite α] : Nat.card α ≤ 1 ↔ Subsingleton α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ Nat.card α ≤ 1 ↔ Subsingleton α

Next tactic:
haveI := Fintype.ofFinite α
theorem card_le_one_iff_subsingleton [Finite α] : Nat.card α ≤ 1 ↔ Subsingleton α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
this : Fintype α
⊢ Nat.card α ≤ 1 ↔ Subsingleton α

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.card_le_one_iff_subsingleton]
theorem one_lt_card_iff_nontrivial [Finite α] : 1 < Nat.card α ↔ Nontrivial α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ 1 < Nat.card α ↔ Nontrivial α

Next tactic:
haveI := Fintype.ofFinite α
theorem one_lt_card_iff_nontrivial [Finite α] : 1 < Nat.card α ↔ Nontrivial α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
this : Fintype α
⊢ 1 < Nat.card α ↔ Nontrivial α

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.one_lt_card_iff_nontrivial]
@[simp]
theorem card_option [Finite α] : Nat.card (Option α) = Nat.card α + 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ Nat.card (Option α) = Nat.card α + 1

Next tactic:
haveI := Fintype.ofFinite α
@[simp]
theorem card_option [Finite α] : Nat.card (Option α) = Nat.card α + 1 := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
this : Fintype α
⊢ Nat.card (Option α) = Nat.card α + 1

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.card_option]
theorem card_le_of_injective [Finite β] (f : α → β) (hf : Function.Injective f) :
    Nat.card α ≤ Nat.card β := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite β
f : α → β
hf : Function.Injective f
⊢ Nat.card α ≤ Nat.card β

Next tactic:
haveI := Fintype.ofFinite β
theorem card_le_of_injective [Finite β] (f : α → β) (hf : Function.Injective f) :
    Nat.card α ≤ Nat.card β := by
  haveI := Fintype.ofFinite β
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite β
f : α → β
hf : Function.Injective f
this : Fintype β
⊢ Nat.card α ≤ Nat.card β

Next tactic:
haveI := Fintype.ofInjective f hf
theorem card_le_of_injective [Finite β] (f : α → β) (hf : Function.Injective f) :
    Nat.card α ≤ Nat.card β := by
  haveI := Fintype.ofFinite β
  haveI := Fintype.ofInjective f hf
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite β
f : α → β
hf : Function.Injective f
this✝ : Fintype β
this : Fintype α
⊢ Nat.card α ≤ Nat.card β

Next tactic:
simpa only [Nat.card_eq_fintype_card, ge_iff_le] using Fintype.card_le_of_injective f hf
theorem card_le_of_surjective [Finite α] (f : α → β) (hf : Function.Surjective f) :
    Nat.card β ≤ Nat.card α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
f : α → β
hf : Function.Surjective f
⊢ Nat.card β ≤ Nat.card α

Next tactic:
haveI := Fintype.ofFinite α
theorem card_le_of_surjective [Finite α] (f : α → β) (hf : Function.Surjective f) :
    Nat.card β ≤ Nat.card α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
f : α → β
hf : Function.Surjective f
this : Fintype α
⊢ Nat.card β ≤ Nat.card α

Next tactic:
haveI := Fintype.ofSurjective f hf
theorem card_le_of_surjective [Finite α] (f : α → β) (hf : Function.Surjective f) :
    Nat.card β ≤ Nat.card α := by
  haveI := Fintype.ofFinite α
  haveI := Fintype.ofSurjective f hf
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
f : α → β
hf : Function.Surjective f
this✝ : Fintype α
this : Fintype β
⊢ Nat.card β ≤ Nat.card α

Next tactic:
simpa only [Nat.card_eq_fintype_card, ge_iff_le] using Fintype.card_le_of_surjective f hf
theorem card_eq_zero_iff [Finite α] : Nat.card α = 0 ↔ IsEmpty α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
⊢ Nat.card α = 0 ↔ IsEmpty α

Next tactic:
haveI := Fintype.ofFinite α
theorem card_eq_zero_iff [Finite α] : Nat.card α = 0 ↔ IsEmpty α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
this : Fintype α
⊢ Nat.card α = 0 ↔ IsEmpty α

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.card_eq_zero_iff]
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
⊢ Nat.card α = 0

Next tactic:
cases finite_or_infinite β
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  cases finite_or_infinite β
  · 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
h✝ : Finite β
⊢ Nat.card α = 0

Next tactic:
haveI := card_eq_zero_iff.mp h
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  cases finite_or_infinite β
  · haveI := card_eq_zero_iff.mp h
    

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
h✝ : Finite β
this : IsEmpty β
⊢ Nat.card α = 0

Next tactic:
haveI := Function.isEmpty f
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  cases finite_or_infinite β
  · haveI := card_eq_zero_iff.mp h
    haveI := Function.isEmpty f
    

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
h✝ : Finite β
this✝ : IsEmpty β
this : IsEmpty α
⊢ Nat.card α = 0

Next tactic:
exact Nat.card_of_isEmpty
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  cases finite_or_infinite β
  · haveI := card_eq_zero_iff.mp h
    haveI := Function.isEmpty f
    exact Nat.card_of_isEmpty
  · 

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
h✝ : Infinite β
⊢ Nat.card α = 0

Next tactic:
haveI := Infinite.of_surjective f hf
/-- NB: `Nat.card` is defined to be `0` for infinite types. -/
theorem card_eq_zero_of_surjective {f : α → β} (hf : Function.Surjective f) (h : Nat.card β = 0) :
    Nat.card α = 0 := by
  cases finite_or_infinite β
  · haveI := card_eq_zero_iff.mp h
    haveI := Function.isEmpty f
    exact Nat.card_of_isEmpty
  · haveI := Infinite.of_surjective f hf
    

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
hf : Function.Surjective f
h : Nat.card β = 0
h✝ : Infinite β
this : Infinite α
⊢ Nat.card α = 0

Next tactic:
exact Nat.card_eq_zero_of_infinite
theorem card_sum [Finite α] [Finite β] : Nat.card (Sum α β) = Nat.card α + Nat.card β := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
⊢ Nat.card (α ⊕ β) = Nat.card α + Nat.card β

Next tactic:
haveI := Fintype.ofFinite α
theorem card_sum [Finite α] [Finite β] : Nat.card (Sum α β) = Nat.card α + Nat.card β := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
this : Fintype α
⊢ Nat.card (α ⊕ β) = Nat.card α + Nat.card β

Next tactic:
haveI := Fintype.ofFinite β
theorem card_sum [Finite α] [Finite β] : Nat.card (Sum α β) = Nat.card α + Nat.card β := by
  haveI := Fintype.ofFinite α
  haveI := Fintype.ofFinite β
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Finite α
inst✝ : Finite β
this✝ : Fintype α
this : Fintype β
⊢ Nat.card (α ⊕ β) = Nat.card α + Nat.card β

Next tactic:
simp only [Nat.card_eq_fintype_card, Fintype.card_sum]
theorem card_subtype_le [Finite α] (p : α → Prop) : Nat.card { x // p x } ≤ Nat.card α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
p : α → Prop
⊢ Nat.card { x // p x } ≤ Nat.card α

Next tactic:
haveI := Fintype.ofFinite α
theorem card_subtype_le [Finite α] (p : α → Prop) : Nat.card { x // p x } ≤ Nat.card α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
p : α → Prop
this : Fintype α
⊢ Nat.card { x // p x } ≤ Nat.card α

Next tactic:
simpa only [Nat.card_eq_fintype_card, ge_iff_le] using Fintype.card_subtype_le p
theorem card_subtype_lt [Finite α] {p : α → Prop} {x : α} (hx : ¬p x) :
    Nat.card { x // p x } < Nat.card α := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
p : α → Prop
x : α
hx : ¬p x
⊢ Nat.card { x // p x } < Nat.card α

Next tactic:
haveI := Fintype.ofFinite α
theorem card_subtype_lt [Finite α] {p : α → Prop} {x : α} (hx : ¬p x) :
    Nat.card { x // p x } < Nat.card α := by
  haveI := Fintype.ofFinite α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Finite α
p : α → Prop
x : α
hx : ¬p x
this : Fintype α
⊢ Nat.card { x // p x } < Nat.card α

Next tactic:
simpa only [Nat.card_eq_fintype_card, gt_iff_lt] using Fintype.card_subtype_lt hx
theorem card_eq_coe_nat_card (α : Type*) [Finite α] : card α = Nat.card α := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
⊢ card α = ↑(Nat.card α)

Next tactic:
unfold PartENat.card
theorem card_eq_coe_nat_card (α : Type*) [Finite α] : card α = Nat.card α := by
  unfold PartENat.card
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
⊢ Cardinal.toPartENat (Cardinal.mk α) = ↑(Nat.card α)

Next tactic:
apply symm
theorem card_eq_coe_nat_card (α : Type*) [Finite α] : card α = Nat.card α := by
  unfold PartENat.card
  apply symm
  

Proof state:
case a
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
⊢ ↑(Nat.card α) = Cardinal.toPartENat (Cardinal.mk α)

Next tactic:
rw [Cardinal.natCast_eq_toPartENat_iff]
theorem card_eq_coe_nat_card (α : Type*) [Finite α] : card α = Nat.card α := by
  unfold PartENat.card
  apply symm
  rw [Cardinal.natCast_eq_toPartENat_iff]
  

Proof state:
case a
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Finite α
⊢ ↑(Nat.card α) = Cardinal.mk α

Next tactic:
exact Finite.cast_card_eq_mk
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
⊢ Nat.card ↑(s ∪ t) ≤ Nat.card ↑s + Nat.card ↑t

Next tactic:
cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
  · 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
h : Finite ↑(s ∪ t)
⊢ Nat.card ↑(s ∪ t) ≤ Nat.card ↑s + Nat.card ↑t

Next tactic:
rw [finite_coe_iff, finite_union, ← finite_coe_iff, ← finite_coe_iff] at h
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
  · rw [finite_coe_iff, finite_union, ← finite_coe_iff, ← finite_coe_iff] at h
    

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
h : Finite ↑s ∧ Finite ↑t
⊢ Nat.card ↑(s ∪ t) ≤ Nat.card ↑s + Nat.card ↑t

Next tactic:
cases h
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
  · rw [finite_coe_iff, finite_union, ← finite_coe_iff, ← finite_coe_iff] at h
    cases h
    

Proof state:
case inl.intro
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
left✝ : Finite ↑s
right✝ : Finite ↑t
⊢ Nat.card ↑(s ∪ t) ≤ Nat.card ↑s + Nat.card ↑t

Next tactic:
rw [← Cardinal.natCast_le, Nat.cast_add, Finite.cast_card_eq_mk, Finite.cast_card_eq_mk,
      Finite.cast_card_eq_mk]
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
  · rw [finite_coe_iff, finite_union, ← finite_coe_iff, ← finite_coe_iff] at h
    cases h
    rw [← Cardinal.natCast_le, Nat.cast_add, Finite.cast_card_eq_mk, Finite.cast_card_eq_mk,
      Finite.cast_card_eq_mk]
    

Proof state:
case inl.intro
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
left✝ : Finite ↑s
right✝ : Finite ↑t
⊢ Cardinal.mk ↑(s ∪ t) ≤ Cardinal.mk ↑s + Cardinal.mk ↑t

Next tactic:
exact Cardinal.mk_union_le s t
theorem card_union_le (s t : Set α) : Nat.card (↥(s ∪ t)) ≤ Nat.card s + Nat.card t := by
  cases' _root_.finite_or_infinite (↥(s ∪ t)) with h h
  · rw [finite_coe_iff, finite_union, ← finite_coe_iff, ← finite_coe_iff] at h
    cases h
    rw [← Cardinal.natCast_le, Nat.cast_add, Finite.cast_card_eq_mk, Finite.cast_card_eq_mk,
      Finite.cast_card_eq_mk]
    exact Cardinal.mk_union_le s t
  · 

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
h : Infinite ↑(s ∪ t)
⊢ Nat.card ↑(s ∪ t) ≤ Nat.card ↑s + Nat.card ↑t

Next tactic:
exact Nat.card_eq_zero_of_infinite.trans_le (zero_le _)
theorem card_lt_card (hsub : s ⊂ t) : Nat.card s < Nat.card t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
ht : Set.Finite t
hsub : s ⊂ t
⊢ Nat.card ↑s < Nat.card ↑t

Next tactic:
have : Fintype t := Finite.fintype ht
theorem card_lt_card (hsub : s ⊂ t) : Nat.card s < Nat.card t := by
  have : Fintype t := Finite.fintype ht
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
ht : Set.Finite t
hsub : s ⊂ t
this : Fintype ↑t
⊢ Nat.card ↑s < Nat.card ↑t

Next tactic:
have : Fintype s := Finite.fintype (subset ht (subset_of_ssubset hsub))
theorem card_lt_card (hsub : s ⊂ t) : Nat.card s < Nat.card t := by
  have : Fintype t := Finite.fintype ht
  have : Fintype s := Finite.fintype (subset ht (subset_of_ssubset hsub))
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
ht : Set.Finite t
hsub : s ⊂ t
this✝ : Fintype ↑t
this : Fintype ↑s
⊢ Nat.card ↑s < Nat.card ↑t

Next tactic:
simp only [Nat.card_eq_fintype_card]
theorem card_lt_card (hsub : s ⊂ t) : Nat.card s < Nat.card t := by
  have : Fintype t := Finite.fintype ht
  have : Fintype s := Finite.fintype (subset ht (subset_of_ssubset hsub))
  simp only [Nat.card_eq_fintype_card]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
ht : Set.Finite t
hsub : s ⊂ t
this✝ : Fintype ↑t
this : Fintype ↑s
⊢ Fintype.card ↑s < Fintype.card ↑t

Next tactic:
exact Set.card_lt_card hsub
theorem equiv_image_eq_iff_subset (e : α ≃ α) (hs : s.Finite) : e '' s = s ↔ e '' s ⊆ s :=
  ⟨fun h ↦ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s t : Set α
ht : Set.Finite t
e : α ≃ α
hs : Set.Finite s
h : ⇑e '' s = s
⊢ ⇑e '' s ⊆ s

Next tactic:
rw [h]
/-- Auxliary construction used to build `TensorProduct.gradedComm`.

This operates on direct sums of tensors instead of tensors of direct sums. -/
def gradedCommAux : DirectSum _ 𝒜ℬ →ₗ[R] DirectSum _ ℬ𝒜 := by
  

Proof state:
R : Type u_1
ι : Type u_2
A : Type u_3
B : Type u_4
inst✝¹¹ : CommSemiring ι
inst✝¹⁰ : Module ι (Additive ℤˣ)
inst✝⁹ : DecidableEq ι
𝒜 : ι → Type u_5
ℬ : ι → Type u_6
inst✝⁸ : CommRing R
inst✝⁷ : (i : ι) → AddCommGroup (𝒜 i)
inst✝⁶ : (i : ι) → AddCommGroup (ℬ i)
inst✝⁵ : (i : ι) → Module R (𝒜 i)
inst✝⁴ : (i : ι) → Module R (ℬ i)
inst✝³ : DirectSum.GRing 𝒜
inst✝² : DirectSum.GRing ℬ
inst✝¹ : DirectSum.GAlgebra R 𝒜
inst✝ : DirectSum.GAlgebra R ℬ
⊢ (⨁ (i : ι × ι), 𝒜 i.1 ⊗[R] ℬ i.2) →ₗ[R] ⨁ (i : ι × ι), ℬ i.1 ⊗[R] 𝒜 i.2

Next tactic:
refine DirectSum.toModule R _ _ fun i => ?_
/-- Auxliary construction used to build `TensorProduct.gradedComm`.

This operates on direct sums of tensors instead of tensors of direct sums. -/
def gradedCommAux : DirectSum _ 𝒜ℬ →ₗ[R] DirectSum _ ℬ𝒜 := by
  refine DirectSum.toModule R _ _ fun i => ?_
  

Proof state:
R : Type u_1
ι : Type u_2
A : Type u_3
B : Type u_4
inst✝¹¹ : CommSemiring ι
inst✝¹⁰ : Module ι (Additive ℤˣ)
inst✝⁹ : DecidableEq ι
𝒜 : ι → Type u_5
ℬ : ι → Type u_6
inst✝⁸ : CommRing R
inst✝⁷ : (i : ι) → AddCommGroup (𝒜 i)
inst✝⁶ : (i : ι) → AddCommGroup (ℬ i)
inst✝⁵ : (i : ι) → Module R (𝒜 i)
inst✝⁴ : (i : ι) → Module R (ℬ i)
inst✝³ : DirectSum.GRing 𝒜
inst✝² : DirectSum.GRing ℬ
inst✝¹ : DirectSum.GAlgebra R 𝒜
inst✝ : DirectSum.GAlgebra R ℬ
i : ι × ι
⊢ 𝒜 i.1 ⊗[R] ℬ i.2 →ₗ[R] ⨁ (i : ι × ι), ℬ i.1 ⊗[R] 𝒜 i.2

Next tactic:
have o := DirectSum.lof R _ ℬ𝒜 i.swap
/-- Auxliary construction used to build `TensorProduct.gradedComm`.

This operates on direct sums of tensors instead of tensors of direct sums. -/
def gradedCommAux : DirectSum _ 𝒜ℬ →ₗ[R] DirectSum _ ℬ𝒜 := by
  refine DirectSum.toModule R _ _ fun i => ?_
  have o := DirectSum.lof R _ ℬ𝒜 i.swap
  

Proof state:
R : Type u_1
ι : Type u_2
A : Type u_3
B : Type u_4
inst✝¹¹ : CommSemiring ι
inst✝¹⁰ : Module ι (Additive ℤˣ)
inst✝⁹ : DecidableEq ι
𝒜 : ι → Type u_5
ℬ : ι → Type u_6
inst✝⁸ : CommRing R
inst✝⁷ : (i : ι) → AddCommGroup (𝒜 i)
inst✝⁶ : (i : ι) → AddCommGroup (ℬ i)
inst✝⁵ : (i : ι) → Module R (𝒜 i)
inst✝⁴ : (i : ι) → Module R (ℬ i)
inst✝³ : DirectSum.GRing 𝒜
inst✝² : DirectSum.GRing ℬ
inst✝¹ : DirectSum.GAlgebra R 𝒜
inst✝ : DirectSum.GAlgebra R ℬ
i : ι × ι
o : ℬ (Prod.swap i).1 ⊗[R] 𝒜 (Prod.swap i).2 →ₗ[R] ⨁ (i : ι × ι), ℬ i.1 ⊗[R] 𝒜 i.2
⊢ 𝒜 i.1 ⊗[R] ℬ i.2 →ₗ[R] ⨁ (i : ι × ι), ℬ i.1 ⊗[R] 𝒜 i.2

Next tactic:
have s : ℤˣ := ((-1 : ℤˣ)^(i.1* i.2 : ι) : ℤˣ)