l3lab/ntp-mathlib huggingface dataset:
/-- If `s` is a finite subset of `I`, then the good products span. -/
theorem GoodProducts.spanFin : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (· ∈ s)))) := by
  rw [span_iff_products]
  refine le_trans (spanFinBasis.span C s) ?_
  rw [Submodule.span_le]
  rintro _ ⟨x, rfl⟩
  rw [← factors_prod_eq_basis]
  let l := s.sort (·≥·)
  dsimp [factors]
  suffices : l.Chain' (·>·) → (l.map (fun i ↦ if x.val i = true then e (π C (· ∈ s)) i
      else (1 - (e (π C (· ∈ s)) i)))).prod ∈
      Submodule.span ℤ ((Products.eval (π C (· ∈ s))) '' {m | m.val ≤ l})
  · exact Submodule.span_mono (Set.image_subset_range _ _) (this (Finset.sort_sorted_gt _).chain')
  induction l with
  | nil =>
    intro _
    apply Submodule.subset_span
    exact ⟨⟨[], List.chain'_nil⟩,⟨Or.inl rfl, rfl⟩⟩
  | cons a as ih =>
    rw [List.map_cons, List.prod_cons]
    intro ha
    specialize ih (by rw [List.chain'_cons'] at ha; exact ha.2)
    rw [Finsupp.mem_span_image_iff_total] at ih
    simp only [Finsupp.mem_supported, Finsupp.total_apply] at ih
    obtain ⟨c, hc, hc'⟩ := ih
    rw [← hc']; clear hc'
    have hmap := fun g ↦ map_finsupp_sum (LinearMap.mulLeft ℤ (e (π C (· ∈ s)) a)) c g
    dsimp at hmap ⊢
    split_ifs
    · rw [hmap]
      exact finsupp_sum_mem_span_eval _ _ ha hc
    · ring_nf
      rw [hmap]
      apply Submodule.add_mem
      · apply Submodule.neg_mem
        exact finsupp_sum_mem_span_eval _ _ ha hc
      · apply Submodule.finsupp_sum_mem
        intro m hm
        apply Submodule.smul_mem
        apply Submodule.subset_span
        refine ⟨m, ⟨?_, rfl⟩⟩
        simp only [Set.mem_setOf_eq]
        have hmas : m.val ≤ as :=
          hc (by simpa only [Finset.mem_coe, Finsupp.mem_support_iff] using hm)
        refine le_trans hmas ?_
        cases as with
        | nil => exact (List.nil_lt_cons a []).le
        | cons b bs =>
          apply le_of_lt
          rw [List.chain'_cons] at ha
          

Proof state:
case neg.h₂.h.h.a.cons.a
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)
l : List I := Finset.sort (fun x x_1 => x ≥ x_1) s
a : I
c : Products I →₀ ℤ
hmap :
  ∀ (g : Products I → ℤ → LocallyConstant ↑(π C fun x => x ∈ s) ℤ),
    e (π C fun x => x ∈ s) a * Finsupp.sum c g = Finsupp.sum c fun a_1 b => e (π C fun x => x ∈ s) a * g a_1 b
h✝ : ¬↑x a = true
m : Products I
hm : c m ≠ 0
b : I
bs : List I
ha : a > b ∧ List.Chain' (fun x x_1 => x > x_1) (b :: bs)
hc : ↑c.support ⊆ {m | ↑m ≤ b :: bs}
hmas : ↑m ≤ b :: bs
⊢ b :: bs < a :: b :: bs

Next tactic:
have hlex := List.lt.head bs (b :: bs) ha.1
/-- If `s` is a finite subset of `I`, then the good products span. -/
theorem GoodProducts.spanFin : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (· ∈ s)))) := by
  rw [span_iff_products]
  refine le_trans (spanFinBasis.span C s) ?_
  rw [Submodule.span_le]
  rintro _ ⟨x, rfl⟩
  rw [← factors_prod_eq_basis]
  let l := s.sort (·≥·)
  dsimp [factors]
  suffices : l.Chain' (·>·) → (l.map (fun i ↦ if x.val i = true then e (π C (· ∈ s)) i
      else (1 - (e (π C (· ∈ s)) i)))).prod ∈
      Submodule.span ℤ ((Products.eval (π C (· ∈ s))) '' {m | m.val ≤ l})
  · exact Submodule.span_mono (Set.image_subset_range _ _) (this (Finset.sort_sorted_gt _).chain')
  induction l with
  | nil =>
    intro _
    apply Submodule.subset_span
    exact ⟨⟨[], List.chain'_nil⟩,⟨Or.inl rfl, rfl⟩⟩
  | cons a as ih =>
    rw [List.map_cons, List.prod_cons]
    intro ha
    specialize ih (by rw [List.chain'_cons'] at ha; exact ha.2)
    rw [Finsupp.mem_span_image_iff_total] at ih
    simp only [Finsupp.mem_supported, Finsupp.total_apply] at ih
    obtain ⟨c, hc, hc'⟩ := ih
    rw [← hc']; clear hc'
    have hmap := fun g ↦ map_finsupp_sum (LinearMap.mulLeft ℤ (e (π C (· ∈ s)) a)) c g
    dsimp at hmap ⊢
    split_ifs
    · rw [hmap]
      exact finsupp_sum_mem_span_eval _ _ ha hc
    · ring_nf
      rw [hmap]
      apply Submodule.add_mem
      · apply Submodule.neg_mem
        exact finsupp_sum_mem_span_eval _ _ ha hc
      · apply Submodule.finsupp_sum_mem
        intro m hm
        apply Submodule.smul_mem
        apply Submodule.subset_span
        refine ⟨m, ⟨?_, rfl⟩⟩
        simp only [Set.mem_setOf_eq]
        have hmas : m.val ≤ as :=
          hc (by simpa only [Finset.mem_coe, Finsupp.mem_support_iff] using hm)
        refine le_trans hmas ?_
        cases as with
        | nil => exact (List.nil_lt_cons a []).le
        | cons b bs =>
          apply le_of_lt
          rw [List.chain'_cons] at ha
          have hlex := List.lt.head bs (b :: bs) ha.1
          

Proof state:
case neg.h₂.h.h.a.cons.a
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)
l : List I := Finset.sort (fun x x_1 => x ≥ x_1) s
a : I
c : Products I →₀ ℤ
hmap :
  ∀ (g : Products I → ℤ → LocallyConstant ↑(π C fun x => x ∈ s) ℤ),
    e (π C fun x => x ∈ s) a * Finsupp.sum c g = Finsupp.sum c fun a_1 b => e (π C fun x => x ∈ s) a * g a_1 b
h✝ : ¬↑x a = true
m : Products I
hm : c m ≠ 0
b : I
bs : List I
ha : a > b ∧ List.Chain' (fun x x_1 => x > x_1) (b :: bs)
hc : ↑c.support ⊆ {m | ↑m ≤ b :: bs}
hmas : ↑m ≤ b :: bs
hlex : List.lt (b :: bs) (a :: b :: bs)
⊢ b :: bs < a :: b :: bs

Next tactic:
exact (List.lt_iff_lex_lt _ _).mp hlex
theorem fin_comap_jointlySurjective
    (hC : IsClosed C)
    (f : LocallyConstant C ℤ) : ∃ (s : Finset I)
    (g : LocallyConstant (π C (· ∈ s)) ℤ), f = g.comap (ProjRestrict 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)
hC : IsClosed C
f : LocallyConstant ↑C ℤ
⊢ ∃ s g, f = LocallyConstant.comap (ProjRestrict C fun x => x ∈ s) g

Next tactic:
obtain ⟨J, g, h⟩ := @Profinite.exists_locallyConstant.{0, u, u} (Finset I)ᵒᵖ _ _ _
    (spanCone hC.isCompact) ℤ
    (spanCone_isLimit hC.isCompact) f
theorem fin_comap_jointlySurjective
    (hC : IsClosed C)
    (f : LocallyConstant C ℤ) : ∃ (s : Finset I)
    (g : LocallyConstant (π C (· ∈ s)) ℤ), f = g.comap (ProjRestrict C (· ∈ s)) := by
  obtain ⟨J, g, h⟩ := @Profinite.exists_locallyConstant.{0, u, u} (Finset I)ᵒᵖ _ _ _
    (spanCone hC.isCompact) ℤ
    (spanCone_isLimit hC.isCompact) f
  

Proof state:
case 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)
hC : IsClosed C
f : LocallyConstant ↑C ℤ
J : (Finset I)ᵒᵖ
g : LocallyConstant ↑((spanFunctor (_ : IsCompact C)).obj J).toCompHaus.toTop ℤ
h : f = LocallyConstant.comap (⇑((spanCone (_ : IsCompact C)).π.app J)) g
⊢ ∃ s g, f = LocallyConstant.comap (ProjRestrict C fun x => x ∈ s) g

Next tactic:
exact ⟨(Opposite.unop J), g, h⟩
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := 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)
hC : IsClosed C
⊢ ⊤ ≤ Submodule.span ℤ (Set.range (eval C))

Next tactic:
rw [span_iff_products]
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by
  rw [span_iff_products]
  

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)
hC : IsClosed C
⊢ ⊤ ≤ Submodule.span ℤ (Set.range (Products.eval C))

Next tactic:
intro f _
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by
  rw [span_iff_products]
  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)
hC : IsClosed C
f : LocallyConstant ↑C ℤ
a✝ : f ∈ ⊤
⊢ f ∈ Submodule.span ℤ (Set.range (Products.eval C))

Next tactic:
obtain ⟨K, f', rfl⟩ : ∃ K f', f = πJ C K f' := fin_comap_jointlySurjective C hC f
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by
  rw [span_iff_products]
  intro f _
  obtain ⟨K, f', rfl⟩ : ∃ K f', f = πJ C K f' := fin_comap_jointlySurjective C hC f
  

Proof state:
case 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)
hC : IsClosed C
K : Finset I
f' : LocallyConstant ↑(π C fun x => x ∈ K) ℤ
a✝ : (πJ C K) f' ∈ ⊤
⊢ (πJ C K) f' ∈ Submodule.span ℤ (Set.range (Products.eval C))

Next tactic:
refine Submodule.span_mono ?_ <| Submodule.apply_mem_span_image_of_mem_span (πJ C K) <|
    spanFin C K (Submodule.mem_top : f' ∈ ⊤)
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by
  rw [span_iff_products]
  intro f _
  obtain ⟨K, f', rfl⟩ : ∃ K f', f = πJ C K f' := fin_comap_jointlySurjective C hC f
  refine Submodule.span_mono ?_ <| Submodule.apply_mem_span_image_of_mem_span (πJ C K) <|
    spanFin C K (Submodule.mem_top : f' ∈ ⊤)
  

Proof state:
case 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)
hC : IsClosed C
K : Finset I
f' : LocallyConstant ↑(π C fun x => x ∈ K) ℤ
a✝ : (πJ C K) f' ∈ ⊤
⊢ ⇑(πJ C K) '' Set.range (eval (π C fun x => x ∈ K)) ⊆ Set.range (Products.eval C)

Next tactic:
rintro l ⟨y, ⟨m, rfl⟩, rfl⟩
/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by
  rw [span_iff_products]
  intro f _
  obtain ⟨K, f', rfl⟩ : ∃ K f', f = πJ C K f' := fin_comap_jointlySurjective C hC f
  refine Submodule.span_mono ?_ <| Submodule.apply_mem_span_image_of_mem_span (πJ C K) <|
    spanFin C K (Submodule.mem_top : f' ∈ ⊤)
  rintro l ⟨y, ⟨m, rfl⟩, rfl⟩
  

Proof state:
case intro.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)
hC : IsClosed C
K : Finset I
f' : LocallyConstant ↑(π C fun x => x ∈ K) ℤ
a✝ : (πJ C K) f' ∈ ⊤
m : { l // Products.isGood (π C fun x => x ∈ K) l }
⊢ (πJ C K) (eval (π C fun x => x ∈ K) m) ∈ Set.range (Products.eval C)

Next tactic:
exact ⟨m.val, eval_eq_πJ C K m.val m.prop⟩
theorem term_ord_aux {i : I} (ho : ord I i < Ordinal.type ((·<·) : I → I → Prop)) :
    term I ho = i := 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)
i : I
ho : ord I i < Ordinal.type fun x x_1 => x < x_1
⊢ term I ho = i

Next tactic:
simp only [term, ord, Ordinal.enum_typein]
@[simp]
theorem ord_term_aux {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) :
    ord I (term I ho) = o := 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)
o : Ordinal.{u}
ho : o < Ordinal.type fun x x_1 => x < x_1
⊢ ord I (term I ho) = o

Next tactic:
simp only [ord, term, Ordinal.typein_enum]
theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i := 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)
o : Ordinal.{u}
ho : o < Ordinal.type fun x x_1 => x < x_1
i : I
⊢ ord I i = o ↔ term I ho = i

Next tactic:
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · 

Proof state:
case refine_1
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
o : Ordinal.{u}
ho : o < Ordinal.type fun x x_1 => x < x_1
i : I
h : ord I i = o
⊢ term I ho = i

Next tactic:
subst h
theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · subst h
    

Proof state:
case refine_1
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
i : I
ho : ord I i < Ordinal.type fun x x_1 => x < x_1
⊢ term I ho = i

Next tactic:
exact term_ord_aux ho
theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · subst h
    exact term_ord_aux ho
  · 

Proof state:
case refine_2
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
o : Ordinal.{u}
ho : o < Ordinal.type fun x x_1 => x < x_1
i : I
h : term I ho = i
⊢ ord I i = o

Next tactic:
subst h
theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · subst h
    exact term_ord_aux ho
  · subst h
    

Proof state:
case refine_2
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
o : Ordinal.{u}
ho : o < Ordinal.type fun x x_1 => x < x_1
⊢ ord I (term I ho) = o

Next tactic:
exact ord_term_aux ho
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := 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)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
⊢ ord I i < o

Next tactic:
by_contra h'
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  

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)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
⊢ False

Next tactic:
apply h
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  

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)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
⊢ eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})

Next tactic:
suffices : eval C l = 0
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  suffices : eval C l = 0
  · 

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)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
this : eval C l = 0
⊢ eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})

Next tactic:
simp [this, Submodule.zero_mem]
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  suffices : eval C l = 0
  · simp [this, Submodule.zero_mem]
  

Proof state:
case this
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
⊢ eval C l = 0

Next tactic:
ext x
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  suffices : eval C l = 0
  · simp [this, Submodule.zero_mem]
  ext x
  

Proof state:
case this.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
x : ↑C
⊢ (eval C l) x = 0 x

Next tactic:
simp only [eval_eq, LocallyConstant.coe_zero, Pi.zero_apply, ite_eq_right_iff, one_ne_zero]
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  suffices : eval C l = 0
  · simp [this, Submodule.zero_mem]
  ext x
  simp only [eval_eq, LocallyConstant.coe_zero, Pi.zero_apply, ite_eq_right_iff, one_ne_zero]
  

Proof state:
case this.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
h' : ¬ord I i < o
x : ↑C
⊢ (∀ i ∈ ↑l, ↑x i = true) → False

Next tactic:
contrapose! h'
theorem Products.prop_of_isGood_of_contained  {l : Products I} (o : Ordinal) (h : l.isGood C)
    (hsC : contained C o) (i : I) (hi : i ∈ l.val) : ord I i < o := by
  by_contra h'
  apply h
  suffices : eval C l = 0
  · simp [this, Submodule.zero_mem]
  ext x
  simp only [eval_eq, LocallyConstant.coe_zero, Pi.zero_apply, ite_eq_right_iff, one_ne_zero]
  contrapose! h'
  

Proof state:
case this.h
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
l : Products I
o : Ordinal.{u}
h : isGood C l
hsC : contained C o
i : I
hi : i ∈ ↑l
x : ↑C
h' : (∀ i ∈ ↑l, ↑x i = true) ∧ ¬False
⊢ ord I i < o

Next tactic:
exact hsC x.val x.prop i (h'.1 i hi)
instance : IsEmpty { l // Products.isGood (∅ : Set (I → Bool)) l } :=
  isEmpty_iff.mpr fun ⟨l, hl⟩ ↦ hl <| 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)
x✝ : { l // Products.isGood ∅ l }
l : Products I
hl : Products.isGood ∅ l
⊢ Products.eval ∅ l ∈ Submodule.span ℤ (Products.eval ∅ '' {m | m < l})

Next tactic:
rw [subsingleton_iff.mp inferInstance (Products.eval ∅ l) 0]
instance : IsEmpty { l // Products.isGood (∅ : Set (I → Bool)) l } :=
  isEmpty_iff.mpr fun ⟨l, hl⟩ ↦ hl <| by
    rw [subsingleton_iff.mp inferInstance (Products.eval ∅ l) 0]
    

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)
x✝ : { l // Products.isGood ∅ l }
l : Products I
hl : Products.isGood ∅ l
⊢ 0 ∈ Submodule.span ℤ (Products.eval ∅ '' {m | m < l})

Next tactic:
exact Submodule.zero_mem _
/-- The empty list as a `Products` -/
def Products.nil : Products I := ⟨[], 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)
⊢ List.Chain' (fun x x_1 => x > x_1) []

Next tactic:
simp only [List.chain'_nil]
theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ := 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)
⊢ {m | m < nil} = ∅

Next tactic:
ext ⟨m, hm⟩
theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ := by
  ext ⟨m, hm⟩
  

Proof state:
case h.mk
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
m : List I
hm : List.Chain' (fun x x_1 => x > x_1) m
⊢ { val := m, property := hm } ∈ {m | m < nil} ↔ { val := m, property := hm } ∈ ∅

Next tactic:
refine ⟨fun h ↦ ?_, by tauto⟩
theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ := by
  ext ⟨m, hm⟩
  refine ⟨fun h ↦ ?_, 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)
m : List I
hm : List.Chain' (fun x x_1 => x > x_1) m
⊢ { val := m, property := hm } ∈ ∅ → { val := m, property := hm } ∈ {m | m < nil}

Next tactic:
tauto
theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ := by
  ext ⟨m, hm⟩
  refine ⟨fun h ↦ ?_, by tauto⟩
  

Proof state:
case h.mk
I : Type u
inst✝² : Inhabited I
inst✝¹ : LinearOrder I
inst✝ : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
m : List I
hm : List.Chain' (fun x x_1 => x > x_1) m
h : { val := m, property := hm } ∈ {m | m < nil}
⊢ { val := m, property := hm } ∈ ∅

Next tactic:
simp only [Set.mem_setOf_eq, lt_iff_lex_lt, nil, List.Lex.not_nil_right] at h
instance {α : Type*} [TopologicalSpace α] [Inhabited α] : Nontrivial (LocallyConstant α ℤ) := 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)
α : Type u_1
inst✝¹ : TopologicalSpace α
inst✝ : Inhabited α
⊢ Nontrivial (LocallyConstant α ℤ)

Next tactic:
refine ⟨0, 1, fun h ↦ ?_⟩
instance {α : Type*} [TopologicalSpace α] [Inhabited α] : Nontrivial (LocallyConstant α ℤ) := by
  refine ⟨0, 1, fun h ↦ ?_⟩
  

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)
α : Type u_1
inst✝¹ : TopologicalSpace α
inst✝ : Inhabited α
h : 0 = 1
⊢ False

Next tactic:
apply @zero_ne_one ℤ
instance {α : Type*} [TopologicalSpace α] [Inhabited α] : Nontrivial (LocallyConstant α ℤ) := by
  refine ⟨0, 1, fun h ↦ ?_⟩
  apply @zero_ne_one ℤ
  

Proof state:
case a
I : Type u
inst✝⁴ : Inhabited I
inst✝³ : LinearOrder I
inst✝² : IsWellOrder I fun x x_1 => x < x_1
C : Set (I → Bool)
α : Type u_1
inst✝¹ : TopologicalSpace α
inst✝ : Inhabited α
h : 0 = 1
⊢ 0 = 1

Next tactic:
exact FunLike.congr_fun h default
theorem Products.isGood_nil : Products.isGood ({fun _ ↦ false} : Set (I → Bool)) Products.nil := 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)
⊢ isGood {fun x => false} nil

Next tactic:
intro h
theorem Products.isGood_nil : Products.isGood ({fun _ ↦ false} : Set (I → Bool)) Products.nil := by
  intro h
  

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)
h : eval {fun x => false} nil ∈ Submodule.span ℤ (eval {fun x => false} '' {m | m < nil})
⊢ False

Next tactic:
simp only [Products.lt_nil_empty, Products.eval, List.map, List.prod_nil, Set.image_empty,
    Submodule.span_empty, Submodule.mem_bot, one_ne_zero] at h
theorem Products.span_nil_eq_top :
    Submodule.span ℤ (eval ({fun _ ↦ false} : Set (I → Bool)) '' {nil}) = ⊤ := 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)
⊢ Submodule.span ℤ (eval {fun x => false} '' {nil}) = ⊤

Next tactic:
rw [Set.image_singleton, eq_top_iff]
theorem Products.span_nil_eq_top :
    Submodule.span ℤ (eval ({fun _ ↦ false} : Set (I → Bool)) '' {nil}) = ⊤ := by
  rw [Set.image_singleton, eq_top_iff]
  

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)
⊢ ⊤ ≤ Submodule.span ℤ {eval {fun x => false} nil}

Next tactic:
intro f _
theorem Products.span_nil_eq_top :
    Submodule.span ℤ (eval ({fun _ ↦ false} : Set (I → Bool)) '' {nil}) = ⊤ := by
  rw [Set.image_singleton, eq_top_iff]
  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)
f : LocallyConstant ↑{fun x => false} ℤ
a✝ : f ∈ ⊤
⊢ f ∈ Submodule.span ℤ {eval {fun x => false} nil}

Next tactic:
rw [Submodule.mem_span_singleton]