l3lab/ntp-mathlib huggingface dataset:
theorem evalFacProps {l : Products I} (J K : I → Prop)
    (h : ∀ a, a ∈ l.val → J a) [∀ j, Decidable (J j)] [∀ j, Decidable (K j)]
    (hJK : ∀ i, J i → K i) :
    l.eval (π C J) ∘ ProjRestricts C hJK = l.eval (π C K) := 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
J K : I → Prop
h : ∀ a ∈ ↑l, J a
inst✝¹ : (j : I) → Decidable (J j)
inst✝ : (j : I) → Decidable (K j)
hJK : ∀ (i : I), J i → K i
⊢ ⇑(eval (π C J) l) ∘ ProjRestricts C hJK = ⇑(eval (π C K) l)

Next tactic:
have : l.eval (π C J) ∘ Homeomorph.setCongr (proj_eq_of_subset C J K hJK) =
      l.eval (π (π C K) J) := by
    ext; simp [Homeomorph.setCongr, Products.eval_eq]
theorem evalFacProps {l : Products I} (J K : I → Prop)
    (h : ∀ a, a ∈ l.val → J a) [∀ j, Decidable (J j)] [∀ j, Decidable (K j)]
    (hJK : ∀ i, J i → K i) :
    l.eval (π C J) ∘ ProjRestricts C hJK = l.eval (π C K) := by
  have : l.eval (π C J) ∘ Homeomorph.setCongr (proj_eq_of_subset C J K hJK) =
      l.eval (π (π C K) J) := 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
J K : I → Prop
h : ∀ a ∈ ↑l, J a
inst✝¹ : (j : I) → Decidable (J j)
inst✝ : (j : I) → Decidable (K j)
hJK : ∀ (i : I), J i → K i
⊢ ⇑(eval (π C J) l) ∘ ⇑(Homeomorph.setCongr (_ : π (π C K) J = π C J)) = ⇑(eval (π (π C K) J) l)

Next tactic:
ext
theorem evalFacProps {l : Products I} (J K : I → Prop)
    (h : ∀ a, a ∈ l.val → J a) [∀ j, Decidable (J j)] [∀ j, Decidable (K j)]
    (hJK : ∀ i, J i → K i) :
    l.eval (π C J) ∘ ProjRestricts C hJK = l.eval (π C K) := by
  have : l.eval (π C J) ∘ Homeomorph.setCongr (proj_eq_of_subset C J K hJK) =
      l.eval (π (π C K) J) := by
    ext; 

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)
l : Products I
J K : I → Prop
h : ∀ a ∈ ↑l, J a
inst✝¹ : (j : I) → Decidable (J j)
inst✝ : (j : I) → Decidable (K j)
hJK : ∀ (i : I), J i → K i
x✝ : ↑(π (π C K) J)
⊢ (⇑(eval (π C J) l) ∘ ⇑(Homeomorph.setCongr (_ : π (π C K) J = π C J))) x✝ = (eval (π (π C K) J) l) x✝

Next tactic:
simp [Homeomorph.setCongr, Products.eval_eq]
theorem evalFacProps {l : Products I} (J K : I → Prop)
    (h : ∀ a, a ∈ l.val → J a) [∀ j, Decidable (J j)] [∀ j, Decidable (K j)]
    (hJK : ∀ i, J i → K i) :
    l.eval (π C J) ∘ ProjRestricts C hJK = l.eval (π C K) := by
  have : l.eval (π C J) ∘ Homeomorph.setCongr (proj_eq_of_subset C J K hJK) =
      l.eval (π (π C K) J) := by
    ext; simp [Homeomorph.setCongr, Products.eval_eq]
  

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
J K : I → Prop
h : ∀ a ∈ ↑l, J a
inst✝¹ : (j : I) → Decidable (J j)
inst✝ : (j : I) → Decidable (K j)
hJK : ∀ (i : I), J i → K i
this : ⇑(eval (π C J) l) ∘ ⇑(Homeomorph.setCongr (_ : π (π C K) J = π C J)) = ⇑(eval (π (π C K) J) l)
⊢ ⇑(eval (π C J) l) ∘ ProjRestricts C hJK = ⇑(eval (π C K) l)

Next tactic:
rw [ProjRestricts, ← Function.comp.assoc, this, ← evalFacProp (π C K) J h]
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := 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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
⊢ ∀ a ∈ ↑l, J a

Next tactic:
intro i hi
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  

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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
⊢ J i

Next tactic:
by_contra h'
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
⊢ False

Next tactic:
apply h
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
⊢ eval (π C J) l ∈ Submodule.span ℤ (eval (π C J) '' {m | m < l})

Next tactic:
suffices : eval (π C J) l = 0
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) 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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
this : eval (π C J) l = 0
⊢ eval (π C J) l ∈ Submodule.span ℤ (eval (π C J) '' {m | m < l})

Next tactic:
rw [this]
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    

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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
this : eval (π C J) l = 0
⊢ 0 ∈ Submodule.span ℤ (eval (π C J) '' {m | m < l})

Next tactic:
exact Submodule.zero_mem _
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact 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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
⊢ eval (π C J) l = 0

Next tactic:
ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  

Proof state:
case this.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)
l : Products I
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
⊢ (eval (π C J) l) { val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) } =
    0 { val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) }

Next tactic:
rw [eval_eq, if_neg]
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  rw [eval_eq, if_neg]
  · 

Proof state:
case this.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)
l : Products I
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
⊢ 0 = 0 { val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) }

Next tactic:
rfl
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  rw [eval_eq, if_neg]
  · rfl
  · 

Proof state:
case this.h.mk.intro.intro.hnc
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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
⊢ ¬∀ i ∈ ↑l, ↑{ val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) } i = true

Next tactic:
intro h
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  rw [eval_eq, if_neg]
  · rfl
  · intro h
    

Proof state:
case this.h.mk.intro.intro.hnc
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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h✝ : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
h : ∀ i ∈ ↑l, ↑{ val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) } i = true
⊢ False

Next tactic:
specialize h i hi
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  rw [eval_eq, if_neg]
  · rfl
  · intro h
    specialize h i hi
    

Proof state:
case this.h.mk.intro.intro.hnc
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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h✝ : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
h : ↑{ val := Proj J w✝, property := (_ : ∃ a ∈ C, Proj J a = Proj J w✝) } i = true
⊢ False

Next tactic:
simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at h
theorem prop_of_isGood  {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)]
    (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by
  intro i hi
  by_contra h'
  apply h
  suffices : eval (π C J) l = 0
  · rw [this]
    exact Submodule.zero_mem _
  ext ⟨_, ⟨_, ⟨_, rfl⟩⟩⟩
  rw [eval_eq, if_neg]
  · rfl
  · intro h
    specialize h i hi
    simp only [Proj, Bool.ite_eq_true_distrib, if_false_right_eq_and] at h
    

Proof state:
case this.h.mk.intro.intro.hnc
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
J : I → Prop
inst✝ : (j : I) → Decidable (J j)
h✝ : isGood (π C J) l
i : I
hi : i ∈ ↑l
h' : ¬J i
w✝ : I → Bool
left✝ : w✝ ∈ C
h : J i ∧ w✝ i = true
⊢ False

Next tactic:
exact h' h.1
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.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)
l : Products I
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  

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
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
suffices L l by assumption
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l 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
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
this : L l
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
assumption
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  

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
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
⊢ L l

Next tactic:
apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  

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)
l : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
⊢ ∀ (x : Products I), (∀ y < x, L y) → L x

Next tactic:
intro l h
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
⊢ L l

Next tactic:
dsimp
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
by_cases hl : l.isGood C
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · 

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : isGood C l
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
apply subset_span
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    

Proof state:
case pos.a
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
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : isGood C l
⊢ eval C l ∈ Set.range (GoodProducts.eval C)

Next tactic:
exact ⟨⟨l, hl⟩, rfl⟩
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    exact ⟨⟨l, hl⟩, rfl⟩
  · 

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : ¬isGood C l
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
simp only [Products.isGood, not_not] at hl
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    exact ⟨⟨l, hl⟩, rfl⟩
  · simp only [Products.isGood, not_not] at hl
    

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
suffices : Products.eval C '' {m | m < l} ⊆ span ℤ (Set.range (GoodProducts.eval C))
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    exact ⟨⟨l, hl⟩, rfl⟩
  · simp only [Products.isGood, not_not] at hl
    suffices : Products.eval C '' {m | m < l} ⊆ span ℤ (Set.range (GoodProducts.eval C))
    · 

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})
this : eval C '' {m | m < l} ⊆ ↑(Submodule.span ℤ (Set.range (GoodProducts.eval C)))
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
rw [← span_le] at this
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    exact ⟨⟨l, hl⟩, rfl⟩
  · simp only [Products.isGood, not_not] at hl
    suffices : Products.eval C '' {m | m < l} ⊆ span ℤ (Set.range (GoodProducts.eval C))
    · rw [← span_le] at this
      

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)
l✝ : Products I
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})
this : Submodule.span ℤ (eval C '' {m | m < l}) ≤ Submodule.span ℤ (Set.range (GoodProducts.eval C))
⊢ eval C l ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))

Next tactic:
exact this hl
/-- An arbitrary product `e C i₁ * e C i₂ * ... * e C iᵣ` is in the ℤ-span of the good products. -/
theorem eval_mem_span_goodProducts (l : Products I) :
    l.eval C ∈ span ℤ (Set.range (GoodProducts.eval C)) := by
  let L : Products I → Prop := fun m ↦ m.eval C ∈ span ℤ (Set.range (GoodProducts.eval C))
  suffices L l by assumption
  apply IsWellFounded.induction (·<· : Products I → Products I → Prop)
  intro l h
  dsimp
  by_cases hl : l.isGood C
  · apply subset_span
    exact ⟨⟨l, hl⟩, rfl⟩
  · simp only [Products.isGood, not_not] at hl
    suffices : Products.eval C '' {m | m < l} ⊆ span ℤ (Set.range (GoodProducts.eval C))
    · rw [← span_le] at this
      exact this hl
    

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
L : Products I → Prop := fun m => eval C m ∈ Submodule.span ℤ (Set.range (GoodProducts.eval C))
l : Products I
h : ∀ y < l, L y
hl : eval C l ∈ Submodule.span ℤ (eval C '' {m | m < l})
⊢ eval C '' {m | m < l} ⊆ ↑(Submodule.span ℤ (Set.range (GoodProducts.eval C)))

Next tactic:
rintro a ⟨m, hm, rfl⟩