File: Mathlib/Topology/Category/Profinite/Nobeling.lean

full_name: Profinite.NobelingProof.Proj
code: /--
The projection mapping everything that satisfies `J i` to itself, and everything else to `false`
-/
def Proj : (I → Bool) → (I → Bool) 
goal: (I → Bool) → I → Bool

full_name: Profinite.NobelingProof.continuous_proj
code: @[simp]
theorem continuous_proj :
    Continuous (Proj J : (I → Bool) → (I → Bool)) 
goal: Continuous (Profinite.NobelingProof.Proj J)

full_name: Profinite.NobelingProof.π
code: /-- The image of `Proj π J` -/
def π : Set (I → Bool) 
goal: Set (I → Bool)

full_name: Profinite.NobelingProof.ProjRestrict
code: /-- The restriction of `Proj π J` to a subset, mapping to its image. -/
@[simps!]
def ProjRestrict : C → π C J 
goal: ↑C → ↑(Profinite.NobelingProof.π C J)

full_name: Profinite.NobelingProof.ProjRestrict_coe
code: /-- The restriction of `Proj π J` to a subset, mapping to its image. -/
@[simps!]
def ProjRestrict : C → π C J 
goal: ∀ (a : ↑C) (a_1 : I), ↑(Profinite.NobelingProof.ProjRestrict C J a) a_1 = Profinite.NobelingProof.Proj J (↑a) a_1

full_name: Profinite.NobelingProof.continuous_projRestrict
code: @[simp]
theorem continuous_projRestrict : Continuous (ProjRestrict C J) 
goal: Continuous (Profinite.NobelingProof.ProjRestrict C J)

full_name: Profinite.NobelingProof.proj_eq_self
code: theorem proj_eq_self {x : I → Bool} (h : ∀ i, x i ≠ false → J i) : Proj J x = x 
goal: Profinite.NobelingProof.Proj J x = x

full_name: Profinite.NobelingProof.proj_prop_eq_self
code: theorem proj_prop_eq_self (hh : ∀ i x, x ∈ C → x i ≠ false → J i) : π C J = C 
goal: Profinite.NobelingProof.π C J = C

full_name: Profinite.NobelingProof.proj_comp_of_subset
code: theorem proj_comp_of_subset (h : ∀ i, J i → K i) : (Proj J ∘ Proj K) =
    (Proj J : (I → Bool) → (I → Bool)) 
goal: Profinite.NobelingProof.Proj J ∘ Profinite.NobelingProof.Proj K = Profinite.NobelingProof.Proj J

full_name: Profinite.NobelingProof.proj_eq_of_subset
code: theorem proj_eq_of_subset (h : ∀ i, J i → K i) : π (π C K) J = π C J 
goal: Profinite.NobelingProof.π (Profinite.NobelingProof.π C K) J = Profinite.NobelingProof.π C J

full_name: Profinite.NobelingProof.ProjRestricts_coe
code: /-- A variant of `ProjRestrict` with domain of the form `π C K` -/
@[simps!]
def ProjRestricts (h : ∀ i, J i → K i) : π C K → π C J 
goal: ∀ (a : ↑(Profinite.NobelingProof.π C K)) (a_1 : I),
  ↑(Profinite.NobelingProof.ProjRestricts C h a) a_1 = Profinite.NobelingProof.Proj J (↑a) a_1

full_name: Profinite.NobelingProof.ProjRestricts
code: /-- A variant of `ProjRestrict` with domain of the form `π C K` -/
@[simps!]
def ProjRestricts (h : ∀ i, J i → K i) : π C K → π C J 
goal: ↑(Profinite.NobelingProof.π C K) → ↑(Profinite.NobelingProof.π C J)

full_name: Profinite.NobelingProof.continuous_projRestricts
code: @[simp]
theorem continuous_projRestricts (h : ∀ i, J i → K i) : Continuous (ProjRestricts C h) 
goal: Continuous (Profinite.NobelingProof.ProjRestricts C h)

full_name: Profinite.NobelingProof.surjective_projRestricts
code: theorem surjective_projRestricts (h : ∀ i, J i → K i) : Function.Surjective (ProjRestricts C h) 
goal: Function.Surjective (Profinite.NobelingProof.ProjRestricts C h)

full_name: Profinite.NobelingProof.projRestricts_eq_id
code: theorem projRestricts_eq_id : ProjRestricts C (fun i (h : J i) ↦ h) = id 
goal: Profinite.NobelingProof.ProjRestricts C ⋯ = id

full_name: Profinite.NobelingProof.projRestricts_eq_comp
code: theorem projRestricts_eq_comp (hJK : ∀ i, J i → K i) (hKL : ∀ i, K i → L i) :
    ProjRestricts C hJK ∘ ProjRestricts C hKL = ProjRestricts C (fun i ↦ hKL i ∘ hJK i) 
goal: Profinite.NobelingProof.ProjRestricts C hJK ∘ Profinite.NobelingProof.ProjRestricts C hKL =
  Profinite.NobelingProof.ProjRestricts C ⋯

full_name: Profinite.NobelingProof.projRestricts_comp_projRestrict
code: theorem projRestricts_comp_projRestrict (h : ∀ i, J i → K i) :
    ProjRestricts C h ∘ ProjRestrict C K = ProjRestrict C J 
goal: Profinite.NobelingProof.ProjRestricts C h ∘ Profinite.NobelingProof.ProjRestrict C K =
  Profinite.NobelingProof.ProjRestrict C J

full_name: Profinite.NobelingProof.iso_map
code: /-- The objectwise map in the isomorphism `spanFunctor ≅ Profinite.indexFunctor`. -/
def iso_map : C(π C J, (IndexFunctor.obj C J)) 
goal: C(↑(Profinite.NobelingProof.π C J), ↑(Profinite.IndexFunctor.obj C J))

full_name: Profinite.NobelingProof.iso_map_bijective
code: lemma iso_map_bijective : Function.Bijective (iso_map C J) 
goal: Function.Bijective ⇑(Profinite.NobelingProof.iso_map C J)

full_name: Profinite.NobelingProof.spanFunctor
code: /--
For a given compact subset `C` of `I → Bool`, `spanFunctor` is the functor from the poset of finsets
of `I` to `Profinite`, sending a finite subset set `J` to the image of `C` under the projection
`Proj J`.
-/
noncomputable
def spanFunctor [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] :
    (Finset I)ᵒᵖ ⥤ Profinite.{u} 
goal: CategoryTheory.Functor (Finset I)ᵒᵖ Profinite

full_name: Profinite.NobelingProof.spanCone
code: /-- The limit cone on `spanFunctor` with point `C`. -/
noncomputable
def spanCone [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : Cone (spanFunctor hC) 
goal: CategoryTheory.Limits.Cone (Profinite.NobelingProof.spanFunctor hC)

full_name: Profinite.NobelingProof.spanCone_isLimit
code: /-- `spanCone` is a limit cone. -/
noncomputable
def spanCone_isLimit [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] :
    CategoryTheory.Limits.IsLimit (spanCone hC) 
goal: CategoryTheory.Limits.IsLimit (Profinite.NobelingProof.spanCone hC)

full_name: Profinite.NobelingProof.e
code: /--
`e C i` is the locally constant map from `C : Set (I → Bool)` to `ℤ` sending `f` to 1 if
`f.val i = true`, and 0 otherwise.
-/
def e (i : I) : LocallyConstant C ℤ 
goal: LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.Products
code: /--
`Products I` is the type of lists of decreasing elements of `I`, so a typical element is
`[i₁, i₂, ...]` with `i₁ > i₂ > ...`. We order `Products I` lexicographically, so `[] < [i₁, ...]`,
and `[i₁, i₂, ...] < [j₁, j₂, ...]` if either `i₁ < j₁`, or `i₁ = j₁` and `[i₂, ...] < [j₂, ...]`.

Terms `m = [i₁, i₂, ..., iᵣ]` of this type will be used to represent products of the form
`e C i₁ ··· e C iᵣ : LocallyConstant C ℤ` . The function associated to `m` is `m.eval`.
-/
def Products (I : Type*) [LinearOrder I] 
goal: Type u_1

full_name: Profinite.NobelingProof.Products.instLinearOrder
code: instance : LinearOrder (Products I) 
goal: LinearOrder (Profinite.NobelingProof.Products I)

full_name: Profinite.NobelingProof.Products.lt_iff_lex_lt
code: @[simp]
theorem lt_iff_lex_lt (l m : Products I) : l < m ↔ List.Lex (·<·) l.val m.val 
goal: l < m ↔ List.Lex (fun x x_1 => x < x_1) ↑l ↑m

full_name: Profinite.NobelingProof.Products.instIsWellFoundedLt
code: instance : IsWellFounded (Products I) (·<·) 
goal: IsWellFounded (Profinite.NobelingProof.Products I) fun x x_1 => x < x_1

full_name: Profinite.NobelingProof.Products.eval
code: /-- The evaluation `e C i₁ ··· e C iᵣ : C → ℤ`  of a formal product `[i₁, i₂, ..., iᵣ]`. -/
def eval (l : Products I) 
goal: LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.Products.isGood
code: /--
The predicate on products which we prove picks out a basis of `LocallyConstant C ℤ`. We call such a
product "good".
-/
def isGood (l : Products I) : Prop 
goal: Prop

full_name: Profinite.NobelingProof.Products.rel_head!_of_mem
code: theorem rel_head!_of_mem [Inhabited I] {i : I} {l : Products I} (hi : i ∈ l.val) :
    i ≤ l.val.head! 
goal: i ≤ (↑l).head!

full_name: Profinite.NobelingProof.Products.head!_le_of_lt
code: theorem head!_le_of_lt [Inhabited I] {q l : Products I} (h : q < l) (hq : q.val ≠ []) :
    q.val.head! ≤ l.val.head! 
goal: (↑q).head! ≤ (↑l).head!

full_name: Profinite.NobelingProof.GoodProducts
code: /-- The set of good products. -/
def GoodProducts 
goal: Set (Profinite.NobelingProof.Products I)

full_name: Profinite.NobelingProof.GoodProducts.eval
code: /-- Evaluation of good products. -/
def eval (l : {l : Products I // l.isGood C}) : LocallyConstant C ℤ 
goal: LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.GoodProducts.injective
code: theorem injective : Function.Injective (eval C) 
goal: Function.Injective (Profinite.NobelingProof.GoodProducts.eval C)

full_name: Profinite.NobelingProof.GoodProducts.range
code: /-- The image of the good products in the module `LocallyConstant C ℤ`. -/
def range 
goal: Set (LocallyConstant ↑C ℤ)

full_name: Profinite.NobelingProof.GoodProducts.equiv_range
code: /-- The type of good products is equivalent to its image. -/
noncomputable
def equiv_range : GoodProducts C ≃ range C 
goal: ↑(Profinite.NobelingProof.GoodProducts C) ≃ ↑(Profinite.NobelingProof.GoodProducts.range C)

full_name: Profinite.NobelingProof.GoodProducts.equiv_toFun_eq_eval
code: theorem equiv_toFun_eq_eval : (equiv_range C).toFun = Set.rangeFactorization (eval C) 
goal: (Profinite.NobelingProof.GoodProducts.equiv_range C).toFun =
  Set.rangeFactorization (Profinite.NobelingProof.GoodProducts.eval C)

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent_iff_range
code: theorem linearIndependent_iff_range : LinearIndependent ℤ (GoodProducts.eval C) ↔
    LinearIndependent ℤ (fun (p : range C) ↦ p.1) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval C) ↔
  LinearIndependent ℤ fun (p : ↑(Profinite.NobelingProof.GoodProducts.range C)) => ↑p

full_name: Profinite.NobelingProof.Products.eval_eq
code: theorem eval_eq (l : Products I) (x : C) :
    l.eval C x = if ∀ i, i ∈ l.val → (x.val i = true) then 1 else 0 
goal: (Profinite.NobelingProof.Products.eval C l) x = if ∀ i ∈ ↑l, ↑x i = true then 1 else 0

full_name: Profinite.NobelingProof.Products.evalFacProp
code: theorem evalFacProp {l : Products I} (J : I → Prop)
    (h : ∀ a, a ∈ l.val → J a) [∀ j, Decidable (J j)] :
    l.eval (π C J) ∘ ProjRestrict C J = l.eval C 
goal: ⇑(Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C J) l) ∘ Profinite.NobelingProof.ProjRestrict C J =
  ⇑(Profinite.NobelingProof.Products.eval C l)

full_name: Profinite.NobelingProof.Products.evalFacProps
code: 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) 
goal: ⇑(Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C J) l) ∘
    Profinite.NobelingProof.ProjRestricts C hJK =
  ⇑(Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C K) l)

full_name: Profinite.NobelingProof.Products.prop_of_isGood
code: 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 
goal: a ∈ ↑l → J a

full_name: Profinite.NobelingProof.GoodProducts.span_iff_products
code: /-- The good products span `LocallyConstant C ℤ` if and only all the products do. -/
theorem GoodProducts.span_iff_products : ⊤ ≤ span ℤ (Set.range (eval C)) ↔
    ⊤ ≤ span ℤ (Set.range (Products.eval C)) 
goal: ⊤ ≤ Submodule.span ℤ (Set.range (Profinite.NobelingProof.GoodProducts.eval C)) ↔
  ⊤ ≤ Submodule.span ℤ (Set.range (Profinite.NobelingProof.Products.eval C))

full_name: Profinite.NobelingProof.πJ
code: /-- The `ℤ`-linear map induced by precomposition of the projection `C → π C (· ∈ s)`. -/
noncomputable
def πJ : LocallyConstant (π C (· ∈ s)) ℤ →ₗ[ℤ] LocallyConstant C ℤ 
goal: LocallyConstant ↑(Profinite.NobelingProof.π C fun x => x ∈ s) ℤ →ₗ[ℤ] LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.eval_eq_πJ
code: theorem eval_eq_πJ (l : Products I) (hl : l.isGood (π C (· ∈ s))) :
    l.eval C = πJ C s (l.eval (π C (· ∈ s))) 
goal: Profinite.NobelingProof.Products.eval C l =
  (Profinite.NobelingProof.πJ C s)
    (Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => x ∈ s) l)

full_name: Profinite.NobelingProof.instFintypeElemForallBoolπMemFinset
code: /-- `π C (· ∈ s)` is finite for a finite set `s`. -/
noncomputable
instance : Fintype (π C (· ∈ s)) 
goal: Fintype ↑(Profinite.NobelingProof.π C fun x => x ∈ s)

full_name: Profinite.NobelingProof.spanFinBasis
code: /-- The Kronecker delta as a locally constant map from `π C (· ∈ s)` to `ℤ`. -/
noncomputable
def spanFinBasis (x : π C (· ∈ s)) : LocallyConstant (π C (· ∈ s)) ℤ 
goal: LocallyConstant ↑(Profinite.NobelingProof.π C fun x => x ∈ s) ℤ

full_name: Profinite.NobelingProof.spanFinBasis.span
code: theorem spanFinBasis.span : ⊤ ≤ Submodule.span ℤ (Set.range (spanFinBasis C s)) 
goal: ⊤ ≤ Submodule.span ℤ (Set.range (Profinite.NobelingProof.spanFinBasis C s))

full_name: Profinite.NobelingProof.factors
code: /--
A certain explicit list of locally constant maps. The theorem `factors_prod_eq_basis` shows that the
product of the elements in this list is the delta function `spanFinBasis C s x`.
-/
def factors (x : π C (· ∈ s)) : List (LocallyConstant (π C (· ∈ s)) ℤ) 
goal: List (LocallyConstant ↑(Profinite.NobelingProof.π C fun x => x ∈ s) ℤ)

full_name: Profinite.NobelingProof.list_prod_apply
code: theorem list_prod_apply (x : C) (l : List (LocallyConstant C ℤ)) :
    l.prod x = (l.map (LocallyConstant.evalMonoidHom x)).prod 
goal: l.prod x = (List.map (⇑(LocallyConstant.evalMonoidHom x)) l).prod

full_name: Profinite.NobelingProof.factors_prod_eq_basis_of_eq
code: theorem factors_prod_eq_basis_of_eq {x y : (π C fun x ↦ x ∈ s)} (h : y = x) :
    (factors C s x).prod y = 1 
goal: (Profinite.NobelingProof.factors C s x).prod y = 1

full_name: Profinite.NobelingProof.e_mem_of_eq_true
code: theorem e_mem_of_eq_true {x : (π C (· ∈ s))} {a : I} (hx : x.val a = true) :
    e (π C (· ∈ s)) a ∈ factors C s x 
goal: Profinite.NobelingProof.e (Profinite.NobelingProof.π C fun x => x ∈ s) a ∈ Profinite.NobelingProof.factors C s x

full_name: Profinite.NobelingProof.one_sub_e_mem_of_false
code: 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 
goal: 1 - Profinite.NobelingProof.e (Profinite.NobelingProof.π C fun x => x ∈ s) a ∈ Profinite.NobelingProof.factors C s x

full_name: Profinite.NobelingProof.factors_prod_eq_basis_of_ne
code: theorem factors_prod_eq_basis_of_ne {x y : (π C (· ∈ s))} (h : y ≠ x) :
    (factors C s x).prod y = 0 
goal: (Profinite.NobelingProof.factors C s x).prod y = 0

full_name: Profinite.NobelingProof.factors_prod_eq_basis
code: /-- If `s` is finite, the product of the elements of the list `factors C s x`
is the delta function at `x`. -/
theorem factors_prod_eq_basis (x : π C (· ∈ s)) :
    (factors C s x).prod = spanFinBasis C s x 
goal: (Profinite.NobelingProof.factors C s x).prod = Profinite.NobelingProof.spanFinBasis C s x

full_name: Profinite.NobelingProof.GoodProducts.finsupp_sum_mem_span_eval
code: theorem GoodProducts.finsupp_sum_mem_span_eval {a : I} {as : List I}
    (ha : List.Chain' (· > ·) (a :: as)) {c : Products I →₀ ℤ}
    (hc : (c.support : Set (Products I)) ⊆ {m | m.val ≤ as}) :
    (Finsupp.sum c fun a_1 b ↦ e (π C (· ∈ s)) a * b • Products.eval (π C (· ∈ s)) a_1) ∈
      Submodule.span ℤ (Products.eval (π C (· ∈ s)) '' {m | m.val ≤ a :: as}) 
goal: (c.sum fun a_1 b =>
    Profinite.NobelingProof.e (Profinite.NobelingProof.π C fun x => x ∈ s) a *
      b • Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => x ∈ s) a_1) ∈
  Submodule.span ℤ
    (Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => x ∈ s) '' {m | ↑m ≤ a :: as})

full_name: Profinite.NobelingProof.GoodProducts.spanFin
code: /-- If `s` is a finite subset of `I`, then the good products span. -/
theorem GoodProducts.spanFin : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (· ∈ s)))) 
goal: ⊤ ≤
  Submodule.span ℤ (Set.range (Profinite.NobelingProof.GoodProducts.eval (Profinite.NobelingProof.π C fun x => x ∈ s)))

full_name: Profinite.NobelingProof.fin_comap_jointlySurjective
code: theorem fin_comap_jointlySurjective
    (hC : IsClosed C)
    (f : LocallyConstant C ℤ) : ∃ (s : Finset I)
    (g : LocallyConstant (π C (· ∈ s)) ℤ), f = g.comap ⟨(ProjRestrict C (· ∈ s)),
      continuous_projRestrict _ _⟩ 
goal: ∃ s g,
  f = LocallyConstant.comap { toFun := Profinite.NobelingProof.ProjRestrict C fun x => x ∈ s, continuous_toFun := ⋯ } g

full_name: Profinite.NobelingProof.GoodProducts.span
code: /-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/
theorem GoodProducts.span (hC : IsClosed C) :
    ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) 
goal: ⊤ ≤ Submodule.span ℤ (Set.range (Profinite.NobelingProof.GoodProducts.eval C))

full_name: Profinite.NobelingProof.ord
code: /-- A term of `I` regarded as an ordinal. -/
def ord (i : I) : Ordinal 
goal: Ordinal.{u}

full_name: Profinite.NobelingProof.term
code: /-- An ordinal regarded as a term of `I`. -/
noncomputable
def term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) : I 
goal: I

full_name: Profinite.NobelingProof.term_ord_aux
code: theorem term_ord_aux {i : I} (ho : ord I i < Ordinal.type ((·<·) : I → I → Prop)) :
    term I ho = i 
goal: Profinite.NobelingProof.term I ho = i

full_name: Profinite.NobelingProof.ord_term_aux
code: @[simp]
theorem ord_term_aux {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) :
    ord I (term I ho) = o 
goal: Profinite.NobelingProof.ord I (Profinite.NobelingProof.term I ho) = o

full_name: Profinite.NobelingProof.ord_term
code: theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) (i : I) :
    ord I i = o ↔ term I ho = i 
goal: Profinite.NobelingProof.ord I i = o ↔ Profinite.NobelingProof.term I ho = i

full_name: Profinite.NobelingProof.contained
code: /-- A predicate saying that `C` is "small" enough to satisfy the inductive hypothesis. -/
def contained (o : Ordinal) : Prop 
goal: Prop

full_name: Profinite.NobelingProof.P
code: /--
The predicate on ordinals which we prove by induction, see `GoodProducts.P0`,
`GoodProducts.Plimit` and `GoodProducts.linearIndependentAux` in the section `Induction` below
-/
def P (o : Ordinal) : Prop 
goal: Prop

full_name: Profinite.NobelingProof.Products.prop_of_isGood_of_contained
code: 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 
goal: Profinite.NobelingProof.ord I i < o

full_name: Profinite.NobelingProof.instSubsingletonLocallyConstantElemForallBoolEmptyCollectionSetInt
code: instance : Subsingleton (LocallyConstant (∅ : Set (I → Bool)) ℤ) 
goal: Subsingleton (LocallyConstant ↑∅ ℤ)

full_name: Profinite.NobelingProof.instIsEmptySubtypeProductsIsGoodEmptyCollectionSetForallBool
code: instance : IsEmpty { l // Products.isGood (∅ : Set (I → Bool)) l } 
goal: IsEmpty { l // Profinite.NobelingProof.Products.isGood ∅ l }

full_name: Profinite.NobelingProof.GoodProducts.linearIndependentEmpty
code: theorem GoodProducts.linearIndependentEmpty :
    LinearIndependent ℤ (eval (∅ : Set (I → Bool))) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval ∅)

full_name: Profinite.NobelingProof.Products.nil
code: /-- The empty list as a `Products` -/
def Products.nil : Products I 
goal: Profinite.NobelingProof.Products I

full_name: Profinite.NobelingProof.Products.lt_nil_empty
code: theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ 
goal: {m | m < Profinite.NobelingProof.Products.nil} = ∅

full_name: Profinite.NobelingProof.instNontrivialLocallyConstantIntOfNonempty
code: instance {α : Type*} [TopologicalSpace α] [Nonempty α] : Nontrivial (LocallyConstant α ℤ) 
goal: Nontrivial (LocallyConstant α ℤ)

full_name: Profinite.NobelingProof.Products.isGood_nil
code: theorem Products.isGood_nil : Products.isGood ({fun _ ↦ false} : Set (I → Bool)) Products.nil 
goal: Profinite.NobelingProof.Products.isGood {fun x => false} Profinite.NobelingProof.Products.nil

full_name: Profinite.NobelingProof.Products.span_nil_eq_top
code: theorem Products.span_nil_eq_top :
    Submodule.span ℤ (eval ({fun _ ↦ false} : Set (I → Bool)) '' {nil}) = ⊤ 
goal: Submodule.span ℤ (Profinite.NobelingProof.Products.eval {fun x => false} '' {Profinite.NobelingProof.Products.nil}) = ⊤

full_name: Profinite.NobelingProof.instUniqueSubtypeProductsIsGoodSingletonForallBoolSetFalse
code: /-- There is a unique `GoodProducts` for the singleton `{fun _ ↦ false}`. -/
noncomputable
instance : Unique { l // Products.isGood ({fun _ ↦ false} : Set (I → Bool)) l } 
goal: Unique { l // Profinite.NobelingProof.Products.isGood {fun x => false} l }

full_name: Profinite.NobelingProof.instNoZeroSMulDivisorsIntLocallyConstant
code: instance (α : Type*) [TopologicalSpace α] : NoZeroSMulDivisors ℤ (LocallyConstant α ℤ) 
goal: NoZeroSMulDivisors ℤ (LocallyConstant α ℤ)

full_name: Profinite.NobelingProof.GoodProducts.linearIndependentSingleton
code: theorem GoodProducts.linearIndependentSingleton :
    LinearIndependent ℤ (eval ({fun _ ↦ false} : Set (I → Bool))) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval {fun x => false})

full_name: Profinite.NobelingProof.contained_eq_proj
code: theorem contained_eq_proj (o : Ordinal) (h : contained C o) :
    C = π C (ord I · < o) 
goal: C = Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o

full_name: Profinite.NobelingProof.isClosed_proj
code: theorem isClosed_proj (o : Ordinal) (hC : IsClosed C) : IsClosed (π C (ord I · < o)) 
goal: IsClosed (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)

full_name: Profinite.NobelingProof.contained_proj
code: theorem contained_proj (o : Ordinal) : contained (π C (ord I · < o)) o 
goal: Profinite.NobelingProof.contained (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) o

full_name: Profinite.NobelingProof.πs_apply_apply
code: /-- The `ℤ`-linear map induced by precomposition of the projection `C → π C (ord I · < o)`. -/
@[simps!]
noncomputable
def πs (o : Ordinal) : LocallyConstant (π C (ord I · < o)) ℤ →ₗ[ℤ] LocallyConstant C ℤ 
goal: ∀ (a : ↑C),
  ((Profinite.NobelingProof.πs C o) g) a =
    g (Profinite.NobelingProof.ProjRestrict C (fun x => Profinite.NobelingProof.ord I x < o) a)

full_name: Profinite.NobelingProof.πs
code: /-- The `ℤ`-linear map induced by precomposition of the projection `C → π C (ord I · < o)`. -/
@[simps!]
noncomputable
def πs (o : Ordinal) : LocallyConstant (π C (ord I · < o)) ℤ →ₗ[ℤ] LocallyConstant C ℤ 
goal: LocallyConstant ↑(Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) ℤ →ₗ[ℤ] LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.coe_πs
code: theorem coe_πs (o : Ordinal) (f : LocallyConstant (π C (ord I · < o)) ℤ) :
    πs C o f = f ∘ ProjRestrict C (ord I · < o) 
goal: ⇑((Profinite.NobelingProof.πs C o) f) =
  ⇑f ∘ Profinite.NobelingProof.ProjRestrict C fun x => Profinite.NobelingProof.ord I x < o

full_name: Profinite.NobelingProof.injective_πs
code: theorem injective_πs (o : Ordinal) : Function.Injective (πs C o) 
goal: Function.Injective ⇑(Profinite.NobelingProof.πs C o)

full_name: Profinite.NobelingProof.πs'
code: /-- The `ℤ`-linear map induced by precomposition of the projection
    `π C (ord I · < o₂) → π C (ord I · < o₁)` for `o₁ ≤ o₂`. -/
@[simps!]
noncomputable
def πs' {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) :
    LocallyConstant (π C (ord I · < o₁)) ℤ →ₗ[ℤ] LocallyConstant (π C (ord I · < o₂)) ℤ 
goal: LocallyConstant ↑(Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₁) ℤ →ₗ[ℤ]
  LocallyConstant ↑(Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₂) ℤ

full_name: Profinite.NobelingProof.πs'_apply_apply
code: /-- The `ℤ`-linear map induced by precomposition of the projection
    `π C (ord I · < o₂) → π C (ord I · < o₁)` for `o₁ ≤ o₂`. -/
@[simps!]
noncomputable
def πs' {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) :
    LocallyConstant (π C (ord I · < o₁)) ℤ →ₗ[ℤ] LocallyConstant (π C (ord I · < o₂)) ℤ 
goal: ∀ (a : ↑(Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₂)),
  ((Profinite.NobelingProof.πs' C h) g) a = g (Profinite.NobelingProof.ProjRestricts C ⋯ a)

full_name: Profinite.NobelingProof.coe_πs'
code: theorem coe_πs' {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) (f : LocallyConstant (π C (ord I · < o₁)) ℤ) :
    (πs' C h f).toFun = f.toFun ∘ (ProjRestricts C (fun _ hh ↦ lt_of_lt_of_le hh h)) 
goal: ((Profinite.NobelingProof.πs' C h) f).toFun = f.toFun ∘ Profinite.NobelingProof.ProjRestricts C ⋯

full_name: Profinite.NobelingProof.injective_πs'
code: theorem injective_πs' {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) : Function.Injective (πs' C h) 
goal: Function.Injective ⇑(Profinite.NobelingProof.πs' C h)

full_name: Profinite.NobelingProof.Products.lt_ord_of_lt
code: theorem lt_ord_of_lt {l m : Products I} {o : Ordinal} (h₁ : m < l)
    (h₂ : ∀ i ∈ l.val, ord I i < o) : ∀ i ∈ m.val, ord I i < o 
goal: i ∈ ↑m → Profinite.NobelingProof.ord I i < o

full_name: Profinite.NobelingProof.Products.eval_πs
code: theorem eval_πs {l : Products I} {o : Ordinal} (hlt : ∀ i ∈ l.val, ord I i < o) :
    πs C o (l.eval (π C (ord I · < o))) = l.eval C 
goal: (Profinite.NobelingProof.πs C o)
    (Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)
      l) =
  Profinite.NobelingProof.Products.eval C l

full_name: Profinite.NobelingProof.Products.eval_πs'
code: theorem eval_πs' {l : Products I} {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂)
    (hlt : ∀ i ∈ l.val, ord I i < o₁) :
    πs' C h (l.eval (π C (ord I · < o₁))) = l.eval (π C (ord I · < o₂)) 
goal: (Profinite.NobelingProof.πs' C h)
    (Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₁)
      l) =
  Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₂) l

full_name: Profinite.NobelingProof.Products.eval_πs_image
code: theorem eval_πs_image {l : Products I} {o : Ordinal}
    (hl : ∀ i ∈ l.val, ord I i < o) : eval C '' { m | m < l } =
    (πs C o) '' (eval (π C (ord I · < o)) '' { m | m < l }) 
goal: Profinite.NobelingProof.Products.eval C '' {m | m < l} =
  ⇑(Profinite.NobelingProof.πs C o) ''
    (Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) ''
      {m | m < l})

full_name: Profinite.NobelingProof.Products.eval_πs_image'
code: theorem eval_πs_image' {l : Products I} {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂)
    (hl : ∀ i ∈ l.val, ord I i < o₁) : eval (π C (ord I · < o₂)) '' { m | m < l } =
    (πs' C h) '' (eval (π C (ord I · < o₁)) '' { m | m < l }) 
goal: Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₂) ''
    {m | m < l} =
  ⇑(Profinite.NobelingProof.πs' C h) ''
    (Profinite.NobelingProof.Products.eval
        (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₁) ''
      {m | m < l})

full_name: Profinite.NobelingProof.Products.head_lt_ord_of_isGood
code: theorem head_lt_ord_of_isGood [Inhabited I] {l : Products I} {o : Ordinal}
    (h : l.isGood (π C (ord I · < o))) (hn : l.val ≠ []) : ord I (l.val.head!) < o 
goal: Profinite.NobelingProof.ord I (↑l).head! < o

full_name: Profinite.NobelingProof.Products.isGood_mono
code: /--
If `l` is good w.r.t. `π C (ord I · < o₁)` and `o₁ ≤ o₂`, then it is good w.r.t.
`π C (ord I · < o₂)`
-/
theorem isGood_mono {l : Products I} {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂)
    (hl : l.isGood (π C (ord I · < o₁))) : l.isGood (π C (ord I · < o₂)) 
goal: Profinite.NobelingProof.Products.isGood (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o₂) l

full_name: Profinite.NobelingProof.GoodProducts.smaller
code: /--
The image of the `GoodProducts` for `π C (ord I · < o)` in `LocallyConstant C ℤ`. The name `smaller`
refers to the setting in which we will use this, when we are mapping in `GoodProducts` from a
smaller set, i.e. when `o` is a smaller ordinal than the one `C` is "contained" in.
-/
def smaller (o : Ordinal) : Set (LocallyConstant C ℤ) 
goal: Set (LocallyConstant ↑C ℤ)

full_name: Profinite.NobelingProof.GoodProducts.range_equiv_smaller_toFun
code: /--
The map from the image of the `GoodProducts` in `LocallyConstant (π C (ord I · < o)) ℤ` to
`smaller C o`
-/
noncomputable
def range_equiv_smaller_toFun (o : Ordinal) (x : range (π C (ord I · < o))) : smaller C o 
goal: ↑(Profinite.NobelingProof.GoodProducts.smaller C o)

full_name: Profinite.NobelingProof.GoodProducts.range_equiv_smaller_toFun_bijective
code: theorem range_equiv_smaller_toFun_bijective (o : Ordinal) :
    Function.Bijective (range_equiv_smaller_toFun C o) 
goal: Function.Bijective (Profinite.NobelingProof.GoodProducts.range_equiv_smaller_toFun C o)

full_name: Profinite.NobelingProof.GoodProducts.range_equiv_smaller
code: /--
The equivalence from the image of the `GoodProducts` in `LocallyConstant (π C (ord I · < o)) ℤ` to
`smaller C o`
-/
noncomputable
def range_equiv_smaller (o : Ordinal) : range (π C (ord I · < o)) ≃ smaller C o 
goal: ↑(Profinite.NobelingProof.GoodProducts.range
      (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)) ≃
  ↑(Profinite.NobelingProof.GoodProducts.smaller C o)

full_name: Profinite.NobelingProof.GoodProducts.smaller_factorization
code: theorem smaller_factorization (o : Ordinal) :
    (fun (p : smaller C o) ↦ p.1) ∘ (range_equiv_smaller C o).toFun =
    (πs C o) ∘ (fun (p : range (π C (ord I · < o))) ↦ p.1) 
goal: (fun p => ↑p) ∘ (Profinite.NobelingProof.GoodProducts.range_equiv_smaller C o).toFun =
  ⇑(Profinite.NobelingProof.πs C o) ∘ fun p => ↑p

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent_iff_smaller
code: theorem linearIndependent_iff_smaller (o : Ordinal) :
    LinearIndependent ℤ (GoodProducts.eval (π C (ord I · < o))) ↔
    LinearIndependent ℤ (fun (p : smaller C o) ↦ p.1) 
goal: LinearIndependent ℤ
    (Profinite.NobelingProof.GoodProducts.eval
      (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)) ↔
  LinearIndependent ℤ fun (p : ↑(Profinite.NobelingProof.GoodProducts.smaller C o)) => ↑p

full_name: Profinite.NobelingProof.GoodProducts.smaller_mono
code: theorem smaller_mono {o₁ o₂ : Ordinal} (h : o₁ ≤ o₂) : smaller C o₁ ⊆ smaller C o₂ 
goal: Profinite.NobelingProof.GoodProducts.smaller C o₁ ⊆ Profinite.NobelingProof.GoodProducts.smaller C o₂

full_name: Profinite.NobelingProof.Products.limitOrdinal
code: theorem Products.limitOrdinal (l : Products I) : l.isGood (π C (ord I · < o)) ↔
    ∃ (o' : Ordinal), o' < o ∧ l.isGood (π C (ord I · < o')) 
goal: Profinite.NobelingProof.Products.isGood (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) l ↔
  ∃ o' < o,
    Profinite.NobelingProof.Products.isGood (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o')
      l

full_name: Profinite.NobelingProof.GoodProducts.union
code: theorem GoodProducts.union : range C = ⋃ (e : {o' // o' < o}), (smaller C e.val) 
goal: Profinite.NobelingProof.GoodProducts.range C = ⋃ e, Profinite.NobelingProof.GoodProducts.smaller C ↑e

full_name: Profinite.NobelingProof.GoodProducts.range_equiv
code: /--
The image of the `GoodProducts` in `C` is equivalent to the union of `smaller C o'` over all
ordinals `o' < o`.
-/
def GoodProducts.range_equiv : range C ≃ ⋃ (e : {o' // o' < o}), (smaller C e.val) 
goal: ↑(Profinite.NobelingProof.GoodProducts.range C) ≃ ↑(⋃ e, Profinite.NobelingProof.GoodProducts.smaller C ↑e)

full_name: Profinite.NobelingProof.GoodProducts.range_equiv_factorization
code: theorem GoodProducts.range_equiv_factorization :
    (fun (p : ⋃ (e : {o' // o' < o}), (smaller C e.val)) ↦ p.1) ∘ (range_equiv C ho hsC).toFun =
    (fun (p : range C) ↦ (p.1 : LocallyConstant C ℤ)) 
goal: (fun p => ↑p) ∘ (Profinite.NobelingProof.GoodProducts.range_equiv C ho hsC).toFun = fun p => ↑p

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent_iff_union_smaller
code: theorem GoodProducts.linearIndependent_iff_union_smaller {o : Ordinal} (ho : o.IsLimit)
    (hsC : contained C o) : LinearIndependent ℤ (GoodProducts.eval C) ↔
    LinearIndependent ℤ (fun (p : ⋃ (e : {o' // o' < o}), (smaller C e.val)) ↦ p.1) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval C) ↔
  LinearIndependent ℤ fun (p : ↑(⋃ e, Profinite.NobelingProof.GoodProducts.smaller C ↑e)) => ↑p

full_name: Profinite.NobelingProof.C0
code: /-- The subset of `C` consisting of those elements whose `o`-th entry is `false`. -/
def C0 
goal: Set (I → Bool)

full_name: Profinite.NobelingProof.C1
code: /-- The subset of `C` consisting of those elements whose `o`-th entry is `true`. -/
def C1 
goal: Set (I → Bool)

full_name: Profinite.NobelingProof.isClosed_C0
code: theorem isClosed_C0 : IsClosed (C0 C ho) 
goal: IsClosed (Profinite.NobelingProof.C0 C ho)

full_name: Profinite.NobelingProof.isClosed_C1
code: theorem isClosed_C1 : IsClosed (C1 C ho) 
goal: IsClosed (Profinite.NobelingProof.C1 C ho)

full_name: Profinite.NobelingProof.contained_C1
code: theorem contained_C1 : contained (π (C1 C ho) (ord I · < o)) o 
goal: Profinite.NobelingProof.contained
  (Profinite.NobelingProof.π (Profinite.NobelingProof.C1 C ho) fun x => Profinite.NobelingProof.ord I x < o) o

full_name: Profinite.NobelingProof.union_C0C1_eq
code: theorem union_C0C1_eq : (C0 C ho) ∪ (C1 C ho) = C 
goal: Profinite.NobelingProof.C0 C ho ∪ Profinite.NobelingProof.C1 C ho = C

full_name: Profinite.NobelingProof.C'
code: /--
The intersection of `C0` and the projection of `C1`. We will apply the inductive hypothesis to
this set.
-/
def C' 
goal: Set (I → Bool)

full_name: Profinite.NobelingProof.isClosed_C'
code: theorem isClosed_C' : IsClosed (C' C ho) 
goal: IsClosed (Profinite.NobelingProof.C' C ho)

full_name: Profinite.NobelingProof.contained_C'
code: theorem contained_C' : contained (C' C ho) o 
goal: Profinite.NobelingProof.contained (Profinite.NobelingProof.C' C ho) o

full_name: Profinite.NobelingProof.SwapTrue
code: /-- Swapping the `o`-th coordinate to `true`. -/
noncomputable
def SwapTrue : (I → Bool) → I → Bool 
goal: (I → Bool) → I → Bool

full_name: Profinite.NobelingProof.continuous_swapTrue
code: theorem continuous_swapTrue  :
    Continuous (SwapTrue o : (I → Bool) → I → Bool) 
goal: Continuous (Profinite.NobelingProof.SwapTrue o)

full_name: Profinite.NobelingProof.swapTrue_mem_C1
code: theorem swapTrue_mem_C1 (f : π (C1 C ho) (ord I · < o)) :
    SwapTrue o f.val ∈ C1 C ho 
goal: Profinite.NobelingProof.SwapTrue o ↑f ∈ Profinite.NobelingProof.C1 C ho

full_name: Profinite.NobelingProof.CC'₀
code: /-- The first way to map `C'` into `C`. -/
def CC'₀ : C' C ho → C 
goal: ↑(Profinite.NobelingProof.C' C ho) → ↑C

full_name: Profinite.NobelingProof.CC'₁
code: /-- The second way to map `C'` into `C`. -/
noncomputable
def CC'₁ : C' C ho → C 
goal: ↑(Profinite.NobelingProof.C' C ho) → ↑C

full_name: Profinite.NobelingProof.continuous_CC'₀
code: theorem continuous_CC'₀ : Continuous (CC'₀ C ho) 
goal: Continuous (Profinite.NobelingProof.CC'₀ C ho)

full_name: Profinite.NobelingProof.continuous_CC'₁
code: theorem continuous_CC'₁ : Continuous (CC'₁ C hsC ho) 
goal: Continuous (Profinite.NobelingProof.CC'₁ C hsC ho)

full_name: Profinite.NobelingProof.Linear_CC'₀
code: /-- The `ℤ`-linear map induced by precomposing with `CC'₀` -/
noncomputable
def Linear_CC'₀ : LocallyConstant C ℤ →ₗ[ℤ] LocallyConstant (C' C ho) ℤ 
goal: LocallyConstant ↑C ℤ →ₗ[ℤ] LocallyConstant ↑(Profinite.NobelingProof.C' C ho) ℤ

full_name: Profinite.NobelingProof.Linear_CC'₁
code: /-- The `ℤ`-linear map induced by precomposing with `CC'₁` -/
noncomputable
def Linear_CC'₁ : LocallyConstant C ℤ →ₗ[ℤ] LocallyConstant (C' C ho) ℤ 
goal: LocallyConstant ↑C ℤ →ₗ[ℤ] LocallyConstant ↑(Profinite.NobelingProof.C' C ho) ℤ

full_name: Profinite.NobelingProof.Linear_CC'
code: /-- The difference between `Linear_CC'₁` and `Linear_CC'₀`. -/
noncomputable
def Linear_CC' : LocallyConstant C ℤ →ₗ[ℤ] LocallyConstant (C' C ho) ℤ 
goal: LocallyConstant ↑C ℤ →ₗ[ℤ] LocallyConstant ↑(Profinite.NobelingProof.C' C ho) ℤ

full_name: Profinite.NobelingProof.CC_comp_zero
code: theorem CC_comp_zero : ∀ y, (Linear_CC' C hsC ho) ((πs C o) y) = 0 
goal: (Profinite.NobelingProof.Linear_CC' C hsC ho) ((Profinite.NobelingProof.πs C o) y) = 0

full_name: Profinite.NobelingProof.C0_projOrd
code: theorem C0_projOrd {x : I → Bool} (hx : x ∈ C0 C ho) : Proj (ord I · < o) x = x 
goal: Profinite.NobelingProof.Proj (fun x => Profinite.NobelingProof.ord I x < o) x = x

full_name: Profinite.NobelingProof.C1_projOrd
code: theorem C1_projOrd {x : I → Bool} (hx : x ∈ C1 C ho) : SwapTrue o (Proj (ord I · < o) x) = x 
goal: Profinite.NobelingProof.SwapTrue o (Profinite.NobelingProof.Proj (fun x => Profinite.NobelingProof.ord I x < o) x) = x

full_name: Profinite.NobelingProof.CC_exact
code: theorem CC_exact {f : LocallyConstant C ℤ} (hf : Linear_CC' C hsC ho f = 0) :
    ∃ y, πs C o y = f 
goal: ∃ y, (Profinite.NobelingProof.πs C o) y = f

full_name: Profinite.NobelingProof.succ_mono
code: theorem succ_mono : CategoryTheory.Mono (ModuleCat.ofHom (πs C o)) 
goal: CategoryTheory.Mono (ModuleCat.ofHom (Profinite.NobelingProof.πs C o))

full_name: Profinite.NobelingProof.succ_exact
code: theorem succ_exact :
    (ShortComplex.mk (ModuleCat.ofHom (πs C o)) (ModuleCat.ofHom (Linear_CC' C hsC ho))
    (by ext; apply CC_comp_zero)).Exact 
goal: (CategoryTheory.ShortComplex.mk (ModuleCat.ofHom (Profinite.NobelingProof.πs C o))
    (ModuleCat.ofHom (Profinite.NobelingProof.Linear_CC' C hsC ho)) ⋯).Exact

full_name: Profinite.NobelingProof.GoodProducts.MaxProducts
code: /--
The `GoodProducts` in `C` that contain `o` (they necessarily start with `o`, see
`GoodProducts.head!_eq_o_of_maxProducts`)
-/
def MaxProducts : Set (Products I) 
goal: Set (Profinite.NobelingProof.Products I)

full_name: Profinite.NobelingProof.GoodProducts.union_succ
code: theorem union_succ : GoodProducts C = GoodProducts (π C (ord I · < o)) ∪ MaxProducts C ho 
goal: Profinite.NobelingProof.GoodProducts C =
  Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) ∪
    Profinite.NobelingProof.GoodProducts.MaxProducts C ho

full_name: Profinite.NobelingProof.GoodProducts.sum_to
code: /-- The inclusion map from the sum of `GoodProducts (π C (ord I · < o))` and
    `(MaxProducts C ho)` to `Products I`. -/
def sum_to : (GoodProducts (π C (ord I · < o))) ⊕ (MaxProducts C ho) → Products I 
goal: ↑(Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)) ⊕
    ↑(Profinite.NobelingProof.GoodProducts.MaxProducts C ho) →
  Profinite.NobelingProof.Products I

full_name: Profinite.NobelingProof.GoodProducts.injective_sum_to
code: theorem injective_sum_to : Function.Injective (sum_to C ho) 
goal: Function.Injective (Profinite.NobelingProof.GoodProducts.sum_to C ho)

full_name: Profinite.NobelingProof.GoodProducts.sum_to_range
code: theorem sum_to_range :
    Set.range (sum_to C ho) = GoodProducts (π C (ord I · < o)) ∪ MaxProducts C ho 
goal: Set.range (Profinite.NobelingProof.GoodProducts.sum_to C ho) =
  Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o) ∪
    Profinite.NobelingProof.GoodProducts.MaxProducts C ho

full_name: Profinite.NobelingProof.GoodProducts.sum_equiv
code: /-- The equivalence from the sum of `GoodProducts (π C (ord I · < o))` and
    `(MaxProducts C ho)` to `GoodProducts C`. -/
noncomputable
def sum_equiv : GoodProducts (π C (ord I · < o)) ⊕ (MaxProducts C ho) ≃ GoodProducts C 
goal: ↑(Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)) ⊕
    ↑(Profinite.NobelingProof.GoodProducts.MaxProducts C ho) ≃
  ↑(Profinite.NobelingProof.GoodProducts C)

full_name: Profinite.NobelingProof.GoodProducts.sum_equiv_comp_eval_eq_elim
code: theorem sum_equiv_comp_eval_eq_elim : eval C ∘ (sum_equiv C hsC ho).toFun =
    (Sum.elim (fun (l : GoodProducts (π C (ord I · < o))) ↦ Products.eval C l.1)
    (fun (l : MaxProducts C ho) ↦ Products.eval C l.1)) 
goal: Profinite.NobelingProof.GoodProducts.eval C ∘ (Profinite.NobelingProof.GoodProducts.sum_equiv C hsC ho).toFun =
  Sum.elim (fun l => Profinite.NobelingProof.Products.eval C ↑l) fun l => Profinite.NobelingProof.Products.eval C ↑l

full_name: Profinite.NobelingProof.GoodProducts.SumEval
code: /-- Let

`N := LocallyConstant (π C (ord I · < o)) ℤ`

`M := LocallyConstant C ℤ`

`P := LocallyConstant (C' C ho) ℤ`

`ι := GoodProducts (π C (ord I · < o))`

`ι' := GoodProducts (C' C ho')`

`v : ι → N := GoodProducts.eval (π C (ord I · < o))`

Then `SumEval C ho` is the map `u` in the diagram below. It is linearly independent if and only if
`GoodProducts.eval C` is, see `linearIndependent_iff_sum`. The top row is the exact sequence given
by `succ_exact` and `succ_mono`. The left square commutes by `GoodProducts.square_commutes`.
```
0 --→ N --→ M --→  P
      ↑     ↑      ↑
     v|    u|      |
      ι → ι ⊕ ι' ← ι'
```
-/
def SumEval : GoodProducts (π C (ord I · < o)) ⊕ MaxProducts C ho →
    LocallyConstant C ℤ 
goal: ↑(Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)) ⊕
    ↑(Profinite.NobelingProof.GoodProducts.MaxProducts C ho) →
  LocallyConstant ↑C ℤ

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent_iff_sum
code: theorem linearIndependent_iff_sum :
    LinearIndependent ℤ (eval C) ↔ LinearIndependent ℤ (SumEval C ho) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval C) ↔
  LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.SumEval C ho)

full_name: Profinite.NobelingProof.GoodProducts.span_sum
code: theorem span_sum : Set.range (eval C) = Set.range (Sum.elim
    (fun (l : GoodProducts (π C (ord I · < o))) ↦ Products.eval C l.1)
    (fun (l : MaxProducts C ho) ↦ Products.eval C l.1)) 
goal: Set.range (Profinite.NobelingProof.GoodProducts.eval C) =
  Set.range
    (Sum.elim (fun l => Profinite.NobelingProof.Products.eval C ↑l) fun l => Profinite.NobelingProof.Products.eval C ↑l)

full_name: Profinite.NobelingProof.GoodProducts.square_commutes
code: theorem square_commutes : SumEval C ho ∘ Sum.inl =
    ModuleCat.ofHom (πs C o) ∘ eval (π C (ord I · < o)) 
goal: Profinite.NobelingProof.GoodProducts.SumEval C ho ∘ Sum.inl =
  ⇑(ModuleCat.ofHom (Profinite.NobelingProof.πs C o)) ∘
    Profinite.NobelingProof.GoodProducts.eval (Profinite.NobelingProof.π C fun x => Profinite.NobelingProof.ord I x < o)

full_name: Profinite.NobelingProof.swapTrue_eq_true
code: theorem swapTrue_eq_true (x : I → Bool) : SwapTrue o x (term I ho) = true 
goal: Profinite.NobelingProof.SwapTrue o x (Profinite.NobelingProof.term I ho) = true

full_name: Profinite.NobelingProof.mem_C'_eq_false
code: theorem mem_C'_eq_false : ∀ x, x ∈ C' C ho → x (term I ho) = false 
goal: x ∈ Profinite.NobelingProof.C' C ho → x (Profinite.NobelingProof.term I ho) = false

full_name: Profinite.NobelingProof.Products.Tail
code: /-- `List.tail` as a `Products`. -/
def Products.Tail (l : Products I) : Products I 
goal: Profinite.NobelingProof.Products I

full_name: Profinite.NobelingProof.Products.max_eq_o_cons_tail
code: theorem Products.max_eq_o_cons_tail [Inhabited I] (l : Products I) (hl : l.val ≠ [])
    (hlh : l.val.head! = term I ho) : l.val = term I ho :: l.Tail.val 
goal: ↑l = Profinite.NobelingProof.term I ho :: ↑l.Tail

full_name: Profinite.NobelingProof.Products.max_eq_o_cons_tail'
code: theorem Products.max_eq_o_cons_tail' [Inhabited I] (l : Products I) (hl : l.val ≠ [])
    (hlh : l.val.head! = term I ho) (hlc : List.Chain' (·>·) (term I ho :: l.Tail.val)) :
    l = ⟨term I ho :: l.Tail.val, hlc⟩ 
goal: l = ⟨Profinite.NobelingProof.term I ho :: ↑l.Tail, hlc⟩

full_name: Profinite.NobelingProof.GoodProducts.head!_eq_o_of_maxProducts
code: theorem GoodProducts.head!_eq_o_of_maxProducts [Inhabited I] (l : ↑(MaxProducts C ho)) :
    l.val.val.head! = term I ho 
goal: (↑↑l).head! = Profinite.NobelingProof.term I ho

full_name: Profinite.NobelingProof.GoodProducts.max_eq_o_cons_tail
code: theorem GoodProducts.max_eq_o_cons_tail (l : MaxProducts C ho) :
    l.val.val = (term I ho) :: l.val.Tail.val 
goal: ↑↑l = Profinite.NobelingProof.term I ho :: ↑(↑l).Tail

full_name: Profinite.NobelingProof.Products.evalCons
code: theorem Products.evalCons {l : List I} {a : I}
    (hla : (a::l).Chain' (·>·)) : Products.eval C ⟨a::l,hla⟩ =
    (e C a) * Products.eval C ⟨l,List.Chain'.sublist hla (List.tail_sublist (a::l))⟩ 
goal: Profinite.NobelingProof.Products.eval C ⟨a :: l, hla⟩ =
  Profinite.NobelingProof.e C a * Profinite.NobelingProof.Products.eval C ⟨l, ⋯⟩

full_name: Profinite.NobelingProof.Products.max_eq_eval
code: theorem Products.max_eq_eval [Inhabited I] (l : Products I) (hl : l.val ≠ [])
    (hlh : l.val.head! = term I ho) :
    Linear_CC' C hsC ho (l.eval C) = l.Tail.eval (C' C ho) 
goal: (Profinite.NobelingProof.Linear_CC' C hsC ho) (Profinite.NobelingProof.Products.eval C l) =
  Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.C' C ho) l.Tail

full_name: Profinite.NobelingProof.GoodProducts.max_eq_eval
code: theorem max_eq_eval (l : MaxProducts C ho) :
    Linear_CC' C hsC ho (l.val.eval C) = l.val.Tail.eval (C' C ho) 
goal: (Profinite.NobelingProof.Linear_CC' C hsC ho) (Profinite.NobelingProof.Products.eval C ↑l) =
  Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.C' C ho) (↑l).Tail

full_name: Profinite.NobelingProof.GoodProducts.max_eq_eval_unapply
code: theorem max_eq_eval_unapply :
    (Linear_CC' C hsC ho) ∘ (fun (l : MaxProducts C ho) ↦ Products.eval C l.val) =
    (fun l ↦ l.val.Tail.eval (C' C ho)) 
goal: (⇑(Profinite.NobelingProof.Linear_CC' C hsC ho) ∘ fun l => Profinite.NobelingProof.Products.eval C ↑l) = fun l =>
  Profinite.NobelingProof.Products.eval (Profinite.NobelingProof.C' C ho) (↑l).Tail

full_name: Profinite.NobelingProof.GoodProducts.chain'_cons_of_lt
code: theorem chain'_cons_of_lt (l : MaxProducts C ho)
    (q : Products I) (hq : q < l.val.Tail) :
    List.Chain' (fun x x_1 ↦ x > x_1) (term I ho :: q.val) 
goal: List.Chain' (fun x x_1 => x > x_1) (Profinite.NobelingProof.term I ho :: ↑q)

full_name: Profinite.NobelingProof.GoodProducts.good_lt_maxProducts
code: theorem good_lt_maxProducts (q : GoodProducts (π C (ord I · < o)))
    (l : MaxProducts C ho) : List.Lex (·<·) q.val.val l.val.val 
goal: List.Lex (fun x x_1 => x < x_1) ↑↑q ↑↑l

full_name: Profinite.NobelingProof.GoodProducts.maxTail_isGood
code: /--
Removing the leading `o` from a term of `MaxProducts C` yields a list which `isGood` with respect to
`C'`.
-/
theorem maxTail_isGood (l : MaxProducts C ho)
    (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) :
    l.val.Tail.isGood (C' C ho) 
goal: Profinite.NobelingProof.Products.isGood (Profinite.NobelingProof.C' C ho) (↑l).Tail

full_name: Profinite.NobelingProof.GoodProducts.MaxToGood
code: /-- Given `l : MaxProducts C ho`, its `Tail` is a `GoodProducts (C' C ho)`. -/
noncomputable
def MaxToGood
    (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) :
    MaxProducts C ho → GoodProducts (C' C ho) 
goal: ↑(Profinite.NobelingProof.GoodProducts.MaxProducts C ho) →
  ↑(Profinite.NobelingProof.GoodProducts (Profinite.NobelingProof.C' C ho))

full_name: Profinite.NobelingProof.GoodProducts.maxToGood_injective
code: theorem maxToGood_injective
    (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) :
    (MaxToGood C hC hsC ho h₁).Injective 
goal: Function.Injective (Profinite.NobelingProof.GoodProducts.MaxToGood C hC hsC ho h₁)

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent_comp_of_eval
code: theorem linearIndependent_comp_of_eval
    (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) :
    LinearIndependent ℤ (eval (C' C ho)) →
    LinearIndependent ℤ (ModuleCat.ofHom (Linear_CC' C hsC ho) ∘ SumEval C ho ∘ Sum.inr) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval (Profinite.NobelingProof.C' C ho)) →
  LinearIndependent (ι := ↑(Profinite.NobelingProof.GoodProducts.MaxProducts C ho)) ℤ
    (⇑(ModuleCat.ofHom (Profinite.NobelingProof.Linear_CC' C hsC ho)) ∘
      Profinite.NobelingProof.GoodProducts.SumEval C ho ∘ Sum.inr)

full_name: Profinite.NobelingProof.GoodProducts.P0
code: theorem GoodProducts.P0 : P I 0 
goal: Profinite.NobelingProof.P I 0

full_name: Profinite.NobelingProof.GoodProducts.Plimit
code: theorem GoodProducts.Plimit (o : Ordinal) (ho : Ordinal.IsLimit o) :
    (∀ (o' : Ordinal), o' < o → P I o') → P I o 
goal: (∀ o' < o, Profinite.NobelingProof.P I o') → Profinite.NobelingProof.P I o

full_name: Profinite.NobelingProof.GoodProducts.linearIndependentAux
code: theorem GoodProducts.linearIndependentAux (μ : Ordinal) : P I μ 
goal: Profinite.NobelingProof.P I μ

full_name: Profinite.NobelingProof.GoodProducts.linearIndependent
code: theorem GoodProducts.linearIndependent (hC : IsClosed C) :
    LinearIndependent ℤ (GoodProducts.eval C) 
goal: LinearIndependent ℤ (Profinite.NobelingProof.GoodProducts.eval C)

full_name: Profinite.NobelingProof.GoodProducts.Basis
code: /-- `GoodProducts C` as a `ℤ`-basis for `LocallyConstant C ℤ`.  -/
noncomputable
def GoodProducts.Basis (hC : IsClosed C) :
    Basis (GoodProducts C) ℤ (LocallyConstant C ℤ) 
goal: Basis ↑(Profinite.NobelingProof.GoodProducts C) ℤ (LocallyConstant ↑C ℤ)

full_name: Profinite.NobelingProof.Nobeling_aux
code: /--
Given a profinite set `S` and a closed embedding `S → (I → Bool)`, the `ℤ`-module
`LocallyConstant C ℤ` is free.
-/
theorem Nobeling_aux : Module.Free ℤ (LocallyConstant S ℤ) 
goal: Module.Free ℤ (LocallyConstant ↑S.toTop ℤ)

full_name: Profinite.Nobeling.ι
code: /-- The embedding `S → (I → Bool)` where `I` is the set of clopens of `S`. -/
noncomputable
def Nobeling.ι : S → ({C : Set S // IsClopen C} → Bool) 
goal: ↑S.toTop → { C // IsClopen C } → Bool

full_name: Profinite.Nobeling.embedding
code: /-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) 
goal: ClosedEmbedding (Profinite.Nobeling.ι S)

full_name: LocallyConstant.freeOfProfinite
code: /-- Nöbeling's theorem: the `ℤ`-module `LocallyConstant S ℤ` is free for every `S : Profinite` -/
instance LocallyConstant.freeOfProfinite (S : Profinite.{u}) :
    Module.Free ℤ (LocallyConstant S ℤ) 
goal: Module.Free ℤ (LocallyConstant ↑S.toTop ℤ)