l3lab/ntp-mathlib huggingface dataset:
/-- `π C (· ∈ s)` is finite for a finite set `s`. -/
noncomputable
instance : Fintype (π C (· ∈ s)) := by
  let f : π C (· ∈ s) → (s → Bool) := fun x j ↦ x.val j.val
  refine Fintype.ofInjective f ?_
  intro ⟨_, x, hx, rfl⟩ ⟨_, y, hy, rfl⟩ h
  ext i
  by_cases hi : i ∈ s
  · 

Proof state:
case pos
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : ↑(π C fun x => x ∈ s) → { x // x ∈ s } → Bool := fun x j => ↑x ↑j
x : I → Bool
hx : x ∈ C
y : I → Bool
hy : y ∈ C
h :
  f { val := Proj (fun x => x ∈ s) x, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) x) } =
    f { val := Proj (fun x => x ∈ s) y, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) y) }
i : I
hi : i ∈ s
⊢ ↑{ val := Proj (fun x => x ∈ s) x, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) x) } i =
    ↑{ val := Proj (fun x => x ∈ s) y, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) y) } i

Next tactic:
exact congrFun h ⟨i, hi⟩
/-- `π C (· ∈ s)` is finite for a finite set `s`. -/
noncomputable
instance : Fintype (π C (· ∈ s)) := by
  let f : π C (· ∈ s) → (s → Bool) := fun x j ↦ x.val j.val
  refine Fintype.ofInjective f ?_
  intro ⟨_, x, hx, rfl⟩ ⟨_, y, hy, rfl⟩ h
  ext i
  by_cases hi : i ∈ s
  · exact congrFun h ⟨i, hi⟩
  · 

Proof state:
case neg
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : ↑(π C fun x => x ∈ s) → { x // x ∈ s } → Bool := fun x j => ↑x ↑j
x : I → Bool
hx : x ∈ C
y : I → Bool
hy : y ∈ C
h :
  f { val := Proj (fun x => x ∈ s) x, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) x) } =
    f { val := Proj (fun x => x ∈ s) y, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) y) }
i : I
hi : i ∉ s
⊢ ↑{ val := Proj (fun x => x ∈ s) x, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) x) } i =
    ↑{ val := Proj (fun x => x ∈ s) y, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) y) } i

Next tactic:
simp only [Proj, if_neg hi]
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
⊢ ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s))

Next tactic:
intro f _
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
⊢ f ∈ Submodule.span ℤ (Set.range (spanFinBasis C s))

Next tactic:
rw [Finsupp.mem_span_range_iff_exists_finsupp]
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
⊢ ∃ c, (Finsupp.sum c fun i a => a • spanFinBasis C s i) = f

Next tactic:
use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  

Proof state:
case h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
⊢ (Finsupp.sum
      (Finsupp.onFinset Finset.univ f.toFun
        (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
      fun i a => a • spanFinBasis C s i) =
    f

Next tactic:
ext x
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  

Proof state:
case h.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
⊢ (Finsupp.sum
        (Finsupp.onFinset Finset.univ f.toFun
          (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
        fun i a => a • spanFinBasis C s i)
      x =
    f x

Next tactic:
change LocallyConstant.evalₗ ℤ x _ = _
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  change LocallyConstant.evalₗ ℤ x _ = _
  

Proof state:
case h.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
⊢ (LocallyConstant.evalₗ ℤ x)
      (Finsupp.sum
        (Finsupp.onFinset Finset.univ f.toFun
          (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
        fun i a => a • spanFinBasis C s i) =
    f x

Next tactic:
simp only [zsmul_eq_mul, map_finsupp_sum, LocallyConstant.evalₗ_apply,
    LocallyConstant.coe_mul, Pi.mul_apply, spanFinBasis, LocallyConstant.coe_mk, mul_ite, mul_one,
    mul_zero, Finsupp.sum_ite_eq, Finsupp.mem_support_iff, ne_eq, ite_not]
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  change LocallyConstant.evalₗ ℤ x _ = _
  simp only [zsmul_eq_mul, map_finsupp_sum, LocallyConstant.evalₗ_apply,
    LocallyConstant.coe_mul, Pi.mul_apply, spanFinBasis, LocallyConstant.coe_mk, mul_ite, mul_one,
    mul_zero, Finsupp.sum_ite_eq, Finsupp.mem_support_iff, ne_eq, ite_not]
  

Proof state:
case h.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
⊢ (if
        (Finsupp.onFinset Finset.univ f.toFun
              (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
            x =
          0 then
      0
    else
      ↑((Finsupp.onFinset Finset.univ f.toFun
              (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
            x)
        x) =
    f x

Next tactic:
split_ifs with h <;> [exact h.symm; rfl]
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  change LocallyConstant.evalₗ ℤ x _ = _
  simp only [zsmul_eq_mul, map_finsupp_sum, LocallyConstant.evalₗ_apply,
    LocallyConstant.coe_mul, Pi.mul_apply, spanFinBasis, LocallyConstant.coe_mk, mul_ite, mul_one,
    mul_zero, Finsupp.sum_ite_eq, Finsupp.mem_support_iff, ne_eq, ite_not]
  

Proof state:
case h.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
⊢ (if
        (Finsupp.onFinset Finset.univ f.toFun
              (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
            x =
          0 then
      0
    else
      ↑((Finsupp.onFinset Finset.univ f.toFun
              (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
            x)
        x) =
    f x

Next tactic:
split_ifs with h
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  change LocallyConstant.evalₗ ℤ x _ = _
  simp only [zsmul_eq_mul, map_finsupp_sum, LocallyConstant.evalₗ_apply,
    LocallyConstant.coe_mul, Pi.mul_apply, spanFinBasis, LocallyConstant.coe_mk, mul_ite, mul_one,
    mul_zero, Finsupp.sum_ite_eq, Finsupp.mem_support_iff, ne_eq, ite_not]
  split_ifs with h <;> [

Proof state:
case pos
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
h :
  (Finsupp.onFinset Finset.univ f.toFun
        (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
      x =
    0
⊢ 0 = f x

Next tactic:
exact h.symm
open Classical in
theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) := by
  intro f _
  rw [Finsupp.mem_span_range_iff_exists_finsupp]
  use Finsupp.onFinset (Finset.univ) f.toFun (fun _ _ ↦ Finset.mem_univ _)
  ext x
  change LocallyConstant.evalₗ ℤ x _ = _
  simp only [zsmul_eq_mul, map_finsupp_sum, LocallyConstant.evalₗ_apply,
    LocallyConstant.coe_mul, Pi.mul_apply, spanFinBasis, LocallyConstant.coe_mk, mul_ite, mul_one,
    mul_zero, Finsupp.sum_ite_eq, Finsupp.mem_support_iff, ne_eq, ite_not]
  split_ifs with h <;> [exact h.symm; 

Proof state:
case neg
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
f : LocallyConstant ↑(π C fun x => x ∈ s) ℤ
a✝ : f ∈ ⊤
x : ↑(π C fun x => x ∈ s)
h :
  ¬(Finsupp.onFinset Finset.univ f.toFun
          (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
        x =
      0
⊢ ↑((Finsupp.onFinset Finset.univ f.toFun
            (_ : ∀ (x : ↑(π C fun x => x ∈ s)), LocallyConstant.toFun f x ≠ 0 → x ∈ Finset.univ))
          x)
      x =
    f x

Next tactic:
rfl
theorem list_prod_apply (x : C) (l : List (LocallyConstant C ℤ)) :
    l.prod x = (l.map (LocallyConstant.evalMonoidHom x)).prod := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x : ↑C
l : List (LocallyConstant ↑C ℤ)
⊢ (List.prod l) x = List.prod (List.map (⇑(LocallyConstant.evalMonoidHom x)) l)

Next tactic:
rw [← map_list_prod (LocallyConstant.evalMonoidHom x) l]
theorem list_prod_apply (x : C) (l : List (LocallyConstant C ℤ)) :
    l.prod x = (l.map (LocallyConstant.evalMonoidHom x)).prod := by
  rw [← map_list_prod (LocallyConstant.evalMonoidHom x) l]
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x : ↑C
l : List (LocallyConstant ↑C ℤ)
⊢ (List.prod l) x = (LocallyConstant.evalMonoidHom x) (List.prod l)

Next tactic:
rfl
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
⊢ (List.prod (factors C s x)) y = 1

Next tactic:
rw [list_prod_apply (π C (· ∈ s)) y _]
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
⊢ List.prod (List.map (⇑(LocallyConstant.evalMonoidHom y)) (factors C s x)) = 1

Next tactic:
apply List.prod_eq_one
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  

Proof state:
case hl
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
⊢ ∀ x_1 ∈ List.map (⇑(LocallyConstant.evalMonoidHom y)) (factors C s x), x_1 = 1

Next tactic:
simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  

Proof state:
case hl
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
⊢ ∀ (x_1 : ℤ),
    (∃ a,
        (∃ a_1 ∈ Finset.sort (fun x x_2 => x ≥ x_2) s,
            (if ↑x a_1 = true then e (π C fun x => x ∈ s) a_1 else 1 - e (π C fun x => x ∈ s) a_1) = a) ∧
          (MonoidHom.comp (Pi.evalMonoidHom (fun a => ℤ) x) LocallyConstant.coeFnMonoidHom) a = x_1) →
      x_1 = 1

Next tactic:
rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
  

Proof state:
case hl.intro.intro.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
b : I
left✝ : b ∈ Finset.sort (fun x x_1 => x ≥ x_1) s
⊢ (MonoidHom.comp (Pi.evalMonoidHom (fun a => ℤ) x) LocallyConstant.coeFnMonoidHom)
      (if ↑x b = true then e (π C fun x => x ∈ s) b else 1 - e (π C fun x => x ∈ s) b) =
    1

Next tactic:
dsimp
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
  dsimp
  

Proof state:
case hl.intro.intro.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
b : I
left✝ : b ∈ Finset.sort (fun x x_1 => x ≥ x_1) s
⊢ (if ↑x b = true then e (π C fun x => x ∈ s) b else 1 - e (π C fun x => x ∈ s) b) x = 1

Next tactic:
split_ifs with hh
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
  dsimp
  split_ifs with hh
  · 

Proof state:
case pos
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
b : I
left✝ : b ∈ Finset.sort (fun x x_1 => x ≥ x_1) s
hh : ↑x b = true
⊢ (e (π C fun x => x ∈ s) b) x = 1

Next tactic:
rw [e, LocallyConstant.coe_mk, if_pos hh]
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
  dsimp
  split_ifs with hh
  · rw [e, LocallyConstant.coe_mk, if_pos hh]
  · 

Proof state:
case neg
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
b : I
left✝ : b ∈ Finset.sort (fun x x_1 => x ≥ x_1) s
hh : ¬↑x b = true
⊢ (1 - e (π C fun x => x ∈ s) b) x = 1

Next tactic:
rw [LocallyConstant.sub_apply, e, LocallyConstant.coe_mk, LocallyConstant.coe_mk, if_neg hh]
theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 := by
  rw [list_prod_apply (π C (· ∈ s)) y _]
  apply List.prod_eq_one
  simp only [h, List.mem_map, LocallyConstant.evalMonoidHom, factors]
  rintro _ ⟨a, ⟨b, _, rfl⟩, rfl⟩
  dsimp
  split_ifs with hh
  · rw [e, LocallyConstant.coe_mk, if_pos hh]
  · rw [LocallyConstant.sub_apply, e, LocallyConstant.coe_mk, LocallyConstant.coe_mk, if_neg hh]
    

Proof state:
case neg
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y = x
b : I
left✝ : b ∈ Finset.sort (fun x x_1 => x ≥ x_1) s
hh : ¬↑x b = true
⊢ LocallyConstant.toFun 1 x - 0 = 1

Next tactic:
simp only [LocallyConstant.toFun_eq_coe, LocallyConstant.coe_one, Pi.one_apply, sub_zero]
theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x : ↑(π C fun x => x ∈ s)
a : I
hx : ↑x a = true
⊢ e (π C fun x => x ∈ s) a ∈ factors C s x

Next tactic:
rcases x with ⟨_, z, hz, rfl⟩
theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x := by
  rcases x with ⟨_, z, hz, rfl⟩
  

Proof state:
case mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
a : I
z : I → Bool
hz : z ∈ C
hx :
  ↑{ val := Proj (fun x => x ∈ s) z, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) z) } a =
    true
⊢ e (π C fun x => x ∈ s) a ∈
    factors C s
      { val := Proj (fun x => x ∈ s) z, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) z) }

Next tactic:
simp only [factors, List.mem_map, Finset.mem_sort]
theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x := by
  rcases x with ⟨_, z, hz, rfl⟩
  simp only [factors, List.mem_map, Finset.mem_sort]
  

Proof state:
case mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
a : I
z : I → Bool
hz : z ∈ C
hx :
  ↑{ val := Proj (fun x => x ∈ s) z, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) z) } a =
    true
⊢ ∃ a_1 ∈ s,
    (if Proj (fun x => x ∈ s) z a_1 = true then e (π C fun x => x ∈ s) a_1 else 1 - e (π C fun x => x ∈ s) a_1) =
      e (π C fun x => x ∈ s) a

Next tactic:
refine ⟨a, ⟨?_, if_pos hx⟩⟩
theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x := by
  rcases x with ⟨_, z, hz, rfl⟩
  simp only [factors, List.mem_map, Finset.mem_sort]
  refine ⟨a, ⟨?_, if_pos hx⟩⟩
  

Proof state:
case mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
a : I
z : I → Bool
hz : z ∈ C
hx :
  ↑{ val := Proj (fun x => x ∈ s) z, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) z) } a =
    true
⊢ a ∈ s

Next tactic:
simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at hx
theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x := by
  rcases x with ⟨_, z, hz, rfl⟩
  simp only [factors, List.mem_map, Finset.mem_sort]
  refine ⟨a, ⟨?_, if_pos hx⟩⟩
  simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at hx
  

Proof state:
case mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
a : I
z : I → Bool
hz : z ∈ C
hx : a ∈ s ∧ z a = true
⊢ a ∈ s

Next tactic:
exact hx.1
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
a : I
ha : ↑y a = true
hx : ↑x a = false
⊢ 1 - e (π C fun x => x ∈ s) a ∈ factors C s x

Next tactic:
simp only [factors, List.mem_map, Finset.mem_sort]
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  simp only [factors, List.mem_map, Finset.mem_sort]
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
a : I
ha : ↑y a = true
hx : ↑x a = false
⊢ ∃ a_1 ∈ s,
    (if ↑x a_1 = true then e (π C fun x => x ∈ s) a_1 else 1 - e (π C fun x => x ∈ s) a_1) =
      1 - e (π C fun x => x ∈ s) a

Next tactic:
use a
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  simp only [factors, List.mem_map, Finset.mem_sort]
  use a
  

Proof state:
case h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
a : I
ha : ↑y a = true
hx : ↑x a = false
⊢ a ∈ s ∧
    (if ↑x a = true then e (π C fun x => x ∈ s) a else 1 - e (π C fun x => x ∈ s) a) = 1 - e (π C fun x => x ∈ s) a

Next tactic:
simp only [hx, ite_false, and_true]
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  simp only [factors, List.mem_map, Finset.mem_sort]
  use a
  simp only [hx, ite_false, and_true]
  

Proof state:
case h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
a : I
ha : ↑y a = true
hx : ↑x a = false
⊢ a ∈ s

Next tactic:
rcases y with ⟨_, z, hz, rfl⟩
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  simp only [factors, List.mem_map, Finset.mem_sort]
  use a
  simp only [hx, ite_false, and_true]
  rcases y with ⟨_, z, hz, rfl⟩
  

Proof state:
case h.mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x : ↑(π C fun x => x ∈ s)
a : I
hx : ↑x a = false
z : I → Bool
hz : z ∈ C
ha :
  ↑{ val := Proj (fun x => x ∈ s) z, property := (_ : ∃ a ∈ C, Proj (fun x => x ∈ s) a = Proj (fun x => x ∈ s) z) } a =
    true
⊢ a ∈ s

Next tactic:
simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at ha
theorem one_sub_e_mem_of_false {x y : (π C (· ∈ s))} {a : I} (ha : y.val a = true)
    (hx : x.val a = false) : 1 - e (π C (· ∈ s)) a ∈ factors C s x := by
  simp only [factors, List.mem_map, Finset.mem_sort]
  use a
  simp only [hx, ite_false, and_true]
  rcases y with ⟨_, z, hz, rfl⟩
  simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at ha
  

Proof state:
case h.mk.intro.intro
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x : ↑(π C fun x => x ∈ s)
a : I
hx : ↑x a = false
z : I → Bool
hz : z ∈ C
ha : a ∈ s ∧ z a = true
⊢ a ∈ s

Next tactic:
exact ha.1
theorem factors_prod_eq_basis_of_ne {x y : (π C (· ∈ s))} (h : y ≠ x) :
    (factors C s x).prod y = 0 := by
  

Proof state:
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
s : Finset I
x y : ↑(π C fun x => x ∈ s)
h : y ≠ x
⊢ (List.prod (factors C s x)) y = 0

Next tactic:
rw [list_prod_apply (π C (· ∈ s)) y _]