l3lab/ntp-mathlib huggingface dataset:
/-- The `positivity` extension which identifies expressions of the form `a ^ (b : ℤ)`,
such that `positivity` successfully recognises both `a` and `b`. -/
@[positivity (_ : α) ^ (_ : ℤ), Pow.pow _ (_ : ℤ)]
def evalZpow : PositivityExt where eval {u α} zα pα e := do
  let .app (.app _ (a : Q($α))) (b : Q(ℤ)) ← withReducible (whnf e) | throwError "not ^"
  let result ← catchNone do
    let _a ← synthInstanceQ q(LinearOrderedField $α)
    assumeInstancesCommute
    match ← whnfR b with
    | .app (.app (.app (.const `OfNat.ofNat _) _) (.lit (Literal.natVal n))) _ =>
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q $m + $m := ⟨⟩ -- b = bit0 m
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a $m))
    | .app (.app (.app (.const `Neg.neg _) _) _) b' =>
      let b' ← whnfR b'
      let .true := b'.isAppOfArity ``OfNat.ofNat 3 | throwError "not a ^ -n where n is a literal"
      let some n := (b'.getRevArg! 1).natLit? | throwError "not a ^ -n where n is a literal"
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q (-$m) + (-$m) := ⟨⟩ -- b = bit0 (-m)
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by 

Proof state:
u : Level
α : Q(Type u)
zα : Q(Zero «$α»)
pα : Q(PartialOrder «$α»)
e : Q(«$α»)
fn✝ : Expr
a : Q(«$α»)
b : Q(ℤ)
_a : Q(LinearOrderedField «$α»)
zα_eq✝ : «$zα» =Q CommMonoidWithZero.toZero
pα_eq✝ : «$pα» =Q StrictOrderedRing.toPartialOrder
us✝ : List Level
arg✝¹ arg✝ b'✝ b' : Expr
n : ℕ
x✝ : PUnit.{1}
m : Q(ℕ)
this✝ : «$b» =Q -↑«$m» + -↑«$m»
this : «$e» =Q «$a» ^ «$b»
⊢ Strictness zα pα e

Next tactic:
exact .nonnegative q(zpow_bit0_nonneg $a (-$m))
/-- The `positivity` extension which identifies expressions of the form `a ^ (b : ℤ)`,
such that `positivity` successfully recognises both `a` and `b`. -/
@[positivity (_ : α) ^ (_ : ℤ), Pow.pow _ (_ : ℤ)]
def evalZpow : PositivityExt where eval {u α} zα pα e := do
  let .app (.app _ (a : Q($α))) (b : Q(ℤ)) ← withReducible (whnf e) | throwError "not ^"
  let result ← catchNone do
    let _a ← synthInstanceQ q(LinearOrderedField $α)
    assumeInstancesCommute
    match ← whnfR b with
    | .app (.app (.app (.const `OfNat.ofNat _) _) (.lit (Literal.natVal n))) _ =>
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q $m + $m := ⟨⟩ -- b = bit0 m
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a $m))
    | .app (.app (.app (.const `Neg.neg _) _) _) b' =>
      let b' ← whnfR b'
      let .true := b'.isAppOfArity ``OfNat.ofNat 3 | throwError "not a ^ -n where n is a literal"
      let some n := (b'.getRevArg! 1).natLit? | throwError "not a ^ -n where n is a literal"
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q (-$m) + (-$m) := ⟨⟩ -- b = bit0 (-m)
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a (-$m)))
    | _ => throwError "not a ^ n where n is a literal or a negated literal"
  orElse result do
    let ra ← core zα pα a
    let ofNonneg (pa : Q(0 ≤ $a)) (_oα : Q(LinearOrderedSemifield $α)) :
        MetaM (Strictness zα pα e) := do
      haveI' : $e =Q $a ^ $b := ⟨⟩
      assumeInstancesCommute
      pure (by 

Proof state:
u : Level
α : Q(Type u)
zα : Q(Zero «$α»)
pα : Q(PartialOrder «$α»)
e : Q(«$α»)
fn✝ : Expr
a : Q(«$α»)
b : Q(ℤ)
result : Strictness zα pα e
ra : Strictness zα pα a
pa : Q(0 ≤ «$a»)
_oα : Q(LinearOrderedSemifield «$α»)
this : «$e» =Q «$a» ^ «$b»
zα_eq✝ : «$zα» =Q CommMonoidWithZero.toZero
pα_eq✝ : «$pα» =Q StrictOrderedSemiring.toPartialOrder
⊢ Strictness zα pα e

Next tactic:
exact .nonnegative (q(zpow_nonneg $pa $b))
/-- The `positivity` extension which identifies expressions of the form `a ^ (b : ℤ)`,
such that `positivity` successfully recognises both `a` and `b`. -/
@[positivity (_ : α) ^ (_ : ℤ), Pow.pow _ (_ : ℤ)]
def evalZpow : PositivityExt where eval {u α} zα pα e := do
  let .app (.app _ (a : Q($α))) (b : Q(ℤ)) ← withReducible (whnf e) | throwError "not ^"
  let result ← catchNone do
    let _a ← synthInstanceQ q(LinearOrderedField $α)
    assumeInstancesCommute
    match ← whnfR b with
    | .app (.app (.app (.const `OfNat.ofNat _) _) (.lit (Literal.natVal n))) _ =>
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q $m + $m := ⟨⟩ -- b = bit0 m
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a $m))
    | .app (.app (.app (.const `Neg.neg _) _) _) b' =>
      let b' ← whnfR b'
      let .true := b'.isAppOfArity ``OfNat.ofNat 3 | throwError "not a ^ -n where n is a literal"
      let some n := (b'.getRevArg! 1).natLit? | throwError "not a ^ -n where n is a literal"
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q (-$m) + (-$m) := ⟨⟩ -- b = bit0 (-m)
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a (-$m)))
    | _ => throwError "not a ^ n where n is a literal or a negated literal"
  orElse result do
    let ra ← core zα pα a
    let ofNonneg (pa : Q(0 ≤ $a)) (_oα : Q(LinearOrderedSemifield $α)) :
        MetaM (Strictness zα pα e) := do
      haveI' : $e =Q $a ^ $b := ⟨⟩
      assumeInstancesCommute
      pure (by exact .nonnegative (q(zpow_nonneg $pa $b)))
    let ofNonzero (pa : Q($a ≠ 0)) (_oα : Q(GroupWithZero $α)) : MetaM (Strictness zα pα e) := do
      haveI' : $e =Q $a ^ $b := ⟨⟩
      let _a ← synthInstanceQ q(GroupWithZero $α)
      assumeInstancesCommute
      pure (.nonzero (by 

Proof state:
u : Level
α : Q(Type u)
zα : Q(Zero «$α»)
pα : Q(PartialOrder «$α»)
e : Q(«$α»)
fn✝ : Expr
a : Q(«$α»)
b : Q(ℤ)
result : Strictness zα pα e
ra : Strictness zα pα a
ofNonneg : Q(0 ≤ «$a») → Q(LinearOrderedSemifield «$α») → MetaM (Strictness zα pα e) :=
  fun pa _oα =>
    let_fun zα_eq := (_ : «$zα» =Q CommMonoidWithZero.toZero);
    let_fun pα_eq := (_ : «$pα» =Q StrictOrderedSemiring.toPartialOrder);
    pure (Strictness.nonnegative q((_ : 0 ≤ «$a» ^ «$b»)))
pa : Q(«$a» ≠ 0)
_oα : Q(GroupWithZero «$α»)
this : «$e» =Q «$a» ^ «$b»
_a : Q(GroupWithZero «$α»)
zα_eq✝ : «$zα» =Q MonoidWithZero.toZero
_oα_eq✝ : «$_oα» =Q «$_a»
⊢ Q(«$e» ≠ 0)

Next tactic:
exact q(zpow_ne_zero $b $pa)
/-- The `positivity` extension which identifies expressions of the form `a ^ (b : ℤ)`,
such that `positivity` successfully recognises both `a` and `b`. -/
@[positivity (_ : α) ^ (_ : ℤ), Pow.pow _ (_ : ℤ)]
def evalZpow : PositivityExt where eval {u α} zα pα e := do
  let .app (.app _ (a : Q($α))) (b : Q(ℤ)) ← withReducible (whnf e) | throwError "not ^"
  let result ← catchNone do
    let _a ← synthInstanceQ q(LinearOrderedField $α)
    assumeInstancesCommute
    match ← whnfR b with
    | .app (.app (.app (.const `OfNat.ofNat _) _) (.lit (Literal.natVal n))) _ =>
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q $m + $m := ⟨⟩ -- b = bit0 m
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a $m))
    | .app (.app (.app (.const `Neg.neg _) _) _) b' =>
      let b' ← whnfR b'
      let .true := b'.isAppOfArity ``OfNat.ofNat 3 | throwError "not a ^ -n where n is a literal"
      let some n := (b'.getRevArg! 1).natLit? | throwError "not a ^ -n where n is a literal"
      guard (n % 2 = 0)
      have m : Q(ℕ) := mkRawNatLit (n / 2)
      haveI' : $b =Q (-$m) + (-$m) := ⟨⟩ -- b = bit0 (-m)
      haveI' : $e =Q $a ^ $b := ⟨⟩
      pure (by exact .nonnegative q(zpow_bit0_nonneg $a (-$m)))
    | _ => throwError "not a ^ n where n is a literal or a negated literal"
  orElse result do
    let ra ← core zα pα a
    let ofNonneg (pa : Q(0 ≤ $a)) (_oα : Q(LinearOrderedSemifield $α)) :
        MetaM (Strictness zα pα e) := do
      haveI' : $e =Q $a ^ $b := ⟨⟩
      assumeInstancesCommute
      pure (by exact .nonnegative (q(zpow_nonneg $pa $b)))
    let ofNonzero (pa : Q($a ≠ 0)) (_oα : Q(GroupWithZero $α)) : MetaM (Strictness zα pα e) := do
      haveI' : $e =Q $a ^ $b := ⟨⟩
      let _a ← synthInstanceQ q(GroupWithZero $α)
      assumeInstancesCommute
      pure (.nonzero (by exact q(zpow_ne_zero $b $pa)))
    match ra with
    | .positive pa =>
      try
        let _a ← synthInstanceQ (q(LinearOrderedSemifield $α) : Q(Type u))
        haveI' : $e =Q $a ^ $b := ⟨⟩
        assumeInstancesCommute
        pure (by 

Proof state:
u : Level
α : Q(Type u)
zα : Q(Zero «$α»)
pα : Q(PartialOrder «$α»)
e : Q(«$α»)
fn✝ : Expr
a : Q(«$α»)
b : Q(ℤ)
result : Strictness zα pα e
ra : Strictness zα pα a
ofNonneg : Q(0 ≤ «$a») → Q(LinearOrderedSemifield «$α») → MetaM (Strictness zα pα e) :=
  fun pa _oα =>
    let_fun zα_eq := (_ : «$zα» =Q CommMonoidWithZero.toZero);
    let_fun pα_eq := (_ : «$pα» =Q StrictOrderedSemiring.toPartialOrder);
    pure (Strictness.nonnegative q((_ : 0 ≤ «$a» ^ «$b»)))
ofNonzero : Q(«$a» ≠ 0) → Q(GroupWithZero «$α») → MetaM (Strictness zα pα e) :=
  fun pa _oα => do
    let _a ← synthInstanceQ q(GroupWithZero «$α»)
    let_fun zα_eq := (_ : «$zα» =Q MonoidWithZero.toZero);
      let_fun _oα_eq := (_ : «$_oα» =Q «$_a»);
      pure (Strictness.nonzero q((_ : «$a» ^ «$b» ≠ 0)))
pa : Q(0 < «$a»)
_a : Q(LinearOrderedSemifield «$α»)
this : «$e» =Q «$a» ^ «$b»
zα_eq✝ : «$zα» =Q CommMonoidWithZero.toZero
pα_eq✝ : «$pα» =Q StrictOrderedSemiring.toPartialOrder
⊢ Strictness zα pα e

Next tactic:
exact .positive (q(zpow_pos_of_pos $pa $b))
instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ where
  coe f := f.toLinearMap
  coe_injective' f g h := by 

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
M₁ : Type u_4
M₂ : Type u_5
M₃ : Type u_6
M₄ : Type u_7
inst✝¹⁰ : CommSemiring R
inst✝⁹ : AddCommMonoid M
inst✝⁸ : AddCommMonoid M₁
inst✝⁷ : AddCommMonoid M₂
inst✝⁶ : AddCommMonoid M₃
inst✝⁵ : AddCommMonoid M₄
inst✝⁴ : Module R M
inst✝³ : Module R M₁
inst✝² : Module R M₂
inst✝¹ : Module R M₃
inst✝ : Module R M₄
Q₁ : QuadraticForm R M₁
Q₂ : QuadraticForm R M₂
Q₃ : QuadraticForm R M₃
Q₄ : QuadraticForm R M₄
f g : Q₁ →qᵢ Q₂
h : (fun f => ⇑f.toLinearMap) f = (fun f => ⇑f.toLinearMap) g
⊢ f = g

Next tactic:
cases f
instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ where
  coe f := f.toLinearMap
  coe_injective' f g h := by cases f; 

Proof state:
case mk
ι : Type u_1
R : Type u_2
M : Type u_3
M₁ : Type u_4
M₂ : Type u_5
M₃ : Type u_6
M₄ : Type u_7
inst✝¹⁰ : CommSemiring R
inst✝⁹ : AddCommMonoid M
inst✝⁸ : AddCommMonoid M₁
inst✝⁷ : AddCommMonoid M₂
inst✝⁶ : AddCommMonoid M₃
inst✝⁵ : AddCommMonoid M₄
inst✝⁴ : Module R M
inst✝³ : Module R M₁
inst✝² : Module R M₂
inst✝¹ : Module R M₃
inst✝ : Module R M₄
Q₁ : QuadraticForm R M₁
Q₂ : QuadraticForm R M₂
Q₃ : QuadraticForm R M₃
Q₄ : QuadraticForm R M₄
g : Q₁ →qᵢ Q₂
toLinearMap✝ : M₁ →ₗ[R] M₂
map_app'✝ : ∀ (m : M₁), Q₂ (AddHom.toFun toLinearMap✝.toAddHom m) = Q₁ m
h : (fun f => ⇑f.toLinearMap) { toLinearMap := toLinearMap✝, map_app' := map_app'✝ } = (fun f => ⇑f.toLinearMap) g
⊢ { toLinearMap := toLinearMap✝, map_app' := map_app'✝ } = g

Next tactic:
cases g
instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ where
  coe f := f.toLinearMap
  coe_injective' f g h := by cases f; cases g; 

Proof state:
case mk.mk
ι : Type u_1
R : Type u_2
M : Type u_3
M₁ : Type u_4
M₂ : Type u_5
M₃ : Type u_6
M₄ : Type u_7
inst✝¹⁰ : CommSemiring R
inst✝⁹ : AddCommMonoid M
inst✝⁸ : AddCommMonoid M₁
inst✝⁷ : AddCommMonoid M₂
inst✝⁶ : AddCommMonoid M₃
inst✝⁵ : AddCommMonoid M₄
inst✝⁴ : Module R M
inst✝³ : Module R M₁
inst✝² : Module R M₂
inst✝¹ : Module R M₃
inst✝ : Module R M₄
Q₁ : QuadraticForm R M₁
Q₂ : QuadraticForm R M₂
Q₃ : QuadraticForm R M₃
Q₄ : QuadraticForm R M₄
toLinearMap✝¹ : M₁ →ₗ[R] M₂
map_app'✝¹ : ∀ (m : M₁), Q₂ (AddHom.toFun toLinearMap✝¹.toAddHom m) = Q₁ m
toLinearMap✝ : M₁ →ₗ[R] M₂
map_app'✝ : ∀ (m : M₁), Q₂ (AddHom.toFun toLinearMap✝.toAddHom m) = Q₁ m
h :
  (fun f => ⇑f.toLinearMap) { toLinearMap := toLinearMap✝¹, map_app' := map_app'✝¹ } =
    (fun f => ⇑f.toLinearMap) { toLinearMap := toLinearMap✝, map_app' := map_app'✝ }
⊢ { toLinearMap := toLinearMap✝¹, map_app' := map_app'✝¹ } = { toLinearMap := toLinearMap✝, map_app' := map_app'✝ }

Next tactic:
congr
instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ where
  coe f := f.toLinearMap
  coe_injective' f g h := by cases f; cases g; congr; 

Proof state:
case mk.mk.e_toLinearMap
ι : Type u_1
R : Type u_2
M : Type u_3
M₁ : Type u_4
M₂ : Type u_5
M₃ : Type u_6
M₄ : Type u_7
inst✝¹⁰ : CommSemiring R
inst✝⁹ : AddCommMonoid M
inst✝⁸ : AddCommMonoid M₁
inst✝⁷ : AddCommMonoid M₂
inst✝⁶ : AddCommMonoid M₃
inst✝⁵ : AddCommMonoid M₄
inst✝⁴ : Module R M
inst✝³ : Module R M₁
inst✝² : Module R M₂
inst✝¹ : Module R M₃
inst✝ : Module R M₄
Q₁ : QuadraticForm R M₁
Q₂ : QuadraticForm R M₂
Q₃ : QuadraticForm R M₃
Q₄ : QuadraticForm R M₄
toLinearMap✝¹ : M₁ →ₗ[R] M₂
map_app'✝¹ : ∀ (m : M₁), Q₂ (AddHom.toFun toLinearMap✝¹.toAddHom m) = Q₁ m
toLinearMap✝ : M₁ →ₗ[R] M₂
map_app'✝ : ∀ (m : M₁), Q₂ (AddHom.toFun toLinearMap✝.toAddHom m) = Q₁ m
h :
  (fun f => ⇑f.toLinearMap) { toLinearMap := toLinearMap✝¹, map_app' := map_app'✝¹ } =
    (fun f => ⇑f.toLinearMap) { toLinearMap := toLinearMap✝, map_app' := map_app'✝ }
⊢ toLinearMap✝¹ = toLinearMap✝

Next tactic:
exact FunLike.coe_injective h
/-- The composition of two isometries between quadratic forms. -/
@[simps]
def comp (g : Q₂ →qᵢ Q₃) (f : Q₁ →qᵢ Q₂) : Q₁ →qᵢ Q₃ where
  toFun x := g (f x)
  map_app' x := by 

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
M₁ : Type u_4
M₂ : Type u_5
M₃ : Type u_6
M₄ : Type u_7
inst✝¹⁰ : CommSemiring R
inst✝⁹ : AddCommMonoid M
inst✝⁸ : AddCommMonoid M₁
inst✝⁷ : AddCommMonoid M₂
inst✝⁶ : AddCommMonoid M₃
inst✝⁵ : AddCommMonoid M₄
inst✝⁴ : Module R M
inst✝³ : Module R M₁
inst✝² : Module R M₂
inst✝¹ : Module R M₃
inst✝ : Module R M₄
Q₁ : QuadraticForm R M₁
Q₂ : QuadraticForm R M₂
Q₃ : QuadraticForm R M₃
Q₄ : QuadraticForm R M₄
g : Q₂ →qᵢ Q₃
f : Q₁ →qᵢ Q₂
src✝ : M₁ →ₗ[R] M₃ := g.toLinearMap ∘ₗ f.toLinearMap
x : M₁
⊢ Q₃
      (AddHom.toFun
        {
            toAddHom :=
              { toFun := fun x => g (f x),
                map_add' :=
                  (_ :
                    ∀ (x y : M₁),
                      AddHom.toFun src✝.toAddHom (x + y) =
                        AddHom.toFun src✝.toAddHom x + AddHom.toFun src✝.toAddHom y) },
            map_smul' :=
              (_ :
                ∀ (r : R) (x : M₁),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
        x) =
    Q₁ x

Next tactic:
rw [← f.map_app, ← g.map_app]
@[simp] lemma sized_empty : (∅ : Set (Finset α)).Sized r := by 

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
A B : Set (Finset α)
s : Finset α
r : ℕ
⊢ Sized r ∅

Next tactic:
simp [Sized]
@[simp] lemma sized_singleton : ({s} : Set (Finset α)).Sized r ↔ s.card = r := by 

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
A B : Set (Finset α)
s : Finset α
r : ℕ
⊢ Sized r {s} ↔ card s = r

Next tactic:
simp [Sized]
@[simp]
theorem sized_iUnion {f : ι → Set (Finset α)} : (⋃ i, f i).Sized r ↔ ∀ i, (f i).Sized r := by
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
A B : Set (Finset α)
s : Finset α
r : ℕ
f : ι → Set (Finset α)
⊢ Sized r (⋃ i, f i) ↔ ∀ (i : ι), Sized r (f i)

Next tactic:
simp_rw [Set.Sized, Set.mem_iUnion, forall_exists_index]
@[simp]
theorem sized_iUnion {f : ι → Set (Finset α)} : (⋃ i, f i).Sized r ↔ ∀ i, (f i).Sized r := by
  simp_rw [Set.Sized, Set.mem_iUnion, forall_exists_index]
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
A B : Set (Finset α)
s : Finset α
r : ℕ
f : ι → Set (Finset α)
⊢ (∀ ⦃x : Finset α⦄ (x_1 : ι), x ∈ f x_1 → card x = r) ↔ ∀ (i : ι) ⦃x : Finset α⦄, x ∈ f i → card x = r

Next tactic:
exact forall_swap
theorem sized_iUnion₂ {f : ∀ i, κ i → Set (Finset α)} :
    (⋃ (i) (j), f i j).Sized r ↔ ∀ i j, (f i j).Sized r :=
 by 

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
A B : Set (Finset α)
s : Finset α
r : ℕ
f : (i : ι) → κ i → Set (Finset α)
⊢ Sized r (⋃ i, ⋃ j, f i j) ↔ ∀ (i : ι) (j : κ i), Sized r (f i j)

Next tactic:
simp only [Set.sized_iUnion]
theorem subset_powersetCard_univ_iff : 𝒜 ⊆ powersetCard r univ ↔ (𝒜 : Set (Finset α)).Sized r :=
  forall_congr' fun A => by 

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
inst✝ : Fintype α
𝒜 : Finset (Finset α)
s : Finset α
r : ℕ
A : Finset α
⊢ A ∈ 𝒜 → A ∈ powersetCard r univ ↔ A ∈ ↑𝒜 → card A = r

Next tactic:
rw [mem_powersetCard_univ, mem_coe]
theorem _root_.Set.Sized.card_le (h𝒜 : (𝒜 : Set (Finset α)).Sized r) :
    card 𝒜 ≤ (Fintype.card α).choose r := by
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
inst✝ : Fintype α
𝒜 : Finset (Finset α)
s : Finset α
r : ℕ
h𝒜 : Set.Sized r ↑𝒜
⊢ card 𝒜 ≤ Nat.choose (Fintype.card α) r

Next tactic:
rw [Fintype.card, ← card_powersetCard]
theorem _root_.Set.Sized.card_le (h𝒜 : (𝒜 : Set (Finset α)).Sized r) :
    card 𝒜 ≤ (Fintype.card α).choose r := by
  rw [Fintype.card, ← card_powersetCard]
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
inst✝ : Fintype α
𝒜 : Finset (Finset α)
s : Finset α
r : ℕ
h𝒜 : Set.Sized r ↑𝒜
⊢ card 𝒜 ≤ card (powersetCard r univ)

Next tactic:
exact card_le_of_subset (subset_powersetCard_univ_iff.mpr h𝒜)
@[simp]
theorem sum_card_slice : (∑ r in Iic (Fintype.card α), (𝒜 # r).card) = 𝒜.card := by
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
𝒜 : Finset (Finset α)
A A₁ A₂ : Finset α
r r₁ r₂ : ℕ
inst✝ : Fintype α
⊢ ∑ r in Iic (Fintype.card α), card (𝒜 # r) = card 𝒜

Next tactic:
letI := Classical.decEq α
@[simp]
theorem sum_card_slice : (∑ r in Iic (Fintype.card α), (𝒜 # r).card) = 𝒜.card := by
  letI := Classical.decEq α
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
𝒜 : Finset (Finset α)
A A₁ A₂ : Finset α
r r₁ r₂ : ℕ
inst✝ : Fintype α
this : DecidableEq α := Classical.decEq α
⊢ ∑ r in Iic (Fintype.card α), card (𝒜 # r) = card 𝒜

Next tactic:
rw [← card_biUnion, biUnion_slice]
@[simp]
theorem sum_card_slice : (∑ r in Iic (Fintype.card α), (𝒜 # r).card) = 𝒜.card := by
  letI := Classical.decEq α
  rw [← card_biUnion, biUnion_slice]
  

Proof state:
α : Type u_1
ι : Sort u_2
κ : ι → Sort u_3
𝒜 : Finset (Finset α)
A A₁ A₂ : Finset α
r r₁ r₂ : ℕ
inst✝ : Fintype α
this : DecidableEq α := Classical.decEq α
⊢ ∀ x ∈ Iic (Fintype.card α), ∀ y ∈ Iic (Fintype.card α), x ≠ y → Disjoint (𝒜 # x) (𝒜 # y)

Next tactic:
exact Finset.pairwiseDisjoint_slice.subset (Set.subset_univ _)
theorem partOfVertex_mem (v : V) : P.partOfVertex v ∈ P.parts := by
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v : V
⊢ partOfVertex P v ∈ P.parts

Next tactic:
obtain ⟨h, -⟩ := (P.isPartition.2 v).choose_spec.1
theorem partOfVertex_mem (v : V) : P.partOfVertex v ∈ P.parts := by
  obtain ⟨h, -⟩ := (P.isPartition.2 v).choose_spec.1
  

Proof state:
case intro
V : Type u
G : SimpleGraph V
P : Partition G
v : V
h : Exists.choose (_ : ∃! b x, v ∈ b) ∈ P.parts
⊢ partOfVertex P v ∈ P.parts

Next tactic:
exact h
theorem mem_partOfVertex (v : V) : v ∈ P.partOfVertex v := by
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v : V
⊢ v ∈ partOfVertex P v

Next tactic:
obtain ⟨⟨h1, h2⟩, _h3⟩ := (P.isPartition.2 v).choose_spec
theorem mem_partOfVertex (v : V) : v ∈ P.partOfVertex v := by
  obtain ⟨⟨h1, h2⟩, _h3⟩ := (P.isPartition.2 v).choose_spec
  

Proof state:
case intro.intro
V : Type u
G : SimpleGraph V
P : Partition G
v : V
_h3 : ∀ (y : Set V), (fun b => ∃! x, v ∈ b) y → y = Exists.choose (_ : ∃! b x, v ∈ b)
h1 : Exists.choose (_ : ∃! b x, v ∈ b) ∈ P.parts
h2 :
  (fun x => v ∈ Exists.choose (_ : ∃! b x, v ∈ b)) h1 ∧
    ∀ (y : Exists.choose (_ : ∃! b x, v ∈ b) ∈ P.parts), (fun x => v ∈ Exists.choose (_ : ∃! b x, v ∈ b)) y → y = h1
⊢ v ∈ partOfVertex P v

Next tactic:
exact h2.1
theorem partOfVertex_ne_of_adj {v w : V} (h : G.Adj v w) : P.partOfVertex v ≠ P.partOfVertex w := by
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v w : V
h : Adj G v w
⊢ partOfVertex P v ≠ partOfVertex P w

Next tactic:
intro hn
theorem partOfVertex_ne_of_adj {v w : V} (h : G.Adj v w) : P.partOfVertex v ≠ P.partOfVertex w := by
  intro hn
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v w : V
h : Adj G v w
hn : partOfVertex P v = partOfVertex P w
⊢ False

Next tactic:
have hw := P.mem_partOfVertex w
theorem partOfVertex_ne_of_adj {v w : V} (h : G.Adj v w) : P.partOfVertex v ≠ P.partOfVertex w := by
  intro hn
  have hw := P.mem_partOfVertex w
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v w : V
h : Adj G v w
hn : partOfVertex P v = partOfVertex P w
hw : w ∈ partOfVertex P w
⊢ False

Next tactic:
rw [← hn] at hw
theorem partOfVertex_ne_of_adj {v w : V} (h : G.Adj v w) : P.partOfVertex v ≠ P.partOfVertex w := by
  intro hn
  have hw := P.mem_partOfVertex w
  rw [← hn] at hw
  

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v w : V
h : Adj G v w
hn : partOfVertex P v = partOfVertex P w
hw : w ∈ partOfVertex P v
⊢ False

Next tactic:
exact P.independent _ (P.partOfVertex_mem v) (P.mem_partOfVertex v) hw (G.ne_of_adj h) h
/-- Create a coloring using the parts themselves as the colors.
Each vertex is colored by the part it's contained in. -/
def toColoring : G.Coloring P.parts :=
  Coloring.mk (fun v ↦ ⟨P.partOfVertex v, P.partOfVertex_mem v⟩) fun hvw ↦ by
    

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v✝ w✝ : V
hvw : Adj G v✝ w✝
⊢ (fun v => { val := partOfVertex P v, property := (_ : partOfVertex P v ∈ P.parts) }) v✝ ≠
    (fun v => { val := partOfVertex P v, property := (_ : partOfVertex P v ∈ P.parts) }) w✝

Next tactic:
rw [Ne.def, Subtype.mk_eq_mk]
/-- Create a coloring using the parts themselves as the colors.
Each vertex is colored by the part it's contained in. -/
def toColoring : G.Coloring P.parts :=
  Coloring.mk (fun v ↦ ⟨P.partOfVertex v, P.partOfVertex_mem v⟩) fun hvw ↦ by
    rw [Ne.def, Subtype.mk_eq_mk]
    

Proof state:
V : Type u
G : SimpleGraph V
P : Partition G
v✝ w✝ : V
hvw : Adj G v✝ w✝
⊢ ¬partOfVertex P v✝ = partOfVertex P w✝

Next tactic:
exact P.partOfVertex_ne_of_adj hvw
/-- Creates a partition from a coloring. -/
@[simps]
def Coloring.toPartition {α : Type v} (C : G.Coloring α) : G.Partition
    where
  parts := C.colorClasses
  isPartition := C.colorClasses_isPartition
  independent := by
    

Proof state:
V : Type u
G : SimpleGraph V
α : Type v
C : Coloring G α
⊢ ∀ s ∈ colorClasses C, IsAntichain G.Adj s

Next tactic:
rintro s ⟨c, rfl⟩
/-- Creates a partition from a coloring. -/
@[simps]
def Coloring.toPartition {α : Type v} (C : G.Coloring α) : G.Partition
    where
  parts := C.colorClasses
  isPartition := C.colorClasses_isPartition
  independent := by
    rintro s ⟨c, rfl⟩
    

Proof state:
case intro
V : Type u
G : SimpleGraph V
α : Type v
C : Coloring G α
c : V
⊢ IsAntichain G.Adj {x | Setoid.Rel (Setoid.ker ⇑C) x c}

Next tactic:
apply C.color_classes_independent
theorem partitionable_iff_colorable {n : ℕ} : G.Partitionable n ↔ G.Colorable n := by
  

Proof state:
V : Type u
G : SimpleGraph V
n : ℕ
⊢ Partitionable G n ↔ Colorable G n

Next tactic:
constructor
theorem partitionable_iff_colorable {n : ℕ} : G.Partitionable n ↔ G.Colorable n := by
  constructor
  · 

Proof state:
case mp
V : Type u
G : SimpleGraph V
n : ℕ
⊢ Partitionable G n → Colorable G n

Next tactic:
rintro ⟨P, hf, hc⟩
theorem partitionable_iff_colorable {n : ℕ} : G.Partitionable n ↔ G.Colorable n := by
  constructor
  · rintro ⟨P, hf, hc⟩
    

Proof state:
case mp.intro.intro
V : Type u
G : SimpleGraph V
n : ℕ
P : Partition G
hf : Set.Finite P.parts
hc : Finset.card (Set.Finite.toFinset hf) ≤ n
⊢ Colorable G n

Next tactic:
have : Fintype P.parts := hf.fintype
theorem partitionable_iff_colorable {n : ℕ} : G.Partitionable n ↔ G.Colorable n := by
  constructor
  · rintro ⟨P, hf, hc⟩
    have : Fintype P.parts := hf.fintype
    

Proof state:
case mp.intro.intro
V : Type u
G : SimpleGraph V
n : ℕ
P : Partition G
hf : Set.Finite P.parts
hc : Finset.card (Set.Finite.toFinset hf) ≤ n
this : Fintype ↑P.parts
⊢ Colorable G n

Next tactic:
rw [Set.Finite.card_toFinset hf] at hc