All problems

E571:Erdős Problem #571 Does every rational exponent in [1,2) occur for one bipartite Turán graph?

September1,2026 announcement, Additional Attempts: full solution to Erdős571 by GPT-6 Astra.

Contributors

Solution

/-
Adapted 2026-09-05 for Jig330 from the proof by GPT-6 Astra in the Epoch AI
FrontierMath Erdős campaign (Tom Adamczewski and Thomas F. Bloom).
Public source: https://github.com/tadamcz/erdos571
Pinned commit: 661cc1d842c54661f55046d27abef531d0583b1e
Original module: Erdos571/Resolutions/Erdos571_325usd_42h.lean
Apache-2.0; accompanying LICENSE and NOTICE retained in campaign-discrete/erdos571-public.
Local changes: narrow Mathlib imports and port from Lean 4.28 to Jig's pinned Lean 4.33.
This is a port of existing mathematics, not a new solution discovered in this campaign.
-/
import Mathlib.Combinatorics.SimpleGraph.Bipartite
import Mathlib.Combinatorics.SimpleGraph.Copy
import Mathlib.Combinatorics.SimpleGraph.Extremal.TuranDensity
import Mathlib.Analysis.SpecialFunctions.Pow.Real
import Mathlib.Analysis.Asymptotics.Theta
import Mathlib.RingTheory.AlgebraicIndependent.TranscendenceBasis
import Mathlib.RingTheory.AlgebraicIndependent.AlgebraicClosure
import Mathlib.FieldTheory.AlgebraicClosure
import Mathlib.FieldTheory.Finite.GaloisField
import Mathlib.Algebra.MvPolynomial.SchwartzZippel
import Mathlib.Algebra.MvPolynomial.Supported
import Mathlib.Order.Filter.Germ.Basic
import Mathlib.LinearAlgebra.Matrix.Rank
import Mathlib.Tactic
import Mathlib.Algebra.Order.Chebyshev
import Mathlib.Analysis.MeanInequalities

set_option backward.isDefEq.respectTransparency false
set_option maxHeartbeats 1600000
set_option linter.all false
set_option linter.unusedTactic false
set_option linter.unusedSimpArgs false
set_option linter.unusedSectionVars false
set_option linter.unusedVariables false


/-!
# Erdős Problem 571

*References:*
- [erdosproblems.com/571](https://www.erdosproblems.com/571)

The proof constructs balanced rooted models for all rational parameters.
Its upper-bound closure replaces old edges by paths of arbitrary length,
adds two color-class hubs, and commutes with positive rooted powers.
-/

section -- RootedUnionDensity

/- Balance is preserved by unions of injective copies agreeing on their roots. -/
open Finset SimpleGraph
namespace RootedUnionDensity

variable {A R V I : Type*} [Fintype A] [Fintype R] [DecidableEq V]

noncomputable def interiors (f : A ⊕ R ↪ V) : Finset V := by
  classical
  exact univ.image (fun a => f (Sum.inl a))

noncomputable def copyEdges (G : SimpleGraph (A ⊕ R)) (f : A ⊕ R ↪ V) :
    Finset (Sym2 V) := by
  classical
  exact G.edgeFinset.image (Sym2.map f)

noncomputable def incident (G : SimpleGraph (A ⊕ R)) (s : Finset A) :
    Finset (Sym2 (A ⊕ R)) := by
  classical
  exact G.edgeFinset.filter (fun e => ∃ a ∈ s, Sum.inl a ∈ e)

lemma mem_interiors (f : A ⊕ R ↪ V) (v : V) :
    v ∈ interiors f ↔ ∃ a, f (Sum.inl a) = v := by
  classical
  simp [interiors]

lemma endpoint_support (G : SimpleGraph (A ⊕ R)) (f : A ⊕ R ↪ V)
    {e : Sym2 V} (he : e ∈ copyEdges G f) {v : V} (hv : v ∈ e) :
    v ∈ interiors f ∨ ∃ r, f (Sum.inr r) = v := by
  classical
  obtain ⟨e, he, rfl⟩ := mem_image.mp he
  obtain ⟨x, hx, rfl⟩ := Sym2.mem_map.mp hv
  cases x with
  | inl a => exact Or.inl ((mem_interiors f _).mpr ⟨a,rfl⟩)
  | inr r => exact Or.inr ⟨r,rfl⟩

/-- Insert one copy into an already-supported edge set. -/
lemma insert_density (G : SimpleGraph (A ⊕ R)) (ρ : ℚ)
    (hbalance : ∀ s : Finset A, ρ * s.card ≤ (incident G s).card)
    (f : A ⊕ R ↪ V) (r : R → V) (hf : ∀ x, f (Sum.inr x) = r x)
    (U : Finset V) (E : Finset (Sym2 V))
    (hsupport : ∀ e ∈ E, ∀ v ∈ e, v ∈ U ∨ ∃ x, r x = v)
    (hdensity : ρ * U.card ≤ E.card) :
    ρ * (U ∪ interiors f).card ≤ (E ∪ copyEdges G f).card := by
  classical
  let s := univ.filter (fun a : A => f (Sum.inl a) ∉ U)
  have hnew : interiors f \ U = s.image (fun a => f (Sum.inl a)) := by
    ext v
    simp only [Finset.mem_sdiff, mem_interiors, mem_image, s, mem_filter, mem_univ,
      true_and]
    aesop
  have hvc : (U ∪ interiors f).card = U.card + s.card := by
    have hh := card_sdiff_add_card_eq_card (subset_union_left (s₁ := U) (s₂ := interiors f))
    rw [union_sdiff_left, hnew,
      card_image_of_injective _ (show Function.Injective (fun a : A => f (Sum.inl a)) from
        f.injective.comp Sum.inl_injective)] at hh
    omega
  have hnewedges : (incident G s).image (Sym2.map f) ⊆ copyEdges G f \ E := by
    intro e he
    obtain ⟨d, hd, rfl⟩ := mem_image.mp he
    obtain ⟨hdG, a, ha, had⟩ := mem_filter.mp hd
    refine Finset.mem_sdiff.mpr ⟨mem_image.mpr ⟨d,hdG,rfl⟩, ?_⟩
    intro hold
    have hmem : f (Sum.inl a) ∈ Sym2.map f d := Sym2.mem_map.mpr ⟨_,had,rfl⟩
    rcases hsupport _ hold _ hmem with hU | ⟨x, hx⟩
    · exact (mem_filter.mp ha).2 hU
    · have heq : Sum.inr x = Sum.inl a := f.injective ((hf x).trans hx)
      exact Sum.inr_ne_inl heq
  have hec : (incident G s).card ≤ (copyEdges G f \ E).card := by
    simpa only [card_image_of_injective _ (Sym2.map.injective f.injective)] using
      card_le_card hnewedges
  have hEc : (E ∪ copyEdges G f).card = E.card + (copyEdges G f \ E).card := by
    have hh := card_sdiff_add_card_eq_card (subset_union_left (s₁ := E) (s₂ := copyEdges G f))
    rw [union_sdiff_left] at hh
    omega
  rw [hvc, hEc, Nat.cast_add, Nat.cast_add, mul_add]
  have hb := hbalance s
  have hec' : ((incident G s).card : ℚ) ≤ (copyEdges G f \ E).card := by exact_mod_cast hec
  linarith

/-- The union of common-root copies of a balanced rooted graph has at least
`ρ` edges per distinct internal vertex. Overlaps of interiors are allowed. -/
lemma union_density (G : SimpleGraph (A ⊕ R)) (ρ : ℚ)
    (hbalance : ∀ s : Finset A, ρ * s.card ≤ (incident G s).card)
    (f : I → (A ⊕ R ↪ V)) (r : R → V) (T : Finset I)
    (hf : ∀ i ∈ T, ∀ x, f i (Sum.inr x) = r x) :
    ρ * (T.biUnion (fun i => interiors (f i))).card ≤
      (T.biUnion (fun i => copyEdges G (f i))).card := by
  classical
  induction T using Finset.induction_on with
  | empty => simp
  | @insert i T hi ih =>
    have hfT : ∀ i ∈ T, ∀ x, f i (Sum.inr x) = r x := fun i hi => hf i (mem_insert_of_mem hi)
    have hs : ∀ e ∈ T.biUnion (fun j => copyEdges G (f j)), ∀ v ∈ e,
        v ∈ T.biUnion (fun j => interiors (f j)) ∨ ∃ x, r x = v := by
      intro e he v hv
      obtain ⟨j, hj, he⟩ := mem_biUnion.mp he
      rcases endpoint_support G (f j) he hv with hv | ⟨x,hx⟩
      · exact Or.inl (mem_biUnion.mpr ⟨j,hj,hv⟩)
      · exact Or.inr ⟨x, (hfT j hj x).symm.trans hx⟩
    simpa only [biUnion_insert, union_comm] using
      insert_density G ρ hbalance (f i) r (hf i (mem_insert_self _ _))
        _ _ hs (ih hfT)

end RootedUnionDensity

end -- RootedUnionDensity

section -- GraphSubdivision

/- Subdivision and the transformation of rooted balance. -/
open Finset SimpleGraph
namespace GraphSubdivision
universe u

variable {V : Type u} (G : SimpleGraph V)
abbrev Edge := G.edgeSet


section Finite
variable [Fintype V] [DecidableEq V] [Fintype (Edge G)]


noncomputable def incidentEdges (s : Finset V) : Finset (Edge G) := by
  classical
  exact univ.filter (fun e => ∃ v ∈ s, v ∈ e.val)


end Finite

section Rooted
variable {A R : Type u} (F : SimpleGraph (A ⊕ R))


variable [Fintype A] [Fintype R] [Fintype (Edge F)] [DecidableEq A] [DecidableEq R]

lemma old_incident_count (s : Finset A) :
    (incidentEdges F (s.image Sum.inl)).card = (RootedUnionDensity.incident F s).card := by
  classical
  apply card_bij (fun e _ => e.val)
  · intro e he
    simp only [incidentEdges,mem_filter,mem_univ,true_and,mem_image] at he
    obtain ⟨v,⟨a,ha,rfl⟩,hv⟩ := he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
    exact ⟨e.property,a,ha,hv⟩
  · intro e he f hf h
    exact Subtype.ext h
  · intro e he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset] at he
    refine ⟨⟨e,he.1⟩,?_,rfl⟩
    simp only [incidentEdges,mem_filter,mem_univ,true_and]
    obtain ⟨a,ha,hae⟩ := he.2
    exact ⟨Sum.inl a,mem_image.mpr ⟨a,ha,rfl⟩,hae⟩


end Rooted
end GraphSubdivision

end -- GraphSubdivision

section -- ColoredEdges

/- Canonically orient the edges of a two-colored simple graph. -/
open SimpleGraph
namespace ColoredEdges
set_option maxHeartbeats 1500000
universe u
variable {W : Type u} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
abbrev Edge := GraphSubdivision.Edge F

noncomputable def left (e : Edge (F := F)) : W := if c e.val.out.1=0 then e.val.out.1 else e.val.out.2
noncomputable def right (e : Edge (F := F)) : W := if c e.val.out.1=0 then e.val.out.2 else e.val.out.1

lemma out_adj (e : Edge (F := F)) : F.Adj e.val.out.1 e.val.out.2 := by
  change s(e.val.out.1,e.val.out.2)∈F.edgeSet
  have he : s(e.val.out.1,e.val.out.2)=e.val := e.val.out_eq
  rw [he]
  exact e.property

lemma left_color (e : Edge (F := F)) : c (left c e)=0 := by
  have hne := c.valid (out_adj e)
  dsimp [left]
  split_ifs with h
  · exact h
  · omega

lemma right_color (e : Edge (F := F)) : c (right c e)=1 := by
  have hne := c.valid (out_adj e)
  dsimp [right]
  split_ifs <;> omega

lemma pair (e : Edge (F := F)) : s(left c e,right c e)=e.val := by
  dsimp [left,right]
  split_ifs
  · exact e.val.out_eq
  · exact (Sym2.eq_swap).trans e.val.out_eq

lemma adj (e : Edge (F := F)) : F.Adj (left c e) (right c e) := by
  change s(left c e,right c e)∈F.edgeSet
  rw [pair]
  exact e.property

lemma mem_iff (e : Edge (F := F)) (w : W) : w∈e.val ↔ w=left c e ∨ w=right c e := by
  rw [← pair c e,Sym2.mem_iff]

lemma left_unique (e : Edge (F := F)) {w : W} (hw : w∈e.val) (hc : c w=0) : w=left c e := by
  rcases (mem_iff c e w).mp hw with h | h
  · exact h
  · rw [h,right_color] at hc; exact (by decide : (1 : Fin 2)≠0) hc |>.elim

lemma right_unique (e : Edge (F := F)) {w : W} (hw : w∈e.val) (hc : c w=1) : w=right c e := by
  rcases (mem_iff c e w).mp hw with h | h
  · rw [h,left_color] at hc; exact (by decide : (0 : Fin 2)≠1) hc |>.elim
  · exact h


end ColoredEdges

end -- ColoredEdges

section -- FinitePathIncidences

/- Incident-edge inequalities for a path with a finite set of selected internal vertices. -/
open Finset
namespace FinitePathIncidences
set_option maxHeartbeats 1500000
noncomputable section
local instance (p : Prop) : Decidable p := Classical.propDecidable p

/-- There are `k` internal vertices and `k+1` edges.  Vertex `v` meets
edges `v.castSucc` and `v.succ`. -/
def incident (k : ℕ) (x z : Prop) (T : Finset (Fin k)) : Finset (Fin (k+1)) :=
  univ.filter (fun i => (i=0 ∧ x) ∨ (i=Fin.last k ∧ z) ∨ ∃ v∈T, i=v.castSucc ∨ i=v.succ)

lemma mem_incident (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (i : Fin (k+1)) :
    i∈incident k x z T ↔ (i=0 ∧ x) ∨ (i=Fin.last k ∧ z) ∨ ∃ v∈T, i=v.castSucc ∨ i=v.succ := by
  simp only [incident,mem_filter,mem_univ,true_and]

lemma left_mem (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (hx : x) : 0∈incident k x z T :=
  (mem_incident k x z T 0).mpr (Or.inl ⟨rfl,hx⟩)

lemma right_mem (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (hz : z) : Fin.last k∈incident k x z T :=
  (mem_incident k x z T _).mpr (Or.inr (Or.inl ⟨rfl,hz⟩))

lemma castSucc_mem (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (v : Fin k) (hv : v∈T) :
    v.castSucc∈incident k x z T :=
  (mem_incident k x z T _).mpr (Or.inr (Or.inr ⟨v,hv,Or.inl rfl⟩))

lemma succ_mem (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (v : Fin k) (hv : v∈T) :
    v.succ∈incident k x z T :=
  (mem_incident k x z T _).mpr (Or.inr (Or.inr ⟨v,hv,Or.inr rfl⟩))


lemma internal_add_one_le (k : ℕ) (x z : Prop) (T : Finset (Fin k)) (hT : T.Nonempty) :
    T.card+1≤(incident k x z T).card := by
  let v := T.max' hT
  let L := T.image Fin.castSucc
  have hv : v∈T := max'_mem T hT
  have hnot : v.succ∉L := by
    intro hh
    obtain ⟨w,hw,he⟩ := mem_image.mp hh
    have hle := le_max' T w hw
    have hval := congrArg Fin.val he
    change w.val=v.val+1 at hval
    have hh : w.val≤v.val := hle
    omega
  have hsub : insert v.succ L⊆incident k x z T := by
    intro i hi
    rcases mem_insert.mp hi with rfl | hi
    · exact succ_mem k x z T v hv
    · obtain ⟨w,hw,rfl⟩ := mem_image.mp hi
      exact castSucc_mem k x z T w hw
  have hcard : (insert v.succ L).card=T.card+1 := by
    rw [card_insert_of_notMem hnot]
    simp only [L,card_image_of_injective _ (Fin.castSucc_injective (n := k))]
  rw [← hcard]
  exact card_le_card hsub

lemma endpoint_plus_internal (k : ℕ) (x z : Prop) (T : Finset (Fin k)) :
    (if x∨z then 1 else 0)+T.card≤(incident k x z T).card := by
  by_cases hT : T.Nonempty
  · have hh := internal_add_one_le k x z T hT
    split_ifs <;> omega
  · have he : T=∅ := not_nonempty_iff_eq_empty.mp hT
    subst T
    simp only [card_empty,add_zero]
    split_ifs with hx
    · apply card_pos.mpr
      rcases hx with hx | hz
      · exact ⟨0,left_mem k x z ∅ hx⟩
      · exact ⟨Fin.last k,right_mem k x z ∅ hz⟩
    · exact Nat.zero_le _

lemma internal_ratio (k : ℕ) (x z : Prop) (T : Finset (Fin k)) :
    (k+1)*T.card≤k*(incident k x z T).card := by
  by_cases hT : T.Nonempty
  · have hh := internal_add_one_le k x z T hT
    have hc : T.card≤k := by simpa only [Fintype.card_fin] using card_le_univ T
    have hm := Nat.mul_le_mul_left k hh
    nlinarith only [hc,hm]
  · rw [not_nonempty_iff_eq_empty.mp hT,card_empty,mul_zero]
    exact Nat.zero_le _

end
end FinitePathIncidences

end -- FinitePathIncidences

section -- HubPathSubdivision

/- Two color-class hubs attached to arbitrary-length edge replacement paths.
This module is finite graph infrastructure, not an extremal upper theorem. -/
open Finset SimpleGraph
namespace HubPathSubdivision
set_option maxHeartbeats 2500000
universe u
variable {W : Type u} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
abbrev E := GraphSubdivision.Edge F
abbrev CoreVertex (k : ℕ) := W ⊕ (E (F := F) × Fin k)
abbrev Vertex (k : ℕ) := Fin 2 ⊕ CoreVertex (F := F) k

noncomputable def point (k : ℕ) (e : E (F := F)) (i : Fin (k+2)) : CoreVertex (F := F) k :=
  if h0 : i.val=0 then Sum.inl (ColoredEdges.left c e)
  else if hlast : i.val=k+1 then Sum.inl (ColoredEdges.right c e)
  else Sum.inr (e,⟨i.val-1,by have := i.isLt; omega⟩)

lemma point_zero (k : ℕ) (e : E (F := F)) : point c k e 0=Sum.inl (ColoredEdges.left c e) := by
  simp [point]

lemma point_last (k : ℕ) (e : E (F := F)) :
    point c k e (Fin.last (k+1))=Sum.inl (ColoredEdges.right c e) := by simp [point]

lemma point_mid_iff (k : ℕ) (e f : E (F := F)) (i : Fin (k+2)) (j : Fin k) :
    point c k e i=Sum.inr (f,j) ↔ e=f ∧ i.val=j.val+1 := by
  dsimp only [point]
  split_ifs with h0 hl
  · simp only [Sum.inl_ne_inr,false_iff,not_and]
    intro _
    omega
  · simp only [Sum.inl_ne_inr,false_iff,not_and]
    intro _
    have := j.isLt
    omega
  · simp only [Sum.inr.injEq,Prod.mk.injEq,Fin.ext_iff]
    have := i.isLt
    apply and_congr Iff.rfl
    omega

lemma point_mid (k : ℕ) (e : E (F := F)) (j : Fin k) :
    point c k e j.succ.castSucc=Sum.inr (e,j) :=
  (point_mid_iff c k e e _ j).mpr ⟨rfl,rfl⟩

lemma left_ne_right (e : E (F := F)) : ColoredEdges.left c e≠ColoredEdges.right c e :=
  (ColoredEdges.adj c e).ne

noncomputable def level (k : ℕ) (e : E (F := F)) : CoreVertex (F := F) k → ℕ := by
  classical
  exact Sum.elim (fun w => if w=ColoredEdges.left c e then 0 else k+1) (fun p => p.2.val+1)

lemma point_level (k : ℕ) (e : E (F := F)) (i : Fin (k+2)) :
    level c k e (point c k e i)=i.val := by
  classical
  dsimp only [point]
  split_ifs with h0 hl
  · simp [level,h0]
  · simp [level,(left_ne_right c e).symm,hl]
  · simp only [level,Sum.elim_inr]
    omega

lemma point_injective (k : ℕ) (e : E (F := F)) : Function.Injective (point c k e) := by
  intro i j he
  apply Fin.ext
  have hh := congrArg (level c k e) he
  simpa only [point_level] using hh

noncomputable def coreEdge (k : ℕ) (e : E (F := F)) (i : Fin (k+1)) : Sym2 (CoreVertex (F := F) k) :=
  s(point c k e i.castSucc,point c k e i.succ)

lemma coreEdge_middle (k : ℕ) (hk : 0<k) (e : E (F := F)) (i : Fin (k+1)) :
    ∃ j : Fin k, Sum.inr (e,j)∈coreEdge c k e i := by
  by_cases hi : i.val=0
  · let j : Fin k := ⟨0,hk⟩
    have he : point c k e i.succ=Sum.inr (e,j) :=
      (point_mid_iff c k e e _ j).mpr ⟨rfl,by change i.val+1=0+1; omega⟩
    refine ⟨j,?_⟩
    rw [← he]
    exact Sym2.mem_mk_right _ _
  · let j : Fin k := ⟨i.val-1,by have := i.isLt; omega⟩
    have he : point c k e i.castSucc=Sum.inr (e,j) :=
      (point_mid_iff c k e e _ j).mpr ⟨rfl,by change i.val=i.val-1+1; omega⟩
    refine ⟨j,?_⟩
    rw [← he]
    exact Sym2.mem_mk_left _ _

lemma middle_mem_coreEdge (k : ℕ) (e f : E (F := F)) (j : Fin k) (i : Fin (k+1))
    (h : Sum.inr (e,j)∈coreEdge c k f i) : e=f := by
  rcases Sym2.mem_iff.mp h with h | h
  · exact ((point_mid_iff c k f e i.castSucc j).mp h.symm).1.symm
  · exact ((point_mid_iff c k f e i.succ j).mp h.symm).1.symm

lemma coreEdge_injective (k : ℕ) : Function.Injective (fun p : E (F := F) × Fin (k+1) => coreEdge c k p.1 p.2) := by
  rintro ⟨e,i⟩ ⟨f,j⟩ h
  dsimp only at h
  have hef : e=f := by
    by_cases hk : k=0
    · subst k
      have hi : i=0 := by apply Fin.ext; have := i.isLt; change i.val=0; omega
      have hj : j=0 := by apply Fin.ext; have := j.isLt; change j.val=0; omega
      have he : coreEdge c 0 e i=Sym2.map Sum.inl e.val := by
        rw [hi]
        rw [← ColoredEdges.pair c e]
        simp [coreEdge,point]
      have hf : coreEdge c 0 f j=Sym2.map Sum.inl f.val := by
        rw [hj]
        rw [← ColoredEdges.pair c f]
        simp [coreEdge,point]
      rw [he,hf] at h
      exact Subtype.ext (Sym2.map.injective Sum.inl_injective h)
    · obtain ⟨l,hl⟩ := coreEdge_middle c k (Nat.pos_of_ne_zero hk) e i
      rw [h] at hl
      exact middle_mem_coreEdge c k e f l j hl
  subst f
  have hij : i=j := by
    have hh : s(i.castSucc,i.succ)=s(j.castSucc,j.succ) :=
      Sym2.map.injective (point_injective c k e) h
    rcases Sym2.eq_iff.mp hh with ⟨h1,h2⟩ | ⟨h1,h2⟩
    · exact Fin.castSucc_injective (k+1) h1
    · have h1' := congrArg Fin.val h1
      have h2' := congrArg Fin.val h2
      simp only [Fin.val_castSucc,Fin.val_succ] at h1' h2'
      omega
  exact Prod.ext rfl hij

noncomputable def graph (k : ℕ) : SimpleGraph (Vertex (F := F) k) where
  Adj u v := match u,v with
    | Sum.inl _,Sum.inl _ => False
    | Sum.inl i,Sum.inr a => match a with
      | Sum.inl w => c w=i
      | Sum.inr _ => False
    | Sum.inr a,Sum.inl i => match a with
      | Sum.inl w => c w=i
      | Sum.inr _ => False
    | Sum.inr a,Sum.inr b => ∃ e i, s(a,b)=coreEdge c k e i
  symm := by
    constructor
    intro u v h
    rcases u with i | a | e <;> rcases v with j | b | f
    all_goals first | exact h | simpa only [Sym2.eq_swap] using h
  loopless := by
    constructor
    intro u
    rcases u with i | a
    · exact not_false
    · rintro ⟨e,j,h⟩
      have hne : point c k e j.castSucc≠point c k e j.succ := by
        intro he
        have hh := congrArg Fin.val (point_injective c k e he)
        simp only [Fin.val_castSucc,Fin.val_succ] at hh
        omega
      rcases Sym2.eq_iff.mp h with ⟨h1,h2⟩ | ⟨h1,h2⟩
      · exact hne (h1.symm.trans h2)
      · exact hne (h2.symm.trans h1)

lemma coreEdge_adj (k : ℕ) (e : E (F := F)) (i : Fin (k+1)) :
    (graph c k).Adj (Sum.inr (point c k e i.castSucc)) (Sum.inr (point c k e i.succ)) := by
  change ∃ e' i', s(point c k e i.castSucc,point c k e i.succ)=coreEdge c k e' i'
  exact ⟨e,i,rfl⟩


def parity (n : ℕ) : Fin 2 := ⟨n%2,by omega⟩
def oldPaint (k : ℕ) (i : Fin 2) : Fin 2 := if i=0 then 0 else parity (k+1)
def flip (i : Fin 2) : Fin 2 := if i=0 then 1 else 0

lemma flip_ne (i : Fin 2) : flip i≠i := by fin_cases i <;> decide

lemma parity_ne_succ (n : ℕ) : parity n≠parity (n+1) := by
  intro h
  have hh := congrArg Fin.val h
  dsimp only [parity] at hh
  omega

noncomputable def corePaint (k : ℕ) : CoreVertex (F := F) k → Fin 2 :=
  Sum.elim (fun w => oldPaint k (c w)) (fun p => parity (p.2.val+1))

lemma point_paint (k : ℕ) (e : E (F := F)) (i : Fin (k+2)) :
    corePaint c k (point c k e i)=parity i.val := by
  dsimp only [point]
  split_ifs with h0 hl
  · simp [corePaint,oldPaint,ColoredEdges.left_color,h0,parity]
  · simp [corePaint,oldPaint,ColoredEdges.right_color,hl]
  · simp only [corePaint,Sum.elim_inr]
    congr 1
    omega

noncomputable def color (k : ℕ) : (graph c k).Coloring (Fin 2) :=
  Coloring.mk (Sum.elim (fun i => flip (oldPaint k i)) (corePaint c k)) (by
    intro u v h
    rcases u with i | a <;> rcases v with j | b
    · exact h.elim
    · cases b with
      | inl w =>
        change c w=i at h
        change flip (oldPaint k i)≠oldPaint k (c w)
        rw [h]
        exact flip_ne _
      | inr e => exact h.elim
    · cases a with
      | inl w =>
        change c w=j at h
        change oldPaint k (c w)≠flip (oldPaint k j)
        rw [h]
        exact (flip_ne _).symm
      | inr e => exact h.elim
    · obtain ⟨e,l,h⟩ := h
      have hne : corePaint c k (point c k e l.castSucc)≠corePaint c k (point c k e l.succ) := by
        rw [point_paint,point_paint]
        exact parity_ne_succ l.val
      rcases Sym2.eq_iff.mp h with ⟨rfl,rfl⟩ | ⟨rfl,rfl⟩
      · exact hne
      · exact hne.symm)

lemma point_reachable (k : ℕ) (e : E (F := F)) (i : Fin (k+2)) :
    (graph c k).Reachable (Sum.inr (point c k e 0)) (Sum.inr (point c k e i)) := by
  induction i using Fin.induction with
  | zero => exact Reachable.refl _
  | succ i ih => exact ih.trans (coreEdge_adj c k e i).reachable

lemma endpoints_reachable (k : ℕ) (e : E (F := F)) :
    (graph c k).Reachable (Sum.inr (Sum.inl (ColoredEdges.left c e)))
      (Sum.inr (Sum.inl (ColoredEdges.right c e))) := by
  simpa only [point_zero,point_last] using point_reachable c k e (Fin.last (k+1))

lemma old_edge_reachable (k : ℕ) {x y : W} (hxy : F.Adj x y) :
    (graph c k).Reachable (Sum.inr (Sum.inl x)) (Sum.inr (Sum.inl y)) := by
  let e : E (F := F) := ⟨s(x,y),hxy⟩
  have hx := (ColoredEdges.mem_iff c e x).mp (Sym2.mem_mk_left _ _)
  have hy := (ColoredEdges.mem_iff c e y).mp (Sym2.mem_mk_right _ _)
  rcases hx with hx | hx <;> rcases hy with hy | hy <;> rw [hx,hy]
  · exact endpoints_reachable c k e
  · exact (endpoints_reachable c k e).symm

lemma old_reachable (k : ℕ) {x y : W} (h : F.Reachable x y) :
    (graph c k).Reachable (Sum.inr (Sum.inl x)) (Sum.inr (Sum.inl y)) := by
  obtain ⟨p⟩ := h
  induction p with
  | nil => exact Reachable.refl _
  | @cons x y z hxy p ih => exact (old_edge_reachable c k hxy).trans ih

lemma connected (k : ℕ) (hF : F.Connected) (hsur : Function.Surjective c) :
    (graph c k).Connected := by
  obtain ⟨x⟩ := hF.nonempty
  rw [connected_iff_exists_forall_reachable]
  refine ⟨Sum.inr (Sum.inl x),?_⟩
  intro v
  rcases v with i | y | ⟨e,j⟩
  · obtain ⟨w,hw⟩ := hsur i
    exact (old_reachable c k (hF x w)).trans
      (show (graph c k).Adj (Sum.inr (Sum.inl w)) (Sum.inl i) from hw).reachable
  · exact old_reachable c k (hF x y)
  · have hh := point_reachable c k e j.succ.castSucc
    rw [point_zero,point_mid] at hh
    exact (old_reachable c k (hF x (ColoredEdges.left c e))).trans hh

end HubPathSubdivision

end -- HubPathSubdivision

section -- HubPathIncidences

/- Summed path-incidence inequalities for arbitrary-length replacement paths. -/
open Finset SimpleGraph
namespace HubPathIncidences
set_option maxHeartbeats 2000000
universe u
variable {W : Type u} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
abbrev E := GraphSubdivision.Edge F
noncomputable section
local instance : DecidableEq W := Classical.decEq _
local instance : DecidableEq (E (F := F)) := Classical.decEq _

variable (k : ℕ)

def midFiber (T : Finset (E (F := F) × Fin k)) (e : E (F := F)) : Finset (Fin k) :=
  univ.filter (fun i => (e,i)∈T)

def edgeFiber (S : Finset W) (T : Finset (E (F := F) × Fin k)) (e : E (F := F)) : Finset (Fin (k+1)) :=
  FinitePathIncidences.incident k (ColoredEdges.left c e∈S) (ColoredEdges.right c e∈S) (midFiber k T e)

variable [Fintype (E (F := F))]

def incidences (S : Finset W) (T : Finset (E (F := F) × Fin k)) : Finset (E (F := F) × Fin (k+1)) :=
  univ.filter (fun p => p.2∈edgeFiber c k S T p.1)

lemma incidences_count (S : Finset W) (T : Finset (E (F := F) × Fin k)) :
    (incidences c k S T).card=∑ e, (edgeFiber c k S T e).card := by
  simp only [incidences,card_filter,Fintype.sum_prod_type]
  apply sum_congr rfl
  intro e _
  symm
  rw [← card_filter]
  congr 1
  ext i
  simp

lemma midpoint_count (T : Finset (E (F := F) × Fin k)) : T.card=∑ e, (midFiber k T e).card := by
  have hT : univ.filter (fun p => p∈T)=T := by ext p; simp
  conv_lhs => rw [← hT]
  simp only [card_filter,Fintype.sum_prod_type,midFiber]

lemma old_count (S : Finset W) : (GraphSubdivision.incidentEdges F S).card=
    ∑ e : E (F := F), if ColoredEdges.left c e∈S ∨ ColoredEdges.right c e∈S then 1 else 0 := by
  simp only [GraphSubdivision.incidentEdges,card_filter]
  apply sum_congr rfl
  intro e _
  congr 1
  apply propext
  constructor
  · rintro ⟨w,hw,hwe⟩
    rcases (ColoredEdges.mem_iff c e w).mp hwe with rfl | rfl
    · exact Or.inl hw
    · exact Or.inr hw
  · rintro (h | h)
    · exact ⟨ColoredEdges.left c e,h,(ColoredEdges.mem_iff c e _).mpr (Or.inl rfl)⟩
    · exact ⟨ColoredEdges.right c e,h,(ColoredEdges.mem_iff c e _).mpr (Or.inr rfl)⟩

lemma old_plus_midpoints (S : Finset W) (T : Finset (E (F := F) × Fin k)) :
    (GraphSubdivision.incidentEdges F S).card+T.card≤(incidences c k S T).card := by
  rw [old_count c,midpoint_count,incidences_count,← sum_add_distrib]
  apply sum_le_sum
  intro e _
  have hh := FinitePathIncidences.endpoint_plus_internal k
    (ColoredEdges.left c e∈S) (ColoredEdges.right c e∈S) (midFiber k T e)
  by_cases he : ColoredEdges.left c e∈S ∨ ColoredEdges.right c e∈S
  · simpa only [if_pos he,edgeFiber] using hh
  · simpa only [if_neg he,edgeFiber] using hh

lemma midpoint_ratio (S : Finset W) (T : Finset (E (F := F) × Fin k)) :
    (k+1)*T.card≤k*(incidences c k S T).card := by
  rw [midpoint_count,incidences_count,mul_sum,mul_sum]
  apply sum_le_sum
  intro e _
  exact FinitePathIncidences.internal_ratio k _ _ (midFiber k T e)

lemma selected (S : Finset W) (T : Finset (E (F := F) × Fin k)) (p : E (F := F) × Fin (k+1))
    (hp : p∈incidences c k S T) :
    ∃ v∈S.disjSum T, v∈HubPathSubdivision.coreEdge c k p.1 p.2 := by
  obtain ⟨e,i⟩ := p
  have hh := (mem_filter.mp hp).2
  change i∈FinitePathIncidences.incident k _ _ _ at hh
  rcases (FinitePathIncidences.mem_incident k _ _ _ i).mp hh with ⟨hi,hs⟩ | ⟨hi,hs⟩ | ⟨j,hj,hi⟩
  · refine ⟨Sum.inl (ColoredEdges.left c e),by simpa using hs,?_⟩
    subst i
    have he : HubPathSubdivision.point c k e (0 : Fin (k+1)).castSucc=Sum.inl (ColoredEdges.left c e) :=
      HubPathSubdivision.point_zero c k e
    rw [← he]
    exact Sym2.mem_mk_left _ _
  · refine ⟨Sum.inl (ColoredEdges.right c e),by simpa using hs,?_⟩
    subst i
    have he : HubPathSubdivision.point c k e (Fin.last k).succ=Sum.inl (ColoredEdges.right c e) :=
      HubPathSubdivision.point_last c k e
    rw [← he]
    exact Sym2.mem_mk_right _ _
  · have hj' : (e,j)∈T := (mem_filter.mp hj).2
    refine ⟨Sum.inr (e,j),by simpa using hj',?_⟩
    rcases hi with rfl | rfl
    · have he : HubPathSubdivision.point c k e j.castSucc.succ=Sum.inr (e,j) :=
        (HubPathSubdivision.point_mid_iff c k e e _ j).mpr ⟨rfl,rfl⟩
      rw [← he]
      exact Sym2.mem_mk_right _ _
    · rw [← HubPathSubdivision.point_mid c k e j]
      exact Sym2.mem_mk_left _ _

end
end HubPathIncidences

end -- HubPathIncidences

section -- HubPathBalanceArithmetic

/- The numerical balance inequality for an arbitrary-length two-hub replacement. -/
namespace HubPathBalanceArithmetic

lemma balance (a b k x y I J N : ℕ)
    (hold : b*x≤a*I) (hpath : I+y≤J) (hmid : (k+1)*y≤k*J) (hspoke : J+x≤N) :
    (a+(k+1)*b)*(x+y)≤(a+k*b)*N := by
  have hp := Nat.mul_le_mul_left a hpath
  have hm := Nat.mul_le_mul_left b hmid
  have hs := Nat.mul_le_mul_left (a+k*b) hspoke
  nlinarith only [hold,hp,hm,hs]

end HubPathBalanceArithmetic

end -- HubPathBalanceArithmetic

section -- EdgeLinks

/- Counting four-cycles through the links of edges. -/
open Finset SimpleGraph
namespace EdgeLinks
set_option maxHeartbeats 1000000
variable {V : Type*} [Fintype V] [DecidableEq V]
    (G : SimpleGraph V) [DecidableRel G.Adj]

def two (x y : V) : ℕ := (univ.filter (fun z => G.Adj x z ∧ G.Adj y z)).card

def three (x y : V) : Finset (V × V) :=
  univ.filter (fun p => G.Adj x p.1 ∧ G.Adj p.1 p.2 ∧ G.Adj p.2 y)

def properThree (x y : V) : Finset (V × V) :=
  (three G x y).filter (fun p => p.1 ≠ y ∧ p.2 ≠ x)

lemma degree_sum (x : V) : G.degree x = ∑ y, if G.Adj x y then 1 else 0 := by
  simp [← G.card_neighborFinset_eq_degree,neighborFinset_eq_filter]

lemma sum_two : ∑ x, ∑ y, two G x y = ∑ z, G.degree z ^ 2 := by
  symm
  calc
    _ = ∑ z, ∑ x, ∑ y, if G.Adj z x ∧ G.Adj z y then 1 else 0 := by
      apply sum_congr rfl
      intro z hz
      rw [pow_two, degree_sum]
      simp_rw [sum_mul, mul_sum]
      apply sum_congr rfl
      intro x hx
      apply sum_congr rfl
      intro y hy
      split_ifs <;> simp_all
    _ = ∑ x, ∑ y, ∑ z, if G.Adj x z ∧ G.Adj y z then 1 else 0 := by
      rw [sum_comm]
      apply sum_congr rfl
      intro x hx
      rw [sum_comm]
      simp_rw [G.adj_comm]
    _ = _ := by simp only [two,card_filter]

lemma two_sq (x y : V) : two G x y ^ 2 =
    ∑ u, ∑ v, if (G.Adj x u ∧ G.Adj y u) ∧ (G.Adj x v ∧ G.Adj y v) then 1 else 0 := by
  rw [pow_two]
  simp only [two,card_filter,sum_mul,mul_sum]
  apply sum_congr rfl
  intro u hu
  apply sum_congr rfl
  intro v hv
  split_ifs <;> simp_all

lemma four_eq_sum_three : (∑ x, ∑ y, two G x y ^ 2) =
    ∑ x, ∑ u, if G.Adj x u then (three G u x).card else 0 := by
  calc
    _ = ∑ x, ∑ y, ∑ u, ∑ v,
        if (G.Adj x u ∧ G.Adj y u) ∧ (G.Adj x v ∧ G.Adj y v) then 1 else 0 := by
      simp only [two_sq]
    _ = ∑ x, ∑ u, ∑ y, ∑ v,
        if G.Adj x u ∧ G.Adj u y ∧ G.Adj y v ∧ G.Adj v x then 1 else 0 := by
      apply sum_congr rfl
      intro x hx
      rw [sum_comm]
      apply sum_congr rfl
      intro u hu
      apply sum_congr rfl
      intro y hy
      apply sum_congr rfl
      intro v hv
      congr 1
      simp only [G.adj_comm,and_assoc,and_comm,and_left_comm]
    _ = _ := by
      apply sum_congr rfl
      intro x hx
      apply sum_congr rfl
      intro u hu
      by_cases hxu : G.Adj x u
      · simp only [hxu,true_and,if_true,three,card_filter,Fintype.sum_prod_type]
      · simp [hxu]

lemma min_degree_four_le [Nonempty V] (δ : ℕ) (hδ : ∀ v, δ ≤ G.degree v) :
    δ^4 ≤ ∑ x, ∑ y, two G x y ^ 2 := by
  have hcs := sq_sum_le_card_mul_sum_sq (s := (univ : Finset (V × V)))
    (f := fun p => two G p.1 p.2)
  simp only [card_univ,Fintype.card_prod,Fintype.sum_prod_type] at hcs
  norm_cast at hcs
  have hl : Fintype.card V * δ^2 ≤ ∑ x, ∑ y, two G x y := by
    rw [sum_two]
    calc
      _ = ∑ _z : V, δ^2 := by simp
      _ ≤ _ := sum_le_sum (fun z hz => Nat.pow_le_pow_left (hδ z) 2)
  have hpow := Nat.pow_le_pow_left hl 2
  have hm : Fintype.card V ^ 2 * δ^4 ≤
      Fintype.card V ^ 2 * (∑ x, ∑ y, two G x y ^ 2) := by
    calc
      _ = (Fintype.card V * δ^2)^2 := by ring
      _ ≤ _ := hpow.trans hcs
      _ = _ := by ring
  exact Nat.le_of_mul_le_mul_left hm (pow_pos Fintype.card_pos 2)

lemma three_le_proper_add_degrees (x y : V) :
    (three G x y).card ≤ (properThree G x y).card + G.degree x + G.degree y := by
  let B₁ := (three G x y).filter (fun p => p.1 = y)
  let B₂ := (three G x y).filter (fun p => p.2 = x)
  have hc : three G x y ⊆ properThree G x y ∪ B₁ ∪ B₂ := by
    intro p hp
    by_cases h₁ : p.1 = y
    · exact mem_union_left _ (mem_union_right _ (mem_filter.mpr ⟨hp,h₁⟩))
    by_cases h₂ : p.2 = x
    · exact mem_union_right _ (mem_filter.mpr ⟨hp,h₂⟩)
    exact mem_union_left _ (mem_union_left _ (mem_filter.mpr ⟨hp,h₁,h₂⟩))
  have hB₁ : B₁.card ≤ G.degree y := by
    rw [← G.card_neighborFinset_eq_degree]
    apply card_le_card_of_injOn Prod.snd
    · intro p hp
      have hh := (mem_filter.mp hp).1
      have he := (mem_filter.mp hp).2
      have ha := (mem_filter.mp hh).2.2.1
      rw [he] at ha
      exact (G.mem_neighborFinset y p.2).mpr ha
    · intro p hp q hq he
      exact Prod.ext ((mem_filter.mp hp).2.trans (mem_filter.mp hq).2.symm) he
  have hB₂ : B₂.card ≤ G.degree x := by
    rw [← G.card_neighborFinset_eq_degree]
    apply card_le_card_of_injOn Prod.fst
    · intro p hp
      have hh := (mem_filter.mp hp).1
      exact (G.mem_neighborFinset x p.1).mpr (mem_filter.mp hh).2.1
    · intro p hp q hq he
      exact Prod.ext he ((mem_filter.mp hp).2.trans (mem_filter.mp hq).2.symm)
  have hh := (card_le_card hc).trans (card_union_le _ _)
  have hh' := card_union_le (properThree G x y) B₁
  omega

/-- A graph in which each edge closes at most `M` injective length-three paths
satisfies this fourth-moment degree inequality. -/
lemma degree_bound [Nonempty V] (δ Δ M : ℕ)
    (hδ : ∀ v, δ ≤ G.degree v) (hΔ : ∀ v, G.degree v ≤ Δ)
    (hlinks : ∀ x y, G.Adj x y → (properThree G x y).card ≤ M) :
    δ^4 ≤ Fintype.card V * Δ * (M + 2*Δ) := by
  have hp (x y : V) (hxy : G.Adj x y) : (three G x y).card ≤ M+2*Δ := by
    have hh := three_le_proper_add_degrees G x y
    have hm := hlinks x y hxy
    have hx := hΔ x
    have hy := hΔ y
    omega
  calc
    δ^4 ≤ ∑ x, ∑ y, two G x y ^ 2 := min_degree_four_le G δ hδ
    _ = ∑ x, ∑ u, if G.Adj x u then (three G u x).card else 0 := four_eq_sum_three G
    _ ≤ ∑ x, ∑ u, if G.Adj x u then M+2*Δ else 0 := by
      apply sum_le_sum
      intro x hx
      apply sum_le_sum
      intro u hu
      split_ifs with hxu
      · exact hp u x hxu.symm
      · rfl
    _ = ∑ x, G.degree x * (M+2*Δ) := by
      apply sum_congr rfl
      intro x hx
      rw [degree_sum,sum_mul]
      simp
    _ ≤ ∑ _x : V, Δ * (M+2*Δ) := sum_le_sum (fun x hx => Nat.mul_le_mul_right _ (hΔ x))
    _ = _ := by simp [mul_assoc]

lemma real_degree_bound [Nonempty V] (δ Δ : ℕ) (M : ℝ) (hM : 0 ≤ M)
    (hδ : ∀ v, δ ≤ G.degree v) (hΔ : ∀ v, G.degree v ≤ Δ)
    (hlinks : ∀ x y, G.Adj x y → ((properThree G x y).card : ℝ) ≤ M) :
    (δ : ℝ)^4 ≤ (Fintype.card V : ℝ) * Δ * (M + 2*Δ) := by
  have hnat : ∀ x y, G.Adj x y → (properThree G x y).card ≤ ⌊M⌋₊ := by
    intro x y hxy
    exact (Nat.le_floor_iff hM).mpr (hlinks x y hxy)
  have hh : (δ : ℝ)^4 ≤ (Fintype.card V : ℝ) * Δ * ((⌊M⌋₊ : ℝ) + 2*Δ) := by
    exact_mod_cast degree_bound G δ Δ ⌊M⌋₊ hδ hΔ hnat
  exact hh.trans (by gcongr; exact Nat.floor_le hM)

end EdgeLinks

end -- EdgeLinks

section -- Regularization

/- Finite sampling and almost-regular dense subgraphs. -/
open Finset SimpleGraph
namespace Regularization
set_option maxHeartbeats 1000000

/-- Among all `k`-subsets, one carries at least a `k / |s|` fraction of any real
weight sum. This is the deterministic averaging step used in regularization. -/
lemma weighted_subset {A : Type*} [DecidableEq A] (s : Finset A) (w : A → ℝ)
    (k : ℕ) (hk : k ≤ s.card) :
    ∃ t ⊆ s, t.card = k ∧ (k : ℝ) * (∑ a ∈ s, w a) ≤ (s.card : ℝ) * ∑ a ∈ t, w a := by
  induction s using Finset.strongInductionOn generalizing k
  rename_i s ih
  by_cases hk0 : k = 0
  · subst k
    exact ⟨∅,empty_subset _,by simp,by simp⟩
  by_cases hkeq : k = s.card
  · exact ⟨s,Subset.refl _,hkeq.symm,by simp [hkeq]⟩
  have hs : s.Nonempty := card_pos.mp (by omega)
  obtain ⟨a,ha,hmin⟩ := s.exists_min_image w hs
  have hks : k ≤ (s.erase a).card := by rw [card_erase_of_mem ha]; omega
  obtain ⟨t,ht,hcard,htsum⟩ := ih (s.erase a) (erase_ssubset ha) k hks
  have hm : (0 : ℝ) < (s.erase a).card := by exact_mod_cast (by omega : 0 < (s.erase a).card)
  have hminsum : ((s.erase a).card : ℝ) * w a ≤ ∑ b ∈ s.erase a, w b := by
    calc
      _ = ∑ _b ∈ s.erase a, w a := by simp
      _ ≤ _ := sum_le_sum (fun b hb => hmin b (mem_of_mem_erase hb))
  have hweight : (k : ℝ) * w a ≤ ∑ b ∈ t, w b := by
    apply le_of_mul_le_mul_left _ hm
    calc
      ((s.erase a).card : ℝ) * ((k : ℝ) * w a) = (k : ℝ) * ((s.erase a).card * w a) := by ring
      _ ≤ (k : ℝ) * ∑ b ∈ s.erase a, w b := mul_le_mul_of_nonneg_left hminsum (Nat.cast_nonneg k)
      _ ≤ _ := htsum
  refine ⟨t,ht.trans (erase_subset _ _),hcard,?_⟩
  have hsum : (∑ b ∈ s, w b) = (∑ b ∈ s.erase a, w b) + w a := (sum_erase_add _ _ ha).symm
  have hcardS : (s.card : ℝ) = (s.erase a).card + 1 := by exact_mod_cast (card_erase_add_one ha).symm
  rw [hsum,hcardS]
  nlinarith

section Sampling
variable {V : Type*} [Fintype V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj]

def cross (s t : Finset V) : ℕ := ∑ y ∈ t, (s.filter (fun x => H.Adj x y)).card

lemma cross_univ (s : Finset V) : cross H s univ = ∑ x ∈ s, H.degree x := by
  simp only [cross,card_filter]
  rw [sum_comm]
  apply sum_congr rfl
  intro x hx
  simp [← H.card_neighborFinset_eq_degree,neighborFinset_eq_filter]

lemma cross_le_induced_edges (s t : Finset V) :
    cross H s t ≤ 2 * (H.induce (↑(s∪t) : Set V)).edgeFinset.card := by
  let C : Finset (V × V) := (s ×ˢ t).filter (fun p => H.Adj p.1 p.2)
  have hC : C.card = cross H s t := by
    simp only [C,card_filter,sum_product,cross]
    rw [sum_comm]
  let f : C → (H.induce (↑(s∪t) : Set V)).Dart := fun p => {
    toProd := (⟨p.val.1,mem_union_left _ (mem_product.mp (mem_filter.mp p.property).1).1⟩,
      ⟨p.val.2,mem_union_right _ (mem_product.mp (mem_filter.mp p.property).1).2⟩)
    adj := (mem_filter.mp p.property).2 }
  have hf : Function.Injective f := by
    intro p q hpq
    apply Subtype.ext
    apply Prod.ext
    · exact congrArg (fun d : (H.induce (↑(s∪t) : Set V)).Dart => d.fst.val) hpq
    · exact congrArg (fun d : (H.induce (↑(s∪t) : Set V)).Dart => d.snd.val) hpq
  have hh := Fintype.card_le_of_injective f hf
  rw [Fintype.card_coe,hC,SimpleGraph.dart_card_eq_twice_card_edges] at hh
  exact hh

/-- The degree mass of any set can be witnessed on an induced subgraph with at
most twice as many vertices. -/
lemma capture_degree_mass (s : Finset V) :
    ∃ u : Finset V, s ⊆ u ∧ u.card ≤ 2*s.card ∧
      (s.card : ℝ) * (∑ v ∈ s, (H.degree v : ℝ)) ≤
        2 * Fintype.card V * ((H.induce (↑u : Set V)).edgeFinset.card : ℝ) := by
  obtain ⟨t,ht,htcard,hw⟩ := weighted_subset univ
    (fun y : V => ((s.filter (fun x => H.Adj x y)).card : ℝ)) s.card (card_le_univ s)
  have hsumeq : (∑ y : V, (s.filter (fun x => H.Adj x y)).card) = ∑ v ∈ s, H.degree v :=
    cross_univ H s
  simp only [card_univ,← Nat.cast_sum] at hw
  rw [hsumeq] at hw
  refine ⟨s∪t,subset_union_left,?_,?_⟩
  · have hh := card_union_le s t
    omega
  · have hc : (cross H s t : ℝ) ≤ 2 * ((H.induce (↑(s∪t) : Set V)).edgeFinset.card : ℝ) := by
      exact_mod_cast cross_le_induced_edges H s t
    rw [← Nat.cast_sum]
    calc
      _ ≤ (Fintype.card V : ℝ) * (cross H s t : ℝ) := hw
      _ ≤ (Fintype.card V : ℝ) * (2 * ((H.induce (↑(s∪t) : Set V)).edgeFinset.card : ℝ)) := by gcongr
      _ = _ := by ring
lemma small_set_degree_mass (γ C : ℝ) (hγ : 1 ≤ γ) (hC : 0 ≤ C)
    (hdensity : ∀ u : Finset V,
      ((H.induce (↑u : Set V)).edgeFinset.card : ℝ) ≤ C * (u.card : ℝ)^γ)
    (s : Finset V) (hs : s.Nonempty) :
    (∑ v ∈ s, (H.degree v : ℝ)) ≤
      2 * Fintype.card V * C * (2 : ℝ)^γ * (s.card : ℝ)^(γ-1) := by
  have hspos : (0 : ℝ) < s.card := by exact_mod_cast hs.card_pos
  obtain ⟨u,hsu,huc,hcap⟩ := capture_degree_mass H s
  have hpow : (u.card : ℝ)^γ ≤ (2*(s.card : ℝ))^γ := by
    apply Real.rpow_le_rpow (Nat.cast_nonneg _) _ (by linarith)
    exact_mod_cast huc
  have hmul : (s.card : ℝ) * (∑ v ∈ s, (H.degree v : ℝ)) ≤
      (s.card : ℝ) * (2 * Fintype.card V * C * (2 : ℝ)^γ * (s.card : ℝ)^(γ-1)) := by
    calc
      _ ≤ 2 * Fintype.card V * ((H.induce (↑u : Set V)).edgeFinset.card : ℝ) := hcap
      _ ≤ 2 * Fintype.card V * (C * (u.card : ℝ)^γ) := by gcongr; exact hdensity u
      _ ≤ 2 * Fintype.card V * (C * (2*(s.card : ℝ))^γ) := by gcongr
      _ = _ := by
        rw [Real.mul_rpow (by norm_num) hspos.le]
        have he : (s.card : ℝ)^γ = (s.card : ℝ)^(γ-1) * s.card := by
          calc
            _ = (s.card : ℝ)^((γ-1)+1) := by congr 1; ring
            _ = _ := by rw [Real.rpow_add hspos,Real.rpow_one]
        rw [he]
        ring
  exact le_of_mul_le_mul_left hmul hspos

/-- If no induced subgraph has greater normalized density, vertices whose degrees
are much larger than average carry at most half the degree mass. -/
lemma high_degree_mass [Nonempty V] (γ C : ℝ) (L : ℕ)
    (hγ : 1 < γ) (hC : 0 ≤ C)
    (he : (H.edgeFinset.card : ℝ) = C * (Fintype.card V : ℝ)^γ)
    (hepos : 0 < H.edgeFinset.card)
    (hL : 4*(2 : ℝ)^γ ≤ (L : ℝ)^(γ-1))
    (hdensity : ∀ u : Finset V,
      ((H.induce (↑u : Set V)).edgeFinset.card : ℝ) ≤ C * (u.card : ℝ)^γ) :
    2 * (∑ v ∈ univ.filter (fun v => 2*L*H.edgeFinset.card < Fintype.card V * H.degree v),
      (H.degree v : ℝ)) ≤ H.edgeFinset.card := by
  let s := univ.filter (fun v => 2*L*H.edgeFinset.card < Fintype.card V * H.degree v)
  change 2 * (∑ v ∈ s, (H.degree v : ℝ)) ≤ H.edgeFinset.card
  have hN : (0 : ℝ) < Fintype.card V := by exact_mod_cast (Fintype.card_pos (α := V))
  have hE : (0 : ℝ) < H.edgeFinset.card := by exact_mod_cast hepos
  have htotal : (∑ v ∈ s, (H.degree v : ℝ)) ≤ 2*H.edgeFinset.card := by
    calc
      _ ≤ ∑ v : V, (H.degree v : ℝ) := sum_le_sum_of_subset_of_nonneg (subset_univ _) (by intros; positivity)
      _ = _ := by exact_mod_cast H.sum_degrees_eq_twice_card_edges
  have hcard : (s.card : ℝ) * L ≤ Fintype.card V := by
    have hm : (s.card : ℝ) * (2*L*H.edgeFinset.card : ℝ) ≤
        (Fintype.card V : ℝ) * ∑ v ∈ s, (H.degree v : ℝ) := by
      rw [mul_sum]
      calc
        _ = ∑ _v ∈ s, (2*L*H.edgeFinset.card : ℝ) := by simp [mul_comm]
        _ ≤ _ := sum_le_sum (by
          intro v hv
          exact_mod_cast ((mem_filter.mp hv).2).le)
    have hh : ((s.card : ℝ)*L) * (2*H.edgeFinset.card : ℝ) ≤
        (Fintype.card V : ℝ) * (2*H.edgeFinset.card : ℝ) := by nlinarith
    exact le_of_mul_le_mul_right hh (by positivity)
  by_cases hs : s.Nonempty
  · have hmass := small_set_degree_mass H γ C hγ.le hC hdensity s hs
    have hp : (4*(2 : ℝ)^γ) * (s.card : ℝ)^(γ-1) ≤ (Fintype.card V : ℝ)^(γ-1) := by
      calc
        _ ≤ (L : ℝ)^(γ-1) * (s.card : ℝ)^(γ-1) := by gcongr
        _ = ((s.card : ℝ)*L)^(γ-1) := by rw [Real.mul_rpow (Nat.cast_nonneg _) (Nat.cast_nonneg _)]; ring
        _ ≤ _ := Real.rpow_le_rpow (by positivity) hcard (by linarith)
    calc
      2 * (∑ v ∈ s, (H.degree v : ℝ)) ≤
          2 * (2 * Fintype.card V * C * (2 : ℝ)^γ * (s.card : ℝ)^(γ-1)) := by gcongr
      _ = C * Fintype.card V * ((4*(2 : ℝ)^γ) * (s.card : ℝ)^(γ-1)) := by ring
      _ ≤ C * Fintype.card V * (Fintype.card V : ℝ)^(γ-1) := by gcongr
      _ = H.edgeFinset.card := by
        rw [he]
        have hpN : (Fintype.card V : ℝ)^γ = (Fintype.card V : ℝ) * (Fintype.card V : ℝ)^(γ-1) := by
          calc
            _ = (Fintype.card V : ℝ)^(1+(γ-1)) := by congr 1; ring
            _ = _ := by rw [Real.rpow_add hN,Real.rpow_one]
        rw [hpN]
        ring
  · simp [not_nonempty_iff_eq_empty.mp hs]
lemma delete_vertices_edge_bound (s : Finset V) :
    H.edgeFinset.card ≤ (H.induce (↑s : Set V)ᶜ).edgeFinset.card + ∑ v ∈ s, H.degree v := by
  let D := s.biUnion (fun v => H.incidenceFinset v)
  have hkeep : (H.edgeFinset ∩ sᶜ.sym2).card = (H.induce (↑s : Set V)ᶜ).edgeFinset.card := by
    have hh := congrArg Finset.card (SimpleGraph.map_edgeFinset_induce (G := H) (s := (↑s : Set V)ᶜ))
    simpa using hh.symm
  have hcover : H.edgeFinset ⊆ (H.edgeFinset ∩ sᶜ.sym2) ∪ D := by
    intro e he
    induction e using Sym2.inductionOn with
    | _ a b =>
      have hab : H.Adj a b := by simpa using he
      by_cases ha : a ∈ s
      · apply mem_union_right
        apply mem_biUnion.mpr
        exact ⟨a,ha,by simp [H.mem_incidenceFinset,H.mk'_mem_incidenceSet_iff,hab]⟩
      by_cases hb : b ∈ s
      · apply mem_union_right
        apply mem_biUnion.mpr
        exact ⟨b,hb,by simp [H.mem_incidenceFinset,H.mk'_mem_incidenceSet_iff,hab]⟩
      apply mem_union_left
      exact mem_inter.mpr ⟨he,by simp [ha,hb]⟩
  calc
    H.edgeFinset.card ≤ ((H.edgeFinset ∩ sᶜ.sym2) ∪ D).card := card_le_card hcover
    _ ≤ (H.edgeFinset ∩ sᶜ.sym2).card + D.card := card_union_le _ _
    _ ≤ (H.induce (↑s : Set V)ᶜ).edgeFinset.card + ∑ v ∈ s, (H.incidenceFinset v).card := by
      rw [hkeep]
      exact Nat.add_le_add_left card_biUnion_le _
    _ = _ := by simp
end Sampling

lemma copy_degree_le {V W : Type*} [Fintype V] [Fintype W]
    {G : SimpleGraph V} {H : SimpleGraph W} [DecidableRel G.Adj] [DecidableRel H.Adj]
    (f : Copy G H) (v : V) : G.degree v ≤ H.degree (f v) := by
  rw [← G.card_neighborSet_eq_degree,← H.card_neighborSet_eq_degree]
  exact Fintype.card_le_of_embedding (f.mapNeighborSet v)

universe u

/-- Peeling vertices of degree below `d` loses at most `d-1` edges per deleted
vertex. The remaining graph is allowed to be empty. -/
lemma minimum_degree_core {V : Type u} [Fintype V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj] (d : ℕ) :
    ∃ (W : Type u) (_ : Fintype W) (G : SimpleGraph W) (_ : DecidableRel G.Adj),
      ∃ f : Copy G H, (∀ v, d ≤ G.degree v) ∧
        H.edgeFinset.card + (d-1)*Fintype.card W ≤
          G.edgeFinset.card + (d-1)*Fintype.card V := by
  classical
  have aux : ∀ m : ℕ, ∀ (V : Type u) [Fintype V] (H : SimpleGraph V) [DecidableRel H.Adj],
      Fintype.card V = m →
      ∃ (W : Type u) (_ : Fintype W) (G : SimpleGraph W) (_ : DecidableRel G.Adj),
        ∃ f : Copy G H, (∀ v, d ≤ G.degree v) ∧
          H.edgeFinset.card + (d-1)*Fintype.card W ≤
            G.edgeFinset.card + (d-1)*Fintype.card V := by
    intro m
    induction m using Nat.strong_induction_on with
    | h m ih =>
      intro V _ H _ hm
      by_cases hmin : ∀ v, d ≤ H.degree v
      · exact ⟨V,inferInstance,H,inferInstance,Copy.id H,hmin,le_rfl⟩
      push_neg at hmin
      obtain ⟨v,hv⟩ := hmin
      letI : Nonempty V := ⟨v⟩
      have hpos : 0 < m := by rw [← hm]; exact Fintype.card_pos
      have hc : Fintype.card ({v}ᶜ : Set V) = m-1 := by
        rw [Fintype.card_compl_set]
        simp [hm]
      obtain ⟨W,hW,G,hG,f,hmin,hcount⟩ := ih (m-1) (by omega) ({v}ᶜ : Set V) (H.induce {v}ᶜ) hc
      refine ⟨W,hW,G,hG,(Copy.induce H {v}ᶜ).comp f,hmin,?_⟩
      rw [H.card_edgeFinset_induce_compl_singleton,H.card_edgeFinset_deleteIncidenceSet,hc] at hcount
      rw [hm]
      have hdeg := H.degree_le_card_edgeFinset v
      have hdpred : H.degree v ≤ d-1 := by omega
      have heq : (d-1)*(m-1)+(d-1) = (d-1)*m := by
        rw [← Nat.mul_succ]
        congr 1
        omega
      omega
  exact aux (Fintype.card V) V H rfl

/-- A graph of maximum normalized induced density has an almost-regular subgraph
whose minimum degree is at least one quarter of the original edge/vertex ratio. -/
lemma almost_regular_of_density_max {V : Type u} [Fintype V] [Nonempty V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj]
    (γ C : ℝ) (L : ℕ) (hγ : 1 < γ) (hC : 0 ≤ C)
    (he : (H.edgeFinset.card : ℝ) = C * (Fintype.card V : ℝ)^γ)
    (hepos : 0 < H.edgeFinset.card)
    (hL : 4*(2 : ℝ)^γ ≤ (L : ℝ)^(γ-1))
    (hdensity : ∀ s : Finset V,
      ((H.induce (↑s : Set V)).edgeFinset.card : ℝ) ≤ C * (s.card : ℝ)^γ) :
    ∃ (W : Type u) (_ : Fintype W) (_ : Nonempty W)
      (G : SimpleGraph W) (_ : DecidableRel G.Adj), ∃ f : Copy G H, ∃ d : ℕ,
      0 < d ∧ (∀ v, d ≤ G.degree v) ∧ (∀ v, G.degree v ≤ 8*L*d) ∧
      H.edgeFinset.card ≤ 4*Fintype.card V*d := by
  classical
  let N := Fintype.card V
  let E := H.edgeFinset.card
  have hN : (0 : ℝ) < N := by exact_mod_cast (Fintype.card_pos (α := V))
  have hE : (0 : ℝ) < E := by exact_mod_cast hepos
  let s := univ.filter (fun v => 2*L*E < N*H.degree v)
  let J := H.induce (↑s : Set V)ᶜ
  have hmass : 2*(∑ v ∈ s, (H.degree v : ℝ)) ≤ E :=
    high_degree_mass H γ C L hγ hC he hepos hL hdensity
  have hdel : (E : ℝ) ≤ J.edgeFinset.card + ∑ v ∈ s, (H.degree v : ℝ) := by
    exact_mod_cast delete_vertices_edge_bound H s
  have hJ : (E : ℝ) ≤ 2*J.edgeFinset.card := by linarith
  let d := ⌈(E : ℝ)/(4*N)⌉₊
  have hx : (0 : ℝ) < (E : ℝ)/(4*N) := by positivity
  have hdlo : (E : ℝ)/(4*N) ≤ (d : ℝ) := Nat.le_ceil _
  have hdhi : (d : ℝ) < (E : ℝ)/(4*N)+1 := Nat.ceil_lt_add_one hx.le
  have hdpos : 0 < d := by
    have hdreal : (0 : ℝ) < d := hx.trans_le hdlo
    exact_mod_cast hdreal
  have hceil : E ≤ 4*N*d := by
    have hh := (div_le_iff₀ (by positivity : (0 : ℝ) < 4*N)).mp hdlo
    have hh' : (E : ℝ) ≤ (4*N)*d := by nlinarith
    exact_mod_cast hh'
  have hcost : (4 : ℝ)*N*(d-1 : ℕ) < E := by
    have hcast : ((d-1 : ℕ) : ℝ) = (d : ℝ)-1 := by rw [Nat.cast_sub (by omega)]; norm_num
    rw [hcast]
    have hh : (d : ℝ)-1 < (E : ℝ)/(4*N) := by linarith
    have hh' := (lt_div_iff₀ (by positivity : (0 : ℝ) < 4*N)).mp hh
    nlinarith
  obtain ⟨W,hW,G,hG,f,hmin,hcount⟩ := minimum_degree_core J d
  have hcardJ : Fintype.card ((↑s : Set V)ᶜ : Set V) ≤ N := by
    exact Fintype.card_le_of_injective Subtype.val Subtype.val_injective
  have hcount' : J.edgeFinset.card ≤ G.edgeFinset.card + (d-1)*N := by
    have hh := Nat.mul_le_mul_left (d-1) hcardJ
    omega
  have hGpos : 0 < G.edgeFinset.card := by
    have hh : (J.edgeFinset.card : ℝ) ≤ G.edgeFinset.card + (d-1 : ℕ)*N := by exact_mod_cast hcount'
    have hGr : (0 : ℝ) < G.edgeFinset.card := by nlinarith
    exact_mod_cast hGr
  have hWpos : 0 < Fintype.card W := by
    have hh := G.card_edgeFinset_le_card_choose_two
    by_contra hn
    have hz : Fintype.card W = 0 := by omega
    simp only [hz,Nat.choose_zero_succ,Nat.le_zero] at hh
    omega
  letI : Nonempty W := Fintype.card_pos_iff.mp hWpos
  refine ⟨W,hW,inferInstance,G,hG,(Copy.induce H (↑s : Set V)ᶜ).comp f,d,hdpos,hmin,?_,hceil⟩
  intro v
  have hc₁ := copy_degree_le f v
  have hc₂ := copy_degree_le (Copy.induce H (↑s : Set V)ᶜ) (f v)
  have hv : (f v).val ∉ s := (f v).property
  have hhigh : N*H.degree (f v).val ≤ 2*L*E := by
    by_contra hh
    exact hv (mem_filter.mpr ⟨mem_univ _,Nat.lt_of_not_ge hh⟩)
  have hmul : N*H.degree (f v).val ≤ N*(8*L*d) := by
    calc
      _ ≤ 2*L*E := hhigh
      _ ≤ 2*L*(4*N*d) := Nat.mul_le_mul_left _ hceil
      _ = _ := by ring
  have hdH := Nat.le_of_mul_le_mul_left hmul (Fintype.card_pos (α := V))
  exact hc₁.trans (hc₂.trans hdH)

section MaximumDensity
variable {V : Type*} [Fintype V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj]

/-- Flatten two nested induced vertex sets. -/
def flattenIso (s : Finset V) (t : Finset s) :
    (H.induce (↑s : Set V)).induce (↑t : Set s) ≃g
      H.induce (↑(t.image Subtype.val) : Set V) where
  toFun v := ⟨v.val.val,mem_image.mpr ⟨v.val,v.property,rfl⟩⟩
  invFun v := ⟨⟨v.val,by
    obtain ⟨w,hw,he⟩ := mem_image.mp v.property
    rw [← he]
    exact w.property⟩,by
    obtain ⟨w,hw,he⟩ := mem_image.mp v.property
    have hh : (⟨v.val,by
      obtain ⟨z,hz,hze⟩ := mem_image.mp v.property
      rw [← hze]
      exact z.property⟩ : s) = w := Subtype.ext he.symm
    simpa only [Finset.mem_coe, hh] using hw⟩
  left_inv v := by apply Subtype.ext; apply Subtype.ext; rfl
  right_inv v := by apply Subtype.ext; rfl
  map_rel_iff' := by intro v w; rfl

/-- A nonzero finite graph has an induced subgraph attaining maximum normalized
edge density, together with the corresponding bound on all its induced subgraphs. -/
lemma maximum_density [Nonempty V] (γ : ℝ) (hγ : 0 < γ)
    (hepos : 0 < H.edgeFinset.card) :
    ∃ s : Finset V, s.Nonempty ∧ 0 < (H.induce (↑s : Set V)).edgeFinset.card ∧
      ∃ C : ℝ, 0 < C ∧
        ((H.induce (↑s : Set V)).edgeFinset.card : ℝ) = C * (s.card : ℝ)^γ ∧
        (H.edgeFinset.card : ℝ) ≤ C * (Fintype.card V : ℝ)^γ ∧
        (∀ t : Finset s,
          (((H.induce (↑s : Set V)).induce (↑t : Set s)).edgeFinset.card : ℝ) ≤
            C * (t.card : ℝ)^γ) := by
  classical
  let density (s : Finset V) : ℝ := ((H.induce (↑s : Set V)).edgeFinset.card : ℝ) / (s.card : ℝ)^γ
  obtain ⟨s,hs,hmax⟩ := (univ : Finset (Finset V)).exists_max_image density (by simp)
  have huniv : (H.induce (↑(univ : Finset V) : Set V)).edgeFinset.card = H.edgeFinset.card := by
    let e : H.induce (↑(univ : Finset V) : Set V) ≃g H := {
      toFun := Subtype.val
      invFun := fun v => ⟨v,mem_univ v⟩
      left_inv := fun v => Subtype.ext rfl
      right_inv := fun v => rfl
      map_rel_iff' := by intro v w; rfl }
    exact e.card_edgeFinset_eq
  have hN : (0 : ℝ) < Fintype.card V := by exact_mod_cast (Fintype.card_pos (α := V))
  have hCpos : 0 < density s := by
    have hpos : 0 < density (univ : Finset V) := by
      dsimp [density]
      rw [huniv]
      exact div_pos (by exact_mod_cast hepos) (Real.rpow_pos_of_pos hN γ)
    exact hpos.trans_le (hmax univ (mem_univ _))
  have hsne : s.Nonempty := by
    by_contra hh
    have hz : s = ∅ := not_nonempty_iff_eq_empty.mp hh
    simp only [density,hz,card_empty,Nat.cast_zero,Real.zero_rpow (ne_of_gt hγ),div_zero] at hCpos
    exact (lt_irrefl 0) hCpos
  have hsp : (0 : ℝ) < s.card := by exact_mod_cast hsne.card_pos
  have heq : ((H.induce (↑s : Set V)).edgeFinset.card : ℝ) = density s * (s.card : ℝ)^γ := by
    dsimp [density]
    rw [div_mul_cancel₀ _ (Real.rpow_pos_of_pos hsp γ).ne']
  have hse : 0 < (H.induce (↑s : Set V)).edgeFinset.card := by
    have hh : (0 : ℝ) < (H.induce (↑s : Set V)).edgeFinset.card :=
      lt_of_lt_of_eq (mul_pos hCpos (Real.rpow_pos_of_pos hsp γ)) heq.symm
    exact_mod_cast hh
  have hall (t : Finset V) :
      ((H.induce (↑t : Set V)).edgeFinset.card : ℝ) ≤ density s * (t.card : ℝ)^γ := by
    by_cases ht : t.Nonempty
    · have htp : (0 : ℝ) < t.card := by exact_mod_cast ht.card_pos
      exact (div_le_iff₀ (Real.rpow_pos_of_pos htp γ)).mp (hmax t (mem_univ _))
    · have ht0 : t = ∅ := not_nonempty_iff_eq_empty.mp ht
      subst t
      have he0 : (H.induce (↑(∅ : Finset V) : Set V)).edgeFinset.card = 0 := by
        have hh := (H.induce (↑(∅ : Finset V) : Set V)).card_edgeFinset_le_card_choose_two
        simpa using hh
      simp only [he0,Nat.cast_zero,card_empty,Real.zero_rpow (ne_of_gt hγ),mul_zero,le_refl]
  refine ⟨s,hsne,hse,density s,hCpos,heq,?_,?_⟩
  · simpa only [huniv,card_univ] using hall univ
  · intro t
    rw [(flattenIso H s t).card_edgeFinset_eq]
    have hh := hall (t.image Subtype.val)
    rwa [card_image_of_injective _ Subtype.val_injective] at hh
end MaximumDensity

/-- Transfer a degree bound for almost-regular copies to an edge bound for the
original graph, without a logarithmic loss. -/
lemma edge_bound_of_almost_regular {V : Type u} [Fintype V] [Nonempty V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj] (γ A : ℝ) (L : ℕ)
    (hγ : 1 < γ) (hA : 0 ≤ A) (hL : 4*(2 : ℝ)^γ ≤ (L : ℝ)^(γ-1))
    (hbound : ∀ (W : Type u) [Fintype W] [Nonempty W]
      (G : SimpleGraph W) [DecidableRel G.Adj], Copy G H → ∀ d : ℕ,
      0 < d → (∀ v, d ≤ G.degree v) → (∀ v, G.degree v ≤ 8*L*d) →
      (d : ℝ) ≤ A * (Fintype.card W : ℝ)^(γ-1)) :
    (H.edgeFinset.card : ℝ) ≤ 4*A * (Fintype.card V : ℝ)^γ := by
  classical
  by_cases he0 : H.edgeFinset.card = 0
  · rw [he0,Nat.cast_zero]
    positivity
  have hepos : 0 < H.edgeFinset.card := Nat.pos_of_ne_zero he0
  obtain ⟨s,hs,hse,C,hC,heq,hH,hmax⟩ := maximum_density H γ (by linarith) hepos
  let J := H.induce (↑s : Set V)
  obtain ⟨v,hv⟩ := hs
  letI : Nonempty s := ⟨⟨v,hv⟩⟩
  have heJ : (J.edgeFinset.card : ℝ) = C * (Fintype.card s : ℝ)^γ := by simpa using heq
  obtain ⟨W,hW,hWne,G,hG,f,d,hdpos,hdmin,hdmax,hed⟩ :=
    almost_regular_of_density_max J γ C L hγ hC.le heJ hse hL hmax
  have hd := hbound W G ((Copy.induce H (↑s : Set V)).comp f) d hdpos hdmin hdmax
  have hcard : Fintype.card W ≤ s.card := by
    simpa using Fintype.card_le_of_embedding f.toEmbedding
  have hd' : (d : ℝ) ≤ A * (s.card : ℝ)^(γ-1) := by
    apply hd.trans
    apply mul_le_mul_of_nonneg_left _ hA
    exact Real.rpow_le_rpow (Nat.cast_nonneg _) (by exact_mod_cast hcard) (by linarith)
  have hspos : (0 : ℝ) < s.card := by exact_mod_cast card_pos.mpr ⟨v,hv⟩
  have hmul : C * (s.card : ℝ)^γ ≤ (4*A) * (s.card : ℝ)^γ := by
    calc
      _ = (J.edgeFinset.card : ℝ) := heq.symm
      _ ≤ 4*(s.card : ℝ)*d := by
        have hsc : Fintype.card (↑s : Set V) = s.card := Fintype.card_coe s
        rw [hsc] at hed
        exact_mod_cast hed
      _ ≤ 4*(s.card : ℝ)*(A*(s.card : ℝ)^(γ-1)) := by gcongr
      _ = _ := by
        have hp : (s.card : ℝ)^γ = (s.card : ℝ) * (s.card : ℝ)^(γ-1) := by
          calc
            _ = (s.card : ℝ)^(1+(γ-1)) := by congr 1; ring
            _ = _ := by rw [Real.rpow_add hspos,Real.rpow_one]
        rw [hp]
        ring
  have hCbound : C ≤ 4*A := le_of_mul_le_mul_right hmul (Real.rpow_pos_of_pos hspos γ)
  exact hH.trans (mul_le_mul_of_nonneg_right hCbound (Real.rpow_nonneg (Nat.cast_nonneg _) _))

lemma exists_regularization_constant (γ : ℝ) (hγ : 1 < γ) :
    ∃ L : ℕ, 4*(2 : ℝ)^γ ≤ (L : ℝ)^(γ-1) := by
  have hβ : 0 < γ-1 := by linarith
  obtain ⟨L,hL⟩ := exists_nat_gt ((4*(2 : ℝ)^γ)^((γ-1)⁻¹))
  refine ⟨L,?_⟩
  have hh := Real.rpow_le_rpow (Real.rpow_nonneg (by positivity) _) hL.le hβ.le
  rw [← Real.rpow_mul (by positivity),inv_mul_cancel₀ hβ.ne',Real.rpow_one] at hh
  exact hh

end Regularization

end -- Regularization

section -- MaxCut

/- A bipartite subgraph retaining at least half the edges. -/
open Finset SimpleGraph
namespace MaxCut
set_option maxHeartbeats 1000000

section Bits
variable {V : Type*} [Fintype V] [DecidableEq V]

lemma half_colorings (x y : V) (hxy : x ≠ y) :
    2 * (univ.filter (fun c : V → Bool => c x ≠ c y)).card = Fintype.card (V → Bool) := by
  let flip (c : V → Bool) := Function.update c x (!(c x))
  have hinv : Function.Involutive flip := by
    intro c
    funext v
    by_cases hv : v = x
    · subst v
      simp [flip]
    · simp [flip,Function.update_apply,hv]
  have hflip (c : V → Bool) : flip c x ≠ flip c y ↔ c x = c y := by
    simp only [flip,Function.update_self,Function.update_of_ne hxy.symm]
    cases c x <;> cases c y <;> decide
  have heq : (univ.filter (fun c : V → Bool => c x ≠ c y)).card =
      (univ.filter (fun c : V → Bool => ¬c x ≠ c y)).card := by
    apply card_bij (fun c _ => flip c)
    · intro c hc
      apply mem_filter.mpr
      refine ⟨mem_univ _,?_⟩
      intro hh
      exact (mem_filter.mp hc).2 ((hflip c).mp hh)
    · intro c hc d hd he
      exact hinv.injective he
    · intro c hc
      refine ⟨flip c,mem_filter.mpr ⟨mem_univ _,?_⟩,hinv c⟩
      exact (hflip c).mpr (not_not.mp (mem_filter.mp hc).2)
  have hh := card_filter_add_card_filter_not (s := (univ : Finset (V → Bool)))
    (fun c => c x ≠ c y)
  rw [← heq,card_univ] at hh
  omega
end Bits

section Graph
variable {V : Type*} [Fintype V] [DecidableEq V] (H : SimpleGraph V) [DecidableRel H.Adj]

def cut (c : V → Bool) : SimpleGraph V where
  Adj x y := H.Adj x y ∧ c x ≠ c y
  symm := by constructor; intro x y h; exact ⟨h.1.symm,h.2.symm⟩
  loopless := by constructor; intro x h; exact h.2 rfl

instance (c : V → Bool) : DecidableRel (cut H c).Adj := fun _ _ => inferInstanceAs (Decidable (_ ∧ _))

lemma cut_le (c : V → Bool) : cut H c ≤ H := fun _ _ h => h.1

lemma cut_bipartite (c : V → Bool) : (cut H c).IsBipartite := by
  let col : (cut H c).Coloring Bool := Coloring.mk c (fun h => h.2)
  simpa using col.colorable

lemma sum_cut_edges : (∑ c : V → Bool, 2*(cut H c).edgeFinset.card) =
    Fintype.card (V → Bool) * H.edgeFinset.card := by
  have hs : (∑ c : V → Bool, 2*(cut H c).edgeFinset.card) =
      ∑ p : V × V, if H.Adj p.1 p.2 then
        (univ.filter (fun c : V → Bool => c p.1 ≠ c p.2)).card else 0 := by
    calc
      _ = ∑ c : V → Bool, ∑ p : V × V,
          if H.Adj p.1 p.2 ∧ c p.1 ≠ c p.2 then 1 else 0 := by
        apply sum_congr rfl
        intro c hc
        rw [SimpleGraph.two_mul_card_edgeFinset,card_filter]
        rfl
      _ = ∑ p : V × V, ∑ c : V → Bool,
          if H.Adj p.1 p.2 ∧ c p.1 ≠ c p.2 then 1 else 0 := sum_comm
      _ = _ := by
        apply sum_congr rfl
        intro p hp
        by_cases ha : H.Adj p.1 p.2 <;> simp [ha,card_filter]
  have hh : 2*(∑ c : V → Bool, 2*(cut H c).edgeFinset.card) =
      Fintype.card (V → Bool) * (2*H.edgeFinset.card) := by
    rw [hs,mul_sum]
    calc
      _ = ∑ p : V × V, if H.Adj p.1 p.2 then Fintype.card (V → Bool) else 0 := by
        apply sum_congr rfl
        intro p hp
        split_ifs with ha
        · exact half_colorings p.1 p.2 ha.ne
        · simp
      _ = Fintype.card (V → Bool) * (2*H.edgeFinset.card) := by
        rw [SimpleGraph.two_mul_card_edgeFinset,card_filter,mul_sum]
        apply sum_congr rfl
        intro p hp
        split_ifs <;> simp
  nlinarith only [hh]

lemma exists_bipartite_subgraph :
    ∃ G : SimpleGraph V, ∃ _ : DecidableRel G.Adj,
      G ≤ H ∧ G.IsBipartite ∧ H.edgeFinset.card ≤ 2*G.edgeFinset.card := by
  have hs : (∑ _c : V → Bool, H.edgeFinset.card) ≤ ∑ c : V → Bool, 2*(cut H c).edgeFinset.card := by
    rw [sum_cut_edges]
    simp
  obtain ⟨c,hc,he⟩ := exists_le_of_sum_le (by simp : (univ : Finset (V → Bool)).Nonempty) hs
  exact ⟨cut H c,inferInstance,cut_le H c,cut_bipartite H c,he⟩
end Graph

end MaxCut

end -- MaxCut

section -- SuspensionBounds

/- The connected bipartite suspension and its edge links. -/
open Finset SimpleGraph
namespace SuspensionBounds
set_option maxHeartbeats 1000000

section Coloring
variable {V : Type*} {G : SimpleGraph V}

lemma walk_color_eq (c d : G.Coloring (Fin 2)) {x y : V}
    (p : G.Walk x y) (h : c x = d x) : c y = d y := by
  induction p with
  | nil => exact h
  | @cons x y z hxy p ih =>
    apply ih
    have hc := c.valid hxy
    have hd := d.valid hxy
    omega

lemma coloring_perm (hG : G.Connected) (c d : G.Coloring (Fin 2)) :
    ∃ e : Fin 2 ≃ Fin 2, ∀ v, e (c v) = d v := by
  classical
  let v := Classical.choice hG.nonempty
  let e : Fin 2 ≃ Fin 2 := Equiv.swap (c v) (d v)
  let c' : G.Coloring (Fin 2) := Coloring.mk (fun w => e (c w))
    (by intro x y hxy he; exact c.valid hxy (e.injective he))
  refine ⟨e,?_⟩
  intro w
  obtain ⟨p⟩ := hG v w
  exact walk_color_eq c' d p (by
    change e (c v) = d v
    exact Equiv.swap_apply_left _ _)
end Coloring

/-- Add one new vertex of each color, join them, and join each new vertex to all
old vertices of the opposite color. -/
def suspend {V : Type*} {F : SimpleGraph V} (c : F.Coloring (Fin 2)) :
    SimpleGraph (Fin 2 ⊕ V) where
  Adj u v := match u,v with
    | Sum.inl i, Sum.inl j => i ≠ j
    | Sum.inl i, Sum.inr v => i ≠ c v
    | Sum.inr u, Sum.inl j => c u ≠ j
    | Sum.inr u, Sum.inr v => F.Adj u v
  symm := by
    constructor
    intro u v h
    cases u <;> cases v
    · exact h.symm
    · exact h.symm
    · exact h.symm
    · exact h.symm
  loopless := by constructor; intro u h; cases u; exact h rfl; exact h.ne rfl


/-- Extend a copy using two new distinct vertices with the necessary adjacencies. -/
def extend {V W : Type*} {F : SimpleGraph V} {H : SimpleGraph W}
    (c : F.Coloring (Fin 2)) (f : Copy F H) (x : Fin 2 ↪ W)
    (havoid : ∀ i v, x i ≠ f v)
    (hxx : H.Adj (x 0) (x 1))
    (hx : ∀ i v, i ≠ c v → H.Adj (x i) (f v)) : Copy (suspend c) H where
  toHom := {
    toFun := Sum.elim x f
    map_rel' := by
      intro u v h
      cases u with
      | inl i =>
        cases v with
        | inl j =>
          fin_cases i <;> fin_cases j
          · exact False.elim (h rfl)
          · exact hxx
          · exact hxx.symm
          · exact False.elim (h rfl)
        | inr v => exact hx i v h
      | inr u =>
        cases v with
        | inl j => exact (hx j u h.symm).symm
        | inr v => exact f.toHom.map_rel' h }
  injective' := by
    intro u v h
    cases u with
    | inl i =>
      cases v with
      | inl j => exact congrArg Sum.inl (x.injective h)
      | inr v => exact False.elim (havoid i v h)
    | inr u =>
      cases v with
      | inl j => exact False.elim (havoid j u h.symm)
      | inr v => exact congrArg Sum.inr (f.injective h)

/-- A relation regarded as a bipartite graph on a disjoint sum. -/
def biGraph {A B : Type*} (R : A → B → Prop) : SimpleGraph (A ⊕ B) where
  Adj u v := match u,v with
    | Sum.inl a, Sum.inr b => R a b
    | Sum.inr b, Sum.inl a => R a b
    | _,_ => False
  symm := by constructor; intro u v h; cases u <;> cases v <;> exact h
  loopless := by constructor; intro u h; cases u <;> exact h

instance {A B : Type*} (R : A → B → Prop) [∀ a b, Decidable (R a b)] :
    DecidableRel (biGraph R).Adj := by
  intro u v
  cases u <;> cases v <;> dsimp [biGraph] <;> infer_instance

def biColor {A B : Type*} (R : A → B → Prop) : (biGraph R).Coloring (Fin 2) :=
  Coloring.mk (Sum.elim (fun _ => 0) (fun _ => 1)) (by
    intro u v h
    cases u <;> cases v <;> simp_all [biGraph])

lemma biGraph_edge_card {A B : Type*} [Fintype A] [Fintype B] [DecidableEq A] [DecidableEq B]
    (R : A → B → Prop) [∀ a b, Decidable (R a b)] :
    (biGraph R).edgeFinset.card = (univ.filter (fun p : A × B => R p.1 p.2)).card := by
  let f : A × B → Sym2 (A ⊕ B) := fun p => s(Sum.inl p.1,Sum.inr p.2)
  have hf : Function.Injective f := by
    intro p q hpq
    simpa [f,Sym2.eq_iff,Prod.ext_iff] using hpq
  have he : (biGraph R).edgeFinset = (univ.filter (fun p : A × B => R p.1 p.2)).image f := by
    ext e
    induction e using Sym2.inductionOn with
    | _ u v =>
      cases u <;> cases v <;> simp [f,biGraph,Sym2.eq_iff]
  rw [he,card_image_of_injective _ hf]

section Link
variable {V : Type*} (H : SimpleGraph V) (x y : V)

abbrev Left := {a : V // H.Adj y a ∧ a ≠ x}
abbrev Right := {b : V // H.Adj x b ∧ b ≠ y}

def link : SimpleGraph (Left H x y ⊕ Right H x y) :=
  biGraph (fun a b => H.Adj a.val b.val)

instance [DecidableRel H.Adj] : DecidableRel (link H x y).Adj := inferInstanceAs (DecidableRel (biGraph _).Adj)

lemma no_triangle (hbip : H.IsBipartite) (hxy : H.Adj x y) (z : V)
    (hxz : H.Adj x z) (hyz : H.Adj y z) : False := by
  obtain ⟨c⟩ := hbip
  have h₁ := c.valid hxy
  have h₂ := c.valid hxz
  have h₃ := c.valid hyz
  omega

def linkCopy (hbip : H.IsBipartite) (hxy : H.Adj x y) : Copy (link H x y) H where
  toHom := {
    toFun := Sum.elim Subtype.val Subtype.val
    map_rel' := by
      intro u v h
      cases u <;> cases v
      · exact False.elim h
      · exact h
      · change H.Adj _ _ at h
        exact h.symm
      · exact False.elim h }
  injective' := by
    intro u v he
    cases u with
    | inl a =>
      cases v with
      | inl b => exact congrArg Sum.inl (Subtype.ext he)
      | inr b =>
        have ha := a.property.1
        have hb := b.property.1
        change a.val = b.val at he
        rw [← he] at hb
        exact False.elim (no_triangle H x y hbip hxy a.val hb ha)
    | inr a =>
      cases v with
      | inl b =>
        have ha := a.property.1
        have hb := b.property.1
        change a.val = b.val at he
        rw [← he] at hb
        exact False.elim (no_triangle H x y hbip hxy a.val ha hb)
      | inr b => exact congrArg Sum.inr (Subtype.ext he)

lemma linkCopy_ne (hbip : H.IsBipartite) (hxy : H.Adj x y)
    (v : Left H x y ⊕ Right H x y) :
    linkCopy H x y hbip hxy v ≠ x ∧ linkCopy H x y hbip hxy v ≠ y := by
  cases v with
  | inl a => exact ⟨a.property.2,a.property.1.ne.symm⟩
  | inr b => exact ⟨b.property.1.ne.symm,b.property.2⟩

lemma link_vertex_count [Fintype V] [DecidableEq V] [DecidableRel H.Adj] :
    Fintype.card (Left H x y ⊕ Right H x y) ≤ H.degree x + H.degree y := by
  have hL : Fintype.card (Left H x y) ≤ H.degree y := by
    rw [← H.card_neighborSet_eq_degree]
    exact Fintype.card_le_of_injective (fun a : Left H x y => (⟨a.val,a.property.1⟩ : H.neighborSet y))
      (by intro a b h; exact Subtype.ext (congrArg (fun z : H.neighborSet y => z.val) h))
  have hR : Fintype.card (Right H x y) ≤ H.degree x := by
    rw [← H.card_neighborSet_eq_degree]
    exact Fintype.card_le_of_injective (fun b : Right H x y => (⟨b.val,b.property.1⟩ : H.neighborSet x))
      (by intro a b h; exact Subtype.ext (congrArg (fun z : H.neighborSet x => z.val) h))
  rw [Fintype.card_sum]
  omega
/-- A connected forbidden graph in an edge link extends to its suspension. -/
lemma suspend_contained_of_link {W : Type*} {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (hbip : H.IsBipartite) (hxy : H.Adj x y) (f : Copy F (link H x y)) :
    suspend c ⊑ H := by
  classical
  let d : F.Coloring (Fin 2) := Coloring.mk
    (fun w => biColor (fun a : Left H x y => fun b : Right H x y => H.Adj a.val b.val) (f w))
    (by intro u v huv; exact (biColor _).valid (f.toHom.map_rel' huv))
  obtain ⟨e,he⟩ := coloring_perm hF c d
  let X : Fin 2 ↪ V := {
    toFun := fun i => if i = 0 then x else y
    inj' := by
      intro i j hij
      fin_cases i <;> fin_cases j <;> simp_all [hxy.ne,hxy.ne.symm] }
  let g : Copy F H := (linkCopy H x y hbip hxy).comp f
  have hXadj (i j : Fin 2) (hij : i ≠ j) : H.Adj (X i) (X j) := by
    fin_cases i <;> fin_cases j <;> simp_all [X,hxy,hxy.symm]
  refine ⟨extend c g (e.toEmbedding.trans X) ?_ ?_ ?_⟩
  · intro i w
    have hw := linkCopy_ne H x y hbip hxy (f w)
    change (if e i = 0 then x else y) ≠ linkCopy H x y hbip hxy (f w)
    split_ifs
    · exact hw.1.symm
    · exact hw.2.symm
  · exact hXadj (e 0) (e 1) (fun hh => (by decide : (0 : Fin 2) ≠ 1) (e.injective hh))
  · intro i w hi
    have hne : e i ≠ d w := by
      rw [← he w]
      exact fun hh => hi (e.injective hh)
    change e i ≠ Sum.elim (fun _ => (0 : Fin 2)) (fun _ => 1) (f w) at hne
    change H.Adj (if e i = 0 then x else y) (linkCopy H x y hbip hxy (f w))
    cases hfw : f w with
    | inl a =>
      have h0 : e i ≠ 0 := by simpa only [hfw,Sum.elim_inl] using hne
      rw [if_neg h0]
      exact a.property.1
    | inr b =>
      have h1 : e i ≠ 1 := by simpa only [hfw,Sum.elim_inr] using hne
      have h0 : e i = 0 := by omega
      rw [if_pos h0]
      exact b.property.1

lemma link_free {W : Type*} {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (hbip : H.IsBipartite) (hxy : H.Adj x y) (hfree : (suspend c).Free H) :
    F.Free (link H x y) := by
  rintro ⟨f⟩
  exact hfree (suspend_contained_of_link H x y hF c hbip hxy f)
lemma link_edge_card [Fintype V] [DecidableEq V] [DecidableRel H.Adj] :
    (link H x y).edgeFinset.card = (EdgeLinks.properThree H x y).card := by
  change (biGraph (fun a : Left H x y => fun b : Right H x y => H.Adj a.val b.val)).edgeFinset.card = _
  rw [biGraph_edge_card]
  apply card_bij (fun p _ => (p.2.val,p.1.val))
  · intro p hp
    have hrel := (mem_filter.mp hp).2
    apply mem_filter.mpr
    refine ⟨mem_filter.mpr ⟨mem_univ _,p.2.property.1,?_,p.1.property.1.symm⟩,
      p.2.property.2,p.1.property.2⟩
    exact hrel.symm
  · intro p hp q hq he
    apply Prod.ext
    · exact Subtype.ext (congrArg Prod.snd he)
    · exact Subtype.ext (congrArg Prod.fst he)
  · intro p hp
    have hpath := (mem_filter.mp (mem_filter.mp hp).1).2
    have hne := (mem_filter.mp hp).2
    refine ⟨(⟨p.2,hpath.2.2.symm,hne.2⟩,⟨p.1,hpath.1,hne.1⟩),?_,rfl⟩
    exact mem_filter.mpr ⟨mem_univ _,hpath.2.1.symm⟩
end Link


lemma suspension_real_degree_bound {V W : Type*} [Fintype V] [Nonempty V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj] {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (hbip : H.IsBipartite) (hfree : (suspend c).Free H)
    (δ Δ : ℕ) (hδ : ∀ v, δ ≤ H.degree v) (hΔ : ∀ v, H.degree v ≤ Δ)
    (α C : ℝ) (hα : 0 ≤ α) (hC : 0 ≤ C)
    (hbound : ∀ m : ℕ, (extremalNumber m F : ℝ) ≤ C * (m : ℝ)^α) :
    (δ : ℝ)^4 ≤ (Fintype.card V : ℝ) * Δ * (C * (2*Δ : ℝ)^α + 2*Δ) := by
  apply EdgeLinks.real_degree_bound H δ Δ (C * (2*Δ : ℝ)^α) (by positivity) hδ hΔ
  intro x y hxy
  have hfree' := link_free H x y hF c hbip hxy hfree
  have hc : Fintype.card (Left H x y ⊕ Right H x y) ≤ 2*Δ := by
    have hh := link_vertex_count H x y
    have hx := hΔ x
    have hy := hΔ y
    omega
  rw [← link_edge_card H x y]
  calc
    ((link H x y).edgeFinset.card : ℝ) ≤
      extremalNumber (Fintype.card (Left H x y ⊕ Right H x y)) F := by
        exact_mod_cast card_edgeFinset_le_extremalNumber hfree'
    _ ≤ C * (Fintype.card (Left H x y ⊕ Right H x y) : ℝ)^α := hbound _
    _ ≤ _ := by
      apply mul_le_mul_of_nonneg_left _ hC
      apply Real.rpow_le_rpow (Nat.cast_nonneg _) _ hα
      exact_mod_cast hc

/-- The expected transformed degree exponent holds for almost-regular bipartite
hosts avoiding the suspension. No lower bound for that suspension is asserted. -/
lemma suspension_almost_regular_bound {V W : Type*} [Fintype V] [Nonempty V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj] {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (hbip : H.IsBipartite) (hfree : (suspend c).Free H)
    (δ K : ℕ) (hδpos : 0 < δ)
    (hδ : ∀ v, δ ≤ H.degree v) (hΔ : ∀ v, H.degree v ≤ K*δ)
    (α C : ℝ) (hα : 1 ≤ α) (hC : 0 ≤ C)
    (hbound : ∀ m : ℕ, (extremalNumber m F : ℝ) ≤ C * (m : ℝ)^α) :
    (δ : ℝ)^(3-α) ≤
      (Fintype.card V : ℝ) * K * (C * (2*K : ℝ)^α + 2*K) := by
  have hd : (0 : ℝ) < δ := by exact_mod_cast hδpos
  have hd1 : (1 : ℝ) ≤ δ := by exact_mod_cast hδpos
  have hp : (δ : ℝ) ≤ (δ : ℝ)^α := by
    simpa only [Real.rpow_one] using Real.rpow_le_rpow_of_exponent_le hd1 hα
  have hh := suspension_real_degree_bound H hF c hbip hfree δ (K*δ) hδ hΔ α C
    (by linarith) hC hbound
  push_cast at hh
  have hmul : (δ : ℝ)^(3-α) * (δ : ℝ)^(α+1) ≤
      ((Fintype.card V : ℝ) * K * (C * (2*K : ℝ)^α + 2*K)) * (δ : ℝ)^(α+1) := by
    calc
      _ = (δ : ℝ)^4 := by
        rw [← Real.rpow_add hd,show 3-α+(α+1) = (4 : ℝ) by ring]
        norm_num
      _ ≤ (Fintype.card V : ℝ) * (K*δ) * (C * (2*(K*δ) : ℝ)^α + 2*(K*δ)) := hh
      _ = (Fintype.card V : ℝ) * K * δ * (C * (2*K : ℝ)^α * (δ : ℝ)^α + 2*K*δ) := by
        rw [show (2*(K*δ) : ℝ) = (2*K)*δ by ring,Real.mul_rpow (by positivity) hd.le]
        ring
      _ ≤ (Fintype.card V : ℝ) * K * δ *
          (C * (2*K : ℝ)^α * (δ : ℝ)^α + 2*K*(δ : ℝ)^α) := by gcongr
      _ = _ := by
        rw [Real.rpow_add hd,Real.rpow_one]
        ring
  exact le_of_mul_le_mul_right hmul (Real.rpow_pos_of_pos hd (α+1))

universe u v

/-- The connected bipartite suspension transforms an upper exponent `α` into
`1 + 1/(3-α)` on arbitrary bipartite hosts; regularization incurs only a constant. -/
lemma suspension_bipartite_upper {W : Type v} {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (α C : ℝ) (hα : 1 ≤ α) (hα₂ : α < 2) (hC : 0 ≤ C)
    (hbound : ∀ m : ℕ, (extremalNumber m F : ℝ) ≤ C * (m : ℝ)^α) :
    ∃ D : ℝ, 0 ≤ D ∧ ∀ (V : Type u) [Fintype V] [Nonempty V] [DecidableEq V]
      (H : SimpleGraph V) [DecidableRel H.Adj], H.IsBipartite → (suspend c).Free H →
        (H.edgeFinset.card : ℝ) ≤ D * (Fintype.card V : ℝ)^(1+1/(3-α)) := by
  classical
  let γ : ℝ := 1+1/(3-α)
  have hβ : 0 < 3-α := by linarith
  have hγ : 1 < γ := by
    dsimp [γ]
    have hp : (0 : ℝ) < 1/(3-α) := one_div_pos.mpr hβ
    linarith
  obtain ⟨L,hL⟩ := Regularization.exists_regularization_constant γ hγ
  let K : ℕ := 8*L
  let B : ℝ := K * (C * (2*K : ℝ)^α + 2*K)
  let A : ℝ := B^((3-α)⁻¹)
  have hB : 0 ≤ B := by dsimp [B]; positivity
  have hA : 0 ≤ A := Real.rpow_nonneg hB _
  refine ⟨4*A,by positivity,?_⟩
  intro V _ _ _ H _ hbip hfree
  apply Regularization.edge_bound_of_almost_regular H γ A L hγ hA hL
  intro U _ _ G _ f d hdpos hdmin hdmax
  have hGbip : G.IsBipartite := SimpleGraph.Colorable.of_hom f.toHom hbip
  have hGfree : (suspend c).Free G := by
    intro hh
    exact hfree (hh.trans ⟨f⟩)
  have hh := suspension_almost_regular_bound G hF c hGbip hGfree d K hdpos hdmin hdmax
    α C hα hC hbound
  have hh' : (d : ℝ)^(3-α) ≤ B * Fintype.card U := by
    calc
      _ ≤ (Fintype.card U : ℝ) * K * (C * (2*K : ℝ)^α + 2*K) := hh
      _ = _ := by dsimp [B]; ring
  have hr := Real.rpow_le_rpow (Real.rpow_nonneg (Nat.cast_nonneg d) _) hh' (inv_nonneg.mpr hβ.le)
  rw [← Real.rpow_mul (Nat.cast_nonneg d),mul_inv_cancel₀ hβ.ne',Real.rpow_one,
    Real.mul_rpow hB (Nat.cast_nonneg _)] at hr
  simpa [A,γ,one_div] using hr

/-- A genuine single-graph upper-bound transformation. This proves only an upper
bound; a matching lower bound for the suspension requires a separate argument. -/
lemma suspension_upper {W : Type v} {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2))
    (α C : ℝ) (hα : 1 ≤ α) (hα₂ : α < 2) (hC : 0 ≤ C)
    (hbound : ∀ m : ℕ, (extremalNumber m F : ℝ) ≤ C * (m : ℝ)^α) :
    ∃ D : ℝ, 0 ≤ D ∧ ∀ m : ℕ,
      (extremalNumber m (suspend c) : ℝ) ≤ D * (m : ℝ)^(1+1/(3-α)) := by
  classical
  obtain ⟨D,hD,hbip⟩ := suspension_bipartite_upper.{0,v} hF c α C hα hα₂ hC hbound
  refine ⟨2*D,by positivity,?_⟩
  intro m
  by_cases hm : m = 0
  · subst m
    have hz : extremalNumber 0 (suspend c) = 0 := by
      apply Nat.eq_zero_of_le_zero
      rw [← Fintype.card_fin 0,extremalNumber_le_iff]
      intro H _ hH
      simpa using H.card_edgeFinset_le_card_choose_two
    rw [hz,Nat.cast_zero]
    positivity
  · letI : Nonempty (Fin m) := ⟨⟨0,Nat.pos_of_ne_zero hm⟩⟩
    rw [← Fintype.card_fin m]
    apply (extremalNumber_le_iff_of_nonneg (suspend c) (by positivity :
      (0 : ℝ) ≤ (2*D) * (Fintype.card (Fin m) : ℝ)^(1+1/(3-α)))).mpr
    intro H _ hH
    obtain ⟨G,hG,hGH,hGbip,hcount⟩ := MaxCut.exists_bipartite_subgraph H
    have hGfree : (suspend c).Free G := by
      intro hh
      exact hH (hh.trans ⟨Copy.ofLE G H hGH⟩)
    have hg := hbip (Fin m) G hGbip hGfree
    have hc : (H.edgeFinset.card : ℝ) ≤ 2*G.edgeFinset.card := by exact_mod_cast hcount
    nlinarith

lemma extremal_le_sq {W : Type*} (F : SimpleGraph W) (n : ℕ) :
    extremalNumber n F ≤ n^2 := by
  rw [← Fintype.card_fin n,extremalNumber_le_iff]
  intro H _ hH
  exact H.card_edgeFinset_le_card_choose_two.trans (Nat.choose_le_pow _ 2)

/-- For an extremal-number function, an asymptotic power upper bound can be made
uniform, including the finitely many small inputs. -/
lemma uniform_bound_of_isBigO {W : Type*} (F : SimpleGraph W) (α : ℝ) (hα : 0 ≤ α)
    (h : Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n F : ℝ)) (fun n : ℕ => (n : ℝ)^α)) :
    ∃ C : ℝ, 0 ≤ C ∧ ∀ n : ℕ, (extremalNumber n F : ℝ) ≤ C * (n : ℝ)^α := by
  obtain ⟨c,hc⟩ := Asymptotics.isBigO_iff.mp h
  obtain ⟨N,hN⟩ := Filter.eventually_atTop.mp hc
  let C : ℝ := |c| + (N : ℝ)^2
  have hC : 0 ≤ C := by dsimp [C]; positivity
  refine ⟨C,hC,?_⟩
  intro n
  by_cases hn0 : n = 0
  · subst n
    have hz : extremalNumber 0 F = 0 := by simpa using extremal_le_sq F 0
    rw [hz,Nat.cast_zero]
    positivity
  by_cases hn : N ≤ n
  · have hh : (extremalNumber n F : ℝ) ≤ c*(n : ℝ)^α := by
      simpa only [Real.norm_natCast,Real.norm_eq_abs,Nat.abs_cast,abs_of_nonneg (Real.rpow_nonneg (Nat.cast_nonneg n) _)] using hN n hn
    apply hh.trans
    apply mul_le_mul_of_nonneg_right _ (Real.rpow_nonneg (Nat.cast_nonneg _) _)
    have hc' := le_abs_self c
    dsimp [C]
    nlinarith [sq_nonneg (N : ℝ)]
  · have hp : (1 : ℝ) ≤ (n : ℝ)^α :=
      Real.one_le_rpow (by exact_mod_cast (Nat.pos_of_ne_zero hn0)) hα
    have hsmall : (extremalNumber n F : ℝ) ≤ (N : ℝ)^2 := by
      have hh := (extremal_le_sq F n).trans (Nat.pow_le_pow_left (by omega : n ≤ N) 2)
      exact_mod_cast hh
    have hCN : (N : ℝ)^2 ≤ C := by dsimp [C]; linarith [abs_nonneg c]
    calc
      _ ≤ (N : ℝ)^2 := hsmall
      _ ≤ C := hCN
      _ ≤ C * (n : ℝ)^α := by simpa using mul_le_mul_of_nonneg_left hp hC

/-- The asymptotic upper-exponent transformation for connected bipartite suspension. -/
lemma suspension_isBigO {W : Type v} {F : SimpleGraph W}
    (hF : F.Connected) (c : F.Coloring (Fin 2)) (α : ℝ) (hα : 1 ≤ α) (hα₂ : α < 2)
    (h : Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n F : ℝ)) (fun n : ℕ => (n : ℝ)^α)) :
    Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n (suspend c) : ℝ))
      (fun n : ℕ => (n : ℝ)^(1+1/(3-α))) := by
  obtain ⟨C,hC,hbound⟩ := uniform_bound_of_isBigO F α (by linarith) h
  obtain ⟨D,hD,hd⟩ := suspension_upper hF c α C hα hα₂ hC hbound
  apply Asymptotics.isBigO_iff.mpr
  refine ⟨D,Filter.Eventually.of_forall ?_⟩
  intro n
  simpa only [Real.norm_natCast,Real.norm_eq_abs,Nat.abs_cast,
    abs_of_nonneg (Real.rpow_nonneg (Nat.cast_nonneg n) _)] using hd n

end SuspensionBounds

end -- SuspensionBounds

section -- UltrafilterField

/- Field extensions obtained from ultrafilter germs. -/
open Filter
namespace UltrafilterField
variable {I K : Type*} [Field K] (u : Ultrafilter I)

noncomputable instance field : Field (Germ (u : Filter I) K) where
  __ := (inferInstance : CommRing (Germ (u : Filter I) K))
  __ := (inferInstance : DivInvMonoid (Germ (u : Filter I) K))
  nnqsmul q a := (q.num : Germ (u : Filter I) K) / q.den * a
  qsmul q a := (q.num : Germ (u : Filter I) K) / q.den * a
  exists_pair_ne := ⟨0,1,zero_ne_one⟩
  mul_inv_cancel := by
    intro x hx
    induction x using Germ.inductionOn with
    | h f =>
      have hne : ∀ᶠ i in (u : Filter I), f i ≠ 0 := by
        apply Ultrafilter.eventually_not.mpr
        intro he
        exact hx (Germ.coe_eq.mpr he)
      apply Germ.coe_eq.mpr
      filter_upwards [hne] with i hi
      exact mul_inv_cancel₀ hi
  inv_zero := by
    change ((fun _ : I => (0 : K)⁻¹) : Germ (u : Filter I) K) =
      ((fun _ : I => (0 : K)) : Germ (u : Filter I) K)
    exact Germ.coe_eq.mpr (Eventually.of_forall (fun _ => inv_zero))

/-- The embedding of the original field as constant germs. -/
def constHom : K →+* Germ (u : Filter I) K where
  toFun := Germ.const
  map_zero' := rfl
  map_one' := rfl
  map_add' _ _ := rfl
  map_mul' _ _ := rfl

noncomputable instance algebra : Algebra K (Germ (u : Filter I) K) := (constHom u).toAlgebra

lemma algebraMap_eq (c : K) : algebraMap K (Germ (u : Filter I) K) c = Germ.const c := rfl

lemma aeval_eq {σ : Type*} (x : I → σ → K) (p : MvPolynomial σ K) :
    MvPolynomial.aeval (fun j => ((fun i => x i j) : Germ (u : Filter I) K)) p =
      ((fun i => MvPolynomial.eval (x i) p) : Germ (u : Filter I) K) := by
  induction p using MvPolynomial.induction_on with
  | C c => simp only [MvPolynomial.aeval_C, MvPolynomial.eval_C, algebraMap_eq]; rfl
  | add p q hp hq =>
    simp only [map_add, hp, hq]
    rfl
  | mul_X p j hp =>
    simp only [map_mul, MvPolynomial.aeval_X, MvPolynomial.eval_X, hp]
    rfl

lemma aeval_zero_of_forall {σ : Type*} (x : I → σ → K) (p : MvPolynomial σ K)
    (h : ∀ i, MvPolynomial.eval (x i) p = 0) :
    MvPolynomial.aeval (fun j => ((fun i => x i j) : Germ (u : Filter I) K)) p = 0 := by
  rw [aeval_eq]
  exact Germ.coe_eq.mpr (Eventually.of_forall h)


lemma polynomial_aeval_eq (f : I → K) (p : Polynomial K) :
    Polynomial.aeval (f : Germ (u : Filter I) K) p =
      ((fun i => p.eval (f i)) : Germ (u : Filter I) K) := by
  induction p using Polynomial.induction_on' with
  | add p q hp hq =>
    simp only [map_add, Polynomial.eval_add, hp, hq]
    rfl
  | monomial n c =>
    simp only [Polynomial.aeval_monomial, Polynomial.eval_monomial, algebraMap_eq]
    rfl

/-- An injective coordinate yields a transcendental element at any cofinite ultrafilter. -/
lemma transcendental_of_injective (hu : (u : Filter I) ≤ cofinite)
    (f : I → K) (hf : Function.Injective f) : Transcendental K (f : Germ (u : Filter I) K) := by
  apply transcendental_iff.mpr
  intro p hp
  by_contra hp0
  have hfinite : {i : I | p.eval (f i) = 0}.Finite := by
    exact (Polynomial.finite_setOf_isRoot hp0).preimage hf.injOn
  have hne : ∀ᶠ i in (u : Filter I), p.eval (f i) ≠ 0 := by
    apply Filter.Eventually.filter_mono hu
    simpa only [eventually_cofinite, not_not] using hfinite
  rw [polynomial_aeval_eq] at hp
  obtain ⟨i,hi,hzi⟩ := (hne.and (Germ.coe_eq.mp hp)).exists
  exact hi hzi

/-- Finite sets of polynomial equalities true at a germ point are simultaneously
true at one of its representatives. -/
lemma finite_equalities {σ : Type*} (x : I → σ → K)
    (P : Finset (MvPolynomial σ K))
    (h : ∀ p ∈ P, MvPolynomial.aeval (fun j => ((fun i => x i j) : Germ (u : Filter I) K)) p = 0) :
    ∃ i, ∀ p ∈ P, MvPolynomial.eval (x i) p = 0 := by
  have he : ∀ p ∈ P, ∀ᶠ i in (u : Filter I), MvPolynomial.eval (x i) p = 0 := by
    intro p hp
    exact Germ.coe_eq.mp ((aeval_eq u x p).symm.trans (h p hp))
  exact ((eventually_all_finset P).mpr he).exists

end UltrafilterField

end -- UltrafilterField

section -- GenericPoint

/- Infinite sets of field-valued tuples admit transcendental points in field extensions. -/
open Filter MvPolynomial
namespace GenericPoint
universe u v
variable {K : Type u} [Field K] {σ : Type v} [Fintype σ]

lemma infinite_coordinate {S : Set (σ → K)} (hS : S.Infinite) :
    ∃ j : σ, ((fun x : σ → K => x j) '' S).Infinite := by
  by_contra h
  push_neg at h
  apply hS
  apply (Set.Finite.pi' h).subset
  intro x hx j
  exact ⟨x,hx,rfl⟩

/-- A field extension contains a point preserving all polynomial identities on `S`,
with at least one coordinate transcendental over the original field. Every finite
set of equalities at this point is witnessed by an actual point of `S`. -/
lemma exists_transcendental_point (S : Set (σ → K)) (hS : S.Infinite) :
    ∃ L : Type u, ∃ _ : Field L, ∃ _ : Algebra K L, ∃ x : σ → L,
      (∀ p : MvPolynomial σ K, (∀ y ∈ S, eval y p = 0) → aeval x p = 0) ∧
      (∀ P : Finset (MvPolynomial σ K), (∀ p ∈ P, aeval x p = 0) →
        ∃ y ∈ S, ∀ p ∈ P, eval y p = 0) ∧
      ∃ j, Transcendental K (x j) := by
  classical
  obtain ⟨j,hj⟩ := infinite_coordinate hS
  let T : Set K := (fun x : σ → K => x j) '' S
  haveI : Infinite T := hj.to_subtype
  have hx : ∀ t : T, ∃ y ∈ S, y j = t.val := fun t => t.property
  choose y hy hcoord using hx
  let u : Ultrafilter T := Ultrafilter.of cofinite
  let L := Germ (u : Filter T) K
  let x : σ → L := fun i => ((fun t => y t i) : Germ (u : Filter T) K)
  refine ⟨L,inferInstance,inferInstance,x,?_,?_,?_⟩
  · intro p hp
    exact UltrafilterField.aeval_zero_of_forall u y p (fun t => hp (y t) (hy t))
  · intro P hP
    obtain ⟨t,ht⟩ := UltrafilterField.finite_equalities u y P hP
    exact ⟨y t,hy t,ht⟩
  · refine ⟨j,?_⟩
    have hf : (fun t : T => y t j) = Subtype.val := funext hcoord
    change Transcendental K ((fun t : T => y t j) : Germ (u : Filter T) K)
    rw [hf]
    exact UltrafilterField.transcendental_of_injective u (Ultrafilter.of_le cofinite)
      Subtype.val Subtype.val_injective

end GenericPoint

end -- GenericPoint

section -- IndependentPoints

/- Independent solutions in field extensions, constructed from an infinite set of tuples. -/
open MvPolynomial
namespace IndependentPoints
universe u v

variable {K E L : Type u} [Field K] [Field E] [Field L]
    [Algebra K E] [Algebra E L] [Algebra K L] [IsScalarTower K E L]
    {σ : Type v}

/-- Polynomial identities on `S` hold at `x`, and every finite collection of
polynomial equalities at `x` has a witness in `S`. -/
def Compatible (S : Set (σ → K)) (x : σ → L) : Prop :=
  (∀ p : MvPolynomial σ K, (∀ y ∈ S, eval y p = 0) → aeval x p = 0) ∧
  (∀ P : Finset (MvPolynomial σ K), (∀ p ∈ P, aeval x p = 0) →
    ∃ y ∈ S, ∀ p ∈ P, eval y p = 0)

lemma aeval_map (x : σ → L) (p : MvPolynomial σ K) :
    aeval x (map (algebraMap K E) p) = aeval x p := by
  simp only [aeval_def, eval₂_map, ← IsScalarTower.algebraMap_eq K E L]

lemma eval_map_coords (y : σ → K) (p : MvPolynomial σ K) :
    eval (algebraMap K E ∘ y) (map (algebraMap K E) p) =
      algebraMap K E (eval y p) := by
  have hh := aeval_map (K := K) (E := E) (L := E) (algebraMap K E ∘ y) p
  rw [MvPolynomial.aeval_eq_eval] at hh
  rw [hh, aeval_algebraMap_apply E, MvPolynomial.aeval_eq_eval]

lemma Compatible.map {S : Set (σ → K)} {x : σ → E} (hx : Compatible S x) :
    Compatible S (algebraMap E L ∘ x) := by
  constructor
  · intro p hp
    rw [aeval_algebraMap_apply L, hx.1 p hp, map_zero]
  · intro P hP
    apply hx.2 P
    intro p hp
    have h := hP p hp
    rw [aeval_algebraMap_apply L] at h
    exact (algebraMap E L).injective (h.trans (map_zero _).symm)

lemma Compatible.descend {S : Set (σ → K)} {x : σ → L}
    (hx : Compatible ((fun y : σ → K => algebraMap K E ∘ y) '' S) x) :
    Compatible S x := by
  classical
  constructor
  · intro p hp
    rw [← aeval_map (E := E)]
    apply hx.1
    rintro y ⟨z,hz,rfl⟩
    rw [eval_map_coords, hp z hz, map_zero]
  · intro P hP
    obtain ⟨y,hy,he⟩ := hx.2 (P.image (MvPolynomial.map (algebraMap K E))) (by
      intro p hp
      obtain ⟨q,hq,rfl⟩ := Finset.mem_image.mp hp
      rw [aeval_map]
      exact hP q hq)
    obtain ⟨z,hz,rfl⟩ := hy
    refine ⟨z,hz,?_⟩
    intro p hp
    have h := he _ (Finset.mem_image.mpr ⟨p,hp,rfl⟩)
    rw [eval_map_coords] at h
    exact (algebraMap K E).injective (h.trans (map_zero _).symm)

lemma infinite_image {S : Set (σ → K)} (hS : S.Infinite) :
    ((fun y : σ → K => algebraMap K E ∘ y) '' S).Infinite := by
  apply hS.image
  intro x _ y _ h
  funext i
  exact (algebraMap K E).injective (congrFun h i)

/-- From any infinite set of tuples, obtain any prescribed finite number of compatible
points with one selected coordinate from each point algebraically independent over `K`. -/
lemma independent_points [Fintype σ] (S : Set (σ → K)) (hS : S.Infinite) (k : ℕ) :
    ∃ L : Type u, ∃ _ : Field L, ∃ _ : Algebra K L,
      ∃ x : Fin k → σ → L, ∃ j : Fin k → σ,
        (∀ i, Compatible S (x i)) ∧ AlgebraicIndependent K (fun i => x i (j i)) := by
  classical
  induction k with
  | zero =>
    refine ⟨K,inferInstance,inferInstance,Fin.elim0,Fin.elim0,?_,?_⟩
    · exact fun i => Fin.elim0 i
    · exact algebraicIndependent_empty_type_iff.mpr (algebraMap K K).injective
  | succ k ih =>
    obtain ⟨E,hEF,hEA,x,j,hx,hi⟩ := ih
    letI := hEF
    letI := hEA
    let S' := (fun y : σ → K => algebraMap K E ∘ y) '' S
    have hS' : S'.Infinite := infinite_image hS
    obtain ⟨L,hLF,hLA,y,hy₁,hy₂,t,ht⟩ := GenericPoint.exists_transcendental_point S' hS'
    letI := hLF
    letI := hLA
    letI : Algebra K L := ((algebraMap E L).comp (algebraMap K E)).toAlgebra
    letI : IsScalarTower K E L := IsScalarTower.of_algebraMap_eq (fun _ => rfl)
    have hy : Compatible S y := Compatible.descend (E := E) ⟨hy₁,hy₂⟩
    have hxi (i : Fin k) : Compatible S (algebraMap E L ∘ x i) := (hx i).map
    have hiy : AlgebraicIndependent E (fun _ : Fin 1 => y t) :=
      algebraicIndependent_unique_type_iff.mpr ht
    have hii := hi.sumElim_comp hiy
    let e : Fin (k+1) ≃ Fin 1 ⊕ Fin k :=
      (finSumFinEquiv : Fin k ⊕ Fin 1 ≃ Fin (k+1)).symm.trans (Equiv.sumComm _ _)
    let xs : Fin 1 ⊕ Fin k → σ → L := Sum.elim (fun _ => y) (fun i => algebraMap E L ∘ x i)
    let js : Fin 1 ⊕ Fin k → σ := Sum.elim (fun _ => t) j
    refine ⟨L,hLF,inferInstance,xs ∘ e,js ∘ e,?_,?_⟩
    · intro i
      change Compatible S (xs (e i))
      cases e i with
      | inl a => exact hy
      | inr b => exact hxi b
    · convert hii.comp e e.injective using 1
      funext i
      change xs (e i) (js (e i)) =
        Sum.elim (fun _ : Fin 1 => y t) (fun i => algebraMap E L (x i (j i))) (e i)
      cases e i <;> rfl

end IndependentPoints

end -- IndependentPoints

section -- PolynomialBipartite

/- Polynomial bipartite graphs over arbitrary fields and compatible coordinate placements. -/
open MvPolynomial Finset SimpleGraph
namespace PolynomialBipartite
universe u v w
variable {K : Type u} [Field K] {τ : Type v} {J : Type*}

abbrev Point (K : Type*) (τ : Type*) := τ → K
abbrev Vertex (K : Type*) (τ : Type*) := Point K τ ⊕ Point K τ
abbrev Variables (τ : Type*) := τ ⊕ τ

def color : Vertex K τ → Fin 2 := Sum.elim (fun _ => 0) (fun _ => 1)
def coord : Vertex K τ → Point K τ := Sum.elim id id

def place {W : Type*} (κ : W → Fin 2) (y : W × τ → K) (w : W) : Vertex K τ :=
  if κ w = 0 then Sum.inl (fun t => y (w,t)) else Sum.inr (fun t => y (w,t))

lemma color_place {W : Type*} (κ : W → Fin 2) (y : W × τ → K) (w : W) :
    color (place κ y w) = κ w := by
  by_cases h : κ w = 0
  · simp [place,h,color]
  · have hh : κ w = 1 := by omega
    simp [place,h,color,hh]

lemma coord_place {W : Type*} (κ : W → Fin 2) (y : W × τ → K) (w : W) :
    coord (place κ y w) = fun t => y (w,t) := by
  simp only [place]
  split_ifs <;> rfl

lemma vertex_ext {x y : Vertex K τ} (hc : color x = color y) (hp : coord x = coord y) : x = y := by
  cases x <;> cases y <;> simp_all [color,coord]

def graph (P : J → MvPolynomial (Variables τ) K) : SimpleGraph (Vertex K τ) where
  Adj u v := match u,v with
    | Sum.inl x, Sum.inr y => ∀ j, eval (Sum.elim x y) (P j) = 0
    | Sum.inr y, Sum.inl x => ∀ j, eval (Sum.elim x y) (P j) = 0
    | _, _ => False
  symm := by constructor; intro u v h; cases u <;> cases v <;> exact h
  loopless := by constructor; intro v; cases v <;> exact not_false


def pairVariables {W : Type*} (u v : W) : Variables τ → W × τ :=
  Sum.elim (fun t => (u,t)) (fun t => (v,t))

lemma eval_edge {W : Type*} (u v : W) (y : W × τ → K) (P : MvPolynomial (Variables τ) K) :
    eval y (rename (pairVariables u v) P) =
      eval (Sum.elim (fun t => y (u,t)) (fun t => y (v,t))) P := by
  rw [eval_rename]
  have h : y ∘ pairVariables u v = Sum.elim (fun t => y (u,t)) (fun t => y (v,t)) := by
    funext z; cases z <;> rfl
  rw [h]

section Extension
variable {L : Type u} [Field L] [Algebra K L]

lemma aeval_edge {W : Type*} (u v : W) (y : W × τ → L) (P : MvPolynomial (Variables τ) K) :
    aeval y (rename (pairVariables u v) P) =
      eval (Sum.elim (fun t => y (u,t)) (fun t => y (v,t))) (map (algebraMap K L) P) := by
  simp only [aeval_def, eval₂_rename, eval_map]
  have h : y ∘ pairVariables u v = Sum.elim (fun t => y (u,t)) (fun t => y (v,t)) := by
    funext z; cases z <;> rfl
  rw [h]

/-- Compatible points preserve injectivity of placements, including the vector disequalities. -/
lemma compatible_injective {W : Type*} [Fintype τ]
    (κ : W → Fin 2) (S : Set (W × τ → K)) (y : W × τ → L)
    (hy : IndependentPoints.Compatible S y)
    (hinj : ∀ z ∈ S, Function.Injective (place κ z)) : Function.Injective (place κ y) := by
  classical
  intro u v huv
  have hc : κ u = κ v := by simpa only [color_place] using congrArg color huv
  have he : ∀ t, y (u,t) = y (v,t) := by
    intro t
    simpa only [coord_place] using congrFun (congrArg coord huv) t
  let D : Finset (MvPolynomial (W × τ) K) :=
    univ.image (fun t => X (u,t) - X (v,t))
  obtain ⟨z,hz,hze⟩ := hy.2 D (by
    intro p hp
    obtain ⟨t,_,rfl⟩ := mem_image.mp hp
    simp only [map_sub, aeval_X, sub_eq_zero]
    exact he t)
  apply hinj z hz
  apply vertex_ext
  · simpa only [color_place] using hc
  · funext t
    have hh := hze _ (mem_image.mpr ⟨t,mem_univ _,rfl⟩)
    simpa only [coord_place, map_sub, eval_X, sub_eq_zero] using hh

/-- Compatible points preserve all polynomial graph adjacency constraints. -/
lemma compatible_hom {W : Type*} (G : SimpleGraph W) (κ : W → Fin 2)
    (P : J → MvPolynomial (Variables τ) K)
    (S : Set (W × τ → K)) (y : W × τ → L) (hS : S.Nonempty)
    (hy : IndependentPoints.Compatible S y)
    (hh : ∀ z ∈ S, ∀ u v, G.Adj u v → (graph P).Adj (place κ z u) (place κ z v)) :
    ∀ u v, G.Adj u v →
      (graph (fun j => map (algebraMap K L) (P j))).Adj (place κ y u) (place κ y v) := by
  intro u v huv
  by_cases hu : κ u = 0 <;> by_cases hv : κ v = 0
  · obtain ⟨z,hz⟩ := hS
    have hg := hh z hz u v huv
    simpa only [place,if_pos hu,if_pos hv,graph] using hg
  · simp only [place, if_pos hu, if_neg hv, graph]
    change ∀ j, eval (Sum.elim (fun t => y (u,t)) (fun t => y (v,t)))
      (map (algebraMap K L) (P j)) = 0
    intro j
    rw [← aeval_edge]
    apply hy.1
    intro z hz
    rw [eval_edge]
    have hg := hh z hz u v huv
    exact (show ∀ j, eval (Sum.elim (fun t => z (u,t)) (fun t => z (v,t))) (P j) = 0 by
      simpa only [place,if_pos hu,if_neg hv,graph] using hg) j
  · simp only [place, if_neg hu, if_pos hv, graph]
    change ∀ j, eval (Sum.elim (fun t => y (v,t)) (fun t => y (u,t)))
      (map (algebraMap K L) (P j)) = 0
    intro j
    rw [← aeval_edge]
    apply hy.1
    intro z hz
    rw [eval_edge]
    have hg := hh z hz u v huv
    exact (show ∀ j, eval (Sum.elim (fun t => z (v,t)) (fun t => z (u,t))) (P j) = 0 by
      simpa only [place,if_neg hu,if_pos hv,graph] using hg) j
  · obtain ⟨z,hz⟩ := hS
    have hg := hh z hz u v huv
    simpa only [place,if_neg hu,if_neg hv,graph] using hg

lemma compatible_fixed_coordinate {W : Type*} (S : Set (W × τ → K)) (y : W × τ → L)
    (hy : IndependentPoints.Compatible S y) (w : W) (t : τ) (c : K)
    (hc : ∀ z ∈ S, z (w,t) = c) : y (w,t) = algebraMap K L c := by
  have hh := hy.1 (X (w,t)-C c) (by
    intro z hz
    simp only [map_sub, eval_X, eval_C, sub_eq_zero]
    exact hc z hz)
  simpa only [map_sub, aeval_X, aeval_C, sub_eq_zero] using hh
end Extension
end PolynomialBipartite

end -- PolynomialBipartite

section -- AlgebraicGeneratorBounds

/- Algebraic independence cannot exceed the size of a generating tuple. -/
namespace AlgebraicGeneratorBounds
open AlgebraicIndependent

variable {K L I J : Type*} [Field K] [Field L] [Algebra K L] [Fintype I] [Fintype J]

lemma independent_card_le_generators (x : I → L) (hx : AlgebraicIndependent K x)
    (z : J → L) (hmem : ∀ i, x i ∈ IntermediateField.adjoin K (Set.range z)) :
    Fintype.card I ≤ Fintype.card J := by
  classical
  let M := AlgebraicIndependent.matroid K L
  have hi : M.Indep (Set.range x) := matroid_indep_iff.mpr hx.to_subtype_range
  have hs : Set.range x ⊆ M.closure (Set.range z) := by
    rintro y ⟨i,rfl⟩
    rw [matroid_closure_eq]
    apply IntermediateField.isAlgebraic_adjoin_iff.mp
    exact isAlgebraic_algebraMap (⟨x i,hmem i⟩ : IntermediateField.adjoin K (Set.range z))
  have hh := hi.cardinalMk_le_cRk_of_subset hs
  rw [M.cRk_closure] at hh
  have hcard := hh.trans (M.cRk_le_cardinalMk (Set.range z))
  have hcard' : Fintype.card (Set.range x) ≤ Fintype.card (Set.range z) := by
    simpa only [Cardinal.mk_fintype, Nat.cast_le] using hcard
  have hxcard : Fintype.card (Set.range x) = Fintype.card I := by
    exact Fintype.card_congr (Equiv.ofInjective x hx.injective).symm
  have hzcard : Fintype.card (Set.range z) ≤ Fintype.card J :=
    Fintype.card_le_of_surjective (fun j => (⟨z j,Set.mem_range_self j⟩ : Set.range z))
      (by rintro ⟨y,⟨j,rfl⟩⟩; exact ⟨j,rfl⟩)
  omega

lemma nested_adjoin_mem (v : I → L) (z : J → L) {c : L}
    (hc : c ∈ Algebra.adjoin (IntermediateField.adjoin K (Set.range v)) (Set.range z)) :
    c ∈ IntermediateField.adjoin K (Set.range (Sum.elim v z)) := by
  let T := IntermediateField.adjoin K (Set.range (Sum.elim v z))
  have hv : IntermediateField.adjoin K (Set.range v) ≤ T := by
    apply IntermediateField.adjoin_le_iff.mpr
    rintro x ⟨i,rfl⟩
    exact IntermediateField.subset_adjoin K _ ⟨Sum.inl i,rfl⟩
  induction hc using Algebra.adjoin_induction with
  | mem x hx =>
    obtain ⟨j,rfl⟩ := hx
    exact IntermediateField.subset_adjoin K _ ⟨Sum.inr j,rfl⟩
  | algebraMap r => exact hv r.property
  | add x y _ _ hx hy => exact T.add_mem hx hy
  | mul x y _ _ hx hy => exact T.mul_mem hx hy

end AlgebraicGeneratorBounds

end -- AlgebraicGeneratorBounds

section -- PolynomialSampling

/- Elementary interpolation and uniform evaluations of bounded-degree random polynomials. -/
open Finset MvPolynomial
namespace PolynomialSampling

section Interpolation
variable {σ F I : Type*} [Field F] [Fintype I] [DecidableEq I]

lemma separator {x y : σ → F} (h : x ≠ y) :
    ∃ p : MvPolynomial σ F, p.totalDegree ≤ 1 ∧ eval x p = 1 ∧ eval y p = 0 := by
  classical
  obtain ⟨c,hc⟩ : ∃ c, x c ≠ y c := Function.ne_iff.mp h
  refine ⟨C ((x c-y c)⁻¹) * (X c-C (y c)), ?_, ?_, ?_⟩
  · calc
      _ ≤ (C ((x c-y c)⁻¹) : MvPolynomial σ F).totalDegree +
          (X c-C (y c)).totalDegree := totalDegree_mul _ _
      _ ≤ 0 + max (X c : MvPolynomial σ F).totalDegree (C (y c) : MvPolynomial σ F).totalDegree := by
        simpa only [totalDegree_C, zero_add] using totalDegree_sub (X c) (C (y c))
      _ = 1 := by simp
  · simp [sub_ne_zero.mpr hc]
  · simp

lemma basis_polynomial (x : I → (σ → F)) (hx : Function.Injective x) (i : I) :
    ∃ p : MvPolynomial σ F, p.totalDegree ≤ Fintype.card I - 1 ∧
      ∀ j, eval (x j) p = if j = i then 1 else 0 := by
  classical
  have hs : ∀ j : I, ∃ p : MvPolynomial σ F,
      p.totalDegree ≤ 1 ∧ eval (x i) p = 1 ∧ (j ≠ i → eval (x j) p = 0) := by
    intro j
    by_cases hji : j = i
    · refine ⟨1, by simp, by simp, ?_⟩
      exact fun h => (h hji).elim
    · obtain ⟨p,hp,hi,hj⟩ := separator (fun h => hji (hx h).symm)
      exact ⟨p,hp,hi,fun _ => hj⟩
  choose p hp hi hj using hs
  refine ⟨∏ j ∈ univ.erase i, p j, ?_, ?_⟩
  · calc
      _ ≤ ∑ j ∈ univ.erase i, (p j).totalDegree := totalDegree_finset_prod _ _
      _ ≤ ∑ _j ∈ univ.erase i, 1 := sum_le_sum (fun j _ => hp j)
      _ = _ := by simp
  · intro j
    rw [map_prod]
    by_cases hji : j = i
    · subst j
      simp [hi]
    · rw [if_neg hji]
      exact prod_eq_zero (mem_erase.mpr ⟨hji,mem_univ j⟩) (hj j hji)

/-- Any values at `m` distinct points admit an interpolant of total degree at most `m-1`.
No lower bound on the field cardinality is needed. -/
lemma interpolate (x : I → (σ → F)) (hx : Function.Injective x) (v : I → F) :
    ∃ p : MvPolynomial σ F, p.totalDegree ≤ Fintype.card I - 1 ∧
      ∀ i, eval (x i) p = v i := by
  classical
  choose p hp he using basis_polynomial x hx
  refine ⟨∑ i, C (v i) * p i, ?_, ?_⟩
  · apply totalDegree_finsetSum_le
    intro i _
    exact (totalDegree_mul _ _).trans (by simpa using hp i)
  · intro i
    simp only [map_sum, map_mul, eval_C, he]
    simp

/-- Simultaneous evaluation on the finite-dimensional space of polynomials of degree at most `d`. -/
noncomputable def evaluation (d : ℕ) (x : I → (σ → F)) :
    restrictTotalDegree σ F d →ₗ[F] (I → F) where
  toFun p i := eval (x i) p.val
  map_add' p q := by ext i; simp
  map_smul' c p := by ext i; simp

lemma evaluation_surjective (d : ℕ) (x : I → (σ → F))
    (hx : Function.Injective x) (hd : Fintype.card I ≤ d+1) :
    Function.Surjective (evaluation d x) := by
  intro v
  obtain ⟨p,hp,he⟩ := interpolate x hx v
  refine ⟨⟨p, (mem_restrictTotalDegree _ _ _).mpr (hp.trans (by omega))⟩, ?_⟩
  exact funext he
end Interpolation

section Fibers
variable {M N : Type*} [AddGroup M] [AddGroup N]

/-- Translation identifies every nonempty fiber of a group homomorphism with its kernel. -/
def fiberEquivZero (f : M →+ N) (y : N) (z : M) (hz : f z = y) :
    {x // f x = y} ≃ {x // f x = 0} where
  toFun x := ⟨x.val-z, by simp [x.property,hz]⟩
  invFun x := ⟨x.val+z, by simp [x.property,hz]⟩
  left_inv x := by ext; simp
  right_inv x := by ext; simp

lemma card_fiber_eq [Fintype M] [Fintype N] (f : M →+ N)
    (hf : Function.Surjective f) (y : N) :
    Nat.card {x // f x = y} = Nat.card {x // f x = 0} := by
  obtain ⟨z,hz⟩ := hf y
  exact Nat.card_congr (fiberEquivZero f y z hz)

lemma card_eq_mul_card_fiber [Fintype M] [Fintype N] (f : M →+ N)
    (hf : Function.Surjective f) (y : N) :
    Fintype.card M = Fintype.card N * Nat.card {x // f x = y} := by
  classical
  have hc : ∀ v : N, Fintype.card {x // f x = v} = Nat.card {x // f x = y} := by
    intro v
    rw [← Nat.card_eq_fintype_card]
    exact (card_fiber_eq f hf v).trans (card_fiber_eq f hf y).symm
  calc
    Fintype.card M = Fintype.card ((v : N) × {x // f x = v}) :=
      (Fintype.card_congr (Equiv.sigmaFiberEquiv f)).symm
    _ = ∑ v : N, Fintype.card {x // f x = v} := Fintype.card_sigma
    _ = _ := by simp only [hc, sum_const, card_univ, smul_eq_mul]
end Fibers

section Uniform
variable {σ F I : Type*} [Field F] [Fintype F] [Fintype σ] [Fintype I]

noncomputable instance boundedPolynomialFintype (d : ℕ) :
    Fintype (restrictTotalDegree σ F d) := by
  haveI := Module.finite_of_finite F (M := restrictTotalDegree σ F d)
  exact Fintype.ofFinite _


/-- Evaluate a system of `a` independently sampled polynomials. -/
noncomputable def systemEvaluation (a d : ℕ) (x : I → (σ → F)) :
    (Fin a → restrictTotalDegree σ F d) →ₗ[F] (Fin a → I → F) where
  toFun p j := evaluation d x (p j)
  map_add' p q := by ext j i; simp [evaluation]
  map_smul' c p := by ext j i; simp [evaluation]

lemma systemEvaluation_surjective (a d : ℕ) (x : I → (σ → F))
    (hx : Function.Injective x) (hd : Fintype.card I ≤ d+1) :
    Function.Surjective (systemEvaluation a d x) := by
  classical
  intro v
  have h : ∀ j, ∃ p, evaluation d x p = v j := fun j => evaluation_surjective d x hx hd (v j)
  choose p hp using h
  exact ⟨p,funext hp⟩

lemma system_probability (a d : ℕ) (x : I → (σ → F))
    (hx : Function.Injective x) (hd : Fintype.card I ≤ d+1) (v : Fin a → I → F) :
    (Nat.card {p : Fin a → restrictTotalDegree σ F d //
        ∀ j i, eval (x i) (p j).val = v j i} : ℚ) /
      Fintype.card (Fin a → restrictTotalDegree σ F d) =
        1 / (Fintype.card F : ℚ) ^ (a * Fintype.card I) := by
  classical
  have hcount : Fintype.card (Fin a → restrictTotalDegree σ F d) =
      Fintype.card F ^ (a * Fintype.card I) *
        Nat.card {p : Fin a → restrictTotalDegree σ F d //
          ∀ j i, eval (x i) (p j).val = v j i} := by
    have h := card_eq_mul_card_fiber (systemEvaluation a d x).toAddMonoidHom
      (systemEvaluation_surjective a d x hx hd) v
    have heq : Nat.card {p // (systemEvaluation a d x).toAddMonoidHom p = v} =
        Nat.card {p : Fin a → restrictTotalDegree σ F d //
          ∀ j i, eval (x i) (p j).val = v j i} := by
      apply Nat.card_congr
      exact Equiv.subtypeEquivRight (fun p =>
        _root_.funext_iff.trans (forall_congr' (fun j => _root_.funext_iff)))
    rw [heq] at h
    simpa only [Fintype.card_fun, Fintype.card_fin, ← pow_mul, Nat.mul_comm] using h
  have hn : (0 : ℚ) < Fintype.card (Fin a → restrictTotalDegree σ F d) := by
    exact_mod_cast Fintype.card_pos
  have hq : (0 : ℚ) < (Fintype.card F : ℚ) ^ (a * Fintype.card I) := by
    exact_mod_cast pow_pos (Fintype.card_pos (α := F)) _
  apply (div_eq_div_iff (ne_of_gt hn) (ne_of_gt hq)).mpr
  norm_cast
  simpa [mul_comm] using hcount.symm
end Uniform
end PolynomialSampling

end -- PolynomialSampling

section -- LinearRelations

/- Independent linear relations reduce the number of algebra generators needed for a tuple. -/
open Finset Module
namespace LinearRelations

variable {K L E M : Type*} [Field K] [Field L] [Algebra K L] [Fintype E] [Fintype M]

lemma independent_rows (B : Matrix E M K) (hB : Function.Surjective B.mulVec) :
    LinearIndependent K (fun e => B e) := by
  classical
  apply Fintype.linearIndependent_iff.mpr
  intro g hg i
  have hg' (m : M) : ∑ e, g e * B e m = 0 := by
    simpa only [Finset.sum_apply, Pi.smul_apply, smul_eq_mul, Pi.zero_apply] using congrFun hg m
  obtain ⟨w,hw⟩ := hB (Pi.single i 1)
  calc
    g i = ∑ e, g e * (Pi.single i (1 : K) : E → K) e := by simp [Pi.single_apply]
    _ = ∑ e, g e * ∑ m, B e m * w m := by
      apply sum_congr rfl
      intro e _
      rw [← hw]
      rfl
    _ = ∑ m, (∑ e, g e * B e m) * w m := by
      simp only [mul_sum, sum_mul]
      rw [sum_comm]
      apply sum_congr rfl
      intro m _
      apply sum_congr rfl
      intro e _
      ring
    _ = 0 := by simp [hg']

lemma small_generating_set (B : Matrix E M K) (hB : Function.Surjective B.mulVec)
    (c : M → L) (hc : ∀ e, ∑ m, B e m • c m = 0) :
    ∃ d : ℕ, d + Fintype.card E ≤ Fintype.card M ∧
      ∃ z : Fin d → L, ∀ m, c m ∈ Algebra.adjoin K (Set.range z) := by
  classical
  let f : (M → K) →ₗ[K] L := ∑ m, (LinearMap.proj m).smulRight (c m)
  have hf (v : M → K) : f v = ∑ m, v m • c m := by
    simp only [f, LinearMap.sum_apply, LinearMap.smulRight_apply, LinearMap.proj_apply]
  let row (e : E) : f.ker := ⟨B e, by rw [LinearMap.mem_ker, hf]; exact hc e⟩
  have hrow : LinearIndependent K row := by
    apply LinearIndependent.of_comp f.ker.subtype
    exact independent_rows B hB
  have he := hrow.fintype_card_le_finrank
  have hdim := f.finrank_range_add_finrank_ker
  rw [Module.finrank_pi] at hdim
  let d := Module.finrank K f.range
  let basis := Module.finBasis K f.range
  let z : Fin d → L := fun i => (basis i).val
  refine ⟨d,by dsimp [d]; omega,z,?_⟩
  intro m
  have hcm : c m ∈ f.range := by
    refine ⟨Pi.single m 1,?_⟩
    rw [hf]
    simp [Pi.single_apply]
  let x : f.range := ⟨c m,hcm⟩
  have hx := congrArg Subtype.val (basis.sum_repr x)
  have hexp : c m = ∑ i : Fin d, (basis.repr x i) • z i := by
    simpa only [Submodule.coe_sum, Submodule.coe_smul] using hx.symm
  rw [hexp]
  apply Subalgebra.sum_mem
  intro i _
  apply Submodule.smul_mem (Algebra.adjoin K (Set.range z)).toSubmodule
  exact Algebra.subset_adjoin ⟨i,rfl⟩

end LinearRelations

end -- LinearRelations

section -- BoundedPolynomialCoefficients

/- Coefficient coordinates and linear elimination for bounded-degree polynomial equations. -/
open Finset MvPolynomial
namespace BoundedPolynomialCoefficients

variable {σ K L I : Type*} [Fintype σ] [Field K] [Field L] [Algebra K L] [Fintype I]

abbrev Exponent (σ : Type*) (d : ℕ) := {s : σ →₀ ℕ // s.sum (fun _ n => n) ≤ d}

noncomputable instance exponentFintype (d : ℕ) : Fintype (Exponent σ d) := by
  classical
  have hb (s : Exponent σ d) (i : σ) : s.val i ≤ d := by
    calc
      s.val i ≤ s.val.sum (fun _ n => n) := by
        rw [Finsupp.sum_fintype]
        · exact single_le_sum (fun _ _ => Nat.zero_le _) (mem_univ i)
        · simp
      _ ≤ d := s.property
  let f : Exponent σ d → (σ → Fin (d+1)) := fun s i => ⟨s.val i, Nat.lt_succ_of_le (hb s i)⟩
  have hf : Function.Injective f := by
    intro s t h
    apply Subtype.ext
    apply Finsupp.ext
    intro i
    exact congrArg Fin.val (congrFun h i)
  exact Fintype.ofInjective f hf

noncomputable def polynomial (d : ℕ) (c : Exponent σ d → K) : MvPolynomial σ K :=
  ∑ s, monomial s.val (c s)

lemma coeff_polynomial (d : ℕ) (c : Exponent σ d → K) (s : Exponent σ d) :
    coeff s.val (polynomial d c) = c s := by
  classical
  have he (z : Exponent σ d) : z.val = s.val ↔ z = s :=
    ⟨Subtype.ext,congrArg Subtype.val⟩
  simp only [polynomial, coeff_sum, coeff_monomial, he, sum_ite_eq', mem_univ, if_true]

lemma polynomial_degree (d : ℕ) (c : Exponent σ d → K) : (polynomial d c).totalDegree ≤ d := by
  apply totalDegree_finsetSum_le
  intro s _
  exact (totalDegree_monomial_le _ _).trans s.property

lemma polynomial_coefficients (d : ℕ) (p : restrictTotalDegree σ K d) :
    polynomial d (fun s => coeff s.val p.val) = p.val := by
  classical
  ext s
  by_cases hs : s.sum (fun _ n => n) ≤ d
  · let t : Exponent σ d := ⟨s,hs⟩
    have he : ∀ z : Exponent σ d, z.val = s ↔ z = t := by
      intro z
      exactfun h => Subtype.ext h, fun h => congrArg Subtype.val h⟩
    simp only [polynomial, coeff_sum, coeff_monomial, he, sum_ite_eq', mem_univ, if_true]
    rfl
  · have hp : coeff s p.val = 0 := by
      apply coeff_eq_zero_of_totalDegree_lt
      exact lt_of_le_of_lt ((mem_restrictTotalDegree _ _ _).mp p.property) (Nat.lt_of_not_ge hs)
    rw [hp, polynomial, coeff_sum]
    apply sum_eq_zero
    intro z _
    rw [coeff_monomial]
    split_ifs with h
    · exact (hs (h ▸ z.property)).elim
    · rfl

noncomputable def coefficientEquiv (d : ℕ) :
    (Exponent σ d → K) ≃ restrictTotalDegree σ K d where
  toFun c := ⟨polynomial d c,(mem_restrictTotalDegree σ d _).mpr (polynomial_degree d c)⟩
  invFun p s := coeff s.val p.val
  left_inv c := funext (coeff_polynomial d c)
  right_inv p := Subtype.ext (polynomial_coefficients d p)

noncomputable def evaluationMatrix (d : ℕ) (x : I → σ → K) : Matrix I (Exponent σ d) K :=
  fun i s => eval (x i) (monomial s.val 1)

lemma eval_polynomial (d : ℕ) (c : Exponent σ d → K) (x : σ → K) :
    eval x (polynomial d c) = ∑ s, eval x (monomial s.val (1 : K)) * c s := by
  classical
  simp only [polynomial, map_sum, eval_monomial]
  apply sum_congr rfl
  intro s _
  ring

lemma matrix_surjective (d : ℕ) (x : I → σ → K) (hx : Function.Injective x)
    (hd : Fintype.card I ≤ d+1) : Function.Surjective (evaluationMatrix d x).mulVec := by
  classical
  intro v
  obtain ⟨p,hp⟩ := PolynomialSampling.evaluation_surjective d x hx hd v
  refine ⟨fun s => coeff s.val p.val,?_⟩
  funext i
  have hh := congrFun hp i
  change eval (x i) p.val = v i at hh
  rw [← polynomial_coefficients d p, eval_polynomial] at hh
  exact hh

lemma mapped_eval_polynomial (d : ℕ) (c : Exponent σ d → L) (x : σ → K) :
    eval (fun i => algebraMap K L (x i)) (polynomial d c) =
      ∑ s, eval x (monomial s.val (1 : K)) • c s := by
  classical
  rw [eval_polynomial]
  apply sum_congr rfl
  intro s _
  simp only [eval_monomial, one_mul, Algebra.smul_def, map_finsuppProd, map_pow]


/-- Simultaneous evaluation eliminates `|J|*|I|` coefficient generators from a system. -/
lemma system_coefficient_generators {J : Type*} [Fintype J]
    (d : ℕ) (x : I → σ → K) (hx : Function.Injective x)
    (hd : Fintype.card I ≤ d+1) (c : J → Exponent σ d → L)
    (hc : ∀ j i, eval (fun t => algebraMap K L (x i t)) (polynomial d (c j)) = 0) :
    ∃ m : ℕ, m + Fintype.card J * Fintype.card I ≤
        Fintype.card J * Fintype.card (Exponent σ d) ∧
      ∃ z : Fin m → L, ∀ j s, c j s ∈ Algebra.adjoin K (Set.range z) := by
  classical
  let B : Matrix (J × I) (J × Exponent σ d) K :=
    fun ji zs => if ji.1 = zs.1 then evaluationMatrix d x ji.2 zs.2 else 0
  have hB : Function.Surjective B.mulVec := by
    intro v
    have hw : ∀ j : J, ∃ w : Exponent σ d → K,
        (evaluationMatrix d x).mulVec w = fun i => v (j,i) :=
      fun j => matrix_surjective d x hx hd (fun i => v (j,i))
    choose w hw using hw
    refine ⟨fun zs => w zs.1 zs.2,?_⟩
    funext ji
    have hh := congrFun (hw ji.1) ji.2
    simpa only [B, Matrix.mulVec, dotProduct, Fintype.sum_prod_type, ite_mul,
      zero_mul, sum_ite_irrel, sum_const_zero, sum_ite_eq, mem_univ, if_true] using hh
  have hrel (ji : J × I) : ∑ zs, B ji zs • c zs.1 zs.2 = 0 := by
    have hh := hc ji.1 ji.2
    rw [mapped_eval_polynomial] at hh
    simpa only [B, Fintype.sum_prod_type, ite_smul, zero_smul, sum_ite_irrel,
      sum_const_zero, sum_ite_eq, mem_univ, if_true, evaluationMatrix] using hh
  obtain ⟨m,hm,z,hz⟩ := LinearRelations.small_generating_set B hB (fun zs => c zs.1 zs.2) hrel
  refine ⟨m,?_,z,fun j s => hz (j,s)⟩
  simpa only [Fintype.card_prod] using hm

end BoundedPolynomialCoefficients

end -- BoundedPolynomialCoefficients

section -- GenericConstraints

/- A finite algebraic-independence bound for generic polynomial incidence constraints. -/
open BoundedPolynomialCoefficients AlgebraicGeneratorBounds
namespace GenericConstraints

variable {F L σ I J M T : Type*} [Field F] [Field L] [Algebra F L]
    [Fintype σ] [Fintype I] [Fintype J] [Fintype M] [Fintype T]

/-- Independent polynomial evaluations consume algebraic degrees of freedom.
This is the coefficient-counting step of the proposed generic-parameter argument. -/
lemma independent_extras_bound (d : ℕ) (v : M → L)
    (x : I → σ → IntermediateField.adjoin F (Set.range v)) (hx : Function.Injective x)
    (hd : Fintype.card I ≤ d+1) (c : J → Exponent σ d → L) (extra : T → L)
    (hc : ∀ j i, MvPolynomial.eval
      (fun t => algebraMap (IntermediateField.adjoin F (Set.range v)) L (x i t))
      (polynomial d (c j)) = 0)
    (hextra : ∀ t, extra t ∈ IntermediateField.adjoin F (Set.range v))
    (hind : AlgebraicIndependent F (Sum.elim (fun js : J × Exponent σ d => c js.1 js.2) extra)) :
    Fintype.card T + Fintype.card J * Fintype.card I ≤ Fintype.card M := by
  classical
  obtain ⟨m,hm,z,hz⟩ := system_coefficient_generators d x hx hd c hc
  have hv : IntermediateField.adjoin F (Set.range v) ≤
      IntermediateField.adjoin F (Set.range (Sum.elim v z)) := by
    apply IntermediateField.adjoin_le_iff.mpr
    rintro y ⟨i,rfl⟩
    exact IntermediateField.subset_adjoin F _ ⟨Sum.inl i,rfl⟩
  have hmem : ∀ i : (J × Exponent σ d) ⊕ T,
      Sum.elim (fun js : J × Exponent σ d => c js.1 js.2) extra i ∈
        IntermediateField.adjoin F (Set.range (Sum.elim v z)) := by
    intro i
    cases i with
    | inl js => exact nested_adjoin_mem v z (hz js.1 js.2)
    | inr t => exact hv (hextra t)
  have hcard := independent_card_le_generators _ hind (Sum.elim v z) hmem
  simp only [Fintype.card_sum, Fintype.card_prod, Fintype.card_fin] at hcard
  omega

end GenericConstraints

end -- GenericConstraints

section -- PolynomialEdgeConstraints

/- Coordinate counts for finite subgraphs of a generic polynomial bipartite graph. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace PolynomialEdgeConstraints
universe u
variable {F L τ J T : Type*} [Field F] [Field L] [Algebra F L]
  [Fintype τ] [Fintype J] [Fintype T]

lemma edge_orientation (P : J → MvPolynomial (Variables τ) L)
    (e : Sym2 (Vertex L τ)) (he : e ∈ (graph P).edgeSet) :
    ∃ x y : τ → L, e = s(Sum.inl x, Sum.inr y) ∧
      ∀ j, eval (Sum.elim x y) (P j) = 0 := by
  induction e using Sym2.inductionOn with
  | _ v w =>
    cases v with
    | inl x =>
      cases w with
      | inl z => exact he.elim
      | inr y => exact ⟨x,y,rfl,he⟩
    | inr y =>
      cases w with
      | inl x => exact ⟨x,y,Sym2.eq_swap,he⟩
      | inr z => exact he.elim

/-- Every edge has a unique left-right evaluation tuple. -/
lemma edge_coordinates (P : J → MvPolynomial (Variables τ) L)
    (E : Finset (Sym2 (Vertex L τ))) (hE : ∀ e ∈ E, e ∈ (graph P).edgeSet) :
    ∃ x : E → Variables τ → L, Function.Injective x ∧
      (∀ e, e.val = s(Sum.inl (fun t => x e (Sum.inl t)),
        Sum.inr (fun t => x e (Sum.inr t)))) ∧
      ∀ j e, eval (x e) (P j) = 0 := by
  classical
  have hh (e : E) := edge_orientation P e.val (hE e.val e.property)
  choose l r he hp using hh
  refine ⟨fun e => Sum.elim (l e) (r e),?_,he,fun j e => hp e j⟩
  intro e f hef
  apply Subtype.ext
  rw [he e, he f]
  have hl : l e = l f := funext (fun t => congrFun hef (Sum.inl t))
  have hr : r e = r f := funext (fun t => congrFun hef (Sum.inr t))
  rw [hl,hr]

/-- Each independent edge evaluation consumes one coefficient degree of freedom
per defining polynomial. Extra independent scalars must fit into the remaining
vertex-coordinate degrees of freedom. -/
lemma independent_bound (d : ℕ) (c : J → Exponent (Variables τ) d → L)
    (U : Finset (Vertex L τ)) (E : Finset (Sym2 (Vertex L τ)))
    (hE : ∀ e ∈ E, e ∈ (graph (fun j => polynomial d (c j))).edgeSet)
    (hsupport : ∀ e ∈ E, ∀ v ∈ e, v ∈ U)
    (hd : E.card ≤ d+1) (extra : T → L)
    (hextra : ∀ t, ∃ v ∈ U, ∃ z : τ, extra t = coord v z)
    (hind : AlgebraicIndependent F
      (Sum.elim (fun js : J × Exponent (Variables τ) d => c js.1 js.2) extra)) :
    Fintype.card T + Fintype.card J * E.card ≤ U.card * Fintype.card τ := by
  classical
  obtain ⟨x,hx,he,hp⟩ := edge_coordinates (fun j => polynomial d (c j)) E hE
  let v : U × τ → L := fun z => coord z.1.val z.2
  let B := IntermediateField.adjoin F (Set.range v)
  have hm (w : Vertex L τ) (hw : w ∈ U) (t : τ) : coord w t ∈ B := by
    exact IntermediateField.subset_adjoin F _ ⟨(⟨w,hw⟩,t),rfl⟩
  have hxB (e : E) (t : Variables τ) : x e t ∈ B := by
    cases t with
    | inl z =>
      have hmem : Sum.inl (fun t => x e (Sum.inl t)) ∈ e.val := by
        rw [he]; exact Sym2.mem_mk_left _ _
      exact hm _ (hsupport _ e.property _ hmem) z
    | inr z =>
      have hmem : Sum.inr (fun t => x e (Sum.inr t)) ∈ e.val := by
        rw [he]; exact Sym2.mem_mk_right _ _
      exact hm _ (hsupport _ e.property _ hmem) z
  let x' : E → Variables τ → B := fun e t => ⟨x e t,hxB e t⟩
  have hx' : Function.Injective x' := by
    intro e f hef
    apply hx
    funext t
    exact congrArg Subtype.val (congrFun hef t)
  have hb := GenericConstraints.independent_extras_bound d v x' hx'
    (by simpa only [Fintype.card_coe] using hd) c extra
    (by intro j e; exact hp j e)
    (by intro t; obtain ⟨w,hw,z,hz⟩ := hextra t; rw [hz]; exact hm w hw z) hind
  simpa only [Fintype.card_prod, Fintype.card_coe] using hb

end PolynomialEdgeConstraints

end -- PolynomialEdgeConstraints

section -- GenericRootedFiber

/- Rooted-copy fibers in generic polynomial graphs are finite. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace GenericRootedFiber
universe u
variable {F : Type*} {K : Type u} [Field F] [Field K] [Algebra F K]
  {A R τ J : Type*} [Fintype A] [Fintype R] [Fintype τ] [Fintype J]

noncomputable def fiber (G : SimpleGraph (A ⊕ R)) (κ : A ⊕ R → Fin 2)
    (P : J → MvPolynomial (Variables τ) K) (root : R → τ → K) :
    Set ((A ⊕ R) × τ → K) :=
  {z | Function.Injective (place κ z) ∧
    (∀ u v, G.Adj u v → (graph P).Adj (place κ z u) (place κ z v)) ∧
    ∀ r t, z (Sum.inr r,t) = root r t}

lemma map_polynomial {L : Type*} [Field L] (f : K →+* L)
    (d : ℕ) (c : Exponent (Variables τ) d → K) :
    map f (polynomial d c) = polynomial d (fun s => f (c s)) := by
  simp only [polynomial, map_sum, map_monomial]

/-- Balance prevents positive-dimensional root fibers for generic coefficients.
The degree is only required to exceed the number of edges in a bounded union
of copies of the rooted graph. -/
lemma finite_fiber (G : SimpleGraph (A ⊕ R)) (κ : A ⊕ R → Fin 2)
    (d : ℕ) (c : J → Exponent (Variables τ) d → K)
    (hc : AlgebraicIndependent F (fun js : J × Exponent (Variables τ) d => c js.1 js.2))
    (ha : 0 < Fintype.card J)
    (hbalance : ∀ s : Finset A,
      Fintype.card τ * s.card ≤ Fintype.card J * (RootedUnionDensity.incident G s).card)
    (hd : (Fintype.card τ * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1)
    (root : R → τ → K) :
    (fiber G κ (fun j => polynomial d (c j)) root).Finite := by
  classical
  by_contra hfin
  let k := Fintype.card τ * Fintype.card R + 1
  let S := fiber G κ (fun j => polynomial d (c j)) root
  have hS : S.Infinite := hfin
  obtain ⟨L,hLF,hLA,y,j,hy,hi⟩ := IndependentPoints.independent_points S hS k
  letI := hLF
  letI := hLA
  letI : Algebra F L := ((algebraMap K L).comp (algebraMap F K)).toAlgebra
  letI : IsScalarTower F K L := IsScalarTower.of_algebraMap_eq (fun _ => rfl)
  let c' : J → Exponent (Variables τ) d → L := fun j s => algebraMap K L (c j s)
  let P' : J → MvPolynomial (Variables τ) L := fun j => polynomial d (c' j)
  have hP' (j : J) : map (algebraMap K L) (polynomial d (c j)) = P' j :=
    map_polynomial _ _ _
  have hinj (i : Fin k) : Function.Injective (place κ (y i)) :=
    compatible_injective κ S (y i) (hy i) (fun z hz => hz.1)
  let f : Fin k → ((A ⊕ R) ↪ Vertex L τ) := fun i => ⟨place κ (y i),hinj i⟩
  have hfhom (i : Fin k) (u v : A ⊕ R) (huv : G.Adj u v) :
      (graph P').Adj (f i u) (f i v) := by
    have hh := compatible_hom G κ (fun j => polynomial d (c j)) S (y i)
      hS.nonempty (hy i) (fun z hz => hz.2.1) u v huv
    simpa only [hP', f, Function.Embedding.coeFn_mk] using hh
  let rL : R → Vertex L τ :=
    place (fun r => κ (Sum.inr r)) (fun z => algebraMap K L (root z.1 z.2))
  have hfroot (i : Fin k) (r : R) : f i (Sum.inr r) = rL r := by
    apply vertex_ext
    · simp only [f, rL, Function.Embedding.coeFn_mk, color_place]
    · funext t
      simp only [f, Function.Embedding.coeFn_mk, coord_place, rL]
      exact compatible_fixed_coordinate S (y i) (hy i) (Sum.inr r) t (root r t)
        (fun z hz => hz.2.2 r t)
  let I : Finset (Vertex L τ) := univ.biUnion (fun i => RootedUnionDensity.interiors (f i))
  let E : Finset (Sym2 (Vertex L τ)) :=
    univ.biUnion (fun i => RootedUnionDensity.copyEdges G (f i))
  let U : Finset (Vertex L τ) := I ∪ univ.image rL
  have huc : U.card ≤ I.card + Fintype.card R :=
    (card_union_le _ _).trans (Nat.add_le_add_left (card_image_le.trans_eq (card_univ)) _)
  have hE (e : Sym2 (Vertex L τ)) (he : e ∈ E) : e ∈ (graph P').edgeSet := by
    obtain ⟨i,_,he⟩ := mem_biUnion.mp he
    obtain ⟨e,hge,rfl⟩ := mem_image.mp he
    induction e using Sym2.inductionOn with
    | _ u v =>
      exact hfhom i u v (SimpleGraph.mem_edgeFinset.mp hge)
  have hsupport (e : Sym2 (Vertex L τ)) (he : e ∈ E) (v : Vertex L τ) (hv : v ∈ e) : v ∈ U := by
    obtain ⟨i,_,he⟩ := mem_biUnion.mp he
    rcases RootedUnionDensity.endpoint_support G (f i) he hv with hI | ⟨r,hr⟩
    · exact mem_union_left _ (mem_biUnion.mpr ⟨i,mem_univ _,hI⟩)
    · exact mem_union_right _ (mem_image.mpr ⟨r,mem_univ _,(hfroot i r).symm.trans hr⟩)
  have hec : E.card ≤ k * Nat.card G.edgeSet := by
    calc
      E.card ≤ ∑ i : Fin k, (RootedUnionDensity.copyEdges G (f i)).card := card_biUnion_le
      _ = k * Nat.card G.edgeSet := by
        simp only [RootedUnionDensity.copyEdges,
          card_image_of_injective _ (Sym2.map.injective (f _).injective),
          sum_const, card_univ, Fintype.card_fin, smul_eq_mul,
          SimpleGraph.edgeFinset_card, ← Nat.card_eq_fintype_card, Nat.card_fin]
  have haQ : (0 : ℚ) < Fintype.card J := by exact_mod_cast ha
  have hb := RootedUnionDensity.union_density G ((Fintype.card τ : ℚ) / Fintype.card J)
    (fun s => by
      rw [div_mul_eq_mul_div, div_le_iff₀ haQ]
      have hh := hbalance s
      exact_mod_cast (by simpa only [Nat.mul_comm] using hh))
    f rL univ (fun i _ r => hfroot i r)
  change (Fintype.card τ : ℚ) / Fintype.card J * I.card ≤ E.card at hb
  rw [div_mul_eq_mul_div, div_le_iff₀ haQ] at hb
  have hbN : Fintype.card τ * I.card ≤ Fintype.card J * E.card := by
    have hh : (Fintype.card τ : ℚ) * I.card ≤ Fintype.card J * E.card := by
      simpa only [mul_comm] using hb
    exact_mod_cast hh
  have hind : AlgebraicIndependent F
      (Sum.elim (fun js : J × Exponent (Variables τ) d => c' js.1 js.2)
        (fun i => y i (j i))) := by
    have hh := (hc.sumElim_comp hi).comp
      (Equiv.sumComm (J × Exponent (Variables τ) d) (Fin k))
      (Equiv.sumComm _ _).injective
    convert hh using 1
    funext z
    cases z <;> rfl
  have hextra (i : Fin k) : ∃ v ∈ U, ∃ t : τ, y i (j i) = coord v t := by
    refine ⟨f i (j i).1,?_,(j i).2,?_⟩
    · cases h : (j i).1 with
      | inl a =>
        exact mem_union_left _ (mem_biUnion.mpr ⟨i,mem_univ _,
          (RootedUnionDensity.mem_interiors _ _).mpr ⟨a,rfl⟩⟩)
      | inr r =>
        exact mem_union_right _ (mem_image.mpr ⟨r,mem_univ _,(hfroot i r).symm⟩)
    · simp only [f, Function.Embedding.coeFn_mk, coord_place]
  have hbound := PolynomialEdgeConstraints.independent_bound d c' U E hE hsupport
    (hec.trans hd) (fun i => y i (j i)) hextra hind
  rw [Fintype.card_fin] at hbound
  have hmul := Nat.mul_le_mul_right (Fintype.card τ) huc
  dsimp only [k] at hbound
  nlinarith

end GenericRootedFiber

end -- GenericRootedFiber

section -- UniformFiberBound

/- A compactness argument for uniform finite bounds on polynomial fibers, via field ultrapowers. -/
open Filter MvPolynomial
namespace UniformFiberBound
universe u v w

/-- Polynomial equations and finite nonvanishing clauses. A clause asserts that at
least one of its polynomials is nonzero; this includes vector disequalities. -/
def Holds {K : Type u} [Field K] {σ : Type v}
    (P : Finset (MvPolynomial σ K)) (Q : Finset (Finset (MvPolynomial σ K)))
    {L : Type*} [Field L] [Algebra K L] (x : σ → L) : Prop :=
  (∀ p ∈ P, aeval x p = 0) ∧ ∀ q ∈ Q, ∃ p ∈ q, aeval x p ≠ 0

lemma holds_germ {K : Type u} [Field K] {σ : Type v} {I : Type*}
    (P : Finset (MvPolynomial σ K)) (Q : Finset (Finset (MvPolynomial σ K)))
    (u : Ultrafilter I) (x : I → σ → K) (h : ∀ᶠ i in (u : Filter I), Holds P Q (x i)) :
    Holds P Q (fun j => ((fun i => x i j) : Germ (u : Filter I) K)) := by
  constructor
  · intro p hp
    rw [UltrafilterField.aeval_eq]
    apply Germ.coe_eq.mpr
    filter_upwards [h] with i hi
    simpa only [aeval_eq_eval] using hi.1 p hp
  · intro q hq
    by_contra hh
    push_neg at hh
    have he : ∀ᶠ i in (u : Filter I), ∀ p ∈ q, eval (x i) p = 0 := by
      apply (eventually_all_finset q).mpr
      intro p hp
      have hh' := hh p hp
      rw [UltrafilterField.aeval_eq] at hh'
      exact Germ.coe_eq.mp hh'
    obtain ⟨i,hi,he⟩ := (h.and he).exists
    obtain ⟨p,hp,hp0⟩ := hi.2 q hq
    exact hp0 (by simpa only [aeval_eq_eval] using he p hp)

/-- If every fiber stays finite in every field extension, its sizes over the original
field are uniformly bounded. No algebraic-geometry counting theorem is assumed. -/
lemma uniform_bound {K : Type u} [Field K] {ρ : Type v} {τ : Type w} [Fintype τ]
    (P : Finset (MvPolynomial (ρ ⊕ τ) K))
    (Q : Finset (Finset (MvPolynomial (ρ ⊕ τ) K)))
    (hfinite : ∀ (L : Type u) [Field L] [Algebra K L] (r : ρ → L),
      Set.Finite {x : τ → L | Holds P Q (Sum.elim r x)}) :
    ∃ N : ℕ, ∀ r : ρ → K,
      Nat.card {x : τ → K // Holds P Q (Sum.elim r x)} ≤ N := by
  classical
  by_contra hbounded
  push_neg at hbounded
  have hchoose : ∀ n : ℕ, ∃ r : ρ → K,
      Nonempty (Fin (n+1) ↪ {x : τ → K // Holds P Q (Sum.elim r x)}) := by
    intro n
    obtain ⟨r,hr⟩ := hbounded n
    letI : Fintype {x : τ → K // Holds P Q (Sum.elim r x)} := (hfinite K r).fintype
    refine ⟨r,Function.Embedding.nonempty_of_card_le ?_⟩
    simpa only [Fintype.card_fin, Nat.card_eq_fintype_card] using Nat.succ_le_of_lt hr
  choose r er using hchoose
  let e (n : ℕ) := Classical.choice (er n)
  let u : Ultrafilter ℕ := Ultrafilter.of atTop
  let L := Germ (u : Filter ℕ) K
  let root : ρ → L := fun j => ((fun n => r n j) : Germ (u : Filter ℕ) K)
  let point (j n : ℕ) : τ → K := if h : j < n+1 then (e n ⟨j,h⟩).val else fun _ => 0
  let limit (j : ℕ) : τ → L := fun t => ((fun n => point j n t) : Germ (u : Filter ℕ) K)
  have hn (j : ℕ) : ∀ᶠ n in (u : Filter ℕ), j < n+1 := by
    apply Filter.Eventually.filter_mono (Ultrafilter.of_le atTop)
    filter_upwards [eventually_ge_atTop j] with n hn
    omega
  have hpoint (j : ℕ) : ∀ᶠ n in (u : Filter ℕ), Holds P Q (Sum.elim (r n) (point j n)) := by
    filter_upwards [hn j] with n hj
    dsimp only [point]
    rw [dif_pos hj]
    exact (e n ⟨j,hj⟩).property
  have hlimit (j : ℕ) : Holds P Q (Sum.elim root (limit j)) := by
    have hh := holds_germ P Q u (fun n => Sum.elim (r n) (point j n)) (hpoint j)
    convert hh using 1
    ext t
    cases t <;> rfl
  have hinj : Function.Injective limit := by
    intro i j hij
    have he : ∀ᶠ n in (u : Filter ℕ), point i n = point j n := by
      have he' : ∀ t : τ, ∀ᶠ n in (u : Filter ℕ), point i n t = point j n t :=
        fun t => Germ.coe_eq.mp (congrFun hij t)
      exact (eventually_all.mpr he').mono (fun _ h => funext h)
    obtain ⟨n,hnij,hnj,hni⟩ := (he.and ((hn j).and (hn i))).exists
    have hval : (e n ⟨i,hni⟩).val = (e n ⟨j,hnj⟩).val := by
      simpa only [point, dif_pos hni, dif_pos hnj] using hnij
    exact congrArg Fin.val ((e n).injective (Subtype.ext hval))
  haveI : Finite {x : τ → L // Holds P Q (Sum.elim root x)} := (hfinite L root).to_subtype
  haveI : Finite ℕ := Finite.of_injective
    (fun j => (⟨limit j,hlimit j⟩ : {x : τ → L // Holds P Q (Sum.elim root x)}))
    (fun i j h => hinj (congrArg Subtype.val h))
  exact not_finite ℕ

end UniformFiberBound

end -- UniformFiberBound

section -- PolynomialCopyConstraints

/- Finite polynomial constraints describing injective copies with a fixed color pattern. -/
open Finset MvPolynomial PolynomialBipartite
namespace PolynomialCopyConstraints
universe u
variable {K : Type u} [Field K] {W τ J : Type*}
  [Fintype W] [Fintype τ] [Fintype J]

noncomputable def edgePolys (κ : W → Fin 2) (P : J → MvPolynomial (Variables τ) K)
    (u v : W) : Finset (MvPolynomial (W × τ) K) := by
  classical
  exact if κ u = κ v then {1} else
    univ.image (fun j => rename (if κ u = 0 then pairVariables u v else pairVariables v u) (P j))

noncomputable def equations (G : SimpleGraph W) (κ : W → Fin 2)
    (P : J → MvPolynomial (Variables τ) K) : Finset (MvPolynomial (W × τ) K) := by
  classical
  exact univ.biUnion (fun uv : W × W => if G.Adj uv.1 uv.2 then edgePolys κ P uv.1 uv.2 else ∅)

noncomputable def clauses (κ : W → Fin 2) : Finset (Finset (MvPolynomial (W × τ) K)) := by
  classical
  exact (univ.filter (fun uv : W × W => uv.1 ≠ uv.2 ∧ κ uv.1 = κ uv.2)).image
    (fun uv => univ.image (fun t : τ => X (uv.1,t) - X (uv.2,t)))

variable {L : Type u} [Field L] [Algebra K L]

lemma edgePolys_iff (κ : W → Fin 2) (P : J → MvPolynomial (Variables τ) K)
    (y : W × τ → L) (u v : W) :
    (∀ p ∈ edgePolys κ P u v, aeval y p = 0) ↔
      (graph (fun j => map (algebraMap K L) (P j))).Adj (place κ y u) (place κ y v) := by
  classical
  by_cases hcol : κ u = κ v
  · have hnot : ¬(graph (fun j => map (algebraMap K L) (P j))).Adj
        (place κ y u) (place κ y v) := by
      simp only [place, ← hcol]
      split_ifs <;> exact not_false
    simp [edgePolys,hcol,hnot]
  · simp only [edgePolys, if_neg hcol, forall_mem_image, mem_univ, forall_const]
    by_cases hu : κ u = 0
    · have hv : κ v ≠ 0 := fun h => hcol (hu.trans h.symm)
      simp only [if_pos hu, aeval_edge, place, if_neg hv, graph]
    · have hv : κ v = 0 := by omega
      simp only [if_neg hu, aeval_edge, place, if_pos hv, graph]

lemma equations_iff (G : SimpleGraph W) (κ : W → Fin 2)
    (P : J → MvPolynomial (Variables τ) K) (y : W × τ → L) :
    (∀ p ∈ equations G κ P, aeval y p = 0) ↔
      ∀ u v, G.Adj u v →
        (graph (fun j => map (algebraMap K L) (P j))).Adj (place κ y u) (place κ y v) := by
  classical
  constructor
  · intro h u v huv
    apply (edgePolys_iff κ P y u v).mp
    intro p hp
    apply h p
    apply mem_biUnion.mpr
    exact ⟨(u,v),mem_univ _,by simpa only [if_pos huv] using hp⟩
  · intro h p hp
    obtain ⟨⟨u,v⟩,_,hp⟩ := mem_biUnion.mp hp
    by_cases huv : G.Adj u v
    · have he : p ∈ edgePolys κ P u v := by simpa only [if_pos huv] using hp
      exact (edgePolys_iff κ P y u v).mpr (h u v huv) p he
    · simpa only [if_neg huv, Finset.notMem_empty] using hp

lemma clauses_iff (κ : W → Fin 2) (y : W × τ → L) :
    (∀ q ∈ clauses (K := K) (τ := τ) κ, ∃ p ∈ q, aeval y p ≠ 0) ↔
      Function.Injective (place κ y) := by
  classical
  simp only [clauses, forall_mem_image, mem_filter, mem_univ, true_and, Prod.forall,
    exists_mem_image, mem_univ, true_and, map_sub, aeval_X, sub_ne_zero]
  constructor
  · intro h u v huv
    by_contra hne
    have hc : κ u = κ v := by simpa only [color_place] using congrArg color huv
    obtain ⟨t,ht⟩ := h u v ⟨hne,hc⟩
    exact ht (by simpa only [coord_place] using congrFun (congrArg coord huv) t)
  · intro h u v huv
    by_contra hn
    push_neg at hn
    apply huv.1
    apply h
    apply vertex_ext
    · simpa only [color_place] using huv.2
    · funext t
      simpa only [coord_place] using hn t

lemma holds_iff (G : SimpleGraph W) (κ : W → Fin 2)
    (P : J → MvPolynomial (Variables τ) K) (y : W × τ → L) :
    UniformFiberBound.Holds (equations G κ P) (clauses κ) y ↔
      Function.Injective (place κ y) ∧
      ∀ u v, G.Adj u v →
        (graph (fun j => map (algebraMap K L) (P j))).Adj (place κ y u) (place κ y v) := by
  rw [UniformFiberBound.Holds, equations_iff, clauses_iff, and_comm]

lemma holds_rename {σ ι : Type*} [DecidableEq (MvPolynomial ι K)] (f : σ → ι)
    (P : Finset (MvPolynomial σ K)) (Q : Finset (Finset (MvPolynomial σ K))) (y : ι → L) :
    UniformFiberBound.Holds (P.image (rename f)) (Q.image (fun q => q.image (rename f))) y ↔
      UniformFiberBound.Holds P Q (y ∘ f) := by
  classical
  simp only [UniformFiberBound.Holds, forall_mem_image, exists_mem_image, aeval_rename]

end PolynomialCopyConstraints

end -- PolynomialCopyConstraints

section -- GenericUniformFiber

/- Uniform bounds for rooted fibers of generic polynomial graphs. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
  PolynomialCopyConstraints
namespace GenericUniformFiber
universe u
variable {F : Type*} {K : Type u} [Field F] [Field K] [Algebra F K]
  {A R τ J : Type*} [Fintype A] [Fintype R] [Fintype τ] [Fintype J]

def splitVariables : (A ⊕ R) × τ ≃ (R × τ) ⊕ (A × τ) :=
  (Equiv.sumProdDistrib A R τ).trans (Equiv.sumComm _ _)

def assemble {L : Type*} (r : R × τ → L) (x : A × τ → L) : (A ⊕ R) × τ → L :=
  Sum.elim r x ∘ splitVariables

lemma assemble_injective {L : Type*} (r : R × τ → L) :
    Function.Injective (assemble (A := A) r) := by
  intro x y h
  funext z
  exact congrFun h (Sum.inl z.1,z.2)

lemma uniform_bound (G : SimpleGraph (A ⊕ R)) (κ : A ⊕ R → Fin 2)
    (d : ℕ) (c : J → Exponent (Variables τ) d → K)
    (hc : AlgebraicIndependent F (fun js : J × Exponent (Variables τ) d => c js.1 js.2))
    (ha : 0 < Fintype.card J)
    (hbalance : ∀ s : Finset A,
      Fintype.card τ * s.card ≤ Fintype.card J * (RootedUnionDensity.incident G s).card)
    (hd : (Fintype.card τ * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1) :
    ∃ N : ℕ, ∀ root : R → τ → K,
      Nat.card (GenericRootedFiber.fiber G κ (fun j => polynomial d (c j)) root) ≤ N := by
  classical
  letI : DecidableEq (Finset (MvPolynomial (R × τ ⊕ A × τ) K)) := Finset.decidableEq
  let P := equations G κ (fun j => polynomial d (c j))
  let Q := clauses (K := K) (τ := τ) κ
  let P' := P.image (rename (splitVariables (A := A) (R := R) (τ := τ)))
  let Q' := Q.image (fun q => q.image (rename (splitVariables (A := A) (R := R) (τ := τ))))
  have hfinite : ∀ (L : Type u) [Field L] [Algebra K L] (root : R × τ → L),
      Set.Finite {x : A × τ → L | UniformFiberBound.Holds P' Q' (Sum.elim root x)} := by
    intro L _ _ root
    letI : Algebra F L := ((algebraMap K L).comp (algebraMap F K)).toAlgebra
    letI : IsScalarTower F K L := IsScalarTower.of_algebraMap_eq (fun _ => rfl)
    let c' : J → Exponent (Variables τ) d → L := fun j s => algebraMap K L (c j s)
    have hc' : AlgebraicIndependent F
        (fun js : J × Exponent (Variables τ) d => c' js.1 js.2) :=
      hc.map' (f := IsScalarTower.toAlgHom F K L) (algebraMap K L).injective
    have hf := GenericRootedFiber.finite_fiber G κ d c' hc' ha hbalance hd
      (fun r t => root (r,t))
    apply Set.Finite.of_injOn (f := assemble root) _ (assemble_injective root).injOn hf
    intro x hx
    have hh := (holds_rename splitVariables P Q (Sum.elim root x)).mp (by simpa only [P', Q', Set.mem_setOf_eq] using hx)
    have he := (holds_iff G κ (fun j => polynomial d (c j)) (assemble root x)).mp hh
    refine ⟨he.1,?_,fun _ _ => rfl⟩
    simpa only [GenericRootedFiber.map_polynomial] using he.2
  obtain ⟨N,hN⟩ := UniformFiberBound.uniform_bound P' Q' hfinite
  refine ⟨N,?_⟩
  intro root
  let r : R × τ → K := fun z => root z.1 z.2
  let T := {x : A × τ → K // UniformFiberBound.Holds P' Q' (Sum.elim r x)}
  let S := GenericRootedFiber.fiber G κ (fun j => polynomial d (c j)) root
  haveI : Finite T := (hfinite K r).to_subtype
  have he (z : S) : assemble r (fun t => z.val (Sum.inl t.1,t.2)) = z.val := by
    funext t
    rcases t with ⟨w,t⟩
    cases w with
    | inl a => rfl
    | inr r => exact (z.property.2.2 r t).symm
  let f : S → T := fun z => ⟨fun t => z.val (Sum.inl t.1,t.2),by
    dsimp only [P', Q']
    apply (holds_rename splitVariables P Q _).mpr
    change UniformFiberBound.Holds P Q (assemble r (fun t => z.val (Sum.inl t.1,t.2)))
    rw [he z]
    apply (holds_iff G κ (fun j => polynomial d (c j)) z.val).mpr
    refine ⟨z.property.1,?_⟩
    simpa only [Algebra.algebraMap_self, MvPolynomial.map_id] using z.property.2.1⟩
  have hf : Function.Injective f := by
    intro x y hxy
    apply Subtype.ext
    rw [← he x,← he y]
    exact congrArg (assemble r) (congrArg Subtype.val hxy)
  exact (Nat.card_le_card_of_injective f hf).trans (hN r)

end GenericUniformFiber

end -- GenericUniformFiber


section -- RootedPowers

/- Rooted powers and their relation to counts of common-root embeddings. -/
open Finset SimpleGraph
namespace RootedPowers
variable {A R V : Type*}

abbrev Vertex (A R : Type*) (t : ℕ) := (Fin t × A) ⊕ R

def graph (G : SimpleGraph (A ⊕ R)) (t : ℕ) : SimpleGraph (Vertex A R t) where
  Adj u v := match u,v with
    | Sum.inl x, Sum.inl y => x.1 = y.1 ∧ G.Adj (Sum.inl x.2) (Sum.inl y.2)
    | Sum.inl x, Sum.inr r => G.Adj (Sum.inl x.2) (Sum.inr r)
    | Sum.inr r, Sum.inl x => G.Adj (Sum.inr r) (Sum.inl x.2)
    | Sum.inr r, Sum.inr s => G.Adj (Sum.inr r) (Sum.inr s)
  symm := by
    constructor
    intro u v h
    cases u <;> cases v
    · exact ⟨h.1.symm,h.2.symm⟩
    · exact h.symm
    · exact h.symm
    · exact h.symm
  loopless := by
    constructor
    intro u h
    cases u
    · exact h.2.ne rfl
    · exact h.ne rfl

/-- One of the copies identified along the roots. -/
def layer (G : SimpleGraph (A ⊕ R)) (t : ℕ) (j : Fin t) : Copy G (graph G t) where
  toHom := {
    toFun := Sum.map (fun a => (j,a)) id
    map_rel' := by
      intro u v h
      cases u <;> cases v
      · exact ⟨rfl,h⟩
      · exact h
      · exact h
      · exact h }
  injective' := by
    intro u v h
    cases u <;> cases v <;> simp_all

/-- A smaller rooted power is a subgraph of a larger rooted power. -/
def inclusion (G : SimpleGraph (A ⊕ R)) {s t : ℕ} (h : s ≤ t) :
    Copy (graph G s) (graph G t) where
  toHom := {
    toFun := Sum.map (fun z => (Fin.castLE h z.1,z.2)) id
    map_rel' := by
      intro u v huv
      cases u <;> cases v
      · exact ⟨congrArg (Fin.castLE h) huv.1,huv.2⟩
      · exact huv
      · exact huv
      · exact huv }
  injective' := by
    intro u v huv
    cases u with
    | inl x =>
      cases v with
      | inl y =>
        have hh : (Fin.castLE h x.1,x.2) = (Fin.castLE h y.1,y.2) := Sum.inl.inj huv
        have hf : Fin.castLE h x.1 = Fin.castLE h y.1 := congrArg Prod.fst hh
        have hs : x.2 = y.2 := congrArg (fun z : Fin t × A => z.2) hh
        exact congrArg Sum.inl (Prod.ext (Fin.castLE_injective h hf) hs)
      | inr y => exact (Sum.inl_ne_inr huv).elim
    | inr x =>
      cases v with
      | inl y => exact (Sum.inr_ne_inl huv).elim
      | inr y => exact congrArg Sum.inr (Sum.inr.inj huv)

lemma graph_bipartite (G : SimpleGraph (A ⊕ R)) (hG : G.IsBipartite) (t : ℕ) :
    (graph G t).IsBipartite := by
  obtain ⟨c⟩ := hG
  refine ⟨Coloring.mk (fun v => match v with
    | Sum.inl x => c (Sum.inl x.2)
    | Sum.inr r => c (Sum.inr r)) ?_⟩
  intro u v h
  cases u <;> cases v
  · exact c.valid h.2
  · exact c.valid h
  · exact c.valid h
  · exact c.valid h

section Counting
variable [Fintype A] [Fintype R] [Fintype V] [DecidableEq V]


end Counting
end RootedPowers

end -- RootedPowers

section -- GenericPowerFree

/- A single rooted power is absent from a generic polynomial bipartite graph. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace GenericPowerFree
universe u
variable {F : Type*} {K : Type u} [Field F] [Field K] [Algebra F K]
  {A R τ J : Type*} [Fintype A] [Fintype R] [Fintype τ] [Fintype J]

lemma place_coord {W : Type*} (f : W → Vertex K τ) (w : W) :
    place (fun w => color (f w)) (fun z => coord (f z.1) z.2) w = f w := by
  apply vertex_ext
  · exact color_place _ _ _
  · exact coord_place _ _ _

lemma exists_power_free (G : SimpleGraph (A ⊕ R)) [Nonempty A]
    (d : ℕ) (c : J → Exponent (Variables τ) d → K)
    (hc : AlgebraicIndependent F (fun js : J × Exponent (Variables τ) d => c js.1 js.2))
    (ha : 0 < Fintype.card J)
    (hbalance : ∀ s : Finset A,
      Fintype.card τ * s.card ≤ Fintype.card J * (RootedUnionDensity.incident G s).card)
    (hd : (Fintype.card τ * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1) :
    ∃ t : ℕ, 0 < t ∧ (RootedPowers.graph G t).Free (graph (fun j => polynomial d (c j))) := by
  classical
  have hbound (κ : A ⊕ R → Fin 2) := GenericUniformFiber.uniform_bound G κ d c hc ha hbalance hd
  choose N hN using hbound
  let M := ∑ κ : A ⊕ R → Fin 2, N κ
  refine ⟨M+1,by omega,?_⟩
  rintro ⟨f⟩
  let g (i : Fin (M+1)) := f.comp (RootedPowers.layer G (M+1) i)
  let root : R → τ → K := fun r => coord (f (Sum.inr r))
  let Fiber (κ : A ⊕ R → Fin 2) :=
    GenericRootedFiber.fiber G κ (fun j => polynomial d (c j)) root
  letI (κ : A ⊕ R → Fin 2) : Fintype (Fiber κ) :=
    (GenericRootedFiber.finite_fiber G κ d c hc ha hbalance hd root).fintype
  let data (i : Fin (M+1)) : Σ κ, Fiber κ :=
    ⟨fun w => color (g i w), ⟨fun z => coord (g i z.1) z.2,by
      constructor
      · intro u v huv
        exact (g i).injective (by change g i u = g i v; simpa only [place_coord] using huv)
      constructor
      · intro u v huv
        simp only [place_coord]
        exact (g i).toHom.map_rel' huv
      · intro r t
        rfl⟩⟩
  have hinj : Function.Injective data := by
    intro i j hij
    let a : A := Classical.choice inferInstance
    have hh := congrArg (fun z : Σ κ, Fiber κ => place z.1 z.2.val (Sum.inl a)) hij
    simp only [data, place_coord] at hh
    have he := f.injective hh
    exact congrArg Prod.fst (Sum.inl.inj he)
  have hcard := Fintype.card_le_of_injective data hinj
  have hcard' : Fintype.card (Σ κ, Fiber κ) ≤ M := by
    rw [Fintype.card_sigma]
    apply sum_le_sum
    intro κ _
    simpa only [Nat.card_eq_fintype_card] using hN κ root
  simp only [Fintype.card_fin] at hcard
  omega

end GenericPowerFree

end -- GenericPowerFree

section -- PolynomialGerm

/- Finite polynomial graph copies pass to ultrafilter germs. -/
open Filter Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace PolynomialGerm
universe u
variable {I : Type*} {K : Type u} [Field K] (u : Ultrafilter I)

/-- The quotient homomorphism to the ring of germs. -/
def coeHom : (I → K) →+* Germ (u : Filter I) K where
  toFun f := (f : Germ (u : Filter I) K)
  map_zero' := rfl
  map_one' := rfl
  map_add' _ _ := rfl
  map_mul' _ _ := rfl

lemma eval_polynomial_germ {σ : Type*} [Fintype σ] (d : ℕ)
    (x : I → σ → K) (c : I → Exponent σ d → K) :
    eval (fun t => coeHom u (fun i => x i t))
      (polynomial d (fun s => coeHom u (fun i => c i s))) =
        coeHom u (fun i => eval (x i) (polynomial d (c i))) := by
  classical
  simp only [eval_polynomial, eval_monomial, one_mul, Finsupp.prod]
  have he : (fun i => ∑ s : Exponent σ d, (∏ t ∈ s.val.support, (x i t)^(s.val t))*c i s) =
      ∑ s : Exponent σ d, (∏ t ∈ s.val.support, (fun i => x i t)^(s.val t))*(fun i => c i s) := by
    funext i
    simp only [Finset.sum_apply, Pi.mul_apply, Finset.prod_apply, Pi.pow_apply]
  rw [he, map_sum]
  apply sum_congr rfl
  intro s _
  simp only [map_mul, map_prod, map_pow]

lemma color_ne_of_adj {τ J : Type*} (P : J → MvPolynomial (Variables τ) K)
    {x y : Vertex K τ} (h : (graph P).Adj x y) : color x ≠ color y := by
  cases x <;> cases y
  · exact h.elim
  · simp [color]
  · simp [color]
  · exact h.elim

lemma copy_germ {W τ J : Type*} [Fintype W] [Fintype τ] [Fintype J]
    (G : SimpleGraph W) (d : ℕ) (c : I → J → Exponent (Variables τ) d → K)
    (hcopy : ∀ᶠ i in (u : Filter I),
      Nonempty (G.Copy (graph (fun j => polynomial d (c i j))))) :
    Nonempty (G.Copy (graph (fun j => polynomial d (fun s => coeHom u (fun i => c i j s))))) := by
  classical
  let f (i : I) : W → Vertex K τ :=
    if h : Nonempty (G.Copy (graph (fun j => polynomial d (c i j))))
    then (fun w => (Classical.choice h).toHom w) else fun _ => Sum.inl (fun _ => 0)
  have hf : ∀ᶠ i in (u : Filter I), Function.Injective (f i) ∧
      ∀ a b, G.Adj a b → (graph (fun j => polynomial d (c i j))).Adj (f i a) (f i b) := by
    filter_upwards [hcopy] with i hi
    dsimp only [f]
    rw [dif_pos hi]
    exact ⟨(Classical.choice hi).injective,fun _ _ h => (Classical.choice hi).toHom.map_rel' h⟩
  obtain ⟨κ,hκ⟩ : ∃ κ : W → Fin 2, ∀ᶠ i in (u : Filter I), (fun w => color (f i w)) = κ :=
    Ultrafilter.eventually_exists_iff.mp (Eventually.of_forall (fun i => ⟨_,rfl⟩))
  let y : W × τ → Germ (u : Filter I) K := fun z => coeHom u (fun i => coord (f i z.1) z.2)
  have hinj : Function.Injective (place κ y) := by
    intro a b hab
    have hcol : κ a = κ b := by simpa only [color_place] using congrArg color hab
    have hcoord : ∀ᶠ i in (u : Filter I), coord (f i a) = coord (f i b) := by
      apply (eventually_all.mpr (fun t : τ => ?_)).mono (fun _ h => funext h)
      apply Germ.coe_eq.mp
      change y (a,t) = y (b,t)
      simpa only [coord_place] using congrFun (congrArg coord hab) t
    obtain ⟨i,hi,hci,hki⟩ := (hf.and (hcoord.and hκ)).exists
    apply hi.1
    apply vertex_ext
    · rw [congrFun hki a, congrFun hki b]
      exact hcol
    · exact hci
  have hproper (a b : W) (hab : G.Adj a b) : κ a ≠ κ b := by
    obtain ⟨i,hi,hki⟩ := (hf.and hκ).exists
    have hh := color_ne_of_adj _ (hi.2 a b hab)
    simpa only [congrFun hki a, congrFun hki b] using hh
  refine ⟨{ toHom := { toFun := place κ y, map_rel' := ?_ }, injective' := hinj }⟩
  intro a b hab
  have hp := hproper a b hab
  have hplace : ∀ᶠ i in (u : Filter I), ∀ w,
      place κ (fun z => coord (f i z.1) z.2) w = f i w := by
    filter_upwards [hκ] with i hi w
    rw [← hi]
    exact GenericPowerFree.place_coord (f i) w
  have hadj : ∀ᶠ i in (u : Filter I),
      (graph (fun j => polynomial d (c i j))).Adj
        (place κ (fun z => coord (f i z.1) z.2) a)
        (place κ (fun z => coord (f i z.1) z.2) b) := by
    filter_upwards [hf,hplace] with i hi hpi
    rw [hpi a,hpi b]
    exact hi.2 a b hab
  by_cases ha : κ a = 0
  · have hb : κ b ≠ 0 := fun h => hp (ha.trans h.symm)
    simp only [place, if_pos ha, if_neg hb, graph] at hadj ⊢
    intro j
    have he := eval_polynomial_germ u d
      (fun i => Sum.elim (coord (f i a)) (coord (f i b))) (fun i => c i j)
    have hcoords : (fun t => coeHom u (fun i =>
        Sum.elim (coord (f i a)) (coord (f i b)) t)) =
        Sum.elim (fun t => y (a,t)) (fun t => y (b,t)) := by
      funext t; cases t <;> rfl
    rw [hcoords] at he
    rw [he]
    exact Germ.coe_eq.mpr (hadj.mono (fun i hi => hi j))
  · have hb : κ b = 0 := by omega
    simp only [place, if_neg ha, if_pos hb, graph] at hadj ⊢
    intro j
    have he := eval_polynomial_germ u d
      (fun i => Sum.elim (coord (f i b)) (coord (f i a))) (fun i => c i j)
    have hcoords : (fun t => coeHom u (fun i =>
        Sum.elim (coord (f i b)) (coord (f i a)) t)) =
        Sum.elim (fun t => y (b,t)) (fun t => y (a,t)) := by
      funext t; cases t <;> rfl
    rw [hcoords] at he
    rw [he]
    exact Germ.coe_eq.mpr (hadj.mono (fun i hi => hi j))

end PolynomialGerm

end -- PolynomialGerm

section -- GenericObstruction

/- Compactness turns generic power-freeness into a finite coefficient obstruction. -/
open Filter Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace GenericObstruction
universe u v
variable {F : Type u} {K : Type v} [Field F] [Field K] [Algebra F K]
  {A R τ J : Type*} [Fintype A] [Fintype R] [Fintype τ] [Fintype J]

/-- Some rooted power is excluded as soon as finitely many nonzero coefficient
polynomials remain nonzero. The proof is a compactness argument over `K`. -/
lemma finite_obstruction (G : SimpleGraph (A ⊕ R)) [Nonempty A]
    (d : ℕ) (ha : 0 < Fintype.card J)
    (hbalance : ∀ s : Finset A,
      Fintype.card τ * s.card ≤ Fintype.card J * (RootedUnionDensity.incident G s).card)
    (hd : (Fintype.card τ * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1) :
    ∃ t : ℕ, ∃ P : Finset {p : MvPolynomial (J × Exponent (Variables τ) d) F // p ≠ 0},
      ∀ c : J × Exponent (Variables τ) d → K,
        (∀ p ∈ P, aeval c p.val ≠ 0) →
          (RootedPowers.graph G t).Free (graph (fun j => polynomial d (fun s => c (j,s)))) := by
  classical
  by_contra hn
  push_neg at hn
  let C := J × Exponent (Variables τ) d
  let NonzeroPoly := {p : MvPolynomial C F // p ≠ 0}
  let I := ℕ × Finset NonzeroPoly
  have hre (i : I) : ∃ c : C → K, (∀ p ∈ i.2, aeval c p.val ≠ 0) ∧
      Nonempty ((RootedPowers.graph G i.1).Copy (graph (fun j => polynomial d (fun s => c (j,s))))) := by
    obtain ⟨c,hc,hh⟩ := hn i.1 i.2
    exact ⟨c,hc,hh⟩
  choose c hc hcopy using hre
  let u : Ultrafilter I := Ultrafilter.of atTop
  let L := Germ (u : Filter I) K
  letI : Algebra F L := ((algebraMap K L).comp (algebraMap F K)).toAlgebra
  letI : SMul K L := (inferInstance : Algebra K L).toSMul
  letI : SMul F L := (inferInstance : Algebra F L).toSMul
  letI : IsScalarTower F K L := IsScalarTower.of_algebraMap_eq (fun _ => rfl)
  let cg : C → L := fun s => PolynomialGerm.coeHom u (fun i => c i s)
  have heval (p : MvPolynomial C F) : aeval cg p =
      PolynomialGerm.coeHom u (fun i => aeval (c i) p) := by
    induction p using MvPolynomial.induction_on with
    | C r => simp only [aeval_C]; rfl
    | add p q hp hq =>
      simp only [map_add, hp, hq]
      rfl
    | mul_X p s hp =>
      simp only [map_mul, hp, aeval_X]
      rfl
  have hind : AlgebraicIndependent F cg := by
    apply algebraicIndependent_iff.mpr
    intro p hp
    by_contra hp0
    have hh : ∀ᶠ i in (u : Filter I), aeval (c i) p ≠ 0 := by
      have he : ∀ᶠ i : I in atTop, (0,({⟨p,hp0⟩} : Finset NonzeroPoly)) ≤ i :=
        eventually_ge_atTop _
      filter_upwards [he.filter_mono (Ultrafilter.of_le atTop)] with i hi
      exact hc i ⟨p,hp0⟩ (hi.2 (mem_singleton_self _))
    rw [heval] at hp
    obtain ⟨i,hi,hzi⟩ := (hh.and (Germ.coe_eq.mp hp)).exists
    exact hi hzi
  obtain ⟨t,ht,hfree⟩ := GenericPowerFree.exists_power_free G d
    (fun j s => cg (j,s)) hind ha hbalance hd
  have hcontains : ∀ᶠ i in (u : Filter I),
      Nonempty ((RootedPowers.graph G t).Copy (graph (fun j => polynomial d (fun s => c i (j,s))))) := by
    have he : ∀ᶠ i : I in atTop, (t,(∅ : Finset NonzeroPoly)) ≤ i := eventually_ge_atTop _
    filter_upwards [he.filter_mono (Ultrafilter.of_le atTop)] with i hi
    exact ⟨(Classical.choice (hcopy i)).comp (RootedPowers.inclusion G hi.1)⟩
  exact hfree (PolynomialGerm.copy_germ u (RootedPowers.graph G t) d
    (fun i j s => c i (j,s)) hcontains)

lemma single_obstruction (G : SimpleGraph (A ⊕ R)) [Nonempty A]
    (d : ℕ) (ha : 0 < Fintype.card J)
    (hbalance : ∀ s : Finset A,
      Fintype.card τ * s.card ≤ Fintype.card J * (RootedUnionDensity.incident G s).card)
    (hd : (Fintype.card τ * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1) :
    ∃ t : ℕ, 0 < t ∧ ∃ Q : MvPolynomial (J × Exponent (Variables τ) d) F,
      Q ≠ 0 ∧ ∀ c : J × Exponent (Variables τ) d → K, aeval c Q ≠ 0 →
        (RootedPowers.graph G t).Free (graph (fun j => polynomial d (fun s => c (j,s)))) := by
  classical
  obtain ⟨t,P,hP⟩ := finite_obstruction (F := F) (K := K) G d ha hbalance hd
  refine ⟨t+1,by omega,∏ p ∈ P, p.val,prod_ne_zero_iff.mpr (fun p _ => p.property),?_⟩
  intro c hc hcopy
  apply hP c _
  · exact ⟨(Classical.choice hcopy).comp (RootedPowers.inclusion G (Nat.le_succ t))⟩
  · rw [map_prod] at hc
    exact prod_ne_zero_iff.mp hc

end GenericObstruction

end -- GenericObstruction

section -- RandomPolynomialGraph

/- Bipartite random polynomial graphs and their exact bounded edge-independence. -/
open Finset SimpleGraph MvPolynomial
namespace RandomPolynomialGraph

variable (F : Type*) [Field F] [Fintype F] [DecidableEq F] (b : ℕ)
abbrev Point := Fin b → F
abbrev Vertex := Point F b ⊕ Point F b
abbrev Variables := Fin b ⊕ Fin b
abbrev Sample (a d : ℕ) := Fin a → restrictTotalDegree (Variables b) F d

variable {F b}
def potentialEdge (xy : Point F b × Point F b) : Sym2 (Vertex F b) :=
  s(Sum.inl xy.1, Sum.inr xy.2)

lemma potentialEdge_injective : Function.Injective (potentialEdge (F := F) (b := b)) := by
  intro x y h
  apply Prod.ext_iff.mpr
  simpa only [potentialEdge, Sym2.eq_iff, Sum.inl.injEq, Sum.inr.injEq,
    Sum.inl_ne_inr, Sum.inr_ne_inl, and_self, or_false, Prod.mk.injEq] using h

lemma potentialEdge_not_diag (xy : Point F b × Point F b) : ¬ (potentialEdge xy).IsDiag := by
  simp [potentialEdge, Sym2.isDiag_iff_proj_eq]

noncomputable def sampleEdges {a d : ℕ} (p : Sample F b a d) : Finset (Sym2 (Vertex F b)) :=
  (univ.filter (fun xy : Point F b × Point F b =>
    ∀ j, eval (Sum.elim xy.1 xy.2) (p j).val = 0)).image potentialEdge

lemma mem_sampleEdges {a d : ℕ} (p : Sample F b a d) (xy : Point F b × Point F b) :
    potentialEdge xy ∈ sampleEdges p ↔ ∀ j, eval (Sum.elim xy.1 xy.2) (p j).val = 0 := by
  classical
  rw [sampleEdges, mem_image]
  constructor
  · rintro ⟨z,hz,hze⟩
    have hzxy := potentialEdge_injective hze
    subst z
    exact (mem_filter.mp hz).2
  · intro h
    exact ⟨xy,mem_filter.mpr ⟨mem_univ _,h⟩,rfl⟩

lemma sampleEdges_subset {a d : ℕ} (p : Sample F b a d) :
    sampleEdges p ⊆ univ.image potentialEdge := image_subset_image (filter_subset _ _)

lemma coordinate_injective : Function.Injective (fun xy : Point F b × Point F b =>
    (Sum.elim xy.1 xy.2 : Variables b → F)) := by
  intro x y h
  apply Prod.ext <;> funext i
  · exact congrFun h (Sum.inl i)
  · exact congrFun h (Sum.inr i)

/-- Encode a supported edge set by distinct points at which the defining polynomials are evaluated. -/
lemma edge_coordinates (E : Finset (Sym2 (Vertex F b)))
    (hE : E ⊆ univ.image potentialEdge) :
    ∃ x : E ↪ (Variables b → F), ∀ a d (p : Sample F b a d),
      E ⊆ sampleEdges p ↔ ∀ j i, eval (x i) (p j).val = 0 := by
  classical
  have hp : ∀ e : E, ∃ xy, potentialEdge xy = e.val := by
    intro e
    obtain ⟨xy,_,hxy⟩ := mem_image.mp (hE e.property)
    exact ⟨xy,hxy⟩
  choose xy hxy using hp
  let x : E ↪ (Variables b → F) := {
    toFun := fun e => Sum.elim (xy e).1 (xy e).2
    inj' := by
      intro e f h
      apply Subtype.ext
      have hpair := coordinate_injective h
      rw [← hxy e, ← hxy f, hpair] }
  refine ⟨x,?_⟩
  intro a d p
  constructor
  · intro h j i
    have hi := h i.property
    rw [← hxy i, mem_sampleEdges] at hi
    exact hi j
  · intro h e he
    let i : E := ⟨e,he⟩
    rw [← show potentialEdge (xy i) = e from hxy i, mem_sampleEdges]
    exact fun j => h j i

/-- A fixed set of at most `d+1` potential edges is present with probability `|F|^(-a|E|)`. -/
lemma edge_probability {a d : ℕ} (E : Finset (Sym2 (Vertex F b)))
    (hE : E ⊆ univ.image potentialEdge) (hd : E.card ≤ d+1) :
    (Nat.card {p : Sample F b a d // E ⊆ sampleEdges p} : ℚ) /
      Fintype.card (Sample F b a d) = 1/(Fintype.card F : ℚ)^(a*E.card) := by
  classical
  obtain ⟨x,hx⟩ := edge_coordinates E hE
  have heq : Nat.card {p : Sample F b a d // E ⊆ sampleEdges p} =
      Nat.card {p : Sample F b a d // ∀ j i, eval (x i) (p j).val = 0} :=
    Nat.card_congr (Equiv.subtypeEquivRight (hx a d))
  rw [heq]
  simpa only [Fintype.card_coe, Pi.zero_apply, Sample] using PolynomialSampling.system_probability a d x
    x.injective (by simpa only [Fintype.card_coe] using hd) 0


lemma uniform_event {Ω : Type*} [Fintype Ω] (P : Ω → Prop) [DecidablePred P] :
    (∑ ω, (1 : ℚ)/Fintype.card Ω * if P ω then 1 else 0) =
      (Nat.card {ω // P ω} : ℚ) / Fintype.card Ω := by
  classical
  simp only [mul_ite, mul_one, mul_zero, ← sum_filter, sum_const, nsmul_eq_mul,
    Nat.card_eq_fintype_card, Fintype.card_subtype]
  rw [mul_one_div]


noncomputable def graph {a d : ℕ} (p : Sample F b a d) : SimpleGraph (Vertex F b) :=
  fromEdgeSet (↑(sampleEdges p))

noncomputable instance {a d : ℕ} (p : Sample F b a d) : DecidableRel (graph p).Adj :=
  Classical.decRel _

lemma graph_edges {a d : ℕ} (p : Sample F b a d) : (graph p).edgeFinset = sampleEdges p := by
  classical
  apply Finset.coe_injective
  rw [coe_edgeFinset, graph, edgeSet_fromEdgeSet]
  ext e
  change (e ∈ sampleEdges p ∧ e ∉ Sym2.diagSet) ↔ e ∈ sampleEdges p
  constructor
  · exact And.left
  · intro he
    refine ⟨he,?_⟩
    obtain ⟨xy,_,rfl⟩ := mem_image.mp (sampleEdges_subset p he)
    simpa using potentialEdge_not_diag xy


lemma single_edge_probability (a d : ℕ) (xy : Point F b × Point F b) :
    (∑ p : Sample F b a d, (1 : ℚ)/Fintype.card (Sample F b a d) *
      if ∀ j, eval (Sum.elim xy.1 xy.2) (p j).val = 0 then 1 else 0) =
        1/(Fintype.card F : ℚ)^a := by
  classical
  have h := edge_probability (a := a) (d := d) {potentialEdge xy}
    (singleton_subset_iff.mpr (mem_image.mpr ⟨xy,mem_univ _,rfl⟩)) (by simp)
  simp only [card_singleton, mul_one] at h
  rw [uniform_event]
  convert h using 2
  apply congrArg (fun n : ℕ => (n : ℚ))
  apply Nat.card_congr
  exact Equiv.subtypeEquivRight (fun p => (singleton_subset_iff.trans (mem_sampleEdges p xy)).symm)


end RandomPolynomialGraph

end -- RandomPolynomialGraph

section -- FiniteVariance

/- Elementary second-moment estimates for finite uniform samples. -/
open Finset
namespace FiniteVariance
variable {Ω E : Type*} [Fintype Ω] [Nonempty Ω] [Fintype E]

noncomputable def avg (X : Ω → ℚ) : ℚ :=
  ∑ ω, (1 : ℚ) / Fintype.card Ω * X ω

lemma avg_const (c : ℚ) : avg (fun _ : Ω => c) = c := by
  have h : (Fintype.card Ω : ℚ) ≠ 0 := by exact_mod_cast Fintype.card_ne_zero
  simp only [avg, sum_const, card_univ, nsmul_eq_mul]
  field_simp

lemma avg_add (X Y : Ω → ℚ) : avg (fun ω => X ω + Y ω) = avg X + avg Y := by
  simp only [avg, mul_add, sum_add_distrib]

lemma avg_sub (X Y : Ω → ℚ) : avg (fun ω => X ω - Y ω) = avg X - avg Y := by
  simp only [avg, mul_sub, sum_sub_distrib]

lemma avg_mul (c : ℚ) (X : Ω → ℚ) : avg (fun ω => c * X ω) = c * avg X := by
  simp only [avg, mul_left_comm _ c, mul_sum]

lemma avg_sum {I : Type*} [Fintype I] (X : Ω → I → ℚ) :
    avg (fun ω => ∑ i, X ω i) = ∑ i, avg (fun ω => X ω i) := by
  simp only [avg, mul_sum]
  exact sum_comm

lemma avg_mono {X Y : Ω → ℚ} (h : ∀ ω, X ω ≤ Y ω) : avg X ≤ avg Y :=
  sum_le_sum (fun ω _ => mul_le_mul_of_nonneg_left (h ω) (by positivity))

lemma avg_indicator (B : Ω → Prop) [DecidablePred B] :
    avg (fun ω => if B ω then 1 else 0) =
      (Nat.card {ω // B ω} : ℚ) / Fintype.card Ω := by
  classical
  simp only [avg, mul_ite, mul_one, mul_zero, ← sum_filter, sum_const, nsmul_eq_mul,
    Nat.card_eq_fintype_card, Fintype.card_subtype]
  rw [mul_one_div]

/-- Pairwise-independent Bernoulli events have second moment at most `μ²+μ`. -/
lemma indicator_moments (B : Ω → E → Prop) [DecidableRel B] (p : ℚ)
    (hfirst : ∀ e, avg (fun ω => if B ω e then 1 else 0) = p)
    (hsecond : ∀ e f, e ≠ f →
      avg (fun ω => if B ω e ∧ B ω f then 1 else 0) = p^2) :
    avg (fun ω => ∑ e, if B ω e then 1 else 0) = Fintype.card E * p ∧
    avg (fun ω => (∑ e, if B ω e then 1 else 0)^2) ≤
      (Fintype.card E * p)^2 + Fintype.card E * p := by
  classical
  constructor
  · rw [avg_sum]
    simp only [hfirst, sum_const, card_univ, nsmul_eq_mul]
  · have hexpand (ω : Ω) : (∑ e, if B ω e then (1 : ℚ) else 0)^2 =
        ∑ e, ∑ f, if B ω e ∧ B ω f then (1 : ℚ) else 0 := by
      rw [pow_two, sum_mul_sum]
      apply sum_congr rfl
      intro e _
      apply sum_congr rfl
      intro f _
      by_cases he : B ω e <;> by_cases hf : B ω f <;> simp [he,hf]
    simp_rw [hexpand, avg_sum]
    calc
      _ ≤ ∑ e : E, ∑ f : E, (p^2 + if e = f then p else 0) := by
        apply sum_le_sum
        intro e _
        apply sum_le_sum
        intro f _
        by_cases hef : e = f
        · subst f
          simp only [and_self, hfirst, if_true]
          nlinarith [sq_nonneg p]
        · rw [hsecond e f hef, if_neg hef, add_zero]
      _ = _ := by
        simp only [sum_add_distrib, sum_const, sum_ite_eq, mem_univ, if_true,
          card_univ, nsmul_eq_mul]
        ring

/-- A small exceptional set cannot contain all samples with at least half the
mean, when the variance is at most the mean and the mean is larger than eight. -/
lemma exists_dense_outside (X : Ω → ℚ) (B : Ω → Prop) [DecidablePred B] (μ : ℚ)
    (hμ : 8 < μ) (hmean : avg X = μ)
    (hsecond : avg (fun ω => (X ω)^2) ≤ μ^2 + μ)
    (hbad : avg (fun ω => if B ω then 1 else 0) < 1/2) :
    ∃ ω, ¬ B ω ∧ μ ≤ 2 * X ω := by
  classical
  by_contra hn
  push_neg at hn
  have hvar : avg (fun ω => (X ω - μ)^2) ≤ μ := by
    have he : (fun ω => (X ω - μ)^2) =
        (fun ω => (X ω)^2 - (2*μ)*X ω + μ^2) := by funext ω; ring
    rw [he, avg_add, avg_sub, avg_mul, avg_const, hmean]
    linarith
  have hpoint (ω : Ω) : μ^2/4 ≤ μ^2/4 * (if B ω then 1 else 0) + (X ω - μ)^2 := by
    by_cases hB : B ω
    · rw [if_pos hB, mul_one]
      nlinarith [sq_nonneg (X ω - μ)]
    · rw [if_neg hB, mul_zero, zero_add]
      have hh := hn ω hB
      have hm : 0 < μ := by linarith
      nlinarith [sq_nonneg (X ω), sq_nonneg (μ/2-X ω)]
  have hh := avg_mono hpoint
  rw [avg_const, avg_add, avg_mul] at hh
  have hp : 0 < μ^2/4 := by positivity
  have hbad' := mul_lt_mul_of_pos_left hbad hp
  nlinarith

end FiniteVariance

end -- FiniteVariance

section -- PolynomialEdgeVariance

/- Pairwise independence and edge-count concentration for random polynomial graphs. -/
open Finset SimpleGraph MvPolynomial RandomPolynomialGraph
namespace PolynomialEdgeVariance
variable {F : Type*} [Field F] [Fintype F] [DecidableEq F] {a b d : ℕ}

lemma pair_probability (hd : 1 ≤ d) (x y : Point F b × Point F b) (hxy : x ≠ y) :
    FiniteVariance.avg (fun p : Sample F b a d =>
      if (∀ j, eval (Sum.elim x.1 x.2) (p j).val = 0) ∧
        (∀ j, eval (Sum.elim y.1 y.2) (p j).val = 0) then 1 else 0) =
      (1/(Fintype.card F : ℚ)^a)^2 := by
  classical
  have he : potentialEdge x ≠ potentialEdge y := fun h => hxy (potentialEdge_injective h)
  have hh := edge_probability (a := a) (d := d) {potentialEdge x,potentialEdge y}
    (by intro e he; simp only [mem_insert, mem_singleton] at he
        rcases he with rfl | rfl <;> exact mem_image.mpr ⟨_,mem_univ _,rfl⟩)
    (by simp only [card_pair he]; omega)
  simp only [card_pair he] at hh
  rw [FiniteVariance.avg_indicator]
  have hcard : Nat.card {p : Sample F b a d //
      (∀ j, eval (Sum.elim x.1 x.2) (p j).val = 0) ∧
      (∀ j, eval (Sum.elim y.1 y.2) (p j).val = 0)} =
      Nat.card {p : Sample F b a d // {potentialEdge x,potentialEdge y} ⊆ sampleEdges p} := by
    apply Nat.card_congr
    exact Equiv.subtypeEquivRight (fun p => by
      simp only [insert_subset_iff, singleton_subset_iff, mem_sampleEdges])
  rw [hcard, hh, one_div_pow, ← pow_mul]

lemma edge_moments (hd : 1 ≤ d) :
    FiniteVariance.avg (fun p : Sample F b a d => ((graph p).edgeFinset.card : ℚ)) =
      (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a ∧
    FiniteVariance.avg (fun p : Sample F b a d => ((graph p).edgeFinset.card : ℚ)^2) ≤
      ((Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a)^2 +
        (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a := by
  classical
  have hc (p : Sample F b a d) : ((graph p).edgeFinset.card : ℚ) =
      ∑ xy : Point F b × Point F b,
        if ∀ j, eval (Sum.elim xy.1 xy.2) (p j).val = 0 then (1 : ℚ) else 0 := by
    rw [graph_edges, sampleEdges, card_image_of_injective _ potentialEdge_injective]
    simp only [card_filter, Nat.cast_sum, Nat.cast_ite, Nat.cast_one, Nat.cast_zero]
  have hh := FiniteVariance.indicator_moments
    (fun (p : Sample F b a d) (xy : Point F b × Point F b) =>
      ∀ j, eval (Sum.elim xy.1 xy.2) (p j).val = 0)
    (1/(Fintype.card F : ℚ)^a) (single_edge_probability a d)
    (fun x y hxy => pair_probability hd x y hxy)
  have hμ : (Fintype.card (Point F b × Point F b) : ℚ) *
      (1/(Fintype.card F : ℚ)^a) =
      (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a := by
    simp only [Fintype.card_prod, Point, Fintype.card_fun, Fintype.card_fin,
      Nat.cast_mul, Nat.cast_pow, mul_one_div]
    rw [← pow_add]
    congr 2
    omega
  simpa only [← hc, hμ] using hh

end PolynomialEdgeVariance

end -- PolynomialEdgeVariance

section -- SchwartzZippelFinite

/- A finite-field Schwartz-Zippel bound for any finite variable type. -/
open Finset MvPolynomial
namespace SchwartzZippelFinite
variable {K σ : Type*} [Field K] [Fintype K] [Fintype σ] [DecidableEq K] [DecidableEq σ]

lemma avg_equiv {Ω Ω' : Type*} [Fintype Ω] [Fintype Ω'] [Nonempty Ω] [Nonempty Ω']
    (e : Ω ≃ Ω') (X : Ω' → ℚ) : FiniteVariance.avg (X ∘ e) = FiniteVariance.avg X := by
  unfold FiniteVariance.avg
  rw [Fintype.card_congr e]
  exact Equiv.sum_comp e (fun ω => (1 : ℚ) / Fintype.card Ω' * X ω)

lemma probability_le (p : MvPolynomial σ K) (hp : p ≠ 0) :
    FiniteVariance.avg (fun x : σ → K => if eval x p = 0 then 1 else 0) ≤
      (p.totalDegree : ℚ) / Fintype.card K := by
  classical
  let e := Fintype.equivFin σ
  let q := rename e p
  have hq : q ≠ 0 := by
    intro hq0
    apply hp
    apply rename_injective e e.injective
    simpa only [map_zero] using hq0
  let f : (Fin (Fintype.card σ) → K) ≃ (σ → K) := {
    toFun := fun x => x ∘ e
    invFun := fun x => x ∘ e.symm
    left_inv := by intro x; funext i; simp
    right_inv := by intro x; funext i; simp }
  have he (x : Fin (Fintype.card σ) → K) : eval (f x) p = eval x q := by
    rw [eval_rename]
    rfl
  rw [← avg_equiv f]
  simp only [Function.comp_def]
  rw [FiniteVariance.avg_indicator]
  have hc : Nat.card {x : Fin (Fintype.card σ) → K // eval (f x) p = 0} =
      (univ.filter (fun x : Fin (Fintype.card σ) → K => eval x q = 0)).card := by
    simp only [Nat.card_eq_fintype_card, Fintype.card_subtype, he]
  rw [hc, Fintype.card_fun, Fintype.card_fin, Nat.cast_pow]
  have hz := schwartz_zippel_totalDegree hq (univ : Finset K)
  have hz' : ((univ.filter (fun x : Fin (Fintype.card σ) → K => eval x q = 0)).card : ℚ) /
      (Fintype.card K : ℚ)^Fintype.card σ ≤ (q.totalDegree : ℚ) / Fintype.card K := by
    exact_mod_cast hz
  exact hz'.trans (div_le_div_of_nonneg_right (by exact_mod_cast totalDegree_rename_le e p) (by positivity))

end SchwartzZippelFinite

end -- SchwartzZippelFinite

section -- DenseGenericSamples

/- Dense polynomial graphs whose coefficients avoid a prescribed proper hypersurface. -/
open Finset MvPolynomial BoundedPolynomialCoefficients
namespace DenseGenericSamples
variable {F : Type*} [Field F] [Fintype F] [DecidableEq F] {a b d : ℕ}

abbrev CoeffIndex (a b d : ℕ) := Fin a × Exponent (RandomPolynomialGraph.Variables b) d

noncomputable def sampleEquiv (a b d : ℕ) :
    (CoeffIndex a b d → F) ≃ RandomPolynomialGraph.Sample F b a d where
  toFun c j := coefficientEquiv d (fun s => c (j,s))
  invFun p js := coeff js.2.val (p js.1).val
  left_inv c := by
    funext js
    exact coeff_polynomial d (fun s => c (js.1,s)) js.2
  right_inv p := by
    funext j
    exact Subtype.ext (polynomial_coefficients d (p j))

lemma graph_eq (p : RandomPolynomialGraph.Sample F b a d) :
    RandomPolynomialGraph.graph p = PolynomialBipartite.graph (fun j => (p j).val) := by
  classical
  ext u v
  change (s(u,v) ∈ (RandomPolynomialGraph.graph p).edgeSet) ↔ _
  rw [← SimpleGraph.mem_edgeFinset, RandomPolynomialGraph.graph_edges]
  cases u with
  | inl x =>
    cases v with
    | inl y =>
      constructor
      · intro he
        obtain ⟨z,_,hz⟩ := mem_image.mp (RandomPolynomialGraph.sampleEdges_subset p he)
        simp only [RandomPolynomialGraph.potentialEdge, Sym2.eq_iff, Sum.inr_ne_inl,
          and_false, false_and, or_self] at hz
      · exact False.elim
    | inr y => exact RandomPolynomialGraph.mem_sampleEdges p (x,y)
  | inr y =>
    cases v with
    | inl x =>
      rw [Sym2.eq_swap]
      exact RandomPolynomialGraph.mem_sampleEdges p (x,y)
    | inr z =>
      constructor
      · intro he
        obtain ⟨z,_,hz⟩ := mem_image.mp (RandomPolynomialGraph.sampleEdges_subset p he)
        simp only [RandomPolynomialGraph.potentialEdge, Sym2.eq_iff, Sum.inl_ne_inr,
          false_and, and_false, or_self] at hz
      · exact False.elim

lemma exists_dense_avoiding (hd : 1 ≤ d)
    (P : MvPolynomial (CoeffIndex a b d) F) (hP : P ≠ 0)
    (hμ : 8 < (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a)
    (hdegree : 2 * P.totalDegree < Fintype.card F) :
    ∃ c : CoeffIndex a b d → F, eval c P ≠ 0 ∧
      Fintype.card F ^ (2*b) ≤ 2 * Fintype.card F ^ a *
        Nat.card (PolynomialBipartite.graph (fun j => polynomial d (fun s => c (j,s)))).edgeSet := by
  classical
  let e := sampleEquiv (F := F) a b d
  let X (c : CoeffIndex a b d → F) : ℚ :=
    ((RandomPolynomialGraph.graph (e c)).edgeFinset.card : ℚ)
  let μ : ℚ := (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a
  have hm := PolynomialEdgeVariance.edge_moments (F := F) (a := a) (b := b) hd
  have hmean : FiniteVariance.avg X = μ := by
    rw [show X = (fun p => ((RandomPolynomialGraph.graph p).edgeFinset.card : ℚ)) ∘ e from rfl,
      SchwartzZippelFinite.avg_equiv e]
    exact hm.1
  have hsecond : FiniteVariance.avg (fun c => (X c)^2) ≤ μ^2 + μ := by
    rw [show (fun c => (X c)^2) =
      (fun p => ((RandomPolynomialGraph.graph p).edgeFinset.card : ℚ)^2) ∘ e from rfl,
      SchwartzZippelFinite.avg_equiv e]
    exact hm.2
  have hq : (0 : ℚ) < Fintype.card F := by exact_mod_cast Fintype.card_pos
  have hbad : FiniteVariance.avg (fun c : CoeffIndex a b d → F =>
      if eval c P = 0 then 1 else 0) < 1/2 := by
    apply (SchwartzZippelFinite.probability_le P hP).trans_lt
    apply (div_lt_iff₀ hq).mpr
    have hh : (2 : ℚ) * P.totalDegree < Fintype.card F := by exact_mod_cast hdegree
    linarith
  obtain ⟨c,hc,hden⟩ := FiniteVariance.exists_dense_outside X (fun c => eval c P = 0)
    μ hμ hmean hsecond hbad
  refine ⟨c,hc,?_⟩
  have hd' := (div_le_iff₀ (pow_pos hq a)).mp hden
  have hgraph : RandomPolynomialGraph.graph (e c) =
      PolynomialBipartite.graph (fun j => polynomial d (fun s => c (j,s))) := graph_eq (e c)
  have hcard : (RandomPolynomialGraph.graph (e c)).edgeFinset.card =
      Nat.card (PolynomialBipartite.graph (fun j => polynomial d (fun s => c (j,s)))).edgeSet := by
    rw [SimpleGraph.edgeFinset_card, ← Nat.card_eq_fintype_card, hgraph]
  change (Fintype.card F : ℚ)^(2*b) ≤ 2*X c*(Fintype.card F : ℚ)^a at hd'
  dsimp only [X] at hd'
  rw [hcard] at hd'
  have hh : (Fintype.card F : ℚ)^(2*b) ≤
      2*(Fintype.card F : ℚ)^a *
        Nat.card (PolynomialBipartite.graph (fun j => polynomial d (fun s => c (j,s)))).edgeSet := by
    nlinarith only [hd']
  exact_mod_cast hh

lemma mean_large (hb : 0 < b) (ha : a ≤ b) (hq : 8 < Fintype.card F) :
    8 < (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a := by
  have hq0 : (0 : ℚ) < Fintype.card F := by exact_mod_cast Fintype.card_pos
  have hq1 : (1 : ℚ) ≤ Fintype.card F := by exact_mod_cast (by omega : 1 ≤ Fintype.card F)
  have hp := pow_le_pow_right₀ hq1 (by omega : a+1 ≤ 2*b)
  rw [pow_succ] at hp
  have hh : (Fintype.card F : ℚ) ≤
      (Fintype.card F : ℚ)^(2*b)/(Fintype.card F : ℚ)^a := by
    apply (le_div_iff₀ (pow_pos hq0 a)).mpr
    simpa only [mul_comm] using hp
  exact lt_of_lt_of_le (by exact_mod_cast hq) hh

end DenseGenericSamples

end -- DenseGenericSamples

section -- PolynomialFieldEmbedding

/- Field embeddings induce injective copies of polynomial bipartite graphs. -/
open MvPolynomial PolynomialBipartite
namespace PolynomialFieldEmbedding
variable {K L τ J : Type*} [Field K] [Field L]

def vertexMap (f : K →+* L) : Vertex K τ → Vertex L τ :=
  Sum.map (fun x => f ∘ x) (fun x => f ∘ x)

lemma vertexMap_injective (f : K →+* L) : Function.Injective (vertexMap (τ := τ) f) := by
  apply Sum.map_injective.mpr
  constructor
  · intro x y h; funext t; exact f.injective (congrFun h t)
  · intro x y h; funext t; exact f.injective (congrFun h t)

lemma map_eval_pair (f : K →+* L) (x y : τ → K) (P : MvPolynomial (Variables τ) K) :
    eval (Sum.elim (f ∘ x) (f ∘ y)) (map f P) = f (eval (Sum.elim x y) P) := by
  rw [MvPolynomial.map_eval]
  have hh : f ∘ Sum.elim x y = Sum.elim (f ∘ x) (f ∘ y) := by
    funext t; cases t <;> rfl
  rw [hh]

def copy (f : K →+* L) (P : J → MvPolynomial (Variables τ) K) :
    SimpleGraph.Copy (graph P) (graph (fun j => map f (P j))) where
  toHom := {
    toFun := vertexMap f
    map_rel' := by
      intro u v huv
      cases u with
      | inl x =>
        cases v with
        | inl y => exact huv.elim
        | inr y =>
          intro j
          change eval (Sum.elim (f ∘ x) (f ∘ y)) (map f (P j)) = 0
          rw [map_eval_pair,huv j,map_zero]
      | inr y =>
        cases v with
        | inl x =>
          intro j
          change eval (Sum.elim (f ∘ x) (f ∘ y)) (map f (P j)) = 0
          rw [map_eval_pair,huv j,map_zero]
        | inr z => exact huv.elim }
  injective' := vertexMap_injective f

end PolynomialFieldEmbedding

end -- PolynomialFieldEmbedding

section -- GenericFiniteFieldLower

/- Dense finite-field graphs avoiding a single rooted power, without a point-counting theorem. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients DenseGenericSamples
namespace GenericFiniteFieldLower
universe u
variable (F : Type u) [Field F]
  {A R : Type*} [Fintype A] [Fintype R]

lemma dense_specializations (G : SimpleGraph (A ⊕ R)) [Nonempty A]
    (a b d : ℕ) (ha : 0 < a) (hab : a ≤ b) (hd : 1 ≤ d)
    (hbalance : ∀ s : Finset A, b * s.card ≤ a * (RootedUnionDensity.incident G s).card)
    (hdegree : (b * Fintype.card R + 1) * Nat.card G.edgeSet ≤ d+1) :
    ∃ t Q : ℕ, 0 < t ∧ ∀ (E : Type u) [Field E] [Fintype E] [Algebra F E]
      [Algebra.IsAlgebraic F E], Q ≤ Fintype.card E →
      ∃ c : CoeffIndex a b d → E,
        (RootedPowers.graph G t).Free (graph (fun j => polynomial d (fun s => c (j,s)))) ∧
        Fintype.card E ^ (2*b) ≤ 2 * Fintype.card E ^ a *
          Nat.card (graph (fun j => polynomial d (fun s => c (j,s)))).edgeSet := by
  classical
  let K := AlgebraicClosure F
  obtain ⟨t,ht,P,hP,hfree⟩ := GenericObstruction.single_obstruction (F := F) (K := K)
    (τ := Fin b) (J := Fin a) G d
    (by simpa only [Fintype.card_fin] using ha)
    (by simpa only [Fintype.card_fin] using hbalance)
    (by simpa only [Fintype.card_fin] using hdegree)
  refine ⟨t,max 9 (2*P.totalDegree+1),ht,?_⟩
  intro E _ _ _ _ hE
  let ψ : E →ₐ[F] K := IsAlgClosed.lift
  let P' : MvPolynomial (CoeffIndex a b d) E := map (algebraMap F E) P
  have hP' : P' ≠ 0 := by
    intro hh
    apply hP
    apply map_injective (algebraMap F E) (algebraMap F E).injective
    simpa only [map_zero] using hh
  have hdeg : P'.totalDegree = P.totalDegree := by
    simp only [P', totalDegree, support_map_of_injective _ (algebraMap F E).injective]
  obtain ⟨c,hc,hden⟩ := DenseGenericSamples.exists_dense_avoiding (F := E) hd P' hP'
    (DenseGenericSamples.mean_large (by omega) hab (by omega)) (by rw [hdeg]; omega)
  have hc' : aeval c P ≠ 0 := by
    simpa only [P', eval_map, aeval_def] using hc
  have hcK : aeval (fun s => ψ (c s)) P ≠ 0 := by
    rw [← MvPolynomial.comp_aeval_apply c ψ P]
    exact fun hh => hc' (ψ.injective (hh.trans (map_zero ψ).symm))
  refine ⟨c,?_,hden⟩
  intro hf
  apply hfree (fun s => ψ (c s)) hcK
  obtain ⟨f⟩ := hf
  have hg := (PolynomialFieldEmbedding.copy ψ.toRingHom
    (fun j => polynomial d (fun s => c (j,s)))).comp f
  have heq : (fun j : Fin a => map ψ.toRingHom (polynomial d (fun s => c (j,s)))) =
      (fun j => polynomial d (fun s => ψ (c (j,s)))) := by
    funext j
    exact GenericRootedFiber.map_polynomial _ _ _
  rw [heq] at hg
  exact ⟨hg⟩

end GenericFiniteFieldLower

end -- GenericFiniteFieldLower

section -- TransferLowerBound

/- Transfer finite-field lower bounds to all sufficiently large vertex counts. -/
open Finset SimpleGraph Filter
namespace TransferLowerBound

lemma density_transfer {W : Type*} (G : SimpleGraph W) (a b n p : ℕ)
    (hp : 0 < p) (hn : 2 ≤ n) (hnp : n ≤ 2*p^b)
    (hlower : (p : ℝ)^(2*b) ≤ 2*(p : ℝ)^a*(extremalNumber (2*p^b) G : ℝ)) :
    (n : ℝ)^2 ≤ 16*(p : ℝ)^a*(extremalNumber n G : ℝ) := by
  have hp' : (0 : ℝ) < p := by exact_mod_cast hp
  have hm : 2 ≤ 2*p^b := hn.trans hnp
  have hcn : (0 : ℝ) < n.choose 2 := by exact_mod_cast Nat.choose_pos hn
  have hcm : (0 : ℝ) < (2*p^b).choose 2 := by exact_mod_cast Nat.choose_pos hm
  have hc := (div_le_div_iff₀ hcm hcn).mp
    (antitoneOn_extremalNumber_div_choose_two G hn hm hnp)
  have hM : ((2*p^b).choose 2 : ℝ) ≤ 2*(p : ℝ)^(2*b) := by
    rw [Nat.cast_choose_two]
    push_cast
    rw [show 2*b = b+b by omega, pow_add]
    have hp0 : (0 : ℝ) ≤ (p : ℝ)^b := pow_nonneg hp'.le b
    nlinarith
  have hh : (n.choose 2 : ℝ) ≤ 4*(p : ℝ)^a*(extremalNumber n G : ℝ) := by
    apply le_of_mul_le_mul_left _ (pow_pos hp' (2*b))
    calc
      (p : ℝ)^(2*b)*(n.choose 2 : ℝ) ≤
          2*(p : ℝ)^a*((extremalNumber (2*p^b) G : ℝ)*(n.choose 2 : ℝ)) := by
        nlinarith only [mul_le_mul_of_nonneg_right hlower hcn.le]
      _ ≤ 2*(p : ℝ)^a*((extremalNumber n G : ℝ)*((2*p^b).choose 2 : ℝ)) :=
        mul_le_mul_of_nonneg_left hc (by positivity)
      _ ≤ 2*(p : ℝ)^a*((extremalNumber n G : ℝ)*(2*(p : ℝ)^(2*b))) :=
        mul_le_mul_of_nonneg_left
          (mul_le_mul_of_nonneg_left hM (by positivity)) (by positivity)
      _ = (p : ℝ)^(2*b)*(4*(p : ℝ)^a*(extremalNumber n G : ℝ)) := by ring
  rw [Nat.cast_choose_two] at hh
  have hn' : (2 : ℝ) ≤ n := by exact_mod_cast hn
  nlinarith


end TransferLowerBound

end -- TransferLowerBound

section -- DyadicLowerTransfer

/- Transfer finite-field graph bounds along powers of two to arbitrary vertex counts. -/
open Finset SimpleGraph Filter
namespace DyadicLowerTransfer

lemma power_at_root_scale (b Q n : ℕ) (hb : 0 < b) (hQ : 1 ≤ Q) (hn : Q^b ≤ n) :
    ∃ s : ℕ, 0 < s ∧ Q ≤ 2^s ∧ n ≤ 2*(2^s)^b ∧
      ((2^s : ℕ) : ℝ) ≤ 2*(n : ℝ)^((b : ℝ)⁻¹) := by
  let x := (n : ℝ)^((b : ℝ)⁻¹)
  have hx0 : 0 ≤ x := Real.rpow_nonneg (Nat.cast_nonneg n) _
  have hxb : x^b = n := Real.rpow_inv_natCast_pow (Nat.cast_nonneg n) (by omega)
  have hQx : (Q : ℝ) ≤ x := by
    apply le_of_pow_le_pow_left₀ (by omega : b ≠ 0) hx0
    rw [hxb]
    exact_mod_cast hn
  have hx1 : 1 ≤ x := (by exact_mod_cast hQ : (1 : ℝ) ≤ Q).trans hQx
  obtain ⟨s,hs,hs'⟩ := exists_nat_pow_near hx1 (by norm_num : (1 : ℝ) < 2)
  refine ⟨s+1,by omega,?_,?_,?_⟩
  · exact_mod_cast hQx.trans hs'.le
  · have hh := pow_le_pow_left₀ hx0 hs'.le b
    rw [hxb] at hh
    have hnp : n ≤ (2^(s+1))^b := by exact_mod_cast hh
    omega
  · push_cast
    rw [pow_succ]
    change (2 : ℝ)^s * 2 ≤ 2*x
    linarith

lemma power_isBigO_extremal {W : Type*} (G : SimpleGraph W) (a b Q : ℕ)
    (hb : 0 < b) (hQ : 1 ≤ Q)
    (hlower : ∀ s : ℕ, 0 < s → Q ≤ 2^s →
      ((2^s : ℕ) : ℝ)^(2*b) ≤ 2*((2^s : ℕ) : ℝ)^a *
        (extremalNumber (2*(2^s)^b) G : ℝ)) :
    Asymptotics.IsBigO atTop (fun n : ℕ => (n : ℝ)^(2-(a : ℝ)/b))
      (fun n : ℕ => (extremalNumber n G : ℝ)) := by
  apply Asymptotics.isBigO_iff.mpr
  refine ⟨16*(2 : ℝ)^a, eventually_atTop.mpr ⟨max 2 (Q^b),?_⟩⟩
  intro n hn
  have hn2 : 2 ≤ n := (le_max_left _ _).trans hn
  have hnQ : Q^b ≤ n := (le_max_right _ _).trans hn
  obtain ⟨s,hs,hsQ,hnp,hpbound⟩ := power_at_root_scale b Q n hb hQ hnQ
  have hd := TransferLowerBound.density_transfer G a b n (2^s) (by positivity)
    hn2 hnp (hlower s hs hsQ)
  have hnpow := pow_le_pow_left₀ (Nat.cast_nonneg (2^s)) hpbound a
  have hrpow : ((n : ℝ)^((b : ℝ)⁻¹))^a = (n : ℝ)^((a : ℝ)/b) := by
    rw [← Real.rpow_mul_natCast (Nat.cast_nonneg n)]
    congr 1
    ring
  rw [mul_pow, hrpow] at hnpow
  have hn0 : (0 : ℝ) < n := by exact_mod_cast (by omega : 0 < n)
  simp only [Real.norm_eq_abs, abs_of_nonneg (Real.rpow_nonneg (Nat.cast_nonneg n) _), Nat.abs_cast]
  rw [Real.rpow_sub hn0, Real.rpow_two]
  apply (div_le_iff₀ (Real.rpow_pos_of_pos hn0 _)).mpr
  have hh := mul_le_mul_of_nonneg_right hnpow (show (0 : ℝ) ≤ extremalNumber n G by positivity)
  nlinarith only [hd,hh]

end DyadicLowerTransfer

end -- DyadicLowerTransfer

section -- UnconditionalRootedLower

/- The random-algebraic lower bound for any balanced rooted graph. -/
open Finset MvPolynomial PolynomialBipartite BoundedPolynomialCoefficients
namespace UnconditionalRootedLower
variable {A R : Type*} [Fintype A] [Fintype R]

/-- Balanced rooted graphs have a power with the predicted extremal lower bound.
This is only a lower bound; the corresponding single-power upper bound is not assumed. -/
lemma exists_power_lower (G : SimpleGraph (A ⊕ R)) [Nonempty A]
    (a b : ℕ) (ha : 0 < a) (hab : a ≤ b)
    (hbalance : ∀ s : Finset A, b * s.card ≤ a * (RootedUnionDensity.incident G s).card) :
    ∃ t : ℕ, 0 < t ∧
      Asymptotics.IsBigO Filter.atTop (fun n : ℕ => (n : ℝ)^(2-(a : ℝ)/b))
        (fun n : ℕ => (SimpleGraph.extremalNumber n (RootedPowers.graph G t) : ℝ)) := by
  classical
  let d := (b * Fintype.card R + 1) * Nat.card G.edgeSet + 1
  obtain ⟨t,Q,ht,hQ⟩ := GenericFiniteFieldLower.dense_specializations (ZMod 2)
    G a b d ha hab (by omega) hbalance (by omega)
  refine ⟨t,ht,?_⟩
  apply DyadicLowerTransfer.power_isBigO_extremal (RootedPowers.graph G t) a b (max 1 Q)
    (by omega) (le_max_left _ _)
  intro s hs hqs
  let E := GaloisField 2 s
  letI : Fintype E := Fintype.ofFinite E
  have hE : Fintype.card E = 2^s := by
    rw [← Nat.card_eq_fintype_card]
    exact GaloisField.card 2 s (by omega)
  obtain ⟨c,hfree,hden⟩ := hQ E (by rw [hE]; exact (le_max_right 1 Q).trans hqs)
  let H := graph (fun j => polynomial d (fun z => c (j,z)))
  have hV : Fintype.card (Vertex E (Fin b)) = 2*(2^s)^b := by
    simp only [Vertex, Point, Fintype.card_sum, Fintype.card_fun, Fintype.card_fin, hE]
    omega
  have he : Nat.card H.edgeSet ≤ SimpleGraph.extremalNumber (2*(2^s)^b) (RootedPowers.graph G t) := by
    have hh := SimpleGraph.card_edgeFinset_le_extremalNumber hfree
    simpa only [SimpleGraph.edgeFinset_card, ← Nat.card_eq_fintype_card, hV,
      Nat.card_eq_fintype_card] using hh
  rw [hE] at hden
  have hh := hden.trans (Nat.mul_le_mul_left (2*(2^s)^a) he)
  exact_mod_cast hh


end UnconditionalRootedLower

end -- UnconditionalRootedLower

section -- RootedSuspension

/- Suspension as a rooted-power operation, including its balance transformation. -/
open Finset SimpleGraph
namespace RootedSuspension
variable {A R : Type*}

def move : A ⊕ (Fin 2 ⊕ R) ≃ Fin 2 ⊕ (A ⊕ R) where
  toFun := Sum.elim (fun a => Sum.inr (Sum.inl a))
    (Sum.elim Sum.inl (fun r => Sum.inr (Sum.inr r)))
  invFun := Sum.elim (fun i => Sum.inr (Sum.inl i))
    (Sum.elim Sum.inl (fun r => Sum.inr (Sum.inr r)))
  left_inv := by intro v; cases v with
    | inl a => rfl
    | inr r => cases r <;> rfl
  right_inv := by intro v; cases v with
    | inl a => rfl
    | inr r => cases r <;> rfl

def graph {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2)) : SimpleGraph (A ⊕ (Fin 2 ⊕ R)) :=
  (SuspensionBounds.suspend c).comap move

def color {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2)) : (graph c).Coloring (Fin 2) :=
  Coloring.mk (fun v => Sum.elim id c (move v)) (by
    intro u v h
    change (SuspensionBounds.suspend c).Adj (move u) (move v) at h
    change Sum.elim id c (move u) ≠ Sum.elim id c (move v)
    cases hu : move u <;> cases hv : move v <;> rw [hu,hv] at h
    · exact h
    · exact h
    · exact h
    · exact c.valid h)

def old : A ⊕ R ↪ A ⊕ (Fin 2 ⊕ R) where
  toFun := Sum.map id Sum.inr
  inj' := Sum.map_injective.mpr ⟨Function.injective_id,Sum.inr_injective⟩

def powerColor {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2)) (t : ℕ) :
    (RootedPowers.graph G t).Coloring (Fin 2) :=
  Coloring.mk (Sum.elim (fun z => c (Sum.inl z.2)) (fun r => c (Sum.inr r))) (by
    intro u v h
    cases u <;> cases v
    · exact c.valid h.2
    · exact c.valid h
    · exact c.valid h
    · exact c.valid h)

def powerIso {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2)) (t : ℕ) :
    RootedPowers.graph (graph c) t ≃g SuspensionBounds.suspend (powerColor c t) where
  toEquiv := move
  map_rel_iff' := by
    intro u v
    cases u with
    | inl a =>
      cases v with
      | inl b => rfl
      | inr r => cases r <;> rfl
    | inr r =>
      cases r with
      | inl i => cases v with
        | inl a => rfl
        | inr s => cases s <;> rfl
      | inr r => cases v with
        | inl a => rfl
        | inr s => cases s <;> rfl

lemma suspend_connected {W : Type*} {G : SimpleGraph W} (c : G.Coloring (Fin 2)) :
    (SuspensionBounds.suspend c).Connected := by
  rw [connected_iff_exists_forall_reachable]
  refine ⟨Sum.inl 0,?_⟩
  intro v
  have he : (SuspensionBounds.suspend c).Adj (Sum.inl 0) (Sum.inl 1) := by
    change (0 : Fin 2) ≠ 1
    decide
  cases v with
  | inl i =>
    fin_cases i
    · exact Reachable.refl _
    · exact he.reachable
  | inr w =>
    by_cases hw : c w = 0
    · apply he.reachable.trans
      exact (show (SuspensionBounds.suspend c).Adj (Sum.inl 1) (Sum.inr w) by
        change (1 : Fin 2) ≠ c w; rw [hw]; decide).reachable
    · exact (show (SuspensionBounds.suspend c).Adj (Sum.inl 0) (Sum.inr w) from Ne.symm hw).reachable

lemma power_connected {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2)) (t : ℕ) :
    (RootedPowers.graph (graph c) t).Connected :=
  (powerIso c t).connected_iff.mpr (suspend_connected _)

section Balance
variable [Fintype A] [Fintype R] {G : SimpleGraph (A ⊕ R)}

lemma incident_gain (c : G.Coloring (Fin 2)) (s : Finset A) :
    (RootedUnionDensity.incident G s).card + s.card ≤ (RootedUnionDensity.incident (graph c) s).card := by
  classical
  let f : A → Sym2 (A ⊕ (Fin 2 ⊕ R)) :=
    fun a => s(Sum.inl a,Sum.inr (Sum.inl (c (Sum.inl a)).rev))
  let I := (RootedUnionDensity.incident G s).image (Sym2.map old)
  let N := s.image f
  have hI : I ⊆ RootedUnionDensity.incident (graph c) s := by
    intro e he
    obtain ⟨e,hge,rfl⟩ := mem_image.mp he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset] at hge ⊢
    refine ⟨?_,?_⟩
    · rcases hge with ⟨heG,_,_,_⟩
      induction e using Sym2.inductionOn with
      | _ u v =>
        cases u <;> cases v <;> exact heG
    · obtain ⟨_,a,ha,hae⟩ := hge
      exact ⟨a,ha,Sym2.mem_map.mpr ⟨Sum.inl a,hae,rfl⟩⟩
  have hN : N ⊆ RootedUnionDensity.incident (graph c) s := by
    intro e he
    obtain ⟨a,ha,rfl⟩ := mem_image.mp he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
    refine ⟨?_,a,ha,Sym2.mem_mk_left _ _⟩
    change c (Sum.inl a) ≠ (c (Sum.inl a)).rev
    generalize c (Sum.inl a) = i
    fin_cases i <;> decide
  have hdis : Disjoint I N := by
    apply Finset.disjoint_left.mpr
    intro e he hn
    obtain ⟨a,_,rfl⟩ := mem_image.mp hn
    obtain ⟨d,_,hd⟩ := mem_image.mp he
    have hmem : Sum.inr (Sum.inl (c (Sum.inl a)).rev) ∈ Sym2.map old d := by
      rw [hd]
      exact Sym2.mem_mk_right _ _
    obtain ⟨v,_,hv⟩ := Sym2.mem_map.mp hmem
    cases v <;> cases hv
  have hf : Function.Injective f := by
    intro a b hab
    have hh := (Sym2.eq_iff.mp hab).resolve_right (by simp [f])
    exact Sum.inl.inj hh.1

  have hcard : (I ∪ N).card = (RootedUnionDensity.incident G s).card + s.card := by
    rw [card_union_of_disjoint hdis]
    simp only [I,N,card_image_of_injective _ (Sym2.map.injective old.injective),
      card_image_of_injective _ hf]
  rw [← hcard]
  exact card_le_card (union_subset hI hN)

lemma balanced (c : G.Coloring (Fin 2)) (a b : ℕ)
    (hbalance : ∀ s : Finset A, b*s.card ≤ a*(RootedUnionDensity.incident G s).card) :
    ∀ s : Finset A, (b+a)*s.card ≤ a*(RootedUnionDensity.incident (graph c) s).card := by
  intro s
  have hh := Nat.mul_le_mul_left a (incident_gain c s)
  nlinarith [hbalance s]
end Balance

lemma upper_transform {G : SimpleGraph (A ⊕ R)} (c : G.Coloring (Fin 2))
    (a b t : ℕ) (ha : 0 < a) (hab : a ≤ b)
    (hconn : (RootedPowers.graph G t).Connected)
    (hupper : Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n (RootedPowers.graph G t) : ℝ))
      (fun n : ℕ => (n : ℝ)^(2-(a : ℝ)/b))) :
    Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n (RootedPowers.graph (graph c) t) : ℝ))
      (fun n : ℕ => (n : ℝ)^(2-(a : ℝ)/(b+a))) := by
  have haR : (0 : ℝ) < a := by exact_mod_cast ha
  have hbR : (0 : ℝ) < b := by exact_mod_cast (by omega : 0 < b)
  have habR : (a : ℝ) ≤ b := by exact_mod_cast hab
  have hα : 1 ≤ 2-(a : ℝ)/b := by have := (div_le_one hbR).mpr habR; linarith
  have hα₂ : 2-(a : ℝ)/b < 2 := by have := div_pos haR hbR; linarith
  have hh := SuspensionBounds.suspension_isBigO hconn (powerColor c t)
    (2-(a : ℝ)/b) hα hα₂ hupper
  have he : 1+1/(3-(2-(a : ℝ)/b)) = 2-(a : ℝ)/(b+a) := by
    have hd : (b : ℝ)+a ≠ 0 := by positivity
    have he0 : 3-(2-(a : ℝ)/b) = ((b : ℝ)+a)/b := by
      field_simp
      ring
    rw [he0,one_div_div]
    field_simp [hd]
    <;> ring
  simpa only [extremalNumber_congr_right (powerIso c t),he] using hh

end RootedSuspension

end -- RootedSuspension

section -- KSTUpper

/- A uniform Kővári–Sós–Turán upper bound, using tuple counts. -/
open Finset SimpleGraph
namespace KSTUpper

/-- The complete bipartite graph with the indicated two parts. -/
def graph (s t : ℕ) : SimpleGraph (Fin s ⊕ Fin t) where
  Adj u v := match u,v with
    | Sum.inl _, Sum.inr _ => True
    | Sum.inr _, Sum.inl _ => True
    | _, _ => False
  symm := by constructor; intro u v h; cases u <;> cases v <;> exact h
  loopless := by constructor; intro v; cases v <;> exact not_false

lemma graph_bipartite (s t : ℕ) : (graph s t).IsBipartite := by
  refine ⟨Coloring.mk (Sum.elim (fun _ => (0 : Fin 2)) (fun _ => 1)) ?_⟩
  intro u v h
  cases u <;> cases v <;> simp_all [graph]

section Counts
variable {V : Type*} [Fintype V] [DecidableEq V]

lemma collision_count (s : ℕ) (i j : Fin s) (hij : i ≠ j) :
    (univ.filter (fun f : Fin s → V => f i = f j)).card ≤ Fintype.card V ^ (s-1) := by
  classical
  let B := {f : Fin s → V // f i = f j}
  let S := {k : Fin s // k ≠ j}
  let r : B → S → V := fun f k => f.val k.val
  have hr : Function.Injective r := by
    intro f g hfg
    apply Subtype.ext
    funext k
    by_cases hk : k = j
    · subst k
      exact f.property.symm.trans ((congrFun hfg ⟨i,hij⟩).trans g.property)
    · exact congrFun hfg ⟨k,hk⟩
  have hS : Fintype.card S = s-1 := by
    simp only [S, Fintype.card_subtype_compl, Fintype.card_fin, Fintype.card_unique]
  have hh := Fintype.card_le_of_injective r hr
  simpa only [B, Fintype.card_subtype, Fintype.card_fun, hS] using hh

lemma noninjective_count (s : ℕ) :
    (univ.filter (fun f : Fin s → V => ¬ Function.Injective f)).card ≤
      s^2 * Fintype.card V ^ (s-1) := by
  classical
  let Bad := univ.filter (fun f : Fin s → V => ¬ Function.Injective f)
  let E (ij : Fin s × Fin s) :=
    univ.filter (fun f : Fin s → V => ij.1 ≠ ij.2 ∧ f ij.1 = f ij.2)
  have hsub : Bad ⊆ univ.biUnion E := by
    intro f hf
    have hh := (mem_filter.mp hf).2
    simp only [Function.Injective] at hh
    push_neg at hh
    obtain ⟨i,j,he,hij⟩ := hh
    exact mem_biUnion.mpr ⟨(i,j),mem_univ _,mem_filter.mpr ⟨mem_univ _,hij,he⟩⟩
  have hcard (ij : Fin s × Fin s) : (E ij).card ≤ Fintype.card V ^ (s-1) := by
    by_cases hij : ij.1 = ij.2
    · simp [E,hij]
    · have he : E ij = univ.filter (fun f : Fin s → V => f ij.1 = f ij.2) := by
        ext f
        simp only [E,mem_filter,mem_univ,true_and]
        exact and_iff_right hij
      rw [he]
      exact collision_count s ij.1 ij.2 hij
  calc
    Bad.card ≤ (univ.biUnion E).card := card_le_card hsub
    _ ≤ ∑ ij, (E ij).card := card_biUnion_le
    _ ≤ ∑ _ij : Fin s × Fin s, Fintype.card V ^ (s-1) := sum_le_sum (fun ij _ => hcard ij)
    _ = _ := by simp only [sum_const,card_univ,Fintype.card_prod,Fintype.card_fin,smul_eq_mul,pow_two]

variable (H : SimpleGraph V) [DecidableRel H.Adj]

def common (s : ℕ) (f : Fin s → V) : Finset V := univ.filter (fun v => ∀ i, H.Adj (f i) v)

lemma common_le (s t : ℕ) (hfree : (graph s t).Free H) (f : Fin s → V)
    (hf : Function.Injective f) : (common H s f).card ≤ t := by
  classical
  by_contra h
  have hle : t ≤ (common H s f).card := by omega
  obtain ⟨g⟩ : Nonempty (Fin t ↪ common H s f) := Function.Embedding.nonempty_of_card_le
    (by simpa only [Fintype.card_fin,Fintype.card_coe] using hle)
  apply hfree
  refine ⟨{toHom := { toFun := Sum.elim f (fun j => (g j).val), map_rel' := ?_}, injective' := ?_}⟩
  · intro u v huv
    cases u with
    | inl i =>
      cases v with
      | inl j => exact huv.elim
      | inr j => exact (mem_filter.mp (g j).property).2 i
    | inr i =>
      cases v with
      | inl j => exact ((mem_filter.mp (g i).property).2 j).symm
      | inr j => exact huv.elim
  · intro u v huv
    cases u with
    | inl i =>
      cases v with
      | inl j => exact congrArg Sum.inl (hf huv)
      | inr j => exact ((mem_filter.mp (g j).property).2 i).ne huv |>.elim
    | inr i =>
      cases v with
      | inl j => exact ((mem_filter.mp (g i).property).2 j).ne huv.symm |>.elim
      | inr j => exact congrArg Sum.inr (g.injective (Subtype.ext huv))

lemma sum_degree_pow (s : ℕ) : ∑ v, H.degree v ^ s = ∑ f : Fin s → V, (common H s f).card := by
  classical
  have hc (v : V) : H.degree v ^ s =
      (univ.filter (fun f : Fin s → V => ∀ i, H.Adj (f i) v)).card := by
    let e : (Fin s → H.neighborSet v) ≃ {f : Fin s → V // ∀ i, H.Adj (f i) v} := {
      toFun f := ⟨fun i => (f i).val,fun i => (f i).property.symm⟩
      invFun f i := ⟨f.val i,(f.property i).symm⟩
      left_inv := by intro f; rfl
      right_inv := by intro f; rfl }
    have hh := Fintype.card_congr e
    simpa only [Fintype.card_fun, Fintype.card_fin, H.card_neighborSet_eq_degree,
      Fintype.card_subtype] using hh
  simp_rw [hc,common,card_filter]
  exact sum_comm

lemma sum_degree_pow_le (s t : ℕ) (hs : 0 < s) (hfree : (graph s t).Free H) :
    ∑ v, H.degree v ^ s ≤ (t+s^2) * Fintype.card V ^ s := by
  classical
  rw [sum_degree_pow]
  have hpoint (f : Fin s → V) : (common H s f).card ≤
      t + if ¬Function.Injective f then Fintype.card V else 0 := by
    by_cases hf : Function.Injective f
    · simp only [hf, not_true_eq_false, if_false, add_zero]
      exact common_le H s t hfree f hf
    · rw [if_pos hf]
      exact (card_le_card (filter_subset _ _)).trans (by simp)
  calc
    _ ≤ ∑ f : Fin s → V, (t + if ¬Function.Injective f then Fintype.card V else 0) :=
      sum_le_sum (fun f _ => hpoint f)
    _ = Fintype.card V ^ s * t +
        (univ.filter (fun f : Fin s → V => ¬Function.Injective f)).card * Fintype.card V := by
      simp only [sum_add_distrib, sum_const, card_univ,Fintype.card_fun,Fintype.card_fin,
        smul_eq_mul, ← sum_filter]
    _ ≤ Fintype.card V ^ s * t + s^2 * Fintype.card V ^ (s-1) * Fintype.card V :=
      Nat.add_le_add_left (Nat.mul_le_mul_right _ (noninjective_count s)) _
    _ = _ := by rw [mul_assoc, ← pow_succ, Nat.sub_add_cancel hs]; ring
end Counts

lemma edge_bound {V : Type*} [Fintype V] [Nonempty V] [DecidableEq V]
    (H : SimpleGraph V) [DecidableRel H.Adj] (s t : ℕ) (hs : 0 < s)
    (hfree : (graph s t).Free H) :
    (H.edgeFinset.card : ℝ) ≤ (t+s^2+1) * (Fintype.card V : ℝ)^(2-(s : ℝ)⁻¹) := by
  let n : ℝ := Fintype.card V
  let C : ℝ := t+s^2+1
  have hn : 0 < n := by
    dsimp only [n]
    exact_mod_cast (Fintype.card_pos : 0 < Fintype.card V)
  have he : (0 : ℝ) ≤ H.edgeFinset.card := by positivity
  have hsR : (1 : ℝ) ≤ s := by exact_mod_cast hs
  have hs0 : (s : ℝ) ≠ 0 := by positivity
  have hC : 1 ≤ C := by dsimp [C]; nlinarith [sq_nonneg (s : ℝ),(Nat.cast_nonneg t : (0 : ℝ) ≤ t)]
  have hm : (∑ v, (H.degree v : ℝ)^s) ≤ (t+s^2)*n^s := by
    dsimp only [n]
    exact_mod_cast sum_degree_pow_le H s t hs hfree
  have hj := Real.rpow_sum_le_const_mul_sum_rpow_of_nonneg univ hsR
    (fun v _ => (show (0 : ℝ) ≤ H.degree v by positivity))
  have hsum : (∑ v, (H.degree v : ℝ)) = 2 * H.edgeFinset.card := by
    exact_mod_cast H.sum_degrees_eq_twice_card_edges
  rw [hsum, Real.rpow_natCast, card_univ] at hj
  simp_rw [Real.rpow_natCast] at hj
  have hnp : (Fintype.card V : ℝ)^((s : ℝ)-1) = n^(s-1) := by
    have hcast : ((s-1 : ℕ) : ℝ) = (s : ℝ)-1 := by
      rw [Nat.cast_sub hs, Nat.cast_one]
    rw [← hcast, Real.rpow_natCast]
  rw [hnp] at hj
  have hrpow : (n^(2-(s : ℝ)⁻¹))^s = n^(2*s-1) := by
    rw [← Real.rpow_mul_natCast hn.le, ← Real.rpow_natCast]
    congr 1
    rw [Nat.cast_sub (by omega : 1 ≤ 2*s), Nat.cast_mul, Nat.cast_ofNat, Nat.cast_one]
    field_simp
  apply le_of_pow_le_pow_left₀ (by omega : s ≠ 0) (by positivity)
  change (H.edgeFinset.card : ℝ)^s ≤ (C*n^(2-(s : ℝ)⁻¹))^s
  rw [mul_pow,hrpow]
  calc
    (H.edgeFinset.card : ℝ)^s ≤ (2*(H.edgeFinset.card : ℝ))^s :=
      pow_le_pow_left₀ he (by linarith) s
    _ ≤ n^(s-1) * ∑ v, (H.degree v : ℝ)^s := hj
    _ ≤ n^(s-1) * ((t+s^2)*n^s) := mul_le_mul_of_nonneg_left hm (by positivity)
    _ ≤ n^(s-1) * (C*n^s) := by
      apply mul_le_mul_of_nonneg_left _ (by positivity)
      apply mul_le_mul_of_nonneg_right _ (by positivity)
      dsimp [C]
      linarith
    _ = C*n^(2*s-1) := by
      rw [mul_left_comm, ← pow_add]
      congr 2
      omega
    _ ≤ C^s*n^(2*s-1) := mul_le_mul_of_nonneg_right
      (by simpa only [pow_one] using pow_le_pow_right₀ hC hs) (by positivity)

lemma upper (s t n : ℕ) (hs : 0 < s) (hn : 0 < n) :
    (extremalNumber n (graph s t) : ℝ) ≤ (t+s^2+1) * (n : ℝ)^(2-(s : ℝ)⁻¹) := by
  classical
  letI : NeZero n := ⟨by omega⟩
  rw [← Fintype.card_fin n, extremalNumber_le_iff_of_nonneg _ (by positivity)]
  intro H _ hH
  exact edge_bound H s t hs hH

lemma upper_isBigO (s t : ℕ) (hs : 0 < s) :
    Asymptotics.IsBigO Filter.atTop (fun n : ℕ => (extremalNumber n (graph s t) : ℝ))
      (fun n : ℕ => (n : ℝ)^(2-(s : ℝ)⁻¹)) := by
  apply Asymptotics.isBigO_iff.mpr
  refine ⟨t+s^2+1,Filter.eventually_atTop.mpr ⟨1,?_⟩⟩
  intro n hn
  simpa only [Real.norm_eq_abs,Nat.abs_cast,
    abs_of_nonneg (Real.rpow_nonneg (Nat.cast_nonneg n) _)] using upper s t n hs (by omega)

end KSTUpper

end -- KSTUpper

section -- RationalKST

/- Every exponent 2-1/s is a single-graph bipartite Turán exponent. -/
open Finset SimpleGraph
namespace RationalKST

lemma finite_realization {W : Type*} [Fintype W] (G : SimpleGraph W) (α : ℚ)
    (hG : G.IsBipartite)
    (hΘ : Asymptotics.IsTheta Filter.atTop (fun n : ℕ => (extremalNumber n G : ℝ))
      (fun n : ℕ => (n : ℝ)^(α : ℝ))) :
    ∃ q : ℕ, ∃ H : SimpleGraph (Fin q), H.IsBipartite ∧
      Asymptotics.IsTheta Filter.atTop (fun n : ℕ => (extremalNumber n H : ℝ))
        (fun n : ℕ => (n : ℝ)^(α : ℝ)) := by
  let e := Fintype.equivFin W
  let H := G.map e.toEmbedding
  let i : G ≃g H := Iso.map e G
  refine ⟨Fintype.card W,H,?_,?_⟩
  · obtain ⟨c⟩ := hG
    exact ⟨Coloring.mk (fun v => c (i.symm v)) (fun h => c.valid (i.symm.toHom.map_rel' h))⟩
  · simpa only [extremalNumber_congr_right i] using hΘ

lemma star_balance (s : ℕ) (u : Finset (Fin 1)) :
    s*u.card ≤ 1*(RootedUnionDensity.incident (KSTUpper.graph 1 s) u).card := by
  classical
  by_cases hu : u.Nonempty
  · have hu1 : u.card = 1 := by
      have h₁ := card_le_univ u
      have h₂ := card_pos.mpr hu
      simp only [Fintype.card_fin] at h₁
      omega
    have hmem : (0 : Fin 1) ∈ u := by
      obtain ⟨i,hi⟩ := hu
      simpa only [Subsingleton.elim i 0] using hi
    let f : Fin s → Sym2 (Fin 1 ⊕ Fin s) := fun j => s(Sum.inl 0,Sum.inr j)
    have hf : Function.Injective f := by
      intro i j hij
      simpa only [f,Sym2.eq_iff,Sum.inr.injEq,Sum.inl_ne_inr,Sum.inr_ne_inl,
        false_and,and_self,and_true,true_and,or_false] using hij
    have hsub : univ.image f ⊆ RootedUnionDensity.incident (KSTUpper.graph 1 s) u := by
      intro e he
      obtain ⟨j,_,rfl⟩ := mem_image.mp he
      simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
      exact ⟨trivial,0,hmem,Sym2.mem_mk_left _ _⟩
    have hh := card_le_card hsub
    rw [card_image_of_injective _ hf,card_univ,Fintype.card_fin] at hh
    simpa only [hu1,mul_one,one_mul] using hh
  · rw [not_nonempty_iff_eq_empty.mp hu]
    simp

/-- A rooted power of a star is a complete bipartite graph. -/
def starPowerIso (s t : ℕ) :
    RootedPowers.graph (KSTUpper.graph 1 s) t ≃g KSTUpper.graph s t where
  toFun := Sum.elim (fun z => Sum.inr z.1) Sum.inl
  invFun := Sum.elim Sum.inr (fun i => Sum.inl (i,0))
  left_inv := by
    intro v
    cases v with
    | inl x => exact congrArg Sum.inl (Prod.ext rfl (Subsingleton.elim _ _))
    | inr y => rfl
  right_inv := by intro v; cases v <;> rfl
  map_rel_iff' := by
    intro u v
    cases u <;> cases v <;> simp [RootedPowers.graph,KSTUpper.graph]


end RationalKST

end -- RationalKST

section -- RootedUpperModels

/- Rooted upper-bound models; the lower bound is supplied by generic polynomial graphs. -/
open Finset SimpleGraph
namespace RootedUpperModels

structure Model (a b : ℕ) where
  A : Type
  R : Type
  [fintypeA : Fintype A]
  [fintypeR : Fintype R]
  [nonemptyA : Nonempty A]
  G : SimpleGraph (A ⊕ R)
  color : G.Coloring (Fin 2)
  balance : ∀ s : Finset A, b*s.card ≤ a*(RootedUnionDensity.incident G s).card
  connected : ∀ t : ℕ, 0 < t → (RootedPowers.graph G t).Connected
  upper : ∀ t : ℕ, 0 < t →
    Asymptotics.IsBigO Filter.atTop
      (fun n : ℕ => (extremalNumber n (RootedPowers.graph G t) : ℝ))
      (fun n : ℕ => (n : ℝ)^(2-(a : ℝ)/b))

noncomputable def initial : Model 1 1 where
  A := Fin 1
  R := Fin 1
  G := KSTUpper.graph 1 1
  color := Classical.choice (KSTUpper.graph_bipartite 1 1)
  balance := RationalKST.star_balance 1
  connected t ht := by
    rw [connected_iff_exists_forall_reachable]
    refine ⟨Sum.inr 0,?_⟩
    intro v
    cases v with
    | inl a => exact (show (RootedPowers.graph (KSTUpper.graph 1 1) t).Adj
        (Sum.inr 0) (Sum.inl a) from trivial).reachable
    | inr r =>
      have hr : r = 0 := Subsingleton.elim _ _
      subst r
      exact Reachable.refl _
  upper t ht := by
    simpa only [Nat.cast_one,one_div,inv_one,
      extremalNumber_congr_right (RationalKST.starPowerIso 1 t)] using
        KSTUpper.upper_isBigO 1 t (by omega)

noncomputable def suspension {a b : ℕ} (M : Model a b) (ha : 0 < a) (hab : a ≤ b) : Model a (b+a) := by
  letI := M.fintypeA
  letI := M.fintypeR
  letI := M.nonemptyA
  exact {
    A := M.A
    R := Fin 2 ⊕ M.R
    G := RootedSuspension.graph M.color
    color := RootedSuspension.color M.color
    balance := RootedSuspension.balanced M.color a b M.balance
    connected := fun t _ => RootedSuspension.power_connected M.color t
    upper := fun t ht => by
      simpa only [Nat.cast_add] using RootedSuspension.upper_transform M.color a b t ha hab
        (M.connected t ht) (M.upper t ht) }

/-- A model gives an actual single forbidden graph with the corresponding two-sided exponent. -/
lemma realization {a b : ℕ} (M : Model a b) (ha : 0 < a) (hab : a ≤ b) :
    ∃ q : ℕ, ∃ G : SimpleGraph (Fin q), G.IsBipartite ∧
      Asymptotics.IsTheta Filter.atTop (fun n : ℕ => (extremalNumber n G : ℝ))
        (fun n : ℕ => (n : ℝ)^((2-(a : ℚ)/b : ℚ) : ℝ)) := by
  letI := M.fintypeA
  letI := M.fintypeR
  letI := M.nonemptyA
  obtain ⟨t,ht,hlo⟩ := UnconditionalRootedLower.exists_power_lower M.G a b ha hab M.balance
  apply RationalKST.finite_realization (RootedPowers.graph M.G t) (2-(a : ℚ)/b)
    (RootedPowers.graph_bipartite M.G ⟨M.color⟩ t)
  constructor
  · simpa only [Rat.cast_sub,Rat.cast_ofNat,Rat.cast_div,Rat.cast_natCast] using M.upper t ht
  · simpa only [Rat.cast_sub,Rat.cast_ofNat,Rat.cast_div,Rat.cast_natCast] using hlo

end RootedUpperModels

end -- RootedUpperModels

section -- RootedHubPathBasic

/- The arbitrary-length rooted hub replacement before promotion of root-edge interiors. -/
open Finset SimpleGraph
namespace RootedHubPathBasic
set_option maxHeartbeats 2500000
universe u
variable {A R : Type u} (F : SimpleGraph (A ⊕ R)) (k : ℕ)
abbrev E := GraphSubdivision.Edge F
abbrev Vertex := (A ⊕ (E F × Fin k)) ⊕ (R ⊕ Fin 2)

def move : Vertex F k ≃ HubPathSubdivision.Vertex (F := F) k where
  toFun := Sum.elim (Sum.elim (fun a => Sum.inr (Sum.inl (Sum.inl a))) (fun e => Sum.inr (Sum.inr e)))
    (Sum.elim (fun r => Sum.inr (Sum.inl (Sum.inr r))) Sum.inl)
  invFun := Sum.elim (fun i => Sum.inr (Sum.inr i))
    (Sum.elim (Sum.elim (fun a => Sum.inl (Sum.inl a)) (fun r => Sum.inr (Sum.inl r)))
      (fun e => Sum.inl (Sum.inr e)))
  left_inv := by intro v; rcases v with (a | e) | (r | i) <;> rfl
  right_inv := by intro v; rcases v with i | (a | r) | e <;> rfl

noncomputable def graph (c : F.Coloring (Fin 2)) : SimpleGraph (Vertex F k) :=
  (HubPathSubdivision.graph c k).comap (move F k)

noncomputable def color (c : F.Coloring (Fin 2)) : (graph F k c).Coloring (Fin 2) :=
  Coloring.mk (fun v => HubPathSubdivision.color c k (move F k v))
    (fun h => (HubPathSubdivision.color c k).valid h)

def coreMap : HubPathSubdivision.CoreVertex (F := F) k ↪ Vertex F k :=
  Function.Embedding.inr.trans (move F k).symm.toEmbedding

lemma move_coreMap (v : HubPathSubdivision.CoreVertex (F := F) k) :
    move F k (coreMap F k v)=Sum.inr v := by
  rcases v with (a | r) | e <;> rfl

def hub : Fin 2 ↪ Vertex F k := ⟨fun i => Sum.inr (Sum.inr i),Sum.inr_injective.comp Sum.inr_injective⟩

lemma spoke_adj (c : F.Coloring (Fin 2)) (a : A) :
    (graph F k c).Adj (Sum.inl (Sum.inl a)) (hub F k (c (Sum.inl a))) := rfl

noncomputable def core (c : F.Coloring (Fin 2)) (p : E F × Fin (k+1)) : Sym2 (Vertex F k) :=
  Sym2.map (coreMap F k) (HubPathSubdivision.coreEdge c k p.1 p.2)

lemma core_injective (c : F.Coloring (Fin 2)) : Function.Injective (core F k c) :=
  (Sym2.map.injective (coreMap F k).injective).comp (HubPathSubdivision.coreEdge_injective c k)

lemma core_adj (c : F.Coloring (Fin 2)) (p : E F × Fin (k+1)) : core F k c p∈(graph F k c).edgeSet := by
  simpa only [core,HubPathSubdivision.coreEdge,Sym2.map_pair_eq,mem_edgeSet,graph,comap_adj,move_coreMap]
    using HubPathSubdivision.coreEdge_adj c k p.1 p.2

section Balance
noncomputable local instance : DecidableEq (A ⊕ R) := Classical.decEq _
variable [Fintype A] [Fintype R] [Fintype (E F)]

lemma selected_core (c : F.Coloring (Fin 2)) (S : Finset (A ⊕ (E F × Fin k)))
    (p : E F × Fin (k+1))
    (hp : p∈HubPathIncidences.incidences c k (S.toLeft.image Sum.inl) S.toRight) :
    ∃ a∈S, Sum.inl a∈core F k c p := by
  classical
  obtain ⟨v,hv,he⟩ := HubPathIncidences.selected c k (S.toLeft.image Sum.inl) S.toRight p hp
  cases v with
  | inl w =>
    obtain ⟨a,ha,rfl⟩ := mem_image.mp (inl_mem_disjSum.mp hv)
    refine ⟨Sum.inl a,mem_toLeft.mp ha,?_⟩
    exact Sym2.mem_map.mpr ⟨Sum.inl (Sum.inl a),he,rfl⟩
  | inr e =>
    refine ⟨Sum.inr e,mem_toRight.mp (inr_mem_disjSum.mp hv),?_⟩
    exact Sym2.mem_map.mpr ⟨Sum.inr e,he,rfl⟩

lemma hub_notMem_core (c : F.Coloring (Fin 2)) (p : E F × Fin (k+1)) (j : Fin 2) :
    hub F k j∉core F k c p := by
  intro h
  obtain ⟨v,hv,he⟩ := Sym2.mem_map.mp h
  have hh := congrArg (move F k) he
  rw [move_coreMap] at hh
  exact Sum.inr_ne_inl hh

lemma incident_gain (c : F.Coloring (Fin 2)) (S : Finset (A ⊕ (E F × Fin k))) :
    (HubPathIncidences.incidences c k (S.toLeft.image Sum.inl) S.toRight).card+S.toLeft.card≤
      (RootedUnionDensity.incident (graph F k c) S).card := by
  classical
  let f (a : A) : Sym2 (Vertex F k) := s(Sum.inl (Sum.inl a),hub F k (c (Sum.inl a)))
  let I := (HubPathIncidences.incidences c k (S.toLeft.image Sum.inl) S.toRight).image (core F k c)
  let N := S.toLeft.image f
  have hI : I⊆RootedUnionDensity.incident (graph F k c) S := by
    intro e he
    obtain ⟨p,hp,rfl⟩ := mem_image.mp he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
    exact ⟨core_adj F k c p,selected_core F k c S p hp⟩
  have hN : N⊆RootedUnionDensity.incident (graph F k c) S := by
    intro e he
    obtain ⟨a,ha,rfl⟩ := mem_image.mp he
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
    exact ⟨spoke_adj F k c a,Sum.inl a,mem_toLeft.mp ha,Sym2.mem_mk_left _ _⟩
  have hdis : Disjoint I N := by
    apply Finset.disjoint_left.mpr
    intro e he hn
    obtain ⟨a,_,rfl⟩ := mem_image.mp hn
    obtain ⟨p,_,he⟩ := mem_image.mp he
    apply hub_notMem_core F k c p (c (Sum.inl a))
    rw [he]
    exact Sym2.mem_mk_right _ _
  have hf : Function.Injective f := by
    intro a b he
    rcases Sym2.eq_iff.mp he with ⟨h,_⟩ | ⟨h,_⟩
    · exact Sum.inl.inj (Sum.inl.inj h)
    · exact (Sum.inl_ne_inr h).elim
  have hcard : (I∪N).card=(HubPathIncidences.incidences c k (S.toLeft.image Sum.inl) S.toRight).card+S.toLeft.card := by
    rw [card_union_of_disjoint hdis]
    simp only [I,N,card_image_of_injective _ (core_injective F k c),card_image_of_injective _ hf]
  rw [← hcard]
  exact card_le_card (union_subset hI hN)

lemma balanced (c : F.Coloring (Fin 2)) (a b : ℕ)
    (hbalance : ∀ s : Finset A, b*s.card≤a*(RootedUnionDensity.incident F s).card)
    (S : Finset (A ⊕ (E F × Fin k))) :
    (a+(k+1)*b)*S.card≤(a+k*b)*(RootedUnionDensity.incident (graph F k c) S).card := by
  classical
  have h1 := HubPathIncidences.old_plus_midpoints c k (S.toLeft.image Sum.inl) S.toRight
  have h2 := HubPathIncidences.midpoint_ratio c k (S.toLeft.image Sum.inl) S.toRight
  have he : (GraphSubdivision.incidentEdges F (S.toLeft.image Sum.inl)).card =
      (RootedUnionDensity.incident F S.toLeft).card := by
    convert GraphSubdivision.old_incident_count F S.toLeft using 1
    congr 1
    ext e
    simp only [GraphSubdivision.incidentEdges,mem_filter,mem_image]
  rw [he] at h1
  rw [← S.card_toLeft_add_card_toRight]
  exact HubPathBalanceArithmetic.balance a b k _ _ _ _ _ (hbalance S.toLeft) h1 h2 (incident_gain F k c S)

end Balance
end RootedHubPathBasic

end -- RootedHubPathBasic

section -- RootPromotion

/- Relabeling rooted graphs while promoting some internal vertices to roots. -/
open Finset SimpleGraph
namespace RootPromotion
universe u v
variable {A R : Type u} {B S : Type v}
  [Fintype A] [Fintype R] [Fintype B] [Fintype S]

lemma incident_card (G : SimpleGraph (A ⊕ R)) (e : (B ⊕ S) ≃ (A ⊕ R))
    (f : B ↪ A) (hf : ∀ b, e (Sum.inl b) = Sum.inl (f b)) (U : Finset B) :
    (RootedUnionDensity.incident (G.comap e) U).card =
      (RootedUnionDensity.incident G (U.map f)).card := by
  classical
  apply card_bij (fun d _ => Sym2.map e d)
  · intro d hd
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset] at hd ⊢
    obtain ⟨hd,b,hb,hbd⟩ := hd
    refine ⟨?_,f b,mem_map.mpr ⟨b,hb,rfl⟩,?_⟩
    · induction d using Sym2.inductionOn with
      | _ x y => exact hd
    · rw [← hf]
      exact Sym2.mem_map.mpr ⟨Sum.inl b,hbd,rfl⟩
  · intro d hd c hc he
    exact Sym2.map.injective e.injective he
  · intro d hd
    simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset] at hd
    obtain ⟨hd,a,ha,had⟩ := hd
    obtain ⟨b,hb,rfl⟩ := mem_map.mp ha
    refine ⟨Sym2.map e.symm d,?_,?_⟩
    · simp only [RootedUnionDensity.incident,mem_filter,mem_edgeFinset]
      refine ⟨?_,b,hb,?_⟩
      · induction d using Sym2.inductionOn with
        | _ x y => simpa [comap_adj] using hd
      · apply Sym2.mem_map.mpr
        refine ⟨Sum.inl (f b),had,?_⟩
        rw [← hf,Equiv.symm_apply_apply]
    · induction d using Sym2.inductionOn with
      | _ x y => simp

lemma balanced (G : SimpleGraph (A ⊕ R)) (e : (B ⊕ S) ≃ (A ⊕ R))
    (f : B ↪ A) (hf : ∀ b, e (Sum.inl b) = Sum.inl (f b))
    (a b : ℕ) (hbalance : ∀ U : Finset A,
      b*U.card ≤ a*(RootedUnionDensity.incident G U).card) (U : Finset B) :
    b*U.card ≤ a*(RootedUnionDensity.incident (G.comap e) U).card := by
  classical
  rw [incident_card G e f hf]
  simpa only [card_map] using hbalance (U.map f)

end RootPromotion

end -- RootPromotion

section -- RootedSubdivision

/- Rooted subdivision with midpoint roots on root-to-root edges. -/
open Finset SimpleGraph
namespace RootedSubdivision
universe u
variable {A R : Type u} (F : SimpleGraph (A ⊕ R))

abbrev E := GraphSubdivision.Edge F

def internalEdge : Set (E F) := {e | ∃ a, Sum.inl a ∈ e.val}


lemma adj_layer (t : ℕ) (ht : 0 < t) {x y : RootedPowers.Vertex A R t}
    (hxy : (RootedPowers.graph F t).Adj x y) :
    ∃ i : Fin t, ∃ u v : A ⊕ R, F.Adj u v ∧
      RootedPowers.layer F t i u = x ∧ RootedPowers.layer F t i v = y := by
  cases x with
  | inl x => cases y with
    | inl y =>
      obtain ⟨he,hadj⟩ := hxy
      refine ⟨x.1,Sum.inl x.2,Sum.inl y.2,hadj,rfl,?_⟩
      exact congrArg Sum.inl (Prod.ext he rfl)
    | inr y => exact ⟨x.1,Sum.inl x.2,Sum.inr y,hxy,rfl,rfl⟩
  | inr x => cases y with
    | inl y => exact ⟨y.1,Sum.inr x,Sum.inl y.2,hxy,rfl,rfl⟩
    | inr y => exact ⟨⟨0,ht⟩,Sum.inr x,Sum.inr y,hxy,rfl,rfl⟩


end RootedSubdivision

end -- RootedSubdivision

section -- SubdivisionPowers

/- Subdivision commutes with rooted powers when root-edge midpoints remain roots. -/
open SimpleGraph
namespace SubdivisionPowers
set_option maxHeartbeats 1000000
universe u
variable {A R : Type u} (F : SimpleGraph (A ⊕ R))

abbrev E := RootedSubdivision.E F
abbrev I := RootedSubdivision.internalEdge F
abbrev J := (RootedSubdivision.internalEdge F)ᶜ

def forget (t : ℕ) : RootedPowers.Vertex A R t → A ⊕ R := Sum.map Prod.snd id

def edge (t : ℕ) (i : Fin t) : E F ↪ GraphSubdivision.Edge (RootedPowers.graph F t) :=
  (RootedPowers.layer F t i).mapEdgeSet

lemma edge_val (t : ℕ) (i : Fin t) (e : E F) :
    (edge F t i e).val = Sym2.map (RootedPowers.layer F t i) e.val := rfl

lemma forget_edge (t : ℕ) (i : Fin t) (e : E F) :
    Sym2.map (forget t) (edge F t i e).val = e.val := by
  rcases e with ⟨e,he⟩
  induction e using Sym2.inductionOn with
  | _ x y => cases x <;> cases y <;> rfl

lemma edge_inl (t : ℕ) (i j : Fin t) (a : A) (e : E F) :
    Sum.inl (i,a) ∈ (edge F t j e).val ↔ i = j ∧ Sum.inl a ∈ e.val := by
  rw [edge_val,Sym2.mem_map]
  constructor
  · rintro ⟨v,hv,he⟩
    cases v with
    | inl b =>
      have h : (j,b) = (i,a) := Sum.inl.inj he
      cases h
      exact ⟨rfl,hv⟩
    | inr r => exact (Sum.inr_ne_inl he).elim
  · rintro ⟨rfl,ha⟩
    exact ⟨Sum.inl a,ha,rfl⟩

lemma edge_inr (t : ℕ) (j : Fin t) (r : R) (e : E F) :
    Sum.inr r ∈ (edge F t j e).val ↔ Sum.inr r ∈ e.val := by
  rw [edge_val,Sym2.mem_map]
  constructor
  · rintro ⟨v,hv,he⟩
    cases v with
    | inl a => exact (Sum.inl_ne_inr he).elim
    | inr s => cases Sum.inr.inj he; exact hv
  · intro hr
    exact ⟨Sum.inr r,hr,rfl⟩

lemma edge_eq_iff (t : ℕ) (i j : Fin t) (e f : E F) :
    edge F t i e = edge F t j f ↔ e = f ∧ (i = j ∨ e ∉ I F) := by
  constructor
  · intro h
    have hef : e = f := by
      apply Subtype.ext
      have hh := congrArg (fun d => Sym2.map (forget t) d.val) h
      simpa only [forget_edge] using hh
    subst f
    refine ⟨rfl,?_⟩
    by_cases he : e ∈ I F
    · left
      obtain ⟨a,ha⟩ := he
      have hh : Sum.inl (i,a) ∈ (edge F t i e).val := (edge_inl F t i i a e).mpr ⟨rfl,ha⟩
      rw [h] at hh
      exact ((edge_inl F t i j a e).mp hh).1
    · exact Or.inr he
  · rintro ⟨rfl,hij | he⟩
    · subst j; rfl
    · apply Subtype.ext
      rcases e with ⟨e,heG⟩
      induction e using Sym2.inductionOn with
      | _ x y =>
        cases x with
        | inl a => exact (he ⟨a,Sym2.mem_mk_left _ _⟩).elim
        | inr r => cases y with
          | inl a => exact (he ⟨a,Sym2.mem_mk_right _ _⟩).elim
          | inr s => rfl

def edgeMap (t : ℕ) (j : Fin t) : (Fin t × I F) ⊕ J F →
    GraphSubdivision.Edge (RootedPowers.graph F t) :=
  Sum.elim (fun p => edge F t p.1 p.2.val) (fun e => edge F t j e.val)

lemma edgeMap_injective (t : ℕ) (j : Fin t) : Function.Injective (edgeMap F t j) := by
  intro x y h
  cases x with
  | inl x => cases y with
    | inl y =>
      obtain ⟨he,hi⟩ := (edge_eq_iff F t x.1 y.1 x.2.val y.2.val).mp h
      have hij := hi.resolve_right (not_not.mpr x.2.property)
      exact congrArg Sum.inl (Prod.ext hij (Subtype.ext he))
    | inr y =>
      have he := ((edge_eq_iff F t x.1 j x.2.val y.val).mp h).1
      exact (y.property (he ▸ x.2.property)).elim
  | inr x => cases y with
    | inl y =>
      have he := ((edge_eq_iff F t j y.1 x.val y.2.val).mp h).1
      exact (x.property (he.symm ▸ y.2.property)).elim
    | inr y =>
      exact congrArg Sum.inr (Subtype.ext ((edge_eq_iff F t j j x.val y.val).mp h).1)

lemma edgeMap_surjective (t : ℕ) (j : Fin t) : Function.Surjective (edgeMap F t j) := by
  classical
  rintro ⟨e,he⟩
  induction e using Sym2.inductionOn with
  | _ x y =>
    obtain ⟨i,u,v,huv,rfl,rfl⟩ := RootedSubdivision.adj_layer F t (Nat.zero_lt_of_lt j.isLt) he
    let e : E F := ⟨s(u,v),huv⟩
    have hh : edge F t i e = ⟨s(RootedPowers.layer F t i u,RootedPowers.layer F t i v),he⟩ := rfl
    by_cases hi : e ∈ I F
    · exact ⟨Sum.inl (i,⟨e,hi⟩),hh⟩
    · refine ⟨Sum.inr ⟨e,hi⟩,?_⟩
      exact ((edge_eq_iff F t j i e e).mpr ⟨rfl,Or.inr hi⟩).trans hh

noncomputable def edgeEquiv (t : ℕ) (j : Fin t) : (Fin t × I F) ⊕ J F ≃
    GraphSubdivision.Edge (RootedPowers.graph F t) :=
  Equiv.ofBijective (edgeMap F t j) ⟨edgeMap_injective F t j,edgeMap_surjective F t j⟩


end SubdivisionPowers

end -- SubdivisionPowers

section -- ChainCounting

/- Uniform counts for fixed-length vertex sequences, including coordinate fibers. -/
open Finset SimpleGraph
namespace ChainCounting
set_option maxHeartbeats 1000000
universe u
variable {V : Type u} (G : SimpleGraph V)

/-- A walk recorded by its ordered vertices. -/
def IsChain {n : ℕ} (p : Fin (n+1) → V) : Prop :=
  ∀ i : Fin n, G.Adj (p i.castSucc) (p i.succ)

instance {n : ℕ} [DecidableRel G.Adj] (p : Fin (n+1) → V) : Decidable (IsChain G p) :=
  inferInstanceAs (Decidable (∀ i : Fin n, G.Adj (p i.castSucc) (p i.succ)))

abbrev Chain (n : ℕ) := {p : Fin (n+1) → V // IsChain G p}
abbrev From (x : V) (n : ℕ) := {p : Chain G n // p.val 0 = x}
abbrev PathFrom (x : V) (n : ℕ) := {p : From G x n // Function.Injective p.val.val}

/-- A consecutive segment, retaining the walk condition. -/
def segment {n : ℕ} (p : Chain G n) (a k : ℕ) (h : a+k ≤ n) : Chain G k :=
  ⟨fun i => p.val ⟨a+i.val,by omega⟩, by
    intro i
    exact p.property ⟨a+i.val,by omega⟩⟩

@[simp] lemma segment_apply {n : ℕ} (p : Chain G n) (a k : ℕ) (h : a+k ≤ n)
    (i : Fin (k+1)) : (segment G p a k h).val i = p.val ⟨a+i.val,by omega⟩ := rfl

variable [Fintype V] [DecidableEq V] [DecidableRel G.Adj]

lemma from_zero (x : V) : Fintype.card (From G x 0) = 1 := by
  classical
  apply Fintype.card_eq_one_iff.mpr
  refine ⟨⟨⟨fun _ => x,fun i => Fin.elim0 i⟩,rfl⟩,?_⟩
  intro p
  apply Subtype.ext
  apply Subtype.ext
  funext i
  have hi : i = 0 := Fin.ext (by omega)
  simpa [hi] using p.property

lemma from_le (D : ℕ) (hD : ∀ v, G.degree v ≤ D) (n : ℕ) (x : V) :
    Fintype.card (From G x n) ≤ D^n := by
  classical
  induction n generalizing x with
  | zero => simp [from_zero]
  | succ n ih =>
    let f : From G x (n+1) → (Σ y : G.neighborSet x, From G y.val n) := fun p =>
      ⟨⟨p.val.val 1,by
        have hh := p.val.property (0 : Fin (n+1))
        simpa [Fin.castSucc_zero, p.property, Fin.succ, SimpleGraph.mem_neighborSet] using hh⟩,
        ⟨segment G p.val 1 n (by omega),rfl⟩⟩
    have hf : Function.Injective f := by
      intro p q hpq
      apply Subtype.ext
      apply Subtype.ext
      funext i
      refine Fin.cases ?_ (fun j => ?_) i
      · exact p.property.trans q.property.symm
      · have hh := congrArg (fun z : Σ y : G.neighborSet x, From G y.val n => z.2.val.val j) hpq
        simpa only [f,segment_apply,Nat.add_comm,Fin.succ] using hh
    calc
      _ ≤ Fintype.card (Σ y : G.neighborSet x, From G y.val n) :=
        Fintype.card_le_of_injective f hf
      _ = ∑ y : G.neighborSet x, Fintype.card (From G y.val n) := Fintype.card_sigma
      _ ≤ ∑ _y : G.neighborSet x, D^n := sum_le_sum (fun y _ => ih y.val)
      _ = G.degree x * D^n := by simp [G.card_neighborSet_eq_degree]
      _ ≤ D * D^n := Nat.mul_le_mul_right _ (hD x)
      _ = D^(n+1) := by rw [pow_succ]; ring


/-- Fixing any noninitial coordinate saves one neighbor choice. -/
lemma coordinate_le (D : ℕ) (hD : ∀ v, G.degree v ≤ D) (n : ℕ) (x v : V)
    (i : Fin n) :
    Fintype.card {p : From G x n // p.val.val i.succ = v} ≤ D^(n-1) := by
  classical
  let f : {p : From G x n // p.val.val i.succ = v} →
      From G x i.val × From G v (n-(i.val+1)) := fun p =>
    (⟨segment G p.val.val 0 i.val (by omega),by simpa using p.val.property⟩,
     ⟨segment G p.val.val (i.val+1) (n-(i.val+1)) (by omega),by simpa [Fin.succ] using p.property⟩)
  have hf : Function.Injective f := by
    intro p q hpq
    apply Subtype.ext
    apply Subtype.ext
    apply Subtype.ext
    funext j
    by_cases hj : j.val ≤ i.val
    · have hh := congrArg (fun z : From G x i.val × From G v (n-(i.val+1)) =>
        z.1.val.val ⟨j.val,by omega⟩) hpq
      simpa only [f,segment_apply,Nat.zero_add] using hh
    · have hh := congrArg (fun z : From G x i.val × From G v (n-(i.val+1)) =>
        z.2.val.val ⟨j.val-(i.val+1),by omega⟩) hpq
      have he : i.val+1+(j.val-(i.val+1)) = j.val := by omega
      simpa only [f,segment_apply,he] using hh
  calc
    _ ≤ Fintype.card (From G x i.val × From G v (n-(i.val+1))) :=
      Fintype.card_le_of_injective f hf
    _ = Fintype.card (From G x i.val) * Fintype.card (From G v (n-(i.val+1))) := Fintype.card_prod _ _
    _ ≤ D^i.val * D^(n-(i.val+1)) := Nat.mul_le_mul (from_le G D hD _ _) (from_le G D hD _ _)
    _ = D^(n-1) := by rw [← pow_add]; congr 1; omega


end ChainCounting

end -- ChainCounting

section -- HubPathCopies

/- Construct copies of arbitrary-length hub replacements from disjoint path data. -/
open SimpleGraph ChainCounting
namespace HubPathCopies
set_option maxHeartbeats 1500000
universe u v
variable {W : Type u} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
variable {V : Type v} (H : SimpleGraph V) (k : ℕ)
abbrev E := GraphSubdivision.Edge F

noncomputable def copyOfData (z : Fin 2 → V) (f : W → V) (m : E (F := F) × Fin k → V)
    (hz : Function.Injective z) (hf : Function.Injective f) (hm : Function.Injective m)
    (hzf : ∀ i w, z i≠f w) (hzm : ∀ i e, z i≠m e) (hfm : ∀ w e, f w≠m e)
    (hpath : ∀ e (i : Fin (k+1)), H.Adj (Sum.elim f m (HubPathSubdivision.point c k e i.castSucc))
      (Sum.elim f m (HubPathSubdivision.point c k e i.succ)))
    (hhub : ∀ i w, c w=i → H.Adj (z i) (f w)) : Copy (HubPathSubdivision.graph c k) H where
  toHom := {
    toFun := Sum.elim z (Sum.elim f m)
    map_rel' := by
      intro u v h
      rcases u with i | a <;> rcases v with j | b
      · exact h.elim
      · cases b with
        | inl w => exact hhub i w h
        | inr e => exact h.elim
      · cases a with
        | inl w => exact (hhub j w h).symm
        | inr e => exact h.elim
      · obtain ⟨e,i,h⟩ := h
        rcases Sym2.eq_iff.mp h with ⟨rfl,rfl⟩ | ⟨rfl,rfl⟩
        · exact hpath e i
        · exact (hpath e i).symm }
  injective' := hz.sumElim (hf.sumElim hm hfm) (by
    intro i a
    cases a with
    | inl w => exact hzf i w
    | inr e => exact hzm i e)

lemma point_eval (f : W → V) (p : E (F := F) → Chain H (k+1))
    (hstart : ∀ e, (p e).val 0=f (ColoredEdges.left c e))
    (hend : ∀ e, (p e).val (Fin.last (k+1))=f (ColoredEdges.right c e))
    (e : E (F := F)) (i : Fin (k+2)) :
    Sum.elim f (fun q : E (F := F) × Fin k => (p q.1).val q.2.succ.castSucc)
      (HubPathSubdivision.point c k e i)=(p e).val i := by
  dsimp only [HubPathSubdivision.point]
  split_ifs with h0 hl
  · have hi : i=0 := Fin.ext h0
    simpa only [hi,Sum.elim_inl] using (hstart e).symm
  · have hi : i=Fin.last (k+1) := Fin.ext hl
    simpa only [hi,Sum.elim_inl] using (hend e).symm
  · simp only [Sum.elim_inr]
    apply congrArg (p e).val
    apply Fin.ext
    simp only [Fin.val_castSucc,Fin.val_succ]
    omega

noncomputable def copyOfChains (z : Fin 2 → V) (f : W → V) (p : E (F := F) → Chain H (k+1))
    (hz : Function.Injective z) (hf : Function.Injective f)
    (hm : Function.Injective (fun e : E (F := F) × Fin k => (p e.1).val e.2.succ.castSucc))
    (hzf : ∀ i w, z i≠f w)
    (hzm : ∀ i e (j : Fin k), z i≠(p e).val j.succ.castSucc)
    (hfm : ∀ w e (j : Fin k), f w≠(p e).val j.succ.castSucc)
    (hstart : ∀ e, (p e).val 0=f (ColoredEdges.left c e))
    (hend : ∀ e, (p e).val (Fin.last (k+1))=f (ColoredEdges.right c e))
    (hhub : ∀ i w, c w=i → H.Adj (z i) (f w)) : Copy (HubPathSubdivision.graph c k) H :=
  copyOfData c H k z f (fun e => (p e.1).val e.2.succ.castSucc) hz hf hm hzf
    (fun i e => hzm i e.1 e.2) (fun w e => hfm w e.1 e.2) (by
      intro e i
      rw [point_eval c H k f p hstart hend,point_eval c H k f p hstart hend]
      exact (p e).property i) hhub

end HubPathCopies

end -- HubPathCopies


section -- ThreeHubSubdivision

/- Replace every old edge by a three-edge path and attach the two old-color hubs. -/
open Finset SimpleGraph
namespace ThreeHubSubdivision
set_option maxHeartbeats 2000000
universe u v
variable {W : Type u} {V : Type v} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
abbrev Edge := GraphSubdivision.Edge F

noncomputable def endpoint (e : Edge (F := F)) (i : Fin 2) : W :=
  if i=0 then ColoredEdges.left c e else ColoredEdges.right c e

lemma endpoint_color (e : Edge (F := F)) (i : Fin 2) : c (endpoint c e i)=i := by
  fin_cases i <;> simp [endpoint,ColoredEdges.left_color,ColoredEdges.right_color]


variable (H : SimpleGraph V)


end ThreeHubSubdivision

end -- ThreeHubSubdivision

section -- ThreeHubCopyTransport

/- Transport copies through the three-edge, two-hub operation. -/
open SimpleGraph
namespace ThreeHubCopyTransport
set_option maxHeartbeats 2000000
universe u v
variable {W : Type u} {V : Type v} {F : SimpleGraph W} {J : SimpleGraph V}

lemma endpoint_mem (c : F.Coloring (Fin 2)) (e : GraphSubdivision.Edge F) (i : Fin 2) :
    ThreeHubSubdivision.endpoint c e i∈e.val := by
  apply (ColoredEdges.mem_iff c e _).mpr
  fin_cases i <;> simp [ThreeHubSubdivision.endpoint]

lemma endpoint_unique (c : F.Coloring (Fin 2)) (e : GraphSubdivision.Edge F) (i : Fin 2)
    {w : W} (hw : w∈e.val) (hc : c w=i) : w=ThreeHubSubdivision.endpoint c e i := by
  fin_cases i
  · exact ColoredEdges.left_unique c e hw hc
  · exact ColoredEdges.right_unique c e hw hc

lemma endpoint_map (c : F.Coloring (Fin 2)) (d : J.Coloring (Fin 2)) (f : Copy F J)
    (e : Fin 2 ≃ Fin 2) (he : ∀ w, e (c w)=d (f w)) (a : GraphSubdivision.Edge F) (i : Fin 2) :
    f (ThreeHubSubdivision.endpoint c a i)=ThreeHubSubdivision.endpoint d (f.mapEdgeSet a) (e i) := by
  apply endpoint_unique d (f.mapEdgeSet a) (e i)
  · change f (ThreeHubSubdivision.endpoint c a i)∈a.val.map f
    exact Sym2.mem_map.mpr ⟨ThreeHubSubdivision.endpoint c a i,endpoint_mem c a i,rfl⟩
  · rw [← he,ThreeHubSubdivision.endpoint_color]


end ThreeHubCopyTransport

end -- ThreeHubCopyTransport

section -- HubPathCopyTransport

/- Transport graph copies through arbitrary-length hub replacement, allowing a color swap. -/
open SimpleGraph
namespace HubPathCopyTransport
set_option maxHeartbeats 2500000
universe u v
variable {W : Type u} {V : Type v} {F : SimpleGraph W} {J : SimpleGraph V}

noncomputable def index (e : Fin 2 ≃ Fin 2) {n : ℕ} (i : Fin n) : Fin n :=
  if e 0=0 then i else i.rev

lemma index_injective (e : Fin 2 ≃ Fin 2) (n : ℕ) : Function.Injective (index e (n := n)) := by
  intro i j h
  dsimp only [index] at h
  split_ifs at h
  · exact h
  · exact Fin.rev_injective h

lemma rev_mid (k : ℕ) (j : Fin k) : (j.succ.castSucc : Fin (k+2)).rev=j.rev.succ.castSucc := by
  apply Fin.ext
  simp only [Fin.val_rev,Fin.val_castSucc,Fin.val_succ]
  have := j.isLt
  omega

lemma point_map (c : F.Coloring (Fin 2)) (d : J.Coloring (Fin 2)) (f : Copy F J)
    (e : Fin 2 ≃ Fin 2) (he : ∀ w, e (c w)=d (f w)) (k : ℕ)
    (a : GraphSubdivision.Edge F) (i : Fin (k+2)) :
    Sum.map f (Prod.map f.mapEdgeSet (index e)) (HubPathSubdivision.point c k a i)=
      HubPathSubdivision.point d k (f.mapEdgeSet a) (index e i) := by
  have h0 := ThreeHubCopyTransport.endpoint_map c d f e he a 0
  have h1 := ThreeHubCopyTransport.endpoint_map c d f e he a 1
  simp [ThreeHubSubdivision.endpoint] at h0 h1
  by_cases hei : e 0=0
  · have he1 : e 1=1 := by
      have hh := e.injective.ne (show (0 : Fin 2)≠1 by decide)
      rw [hei] at hh
      omega
    simp [hei] at h0
    simp [he1] at h1
    simp only [index,if_pos hei]
    dsimp only [HubPathSubdivision.point]
    split_ifs <;> simp [h0,h1,index,hei]
  · have he0 : e 0=1 := by omega
    have he1 : e 1=0 := by
      have hh := e.injective.ne (show (0 : Fin 2)≠1 by decide)
      rw [he0] at hh
      omega
    simp [he0] at h0
    simp [he1] at h1
    simp only [index,if_neg hei]
    by_cases hi0 : i.val=0
    · have hi : i=0 := Fin.ext hi0
      subst i
      simp only [HubPathSubdivision.point_zero,Sum.map_inl,h0,Fin.rev_zero,HubPathSubdivision.point_last]
    · by_cases hil : i.val=k+1
      · have hi : i=Fin.last (k+1) := Fin.ext hil
        subst i
        simp only [HubPathSubdivision.point_last,Sum.map_inl,h1,Fin.rev_last,HubPathSubdivision.point_zero]
      · let j : Fin k := ⟨i.val-1,by have := i.isLt; omega⟩
        have hi : i=j.succ.castSucc := by apply Fin.ext; change i.val=i.val-1+1; omega
        rw [hi,HubPathSubdivision.point_mid,rev_mid,HubPathSubdivision.point_mid]
        simp [index,hei]

noncomputable def mapCopy (c : F.Coloring (Fin 2)) (d : J.Coloring (Fin 2)) (f : Copy F J)
    (e : Fin 2 ≃ Fin 2) (he : ∀ w, e (c w)=d (f w)) (k : ℕ) :
    Copy (HubPathSubdivision.graph c k) (HubPathSubdivision.graph d k) where
  toHom := {
    toFun := Sum.map e (Sum.map f (Prod.map f.mapEdgeSet (index e)))
    map_rel' := by
      intro u v h
      rcases u with i | a <;> rcases v with j | b
      · exact h.elim
      · cases b with
        | inl w => change d (f w)=e i; exact (he w).symm.trans (congrArg e h)
        | inr a => exact h.elim
      · cases a with
        | inl w => change d (f w)=e j; exact (he w).symm.trans (congrArg e h)
        | inr a => exact h.elim
      · obtain ⟨a,i,h⟩ := h
        have hp : (HubPathSubdivision.graph d k).Adj
            (Sum.inr (Sum.map f (Prod.map f.mapEdgeSet (index e)) (HubPathSubdivision.point c k a i.castSucc)))
            (Sum.inr (Sum.map f (Prod.map f.mapEdgeSet (index e)) (HubPathSubdivision.point c k a i.succ))) := by
          rw [point_map c d f e he,point_map c d f e he]
          dsimp only [index]
          split_ifs
          · exact HubPathSubdivision.coreEdge_adj d k (f.mapEdgeSet a) i
          · rw [Fin.rev_castSucc,Fin.rev_succ]
            exact (HubPathSubdivision.coreEdge_adj d k (f.mapEdgeSet a) i.rev).symm
        rcases Sym2.eq_iff.mp h with ⟨rfl,rfl⟩ | ⟨rfl,rfl⟩
        · exact hp
        · exact hp.symm }
  injective' := Sum.map_injective.mpr ⟨e.injective,Sum.map_injective.mpr
    ⟨f.injective,fun p q h => Prod.ext
      (f.mapEdgeSet.injective (congrArg Prod.fst h))
      (index_injective e k (congrArg (fun z : GraphSubdivision.Edge J × Fin k => z.2) h))⟩⟩

lemma copy_of_copy (hF : F.Connected) (c : F.Coloring (Fin 2)) (d : J.Coloring (Fin 2))
    (f : Copy F J) (k : ℕ) : HubPathSubdivision.graph c k ⊑ HubPathSubdivision.graph d k := by
  let d' : F.Coloring (Fin 2) := Coloring.mk (fun w => d (f w)) (fun h => d.valid (f.toHom.map_rel' h))
  obtain ⟨e,he⟩ := SuspensionBounds.coloring_perm hF c d'
  exact ⟨mapCopy c d f e he k⟩

end HubPathCopyTransport

end -- HubPathCopyTransport

section -- HubPathLayers

/- Every edge of a hub replacement of a positive rooted power lies in a
hub replacement of one old layer. -/
open SimpleGraph
namespace HubPathLayers
set_option maxHeartbeats 3000000
universe u
variable {A R : Type u} (F : SimpleGraph (A ⊕ R)) (c : F.Coloring (Fin 2)) (k t : ℕ)

noncomputable def layer (i : Fin t) : Copy (HubPathSubdivision.graph c k)
    (HubPathSubdivision.graph (RootedSuspension.powerColor c t) k) :=
  HubPathCopyTransport.mapCopy c (RootedSuspension.powerColor c t) (RootedPowers.layer F t i)
    (Equiv.refl _) (fun w => by cases w <;> rfl) k


lemma layer_point (i : Fin t) (e : GraphSubdivision.Edge F) (l : Fin (k+2)) :
    layer F c k t i (Sum.inr (HubPathSubdivision.point c k e l))=
      Sum.inr (HubPathSubdivision.point (RootedSuspension.powerColor c t) k (SubdivisionPowers.edge F t i e) l) := by
  have hh := HubPathCopyTransport.point_map c (RootedSuspension.powerColor c t) (RootedPowers.layer F t i)
    (Equiv.refl _) (fun w => by cases w <;> rfl) k e l
  simpa [HubPathCopyTransport.index,Equiv.refl_apply,if_pos rfl,layer,HubPathCopyTransport.mapCopy,
    Sum.map_inr,SubdivisionPowers.edge] using congrArg (Sum.inr (α := Fin 2)) hh

lemma old_layer (j : Fin t) (w : RootedPowers.Vertex A R t) :
    ∃ i : Fin t, ∃ v : A ⊕ R, RootedPowers.layer F t i v=w := by
  cases w with
  | inl p => exact ⟨p.1,Sum.inl p.2,rfl⟩
  | inr r => exact ⟨j,Sum.inr r,rfl⟩

lemma edge_layer (j : Fin t) (e : GraphSubdivision.Edge (RootedPowers.graph F t)) :
    ∃ i : Fin t, ∃ d : GraphSubdivision.Edge F, SubdivisionPowers.edge F t i d=e := by
  obtain ⟨d,hd⟩ := SubdivisionPowers.edgeMap_surjective F t j e
  cases d with
  | inl d => exact ⟨d.1,d.2.val,hd⟩
  | inr d => exact ⟨j,d.val,hd⟩

lemma adj_layer (j : Fin t) {x y : HubPathSubdivision.Vertex (F := RootedPowers.graph F t) k}
    (h : (HubPathSubdivision.graph (RootedSuspension.powerColor c t) k).Adj x y) :
    ∃ i : Fin t, ∃ u v : HubPathSubdivision.Vertex (F := F) k,
      (HubPathSubdivision.graph c k).Adj u v ∧ layer F c k t i u=x ∧ layer F c k t i v=y := by
  rcases x with h₀ | w <;> rcases y with h₁ | z
  · exact h.elim
  · cases z with
    | inl z =>
      obtain ⟨i,v,rfl⟩ := old_layer F t j z
      refine ⟨i,Sum.inl h₀,Sum.inr (Sum.inl v),?_,rfl,rfl⟩
      change c v=h₀
      cases v <;> exact h
    | inr z => exact h.elim
  · cases w with
    | inl w =>
      obtain ⟨i,v,rfl⟩ := old_layer F t j w
      refine ⟨i,Sum.inr (Sum.inl v),Sum.inl h₁,?_,rfl,rfl⟩
      change c v=h₁
      cases v <;> exact h
    | inr w => exact h.elim
  · obtain ⟨e,l,he⟩ := h
    obtain ⟨i,d,rfl⟩ := edge_layer F t j e
    rcases Sym2.eq_iff.mp he with ⟨hw,hz⟩ | ⟨hw,hz⟩
    · refine ⟨i,Sum.inr (HubPathSubdivision.point c k d l.castSucc),
        Sum.inr (HubPathSubdivision.point c k d l.succ),HubPathSubdivision.coreEdge_adj c k d l,?_,?_⟩
      · exact (layer_point F c k t i d l.castSucc).trans (congrArg Sum.inr hw.symm)
      · exact (layer_point F c k t i d l.succ).trans (congrArg Sum.inr hz.symm)
    · refine ⟨i,Sum.inr (HubPathSubdivision.point c k d l.succ),
        Sum.inr (HubPathSubdivision.point c k d l.castSucc),(HubPathSubdivision.coreEdge_adj c k d l).symm,?_,?_⟩
      · exact (layer_point F c k t i d l.succ).trans (congrArg Sum.inr hw.symm)
      · exact (layer_point F c k t i d l.castSucc).trans (congrArg Sum.inr hz.symm)

end HubPathLayers

end -- HubPathLayers

section -- RootedHubPath

/- Promote all replacement-path interiors on root-root edges. -/
open Finset SimpleGraph
namespace RootedHubPath
set_option maxHeartbeats 3000000
universe u
variable {A R : Type u} (F : SimpleGraph (A ⊕ R)) (k : ℕ)
abbrev I := RootedSubdivision.internalEdge F
abbrev J := (RootedSubdivision.internalEdge F)ᶜ
abbrev Internal := A ⊕ (I F × Fin k)
abbrev Roots := Fin 2 ⊕ (R ⊕ (J F × Fin k))
abbrev Vertex := Internal F k ⊕ Roots F k

noncomputable def promote : Vertex F k ≃ RootedHubPathBasic.Vertex F k := by
  classical
  exact {
    toFun := Sum.elim
      (Sum.elim (fun a => Sum.inl (Sum.inl a)) (fun e => Sum.inl (Sum.inr (e.1.val,e.2))))
      (Sum.elim (fun i => Sum.inr (Sum.inr i))
        (Sum.elim (fun r => Sum.inr (Sum.inl r)) (fun e => Sum.inl (Sum.inr (e.1.val,e.2)))))
    invFun := Sum.elim
      (Sum.elim (fun a => Sum.inl (Sum.inl a))
        (fun e => if h : e.1∈I F then Sum.inl (Sum.inr (⟨e.1,h⟩,e.2))
          else Sum.inr (Sum.inr (Sum.inr (⟨e.1,h⟩,e.2)))))
      (Sum.elim (fun r => Sum.inr (Sum.inr (Sum.inl r))) (fun i => Sum.inr (Sum.inl i)))
    left_inv := by
      intro v
      rcases v with (a | ⟨e,k⟩) | i | (r | ⟨e,k⟩)
      · rfl
      · simp [e.property]
      · rfl
      · rfl
      · simp [(show e.val∉I F from e.property)]
    right_inv := by
      intro v
      rcases v with (a | ⟨e,k⟩) | (r | i)
      · rfl
      · dsimp; split_ifs <;> rfl
      · rfl
      · rfl }

noncomputable def graph (c : F.Coloring (Fin 2)) : SimpleGraph (Vertex F k) :=
  (RootedHubPathBasic.graph F k c).comap (promote F k)

noncomputable def color (c : F.Coloring (Fin 2)) : (graph F k c).Coloring (Fin 2) :=
  Coloring.mk (fun v => RootedHubPathBasic.color F k c (promote F k v))
    (fun h => (RootedHubPathBasic.color F k c).valid h)

def internalMap : Internal F k ↪ A ⊕ (RootedSubdivision.E F × Fin k) where
  toFun := Sum.map id (Prod.map Subtype.val id)
  inj' := by
    intro x y h
    cases x with
    | inl a => cases y <;> simp_all
    | inr e => cases y with
      | inl a => simp_all
      | inr f =>
        have h0 : (e.1.val,e.2)=(f.1.val,f.2) := Sum.inr.inj h
        have h1 : e.1.val=f.1.val := congrArg Prod.fst h0
        have h2 : e.2=f.2 := congrArg (fun p : RootedSubdivision.E F × Fin k => p.2) h0
        exact congrArg Sum.inr (Prod.ext (Subtype.ext h1) h2)

lemma promote_internal (a : Internal F k) :
    promote F k (Sum.inl a)=Sum.inl (internalMap F k a) := by cases a <;> rfl

lemma balanced [Fintype A] [Fintype R] [Fintype (RootedSubdivision.E F)]
    [Fintype (I F)] [Fintype (J F)] (c : F.Coloring (Fin 2)) (a b : ℕ)
    (hbalance : ∀ S : Finset A, b*S.card≤a*(RootedUnionDensity.incident F S).card)
    (S : Finset (Internal F k)) :
    (a+(k+1)*b)*S.card≤(a+k*b)*(RootedUnionDensity.incident (graph F k c) S).card :=
  RootPromotion.balanced (RootedHubPathBasic.graph F k c) (promote F k)
    (internalMap F k) (promote_internal F k) (a+k*b) (a+(k+1)*b)
    (RootedHubPathBasic.balanced F k c a b hbalance) S

def powerSplit (t : ℕ) : RootedPowers.Vertex (Internal F k) (Roots F k) t ≃
    Fin 2 ⊕ (RootedPowers.Vertex A R t ⊕ (((Fin t × I F) ⊕ J F) × Fin k)) where
  toFun := Sum.elim (fun p => match p.2 with
    | Sum.inl a => Sum.inr (Sum.inl (Sum.inl (p.1,a)))
    | Sum.inr e => Sum.inr (Sum.inr (Sum.inl (p.1,e.1),e.2)))
    (Sum.elim Sum.inl (Sum.elim (fun r => Sum.inr (Sum.inl (Sum.inr r)))
      (fun e => Sum.inr (Sum.inr (Sum.inr e.1,e.2)))))
  invFun := Sum.elim (fun i => Sum.inr (Sum.inl i))
    (Sum.elim (Sum.elim (fun p => Sum.inl (p.1,Sum.inl p.2)) (fun r => Sum.inr (Sum.inr (Sum.inl r))))
      (fun p => match p.1 with
        | Sum.inl e => Sum.inl (e.1,Sum.inr (e.2,p.2))
        | Sum.inr e => Sum.inr (Sum.inr (Sum.inr (e,p.2)))))
  left_inv := by
    intro v
    rcases v with ⟨i,a | ⟨e,k⟩⟩ | i | (r | ⟨e,k⟩) <;> rfl
  right_inv := by
    intro v
    rcases v with i | (⟨i,a⟩ | r) | ⟨(⟨i,e⟩ | e),k⟩ <;> rfl

noncomputable def powerEquiv (t : ℕ) (j : Fin t) :
    RootedPowers.Vertex (Internal F k) (Roots F k) t ≃
      HubPathSubdivision.Vertex (F := RootedPowers.graph F t) k :=
  (powerSplit F k t).trans (Equiv.sumCongr (Equiv.refl _)
    (Equiv.sumCongr (Equiv.refl _) (Equiv.prodCongr (SubdivisionPowers.edgeEquiv F t j) (Equiv.refl _))))


noncomputable def hubIso (c : F.Coloring (Fin 2)) : graph F k c ≃g HubPathSubdivision.graph c k where
  __ := (promote F k).trans (RootedHubPathBasic.move F k)
  map_rel_iff' := by intro x y; rfl

lemma power_layer (c : F.Coloring (Fin 2)) (t : ℕ) (i j : Fin t) (v : Vertex F k) :
    powerEquiv F k t j (RootedPowers.layer (graph F k c) t i v)=
      HubPathLayers.layer F c k t i (hubIso F k c v) := by
  rcases v with (a | ⟨e,l⟩) | h | (r | ⟨e,l⟩)
  all_goals try rfl
  change Sum.inr (Sum.inr (SubdivisionPowers.edge F t j e.val,l))=
    Sum.inr (Sum.inr (SubdivisionPowers.edge F t i e.val,l))
  exact congrArg Sum.inr (congrArg Sum.inr (Prod.ext
    ((SubdivisionPowers.edge_eq_iff F t j i e.val e.val).mpr ⟨rfl,Or.inr e.property⟩) rfl))

noncomputable def powerIso (c : F.Coloring (Fin 2)) (t : ℕ) (j : Fin t) :
    RootedPowers.graph (graph F k c) t ≃g
      HubPathSubdivision.graph (RootedSuspension.powerColor c t) k where
  __ := powerEquiv F k t j
  map_rel_iff' := by
    intro x y
    constructor
    · intro h
      obtain ⟨i,u,v,huv,hux,hvy⟩ := HubPathLayers.adj_layer F c k t j h
      have hu : RootedPowers.layer (graph F k c) t i ((hubIso F k c).symm u)=x := by
        apply (powerEquiv F k t j).injective
        rw [power_layer,(hubIso F k c).apply_symm_apply]
        exact hux
      have hv : RootedPowers.layer (graph F k c) t i ((hubIso F k c).symm v)=y := by
        apply (powerEquiv F k t j).injective
        rw [power_layer,(hubIso F k c).apply_symm_apply]
        exact hvy
      rw [← hu,← hv]
      exact (RootedPowers.layer (graph F k c) t i).toHom.map_rel'
        ((hubIso F k c).symm.toCopy.toHom.map_rel' huv)
    · intro h
      obtain ⟨i,u,v,huv,rfl,rfl⟩ := RootedSubdivision.adj_layer (graph F k c) t (Nat.zero_lt_of_lt j.isLt) h
      change (HubPathSubdivision.graph (RootedSuspension.powerColor c t) k).Adj
        (powerEquiv F k t j (RootedPowers.layer (graph F k c) t i u))
        (powerEquiv F k t j (RootedPowers.layer (graph F k c) t i v))
      rw [power_layer,power_layer]
      exact (HubPathLayers.layer F c k t i).toHom.map_rel' ((hubIso F k c).toCopy.toHom.map_rel' huv)

end RootedHubPath

end -- RootedHubPath

section -- ChainOperations

/- Reversal, restriction, and lower bounds for injective vertex chains. -/
open Finset SimpleGraph
namespace ChainCounting
universe u
variable {V : Type u} (G : SimpleGraph V)

lemma segment_injective {n : ℕ} {p : Chain G n} (hp : Function.Injective p.val)
    (a k : ℕ) (h : a+k ≤ n) : Function.Injective (segment G p a k h).val := by
  intro i j hij
  have h := congrArg Fin.val (hp hij)
  apply Fin.ext
  dsimp at h
  omega

def reverse {n : ℕ} (p : Chain G n) : Chain G n :=
  ⟨fun i => p.val i.rev,by intro i; simpa only [Fin.rev_castSucc,Fin.rev_succ] using (p.property i.rev).symm⟩

@[simp] lemma reverse_apply {n : ℕ} (p : Chain G n) (i : Fin (n+1)) :
    (reverse G p).val i = p.val i.rev := rfl
@[simp] lemma reverse_reverse {n : ℕ} (p : Chain G n) : reverse G (reverse G p) = p := by
  apply Subtype.ext
  funext i
  simp

lemma reverse_injective {n : ℕ} {p : Chain G n} (hp : Function.Injective p.val) :
    Function.Injective (reverse G p).val := hp.comp Fin.rev_injective

/-- All vertices strictly between the endpoints. -/
def interior [DecidableEq V] {n : ℕ} (p : Chain G n) : Finset V :=
  univ.image (fun i : Fin (n-1) => p.val ⟨i.val+1,by omega⟩)

lemma interior_card_le [DecidableEq V] {n : ℕ} (p : Chain G n) :
    (interior G p).card ≤ n-1 := (card_image_le).trans_eq (by simp)

lemma mem_interior [DecidableEq V] {n : ℕ} (p : Chain G n) (v : V) :
    v ∈ interior G p ↔ ∃ i : Fin (n+1), 0 < i.val ∧ i.val < n ∧ p.val i = v := by
  constructor
  · intro hv
    obtain ⟨i,_,hi⟩ := mem_image.mp hv
    exact ⟨⟨i.val+1,by omega⟩,(by change 0 < i.val+1; omega),
      (by change i.val+1 < n; omega),hi⟩
  · rintro ⟨i,hi0,hin,hiv⟩
    refine mem_image.mpr ⟨⟨i.val-1,by omega⟩,mem_univ _,?_⟩
    have he : (⟨(i.val-1)+1,by omega⟩ : Fin (n+1)) = i := Fin.ext (by change (i.val-1)+1 = i.val; omega)
    simpa only [he] using hiv

lemma endpoints_notMem_interior [DecidableEq V] {n : ℕ} {p : Chain G n}
    (hp : Function.Injective p.val) : p.val 0 ∉ interior G p ∧ p.val (Fin.last n) ∉ interior G p := by
  constructor
  · intro h
    obtain ⟨i,hi,_,he⟩ := (mem_interior G p _).mp h
    have hh := congrArg Fin.val (hp he)
    change i.val = 0 at hh
    omega
  · intro h
    obtain ⟨i,_,hi,he⟩ := (mem_interior G p _).mp h
    have := congrArg Fin.val (hp he)
    simp at this
    omega

lemma split_injective {n a k : ℕ} (h : a+k = n) :
    Function.Injective (fun p : Chain G n =>
      (segment G p 0 a (by omega),segment G p a k (by omega))) := by
  intro p q hpq
  apply Subtype.ext
  funext i
  by_cases hi : i.val ≤ a
  · have hh := congrArg (fun z : Chain G a × Chain G k => z.1.val ⟨i.val,by omega⟩) hpq
    simpa only [segment_apply,Nat.zero_add] using hh
  · have hh := congrArg (fun z : Chain G a × Chain G k => z.2.val ⟨i.val-a,by omega⟩) hpq
    have he : a+(i.val-a) = i.val := by omega
    simpa only [segment_apply,he] using hh

section Lower
variable [Fintype V] [DecidableEq V] [DecidableRel G.Adj]

/-- Append a fresh neighbor to an injective chain. -/
def snocPath {x : V} {n : ℕ} (p : PathFrom G x n) (y : V)
    (hxy : G.Adj (p.val.val.val (Fin.last n)) y) (hy : ∀ i, y ≠ p.val.val.val i) :
    PathFrom G x (n+1) := by
  let f : Fin (n+1+1) → V := Fin.snoc (α := fun _ => V) p.val.val.val y
  have hfold (i : Fin (n+1)) : f i.castSucc = p.val.val.val i := Fin.snoc_castSucc _ _ _
  have hflast : f (Fin.last (n+1)) = y := Fin.snoc_last _ _
  refine ⟨⟨⟨f,?_⟩,?_⟩,?_⟩
  · intro i
    refine Fin.lastCases ?_ (fun i => ?_) i
    · rw [Fin.succ_last,hflast,hfold]
      exact hxy
    · rw [← Fin.castSucc_succ,hfold,hfold]
      exact p.val.val.property i
  · exact (hfold 0).trans p.val.property
  · change Function.Injective f
    intro i j hij
    revert hij
    refine Fin.lastCases ?_ (fun i => ?_) i <;> refine Fin.lastCases ?_ (fun j => ?_) j
    · intro _; rfl
    · rw [hflast,hfold]
      exact fun h => (hy j h).elim
    · rw [hfold,hflast]
      exact fun h => (hy i h.symm).elim
    · rw [hfold,hfold]
      exact fun h => congrArg Fin.castSucc (p.property h)

@[simp] lemma snocPath_old {x : V} {n : ℕ} (p : PathFrom G x n) (y : V)
    (hxy : G.Adj (p.val.val.val (Fin.last n)) y) (hy : ∀ i, y ≠ p.val.val.val i)
    (i : Fin (n+1)) : (snocPath G p y hxy hy).val.val.val i.castSucc = p.val.val.val i := by
  simp only [snocPath,Fin.snoc_castSucc]

@[simp] lemma snocPath_last {x : V} {n : ℕ} (p : PathFrom G x n) (y : V)
    (hxy : G.Adj (p.val.val.val (Fin.last n)) y) (hy : ∀ i, y ≠ p.val.val.val i) :
    (snocPath G p y hxy hy).val.val.val (Fin.last (n+1)) = y := by
  simp only [snocPath,Fin.snoc_last]

lemma pathFrom_lower (d n : ℕ) (hdeg : ∀ v, d+n ≤ G.degree v) (x : V) :
    d^n ≤ Fintype.card (PathFrom G x n) := by
  classical
  induction n with
  | zero =>
    have hne : Nonempty (PathFrom G x 0) := ⟨⟨⟨⟨fun _ => x,fun i => Fin.elim0 i⟩,rfl⟩,
      fun i j _ => Fin.ext (by omega)⟩⟩
    simpa using Nat.succ_le_of_lt (Fintype.card_pos_iff.mpr hne : 0 < Fintype.card (PathFrom G x 0))
  | succ n ih =>
    have hl := ih (fun v => (Nat.add_le_add_left (Nat.le_succ n) d).trans (hdeg v))
    let allowed (p : PathFrom G x n) := G.neighborFinset (p.val.val.val (Fin.last n)) \
      univ.image p.val.val.val
    have hallow (p : PathFrom G x n) : d ≤ (allowed p).card := by
      have hh := card_le_card_sdiff_add_card (s := G.neighborFinset (p.val.val.val (Fin.last n)))
        (t := univ.image p.val.val.val)
      have hi : (univ.image p.val.val.val).card ≤ n+1 := card_image_le.trans_eq (by simp)
      rw [G.card_neighborFinset_eq_degree] at hh
      have hd := hdeg (p.val.val.val (Fin.last n))
      dsimp only [allowed]
      omega
    let f : (Σ p : PathFrom G x n, {y // y ∈ allowed p}) → PathFrom G x (n+1) := fun py =>
      snocPath G py.1 py.2.val
        ((G.mem_neighborFinset _ _).mp (mem_sdiff.mp py.2.property).1)
        (by intro i he; exact (mem_sdiff.mp py.2.property).2 (mem_image.mpr ⟨i,mem_univ _,he.symm⟩))
    have hf : Function.Injective f := by
      rintro ⟨p,y⟩ ⟨q,z⟩ he
      have hpq : p = q := by
        apply Subtype.ext
        apply Subtype.ext
        apply Subtype.ext
        funext i
        have hh := congrArg (fun r : PathFrom G x (n+1) => r.val.val.val i.castSucc) he
        simpa only [f,snocPath_old] using hh
      subst q
      have hyz : y = z := by
        apply Subtype.ext
        have hh := congrArg (fun r : PathFrom G x (n+1) => r.val.val.val (Fin.last (n+1))) he
        simpa only [f,snocPath_last] using hh
      subst z
      rfl
    calc
      d^(n+1) = d^n*d := pow_succ _ _
      _ ≤ Fintype.card (PathFrom G x n)*d := Nat.mul_le_mul_right _ hl
      _ = ∑ _p : PathFrom G x n, d := by simp
      _ ≤ ∑ p : PathFrom G x n, (allowed p).card := sum_le_sum (fun p _ => hallow p)
      _ = Fintype.card (Σ p : PathFrom G x n, {y // y ∈ allowed p}) := by simp
      _ ≤ _ := Fintype.card_le_of_injective f hf

end Lower
end ChainCounting

end -- ChainOperations

section -- FiniteLabelPacking

/- Packing arbitrary finite objects by avoiding their finite vertex labels. -/
open Finset
namespace FiniteLabelPacking
variable {A V : Type*} [DecidableEq V]

lemma select (ℓ k : ℕ) (P : Fin k → Set A) (L : A → Finset V)
    (hcard : ∀ i a, a ∈ P i → (L a).card ≤ ℓ)
    (havoid : ∀ i (S : Finset V), S.card ≤ ℓ*k → ∃ a ∈ P i, Disjoint (L a) S) :
    ∃ f : Fin k → A, (∀ i, f i ∈ P i) ∧
      ∀ i j, i ≠ j → Disjoint (L (f i)) (L (f j)) := by
  classical
  induction k with
  | zero => exact ⟨Fin.elim0,fun i => Fin.elim0 i,fun i => Fin.elim0 i⟩
  | succ k ih =>
    obtain ⟨f,hf,hdis⟩ := ih (fun i => P i.succ) (fun i a ha => hcard i.succ a ha)
      (fun i S hS => havoid i.succ S (by nlinarith))
    let S := univ.biUnion (fun i => L (f i))
    have hS : S.card ≤ ℓ*(k+1) := by
      calc
        _ ≤ ∑ i, (L (f i)).card := card_biUnion_le
        _ ≤ ∑ _i : Fin k, ℓ := sum_le_sum (fun i _ => hcard i.succ (f i) (hf i))
        _ = k*ℓ := by simp
        _ ≤ ℓ*(k+1) := by nlinarith
    obtain ⟨a,ha,haS⟩ := havoid 0 S hS
    let g : Fin (k+1) → A := Fin.cons a f
    have hg : ∀ i, g i ∈ P i := by
      intro i
      exact Fin.cases ha (fun i => hf i) i
    refine ⟨g,hg,?_⟩
    intro i j
    refine Fin.cases ?_ (fun i => ?_) i <;> refine Fin.cases ?_ (fun j => ?_) j
    · exact fun h => (h rfl).elim
    · intro _
      change Disjoint (L a) (L (f j))
      exact haS.mono_right (subset_biUnion_of_mem (fun i => L (f i)) (mem_univ j))
    · intro _
      change Disjoint (L (f i)) (L a)
      exact (haS.mono_right (subset_biUnion_of_mem (fun i => L (f i)) (mem_univ i))).symm
    · intro hij
      exact hdis i j (fun h => hij (congrArg Fin.succ h))

lemma select_fintype {I : Type*} [Fintype I] (ℓ : ℕ) (P : I → Set A) (L : A → Finset V)
    (hcard : ∀ i a, a ∈ P i → (L a).card ≤ ℓ)
    (havoid : ∀ i (S : Finset V), S.card ≤ ℓ*Fintype.card I → ∃ a ∈ P i, Disjoint (L a) S) :
    ∃ f : I → A, (∀ i, f i ∈ P i) ∧
      ∀ i j, i ≠ j → Disjoint (L (f i)) (L (f j)) := by
  classical
  let e := (Fintype.equivFin I).symm
  obtain ⟨f,hf,hdis⟩ := select ℓ (Fintype.card I) (fun i => P (e i)) L
    (fun i a ha => hcard (e i) a ha) (fun i S hS => havoid (e i) S hS)
  refine ⟨fun i => f (e.symm i),fun i => by simpa only [Equiv.apply_symm_apply] using hf (e.symm i),?_⟩
  intro i j hij
  exact hdis (e.symm i) (e.symm j) (fun h => hij (e.symm.injective h))

lemma hit_le [Fintype A] (P : Finset A) (L : A → Finset V) (B : ℕ)
    (hB : ∀ v, (P.filter (fun a => v ∈ L a)).card ≤ B) (S : Finset V) :
    (P.filter (fun a => ¬ Disjoint (L a) S)).card ≤ S.card*B := by
  classical
  have hsub : P.filter (fun a => ¬ Disjoint (L a) S) ⊆
      S.biUnion (fun v => P.filter (fun a => v ∈ L a)) := by
    intro a ha
    have hp := (mem_filter.mp ha).1
    have hd := (mem_filter.mp ha).2
    rw [Finset.disjoint_left] at hd
    push_neg at hd
    obtain ⟨v,hv,hvS⟩ := hd
    exact mem_biUnion.mpr ⟨v,hvS,mem_filter.mpr ⟨hp,hv⟩⟩
  calc
    _ ≤ _ := card_le_card hsub
    _ ≤ ∑ v ∈ S, (P.filter (fun a => v ∈ L a)).card := card_biUnion_le
    _ ≤ ∑ _v ∈ S, B := sum_le_sum (fun v _ => hB v)
    _ = _ := by simp

lemma avoid_of_card [Fintype A] (P : Finset A) (L : A → Finset V) (B : ℕ)
    (hB : ∀ v, (P.filter (fun a => v ∈ L a)).card ≤ B) (S : Finset V)
    (hcard : S.card*B < P.card) : ∃ a ∈ P, Disjoint (L a) S := by
  classical
  have hh := (hit_le P L B hB S).trans_lt hcard
  obtain ⟨a,ha,haS⟩ := exists_mem_notMem_of_card_lt_card hh
  refine ⟨a,ha,?_⟩
  by_contra hd
  exact haS (mem_filter.mpr ⟨ha,hd⟩)

end FiniteLabelPacking

end -- FiniteLabelPacking

section -- GoodChains

/- Recursive good chains and the bounded-fiber mechanism for parallel paths. -/
open Finset SimpleGraph ChainCounting
namespace GoodChains
set_option maxHeartbeats 2000000
set_option synthInstance.maxHeartbeats 200000
universe u
variable {V : Type u} [Fintype V] (G : SimpleGraph V)
noncomputable section
local instance : DecidableEq V := Classical.decEq V
local instance : DecidableRel G.Adj := Classical.decRel _

noncomputable def Good (L : ℕ → ℕ) (n : ℕ) (p : Chain G n) : Prop := by
  classical
  let A (q : Chain G n) : Prop := Function.Injective q.val ∧
    ∀ a k : ℕ, (hk : k < n) → (h : a+k ≤ n) → Good L k (segment G q a k h)
  exact A p ∧ (univ.filter (fun q : Chain G n => A q ∧ q.val 0 = p.val 0 ∧
    q.val (Fin.last n) = p.val (Fin.last n))).card ≤ L n
termination_by n

noncomputable def Admissible (L : ℕ → ℕ) (n : ℕ) (p : Chain G n) : Prop :=
  Function.Injective p.val ∧
    ∀ a k : ℕ, (hk : k < n) → (h : a+k ≤ n) → Good G L k (segment G p a k h)

noncomputable def fiber (L : ℕ → ℕ) (n : ℕ) (x y : V) : Finset (Chain G n) := by
  classical
  exact univ.filter (fun p => Admissible G L n p ∧ p.val 0 = x ∧ p.val (Fin.last n) = y)

noncomputable def goodFiber (L : ℕ → ℕ) (n : ℕ) (x y : V) : Finset (Chain G n) := by
  classical
  exact univ.filter (fun p => Good G L n p ∧ p.val 0 = x ∧ p.val (Fin.last n) = y)

lemma good_iff (L : ℕ → ℕ) (n : ℕ) (p : Chain G n) :
    Good G L n p ↔ Admissible G L n p ∧ (fiber G L n (p.val 0) (p.val (Fin.last n))).card ≤ L n := by
  classical
  rw [Good]
  simp only [fiber,Admissible]

lemma mem_fiber (L : ℕ → ℕ) (n : ℕ) (x y : V) (p : Chain G n) :
    p ∈ fiber G L n x y ↔ Admissible G L n p ∧ p.val 0 = x ∧ p.val (Fin.last n) = y := by
  classical
  simp only [fiber,mem_filter,mem_univ,true_and]

lemma mem_goodFiber (L : ℕ → ℕ) (n : ℕ) (x y : V) (p : Chain G n) :
    p ∈ goodFiber G L n x y ↔ Good G L n p ∧ p.val 0 = x ∧ p.val (Fin.last n) = y := by
  classical
  simp only [goodFiber,mem_filter,mem_univ,true_and]

lemma goodFiber_le (L : ℕ → ℕ) (n : ℕ) (x y : V) : (goodFiber G L n x y).card ≤ L n := by
  classical
  by_cases h : (goodFiber G L n x y).Nonempty
  · obtain ⟨p,hp⟩ := h
    obtain ⟨hp,hx,hy⟩ := (mem_goodFiber G L n x y p).mp hp
    have hb := ((good_iff G L n p).mp hp).2
    rw [hx,hy] at hb
    apply le_trans (card_le_card (t := fiber G L n x y) ?_) hb
    intro q hq
    obtain ⟨hq,hqx,hqy⟩ := (mem_goodFiber G L n x y q).mp hq
    exact (mem_fiber G L n x y q).mpr ⟨((good_iff G L n q).mp hq).1,hqx,hqy⟩
  · rw [not_nonempty_iff_eq_empty.mp h,card_empty]
    exact Nat.zero_le _

lemma coordinate_le (L : ℕ → ℕ) (n : ℕ) (x y v : V) (i : Fin (n-1)) :
    ((fiber G L n x y).filter (fun p => p.val ⟨i.val+1,by omega⟩ = v)).card ≤
      L (i.val+1) * L (n-(i.val+1)) := by
  classical
  let P := (fiber G L n x y).filter (fun p => p.val ⟨i.val+1,by omega⟩ = v)
  let left (p : P) : {q // q ∈ goodFiber G L (i.val+1) x v} := by
    refine ⟨segment G p.val 0 (i.val+1) (by omega),?_⟩
    obtain ⟨hp,hx,hy⟩ := (mem_fiber G L n x y p.val).mp (mem_filter.mp p.property).1
    apply (mem_goodFiber G L (i.val+1) x v _).mpr
    refine ⟨hp.2 0 (i.val+1) (by omega) (by omega),hx,?_⟩
    simpa only [segment_apply,Fin.val_last,Nat.zero_add] using (mem_filter.mp p.property).2
  let right (p : P) : {q // q ∈ goodFiber G L (n-(i.val+1)) v y} := by
    refine ⟨segment G p.val (i.val+1) (n-(i.val+1)) (by omega),?_⟩
    obtain ⟨hp,hx,hy⟩ := (mem_fiber G L n x y p.val).mp (mem_filter.mp p.property).1
    apply (mem_goodFiber G L (n-(i.val+1)) v y _).mpr
    refine ⟨hp.2 (i.val+1) (n-(i.val+1)) (by omega) (by omega),(mem_filter.mp p.property).2,?_⟩
    have he : i.val+1+(n-(i.val+1)) = n := by omega
    simpa only [segment_apply,Fin.val_last,he,Fin.last] using hy
  let f (p : P) := (left p,right p)
  have hf : Function.Injective f := by
    intro p q hpq
    apply Subtype.ext
    apply split_injective G (show (i.val+1)+(n-(i.val+1)) = n by omega)
    exact congrArg (fun z : {q // q ∈ goodFiber G L (i.val+1) x v} ×
      {q // q ∈ goodFiber G L (n-(i.val+1)) v y} => (z.1.val,z.2.val)) hpq
  calc
    _ = Fintype.card P := (Fintype.card_coe _).symm
    _ ≤ Fintype.card ({q // q ∈ goodFiber G L (i.val+1) x v} ×
        {q // q ∈ goodFiber G L (n-(i.val+1)) v y}) := Fintype.card_le_of_injective f hf
    _ = (goodFiber G L (i.val+1) x v).card * (goodFiber G L (n-(i.val+1)) v y).card := by simp
    _ ≤ _ := Nat.mul_le_mul (goodFiber_le G L _ _ _) (goodFiber_le G L _ _ _)

lemma interior_incidence_le (L : ℕ → ℕ) (hL : Monotone L) (n : ℕ) (x y v : V) :
    ((fiber G L n x y).filter (fun p => v ∈ interior G p)).card ≤ (n-1)*(L (n-1))^2 := by
  classical
  let P (i : Fin (n-1)) := (fiber G L n x y).filter (fun p => p.val ⟨i.val+1,by omega⟩ = v)
  have hsub : (fiber G L n x y).filter (fun p => v ∈ interior G p) ⊆ univ.biUnion P := by
    intro p hp
    obtain ⟨i,_,hi⟩ := mem_image.mp (mem_filter.mp hp).2
    exact mem_biUnion.mpr ⟨i,mem_univ _,mem_filter.mpr ⟨(mem_filter.mp hp).1,hi⟩⟩
  have hP (i : Fin (n-1)) : (P i).card ≤ (L (n-1))^2 := by
    apply (coordinate_le G L n x y v i).trans
    rw [pow_two]
    exact Nat.mul_le_mul (hL (by omega)) (hL (by omega))
  calc
    _ ≤ _ := card_le_card hsub
    _ ≤ ∑ i, (P i).card := card_biUnion_le
    _ ≤ ∑ _i : Fin (n-1), (L (n-1))^2 := sum_le_sum (fun i _ => hP i)
    _ = _ := by simp

end
end GoodChains

end -- GoodChains

section -- ThetaChains

/- Thresholds and a path-family formulation of theta graphs. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace ThetaChains
set_option maxHeartbeats 1000000
universe u

def threshold (B : ℕ) : ℕ → ℕ
  | 0 => 1
  | n+1 => (n+1)*(B+1)*(threshold B n)^2+1

lemma threshold_pos (B n : ℕ) : 0 < threshold B n := by
  cases n <;> simp [threshold]

lemma threshold_mono (B : ℕ) : Monotone (threshold B) := by
  apply monotone_nat_of_le_succ
  intro n
  rw [threshold]
  have hp := threshold_pos B n
  have hsq : threshold B n ≤ (threshold B n)^2 := by nlinarith
  have hc : 1 ≤ (n+1)*(B+1) := by nlinarith
  have hm := Nat.mul_le_mul_right ((threshold B n)^2) hc
  nlinarith

lemma threshold_large (B n : ℕ) (hn : 0 < n) :
    n*B*(threshold B (n-1))^2 < threshold B n := by
  obtain ⟨m,rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : n ≠ 0)
  simp only [Nat.succ_sub_one,threshold]
  nlinarith

variable {V : Type u} (G : SimpleGraph V)


noncomputable section
local instance : DecidableEq V := Classical.decEq V
variable [Fintype V]

lemma fiber_avoiding (B n : ℕ) (hn : 0 < n) (x y : V)
    (hheavy : threshold B n < (fiber G (threshold B) n x y).card)
    (S : Finset V) (hS : S.card ≤ B) :
    ∃ p ∈ fiber G (threshold B) n x y, Disjoint (interior G p) S := by
  classical
  apply FiniteLabelPacking.avoid_of_card (fiber G (threshold B) n x y) (interior G)
    ((n-1)*(threshold B (n-1))^2)
    (fun v => interior_incidence_le G (threshold B) (threshold_mono B) n x y v) S
  have hh := Nat.mul_le_mul hS (Nat.sub_le n 1)
  have hm := Nat.mul_le_mul_right ((threshold B (n-1))^2) hh
  have hl := (threshold_large B n hn).trans hheavy
  nlinarith only [hm,hl]


end
end ThetaChains

end -- ThetaChains

section -- ChainComposition

/- Compatibility of chain restriction and reversal. -/
open Finset SimpleGraph
namespace ChainCounting
universe u
variable {V : Type u} (G : SimpleGraph V)

lemma segment_segment {n : ℕ} (p : Chain G n) (a k b j : ℕ)
    (h : a+k ≤ n) (h' : b+j ≤ k) :
    segment G (segment G p a k h) b j h' = segment G p (a+b) j (by omega) := by
  apply Subtype.ext
  funext i
  simp only [segment_apply]
  apply congrArg p.val
  apply Fin.ext
  simp only [Fin.val_mk]
  omega

lemma segment_self {n : ℕ} (p : Chain G n) : segment G p 0 n (by omega) = p := by
  apply Subtype.ext
  funext i
  simp only [segment_apply,Nat.zero_add]

lemma reverse_segment {n : ℕ} (p : Chain G n) (a k : ℕ) (h : a+k ≤ n) :
    segment G (reverse G p) a k h =
      reverse G (segment G p (n-(a+k)) k (by omega)) := by
  apply Subtype.ext
  funext i
  simp only [segment_apply,reverse_apply]
  apply congrArg p.val
  apply Fin.ext
  simp only [Fin.val_rev,Fin.val_mk]
  omega

@[simp] lemma reverse_start {n : ℕ} (p : Chain G n) : (reverse G p).val 0 = p.val (Fin.last n) := by
  simp [reverse_apply]
@[simp] lemma reverse_last {n : ℕ} (p : Chain G n) : (reverse G p).val (Fin.last n) = p.val 0 := by
  simp [reverse_apply]

end ChainCounting

end -- ChainComposition

section -- GoodChainReversal

/- Symmetry of good and admissible chains, and minimal bad-subchain witnesses. -/
open Finset SimpleGraph ChainCounting
namespace GoodChains
set_option maxHeartbeats 1000000
universe u
variable {V : Type u} [Fintype V] (G : SimpleGraph V)
noncomputable section
local instance : DecidableEq V := Classical.decEq V

lemma fiber_card_reverse (L : ℕ → ℕ) (n : ℕ)
    (hA : ∀ p : Chain G n, Admissible G L n (reverse G p) ↔ Admissible G L n p)
    (x y : V) : (fiber G L n x y).card = (fiber G L n y x).card := by
  classical
  have hi : Function.Injective (reverse G : Chain G n → Chain G n) := by
    intro p q h
    have hh := congrArg (reverse G) h
    simpa using hh
  have he : (fiber G L n x y).image (reverse G) = fiber G L n y x := by
    ext p
    constructor
    · intro hp
      obtain ⟨q,hq,rfl⟩ := mem_image.mp hp
      obtain ⟨hq,hx,hy⟩ := (mem_fiber G L n x y q).mp hq
      apply (mem_fiber G L n y x _).mpr
      exact ⟨(hA q).mpr hq,by simpa using hy,by simpa using hx⟩
    · intro hp
      obtain ⟨hp,hy,hx⟩ := (mem_fiber G L n y x p).mp hp
      refine mem_image.mpr ⟨reverse G p,?_,reverse_reverse G p⟩
      apply (mem_fiber G L n x y _).mpr
      exact ⟨(hA p).mpr hp,by simpa using hx,by simpa using hy⟩
  rw [← he,card_image_of_injective _ hi]

lemma good_reverse (L : ℕ → ℕ) (n : ℕ) (p : Chain G n) :
    Good G L n (reverse G p) ↔ Good G L n p := by
  classical
  induction n using Nat.strong_induction_on with
  | h n ih =>
    have hforward : ∀ p : Chain G n, Admissible G L n p → Admissible G L n (reverse G p) := by
      intro p hp
      refine ⟨reverse_injective G hp.1,?_⟩
      intro a k hk h
      rw [reverse_segment]
      exact (ih k hk _).mpr (hp.2 (n-(a+k)) k hk (by omega))
    have hA (p : Chain G n) : Admissible G L n (reverse G p) ↔ Admissible G L n p := by
      constructor
      · intro hp
        simpa using hforward (reverse G p) hp
      · exact hforward p
    rw [good_iff,good_iff,hA,reverse_start,reverse_last,
      fiber_card_reverse G L n hA (p.val (Fin.last n)) (p.val 0)]

lemma admissible_reverse (L : ℕ → ℕ) (n : ℕ) (p : Chain G n) :
    Admissible G L n (reverse G p) ↔ Admissible G L n p := by
  have hf : ∀ p : Chain G n, Admissible G L n p → Admissible G L n (reverse G p) := by
    intro p hp
    refine ⟨reverse_injective G hp.1,?_⟩
    intro a k hk h
    rw [reverse_segment]
    exact (good_reverse G L k _).mpr (hp.2 (n-(a+k)) k hk (by omega))
  exactfun hp => by simpa using hf (reverse G p) hp,hf p⟩

lemma fiber_symmetric (L : ℕ → ℕ) (n : ℕ) (x y : V) :
    (fiber G L n x y).card = (fiber G L n y x).card :=
  fiber_card_reverse G L n (admissible_reverse G L n) x y

/-- A bad injective chain contains an admissible chain with a heavy endpoint fiber. -/
lemma bad_witness (L : ℕ → ℕ) (n : ℕ) (p : Chain G n)
    (hp : Function.Injective p.val) (hbad : ¬ Good G L n p) :
    ∃ a j : ℕ, ∃ h : a+j ≤ n, Admissible G L j (segment G p a j h) ∧
      L j < (fiber G L j ((segment G p a j h).val 0)
        ((segment G p a j h).val (Fin.last j))).card := by
  classical
  induction n using Nat.strong_induction_on with
  | h n ih =>
    by_cases hA : Admissible G L n p
    · have hh : L n < (fiber G L n (p.val 0) (p.val (Fin.last n))).card := by
        by_contra hh
        exact hbad ((good_iff G L n p).mpr ⟨hA,by omega⟩)
      exact ⟨0,n,by omega,by simpa [segment_self] using hA,by simpa [segment_self] using hh⟩
    · have hs : ¬ ∀ a k : ℕ, (hk : k < n) → (h : a+k ≤ n) → Good G L k (segment G p a k h) := by
        exact fun hs => hA ⟨hp,hs⟩
      push_neg at hs
      obtain ⟨a,k,hk,hlen,hkbad⟩ := hs
      obtain ⟨b,j,hbj,hj,hheavy⟩ := ih k hk (segment G p a k hlen)
        (segment_injective G hp a k hlen) hkbad
      refine ⟨a+b,j,by omega,?_,?_⟩
      · simpa only [segment_segment] using hj
      · simpa only [segment_segment] using hheavy


end
end GoodChains

end -- GoodChainReversal

section -- ChainExtensionCounts

/- Extending prescribed consecutive subchains costs at most one degree choice per
additional edge. -/
open Finset SimpleGraph
namespace ChainCounting
set_option maxHeartbeats 1000000
universe u
variable {V : Type u} [Fintype V] (G : SimpleGraph V)
noncomputable section
local instance : DecidableEq V := Classical.decEq V
local instance : DecidableRel G.Adj := Classical.decRel _

def extensions (n a j : ℕ) (h : a+j ≤ n) (P : Finset (Chain G j)) : Finset (Chain G n) := by
  classical
  exact univ.filter (fun p => segment G p a j h ∈ P)

lemma extensions_le (D n a j : ℕ) (hD : ∀ v, G.degree v ≤ D) (h : a+j ≤ n)
    (P : Finset (Chain G j)) : (extensions G n a j h P).card ≤ P.card*D^(n-j) := by
  classical
  let E := extensions G n a j h P
  let center (p : E) : P := ⟨segment G p.val a j h,(mem_filter.mp p.property).2⟩
  let left (p : E) : From G ((center p).val.val 0) a :=
    ⟨reverse G (segment G p.val 0 a (by omega)),by simp [center,reverse_start,segment_apply]⟩
  let right (p : E) : From G ((center p).val.val (Fin.last j)) (n-(a+j)) :=
    ⟨segment G p.val (a+j) (n-(a+j)) (by omega),rfl⟩
  let C (q : P) := From G (q.val.val 0) a × From G (q.val.val (Fin.last j)) (n-(a+j))
  let f : E → Σ q : P, C q := fun p => ⟨center p,(left p,right p)⟩
  have hf : Function.Injective f := by
    intro p q hpq
    apply Subtype.ext
    apply Subtype.ext
    funext i
    by_cases hi : i.val ≤ a
    · have hh := congrArg (fun z : Σ q : P, C q =>
        (reverse G z.2.1.val).val ⟨i.val,by omega⟩) hpq
      simpa only [f,left,reverse_reverse,segment_apply,Nat.zero_add] using hh
    · by_cases hij : i.val ≤ a+j
      · have hh := congrArg (fun z : Σ q : P, C q => z.1.val.val ⟨i.val-a,by omega⟩) hpq
        have he : a+(i.val-a) = i.val := by omega
        simpa only [f,center,segment_apply,he] using hh
      · have hh := congrArg (fun z : Σ q : P, C q => z.2.2.val.val ⟨i.val-(a+j),by omega⟩) hpq
        have he : a+j+(i.val-(a+j)) = i.val := by omega
        simpa only [f,right,segment_apply,he] using hh
  have hC (q : P) : Fintype.card (C q) ≤ D^(n-j) := by
    calc
      _ = Fintype.card (From G (q.val.val 0) a) * Fintype.card (From G (q.val.val (Fin.last j)) (n-(a+j))) := Fintype.card_prod _ _
      _ ≤ D^a*D^(n-(a+j)) := Nat.mul_le_mul (from_le G D hD _ _) (from_le G D hD _ _)
      _ = _ := by rw [← pow_add]; congr 1; omega
  calc
    _ = Fintype.card E := (Fintype.card_coe _).symm
    _ ≤ Fintype.card (Σ q : P, C q) := Fintype.card_le_of_injective f hf
    _ = ∑ q : P, Fintype.card (C q) := Fintype.card_sigma
    _ ≤ ∑ _q : P, D^(n-j) := sum_le_sum (fun q _ => hC q)
    _ = _ := by simp

end
end ChainCounting

end -- ChainExtensionCounts

section -- BasicChainCounting

/- Counting all simple chains by good endpoint fibers and extensions of heavy subchains. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace GeneralThetaCounting
set_option maxHeartbeats 2000000
universe u
variable {V : Type u} [Fintype V] (G : SimpleGraph V)
noncomputable section
local instance : DecidableEq V := Classical.decEq V
local instance : DecidableRel G.Adj := Classical.decRel _

def paths (k : ℕ) : Finset (Chain G k) := by
  classical
  exact univ.filter (fun p => Function.Injective p.val)

lemma paths_lower (d k : ℕ) (hd : ∀ v, d+k ≤ G.degree v) :
    Fintype.card V*d^k ≤ (paths G k).card := by
  classical
  let f : (Σ x : V, PathFrom G x k) → (paths G k) := fun xp =>
    ⟨xp.2.val.val,mem_filter.mpr ⟨mem_univ _,xp.2.property⟩⟩
  have hf : Function.Injective f := by
    rintro ⟨x,p⟩ ⟨y,q⟩ he
    have hpq : p.val.val = q.val.val := congrArg (fun z : paths G k => z.val) he
    have hxy : x = y := p.val.property.symm.trans ((congrArg (fun z : Chain G k => z.val 0) hpq).trans q.val.property)
    subst y
    have hpq' : p = q := Subtype.ext (Subtype.ext hpq)
    subst q
    rfl
  calc
    _ = ∑ _x : V, d^k := by simp
    _ ≤ ∑ x : V, Fintype.card (PathFrom G x k) := sum_le_sum (fun x _ => pathFrom_lower G d k hd x)
    _ = Fintype.card (Σ x : V, PathFrom G x k) := Fintype.card_sigma.symm
    _ ≤ Fintype.card (paths G k) := Fintype.card_le_of_injective f hf
    _ = _ := Fintype.card_coe _

lemma small_fiber (L : ℕ → ℕ) (j : ℕ) (hj : j ≤ 1) (x y : V) :
    (fiber G L j x y).card ≤ 1 := by
  classical
  apply card_le_one.mpr
  intro p hp q hq
  obtain ⟨_,hpx,hpy⟩ := (mem_fiber G L j x y p).mp hp
  obtain ⟨_,hqx,hqy⟩ := (mem_fiber G L j x y q).mp hq
  apply Subtype.ext
  funext i
  by_cases hi : i.val = 0
  · have hi' : i = 0 := Fin.ext hi
    subst i
    exact hpx.trans hqx.symm
  · have hi' : i = Fin.last j := Fin.ext (by change i.val = j; omega)
    subst i
    exact hpy.trans hqy.symm

lemma heavy_length (B j : ℕ) (x y : V)
    (h : threshold B j < (fiber G (threshold B) j x y).card) : 2 ≤ j := by
  by_contra hj
  have hsmall := small_fiber G (threshold B) j (by omega) x y
  have hpos := threshold_pos B j
  omega

end
end GeneralThetaCounting

end -- BasicChainCounting


section -- FiniteDisjointSubfamily

/- A large pairwise-disjoint-label subfamily with explicit cardinality loss. -/
open Finset
namespace FiniteDisjointSubfamily
set_option maxHeartbeats 1500000
universe u v

lemma select {A : Type u} {V : Type v} [Fintype A] [DecidableEq V]
    (P : Finset A) (labels : A → Finset V) (a M : ℕ)
    (hne : ∀ p∈P, (labels p).Nonempty)
    (hsize : ∀ p∈P, (labels p).card≤a)
    (hM : ∀ v, (P.filter (fun p => v∈labels p)).card≤M) :
    ∃ Q : Finset A, Q⊆P ∧ (∀ p∈Q, ∀ q∈Q, p≠q → Disjoint (labels p) (labels q)) ∧
      P.card≤(a*M)*Q.card := by
  classical
  let S := P.powerset.filter (fun Q => ∀ p∈Q, ∀ q∈Q, p≠q → Disjoint (labels p) (labels q))
  have hS : S.Nonempty := ⟨∅,by simp [S]⟩
  obtain ⟨Q,hQ,hmax⟩ := exists_max_image S Finset.card hS
  have hQP : Q⊆P := mem_powerset.mp (mem_filter.mp hQ).1
  have hQdis := (mem_filter.mp hQ).2
  let U := Q.biUnion labels
  have hcover (p : A) (hp : p∈P) : ¬Disjoint (labels p) U := by
    intro hd
    have hdis (q : A) (hq : q∈Q) : Disjoint (labels p) (labels q) :=
      (disjoint_biUnion_right _ _ _).mp hd q hq
    have hpQ : p∉Q := by
      intro hpQ
      obtain ⟨v,hv⟩ := hne p hp
      exact disjoint_left.mp (hdis p hpQ) hv hv
    have hmem : insert p Q∈S := by
      apply mem_filter.mpr
      refine ⟨mem_powerset.mpr (insert_subset hp hQP),?_⟩
      intro r hr s hs hrs
      rcases mem_insert.mp hr with hr | hr
      · subst r
        rcases mem_insert.mp hs with hs | hs
        · subst s
          exact (hrs rfl).elim
        · exact hdis s hs
      · rcases mem_insert.mp hs with hs | hs
        · subst s
          exact (hdis r hr).symm
        · exact hQdis r hr s hs hrs
    have hh := hmax (insert p Q) hmem
    rw [card_insert_of_notMem hpQ] at hh
    omega
  have hfilter : P.filter (fun p => ¬Disjoint (labels p) U)=P := by
    ext p
    simp only [mem_filter,and_iff_left_iff_imp]
    exact hcover p
  have hU : U.card≤a*Q.card := by
    apply card_biUnion_le.trans
    calc
      (∑ p∈Q, (labels p).card) ≤ ∑ _p∈Q, a := sum_le_sum (fun p hp => hsize p (hQP hp))
      _ = _ := by simp [Nat.mul_comm]
  have hhit := FiniteLabelPacking.hit_le P labels M hM U
  rw [hfilter] at hhit
  refine ⟨Q,hQP,hQdis,?_⟩
  exact (hhit.trans (Nat.mul_le_mul_right M hU)).trans_eq (by ring)

end FiniteDisjointSubfamily

end -- FiniteDisjointSubfamily

section -- HubLightPaths

/- Paths with all subpaths up to the core replacement length good.
The longer near-full subpaths are deliberately not required to be good. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace HubLightPaths
set_option maxHeartbeats 2500000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V]
local instance : DecidableEq V := Classical.decEq _
variable (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

abbrev Path (k : ℕ) := Chain H (k+3)

def Good (k : ℕ) (L : ℕ → ℕ) (p : Path H k) : Prop :=
  Function.Injective p.val ∧ ∀ a j : ℕ, (hj : j≤k+1) → (hlen : a+j≤k+3) →
    GoodChains.Good H L j (segment H p a j hlen)

def good (k : ℕ) (L : ℕ → ℕ) : Finset (Path H k) := by
  classical
  exact univ.filter (Good H k L)

def links (k : ℕ) (L : ℕ → ℕ) (x y : V) : Finset (Path H k) :=
  (good H k L).filter (fun p => p.val 0=x ∧ p.val (Fin.last (k+3))=y)

lemma mem_links (k : ℕ) (L : ℕ → ℕ) (x y : V) (p : Path H k) :
    p∈links H k L x y ↔ Good H k L p ∧ p.val 0=x ∧ p.val (Fin.last (k+3))=y := by
  simp only [links,good,mem_filter,mem_univ,true_and]

def first (k : ℕ) (p : Path H k) : V := p.val ⟨1,by omega⟩
def last (k : ℕ) (p : Path H k) : V := p.val ⟨k+2,by omega⟩
def middle (k : ℕ) (p : Path H k) (i : Fin k) : V := p.val ⟨i.val+2,by omega⟩

def core (k : ℕ) (p : Path H k) : Chain H (k+1) := segment H p 1 (k+1) (by omega)

lemma pair_bound (k : ℕ) (L : ℕ → ℕ) (x y : V) (z : V × V) :
    ((links H k L x y).filter (fun p => (first H k p,last H k p)=z)).card≤L (k+1) := by
  let P := (links H k L x y).filter (fun p => (first H k p,last H k p)=z)
  apply (card_le_card_of_injOn (core H k) ?_ ?_).trans (goodFiber_le H L (k+1) z.1 z.2)
  · intro p hp
    have hh := (mem_links H k L x y p).mp (mem_filter.mp hp).1
    have he := (mem_filter.mp hp).2
    apply (mem_goodFiber H L (k+1) z.1 z.2 _).mpr
    refine ⟨hh.1.2 1 (k+1) (by omega) (by omega),?_,?_⟩
    · exact congrArg Prod.fst he
    · simpa only [core,segment_apply,Fin.val_last,last,Nat.add_comm,Nat.add_left_comm,Nat.add_assoc]
        using congrArg Prod.snd he
  · intro p hp q hq he
    have hp' := (mem_links H k L x y p).mp (mem_filter.mp hp).1
    have hq' := (mem_links H k L x y q).mp (mem_filter.mp hq).1
    apply Subtype.ext
    funext i
    by_cases hi0 : i.val=0
    · have hi : i=0 := Fin.ext hi0
      subst i
      exact hp'.2.1.trans hq'.2.1.symm
    · by_cases hil : i.val=k+3
      · have hi : i=Fin.last (k+3) := Fin.ext hil
        subst i
        exact hp'.2.2.trans hq'.2.2.symm
      · have hh := congrArg (fun p : Chain H (k+1) => p.val ⟨i.val-1,by have := i.isLt; omega⟩) he
        have hidx : 1+(i.val-1)=i.val := by omega
        simpa only [core,segment_apply,hidx] using hh

lemma coordinate_bound (k : ℕ) (L : ℕ → ℕ) (x y v : V) (i : Fin k) :
    ((links H k L x y).filter (fun p => middle H k p i=v)).card≤L (i.val+2)*L (k+1-i.val) := by
  let P := (links H k L x y).filter (fun p => middle H k p i=v)
  let left (p : P) : {q // q∈goodFiber H L (i.val+2) x v} := by
    refine ⟨segment H p.val 0 (i.val+2) (by omega),?_⟩
    have hp := (mem_links H k L x y p.val).mp (mem_filter.mp p.property).1
    apply (mem_goodFiber H L (i.val+2) x v _).mpr
    refine ⟨hp.1.2 0 (i.val+2) (by omega) (by omega),hp.2.1,?_⟩
    simpa only [segment_apply,Fin.val_last,Nat.zero_add,middle] using (mem_filter.mp p.property).2
  let right (p : P) : {q // q∈goodFiber H L (k+1-i.val) v y} := by
    refine ⟨segment H p.val (i.val+2) (k+1-i.val) (by omega),?_⟩
    have hp := (mem_links H k L x y p.val).mp (mem_filter.mp p.property).1
    apply (mem_goodFiber H L (k+1-i.val) v y _).mpr
    refine ⟨hp.1.2 (i.val+2) (k+1-i.val) (by omega) (by omega),(mem_filter.mp p.property).2,?_⟩
    have he : i.val+2+(k+1-i.val)=k+3 := by omega
    simpa only [segment_apply,Fin.val_last,he,Fin.last] using hp.2.2
  let f (p : P) := (left p,right p)
  have hf : Function.Injective f := by
    intro p q hpq
    apply Subtype.ext
    apply split_injective H (show (i.val+2)+(k+1-i.val)=k+3 by omega)
    exact congrArg (fun z : {q // q∈goodFiber H L (i.val+2) x v} ×
      {q // q∈goodFiber H L (k+1-i.val) v y} => (z.1.val,z.2.val)) hpq
  calc
    _ = Fintype.card P := (Fintype.card_coe _).symm
    _ ≤ Fintype.card ({q // q∈goodFiber H L (i.val+2) x v} ×
      {q // q∈goodFiber H L (k+1-i.val) v y}) := Fintype.card_le_of_injective f hf
    _ = (goodFiber H L (i.val+2) x v).card*(goodFiber H L (k+1-i.val) v y).card := by simp
    _ ≤ _ := Nat.mul_le_mul (goodFiber_le H L _ _ _) (goodFiber_le H L _ _ _)

lemma coordinate_le (k : ℕ) (L : ℕ → ℕ) (hL : Monotone L) (x y v : V) (i : Fin k) :
    ((links H k L x y).filter (fun p => middle H k p i=v)).card≤(L (k+1))^2 := by
  apply (coordinate_bound H k L x y v i).trans
  rw [pow_two]
  exact Nat.mul_le_mul (hL (by omega)) (hL (by omega))

end
end HubLightPaths

end -- HubLightPaths

section -- ChainAppend

/- Concatenating ordered vertex chains at a common endpoint. -/
open Finset SimpleGraph
namespace ChainCounting
universe u
variable {V : Type u} (G : SimpleGraph V)

private def appendFun {n m : ℕ} (p : Chain G n) (q : Chain G m) : Fin (n+m+1) → V :=
  fun i => if h : i.val ≤ n then p.val ⟨i.val,by omega⟩ else q.val ⟨i.val-n,by omega⟩

private lemma appendFun_left {n m : ℕ} (p : Chain G n) (q : Chain G m) (i : Fin (n+1)) :
    appendFun G p q ⟨i.val,by omega⟩ = p.val i := by
  simp only [appendFun,dif_pos (show i.val ≤ n by omega)]

private lemma appendFun_right {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) (i : Fin (m+1)) :
    appendFun G p q ⟨n+i.val,by omega⟩ = q.val i := by
  by_cases hi : i.val = 0
  · have hi' : i = 0 := Fin.ext hi
    subst i
    simpa [Fin.last,appendFun] using h
  · have hlo : ¬ n+i.val ≤ n := by omega
    simp only [appendFun,dif_neg hlo,Nat.add_sub_cancel_left]

/-- Concatenation, without repeating the common endpoint. -/
def append {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) : Chain G (n+m) := by
  refine ⟨appendFun G p q,?_⟩
  intro i
  by_cases hi : i.val < n
  · have h₁ : i.castSucc = (⟨i.val,by omega⟩ : Fin (n+m+1)) := rfl
    have h₂ : i.succ = (⟨i.val+1,by omega⟩ : Fin (n+m+1)) := rfl
    rw [h₁,h₂,appendFun_left G p q ⟨i.val,by omega⟩,appendFun_left G p q ⟨i.val+1,by omega⟩]
    exact p.property ⟨i.val,hi⟩
  · have h₁ : i.castSucc = (⟨n+(i.val-n),by omega⟩ : Fin (n+m+1)) := Fin.ext (by simp; omega)
    have h₂ : i.succ = (⟨n+((i.val-n)+1),by omega⟩ : Fin (n+m+1)) := Fin.ext (by simp; omega)
    rw [h₁,h₂,appendFun_right G p q h ⟨i.val-n,by omega⟩,
      appendFun_right G p q h ⟨i.val-n+1,by omega⟩]
    exact q.property ⟨i.val-n,by omega⟩

lemma append_left {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) (i : Fin (n+1)) :
    (append G p q h).val ⟨i.val,by omega⟩ = p.val i := appendFun_left G p q i

lemma append_right {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) (i : Fin (m+1)) :
    (append G p q h).val ⟨n+i.val,by omega⟩ = q.val i := appendFun_right G p q h i

@[simp] lemma append_start {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) : (append G p q h).val 0 = p.val 0 := append_left G p q h 0

@[simp] lemma append_last {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) : (append G p q h).val (Fin.last (n+m)) = q.val (Fin.last m) :=
  append_right G p q h (Fin.last m)

lemma append_injective {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) (hp : Function.Injective p.val) (hq : Function.Injective q.val)
    (hcross : ∀ i j, p.val i = q.val j → i = Fin.last n ∧ j = 0) :
    Function.Injective (append G p q h).val := by
  intro i j hij
  change appendFun G p q i = appendFun G p q j at hij
  simp only [appendFun] at hij
  split_ifs at hij with hi hj hj
  · have hh := congrArg Fin.val (hp hij)
    apply Fin.ext
    exact hh
  · have hh := (hcross _ _ hij).2
    have hz := congrArg Fin.val hh
    change j.val-n = 0 at hz
    omega
  · have hh := (hcross _ _ hij.symm).2
    have hz := congrArg Fin.val hh
    change i.val-n = 0 at hz
    omega
  · have hh := congrArg Fin.val (hq hij)
    apply Fin.ext
    dsimp only [Fin.val_mk] at hh
    omega

lemma append_vertex {n m : ℕ} (p : Chain G n) (q : Chain G m)
    (h : p.val (Fin.last n) = q.val 0) (i : Fin (n+m+1)) :
    (∃ j : Fin (n+1), (append G p q h).val i = p.val j) ∨
      ∃ j : Fin (m+1), (append G p q h).val i = q.val j := by
  by_cases hi : i.val ≤ n
  · exact Or.inl ⟨⟨i.val,by omega⟩,append_left G p q h ⟨i.val,by omega⟩⟩
  · refine Or.inr ⟨⟨i.val-n,by omega⟩,?_⟩
    have he : i = (⟨n+(i.val-n),by omega⟩ : Fin (n+m+1)) := Fin.ext (by simp; omega)
    exact (congrArg (append G p q h).val he).trans (append_right G p q h ⟨i.val-n,by omega⟩)

end ChainCounting

end -- ChainAppend

section -- ChainConcatenation

/- Joining a simple chain of internally disjoint replacement paths. -/
open Finset SimpleGraph
namespace ChainCounting
universe u
variable {V : Type u} [DecidableEq V] (G : SimpleGraph V)

lemma vertex_cases {n : ℕ} (p : Chain G n) (i : Fin (n+1)) :
    p.val i = p.val 0 ∨ p.val i = p.val (Fin.last n) ∨ p.val i ∈ interior G p := by
  by_cases hi0 : i.val = 0
  · exact Or.inl (congrArg p.val (Fin.ext hi0))
  · by_cases hin : i.val = n
    · exact Or.inr (Or.inl (congrArg p.val (Fin.ext hin)))
    · exact Or.inr (Or.inr ((mem_interior G p _).mpr ⟨i,by omega,by omega,rfl⟩))

/-- Concatenation of replacement paths. Besides injectivity, record where every
vertex came from; this makes simultaneous liftings straightforward to verify. -/
lemma concatenate (ℓ m : ℕ) (b : Fin (m+1) → V) (f : Fin m → Chain G ℓ)
    (hb : Function.Injective b)
    (hf : ∀ e, Function.Injective (f e).val ∧ (f e).val 0 = b e.castSucc ∧
      (f e).val (Fin.last ℓ) = b e.succ)
    (havoid : ∀ e r, b r ∉ interior G (f e))
    (hdis : ∀ e d, e ≠ d → Disjoint (interior G (f e)) (interior G (f d))) :
    ∃ p : Chain G (m*ℓ), Function.Injective p.val ∧ p.val 0 = b 0 ∧
      p.val (Fin.last (m*ℓ)) = b (Fin.last m) ∧
      ∀ i, (∃ r, p.val i = b r) ∨ ∃ e, p.val i ∈ interior G (f e) := by
  induction m with
  | zero =>
    refine ⟨⟨fun _ => b 0,fun i => by have hi := i.isLt; omega⟩,?_,rfl,rfl,?_⟩
    · intro i j _
      exact Fin.ext (by omega)
    · intro i
      exact Or.inl ⟨0,rfl⟩
  | succ m ih =>
    let b' : Fin (m+1) → V := fun i => b i.castSucc
    let f' : Fin m → Chain G ℓ := fun e => f e.castSucc
    have hb' : Function.Injective b' := hb.comp (Fin.castSucc_injective _)
    have hf' (e : Fin m) : Function.Injective (f' e).val ∧ (f' e).val 0 = b' e.castSucc ∧
        (f' e).val (Fin.last ℓ) = b' e.succ := by
      simpa only [b',f',Fin.castSucc_succ] using hf e.castSucc
    obtain ⟨p,hp,hp0,hplast,hcover⟩ := ih b' f' hb' hf'
      (fun e r => havoid e.castSucc r.castSucc)
      (fun e d hed => hdis e.castSucc d.castSucc (fun h => hed ((Fin.castSucc_injective _) h)))
    let q := f (Fin.last m)
    have hq := hf (Fin.last m)
    have he : p.val (Fin.last (m*ℓ)) = q.val 0 := hplast.trans hq.2.1.symm
    have hnew : ∀ i, p.val i ≠ b (Fin.last (m+1)) := by
      intro i hi
      rcases hcover i with ⟨r,hr⟩ | ⟨e,he'⟩
      · have hh := hb (hr.symm.trans hi)
        have hh' := congrArg Fin.val hh
        dsimp only [Fin.val_castSucc,Fin.val_last] at hh'
        omega
      · have havoid' := havoid e.castSucc (Fin.last (m+1))
        exact havoid' (hi ▸ he')
    have hnewinterior : ∀ i, p.val i ∉ interior G q := by
      intro i hi
      rcases hcover i with ⟨r,hr⟩ | ⟨e,he'⟩
      · change p.val i = b r.castSucc at hr
        exact havoid (Fin.last m) r.castSucc (hr ▸ hi)
      · have hdis' := hdis e.castSucc (Fin.last m) (by
          intro h
          have := congrArg Fin.val h
          simp only [Fin.val_castSucc,Fin.val_last] at this
          omega)
        exact Finset.disjoint_left.mp hdis' he' hi
    have hcross : ∀ i j, p.val i = q.val j → i = Fin.last (m*ℓ) ∧ j = 0 := by
      intro i j hij
      have hj : j = 0 := by
        rcases vertex_cases G q j with hj0 | hjlast | hjmid
        · exact hq.1 hj0
        · have hh : p.val i = b (Fin.last (m+1)) := by
            simpa only [Fin.succ_last] using hij.trans (hjlast.trans hq.2.2)
          exact (hnew i hh).elim
        · exact (hnewinterior i (hij.symm ▸ hjmid)).elim
      refine ⟨hp ?_,hj⟩
      rw [hj] at hij
      exact hij.trans he.symm
    rw [Nat.succ_mul]
    refine ⟨append G p q he,append_injective G p q he hp hq.1 hcross,?_,?_,?_⟩
    · simpa only [append_start,b',Fin.castSucc_zero] using hp0
    · simpa only [append_last,Fin.succ_last] using hq.2.2
    · intro i
      rcases append_vertex G p q he i with ⟨j,hj⟩ | ⟨j,hj⟩
      · rcases hcover j with ⟨r,hr⟩ | ⟨e,he'⟩
        · exact Or.inl ⟨r.castSucc,hj.trans hr⟩
        · exact Or.inr ⟨e.castSucc,hj.symm ▸ he'⟩
      · rcases vertex_cases G q j with hj0 | hjlast | hjmid
        · exact Or.inl ⟨(Fin.last m).castSucc,hj.trans (hj0.trans hq.2.1)⟩
        · exact Or.inl ⟨(Fin.last m).succ,hj.trans (hjlast.trans hq.2.2)⟩
        · exact Or.inr ⟨Fin.last m,hj.symm ▸ hjmid⟩

end ChainCounting

end -- ChainConcatenation

section -- HeavyShadow

/- Lifting theta graphs from the shadow of heavy admissible paths. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace HeavyShadow
set_option maxHeartbeats 2000000
universe u
variable {V : Type u} [Fintype V] (G : SimpleGraph V)
noncomputable section

def heavy (B j : ℕ) (x y : V) : Prop :=
  x ≠ y ∧ threshold B j < (fiber G (threshold B) j x y).card

def graph (B j : ℕ) : SimpleGraph V where
  Adj := heavy G B j
  symm := by
    constructor
    intro x y h
    refine ⟨h.1.symm,?_⟩
    rw [← fiber_symmetric G (threshold B) j x y]
    exact h.2
  loopless := by constructor; intro x h; exact h.1 rfl


end
end HeavyShadow

end -- HeavyShadow

section -- AdmissibleChainCounts

/- Prefix-sensitive counts for admissible paths with a fixed initial vertex. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace AdmissibleChainCounts
set_option maxHeartbeats 2000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

lemma prefix_bound (L : ℕ → ℕ) (n D : ℕ) (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (i : Fin (n+1)) (hi : i.val<n) (v : V) :
    (P.filter (fun p => p.val i=v)).card≤L i.val*D^(n-i.val) := by
  let A := P.filter (fun p => p.val i=v)
  let left (p : A) : {q // q∈goodFiber H L i.val x v} := by
    refine ⟨segment H p.val 0 i.val (by omega),?_⟩
    obtain ⟨hp,hx⟩ := hP p.val (mem_filter.mp p.property).1
    apply (mem_goodFiber H L i.val x v _).mpr
    refine ⟨hp.2 0 i.val hi (by omega),hx,?_⟩
    simpa only [segment_apply,Fin.val_last,Nat.zero_add] using (mem_filter.mp p.property).2
  let right (p : A) : From H v (n-i.val) :=
    ⟨segment H p.val i.val (n-i.val) (by omega),by simpa using (mem_filter.mp p.property).2⟩
  let f (p : A) := (left p,right p)
  have hf : Function.Injective f := by
    intro p q he
    apply Subtype.ext
    apply split_injective H (show i.val+(n-i.val)=n by omega)
    exact congrArg (fun z : {q // q∈goodFiber H L i.val x v} × From H v (n-i.val) =>
      (z.1.val,z.2.val)) he
  calc
    _ = Fintype.card A := (Fintype.card_coe _).symm
    _ ≤ Fintype.card ({q // q∈goodFiber H L i.val x v} × From H v (n-i.val)) :=
      Fintype.card_le_of_injective f hf
    _ = (goodFiber H L i.val x v).card*Fintype.card (From H v (n-i.val)) := by simp
    _ ≤ _ := Nat.mul_le_mul (goodFiber_le H L _ _ _) (from_le H D hD _ _)

lemma two_coordinates_bound (L : ℕ → ℕ) (n D : ℕ) (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (a b : Fin (n+1)) (hab : a.val<b.val) (v w : V) :
    (P.filter (fun p => p.val a=v ∧ p.val b=w)).card≤L a.val*D^(n-a.val-1) := by
  let A := P.filter (fun p => p.val a=v ∧ p.val b=w)
  let i : Fin (n-a.val) := ⟨b.val-a.val-1,by omega⟩
  let left (p : A) : {q // q∈goodFiber H L a.val x v} := by
    refine ⟨segment H p.val 0 a.val (by omega),?_⟩
    obtain ⟨hp,hx⟩ := hP p.val (mem_filter.mp p.property).1
    apply (mem_goodFiber H L a.val x v _).mpr
    refine ⟨hp.2 0 a.val (by omega) (by omega),hx,?_⟩
    simpa only [segment_apply,Fin.val_last,Nat.zero_add] using (mem_filter.mp p.property).2.1
  let right (p : A) : {q : From H v (n-a.val) // q.val.val i.succ=w} := by
    refine ⟨⟨segment H p.val a.val (n-a.val) (by omega),?_⟩,?_⟩
    · simpa using (mem_filter.mp p.property).2.1
    · have he : (⟨a.val+i.succ.val,by omega⟩ : Fin (n+1))=b := by
        apply Fin.ext
        dsimp only [i,Fin.val_succ]
        omega
      simpa only [segment_apply,he] using (mem_filter.mp p.property).2.2
  let f (p : A) := (left p,right p)
  have hf : Function.Injective f := by
    intro p q he
    apply Subtype.ext
    apply split_injective H (show a.val+(n-a.val)=n by omega)
    exact congrArg (fun z : {q // q∈goodFiber H L a.val x v} ×
      {q : From H v (n-a.val) // q.val.val i.succ=w} => (z.1.val,z.2.val.val)) he
  calc
    _ = Fintype.card A := (Fintype.card_coe _).symm
    _ ≤ Fintype.card ({q // q∈goodFiber H L a.val x v} ×
        {q : From H v (n-a.val) // q.val.val i.succ=w}) := Fintype.card_le_of_injective f hf
    _ = (goodFiber H L a.val x v).card*Fintype.card {q : From H v (n-a.val) // q.val.val i.succ=w} := by simp
    _ ≤ _ := Nat.mul_le_mul (goodFiber_le H L _ _ _) (ChainCounting.coordinate_le H D hD _ _ _ i)

lemma index_image_bound (n D : ℕ) (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, p.val 0=x) (hD : ∀ v, H.degree v≤D) (i : Fin (n+1)) :
    (P.image (fun p => p.val i)).card≤D^i.val := by
  let f (p : P) : From H x i.val := ⟨segment H p.val 0 i.val (by omega),hP p.val p.property⟩
  have hsub : P.image (fun p => p.val i) ⊆ univ.image (fun q : From H x i.val => q.val.val (Fin.last i.val)) := by
    intro v hv
    obtain ⟨p,hp,rfl⟩ := mem_image.mp hv
    exact mem_image.mpr ⟨f ⟨p,hp⟩,mem_univ _,by simp only [f,segment_apply,Fin.val_last,Nat.zero_add]⟩
  exact (card_le_card hsub).trans (card_image_le.trans (card_univ.trans_le (from_le H D hD _ _)))

end
end AdmissibleChainCounts

end -- AdmissibleChainCounts

section -- FiniteWeightedCommon

/- Weighted common-neighborhood selection with injective ordered choices. -/
open Finset
namespace FiniteWeightedCommon
set_option maxHeartbeats 2000000
universe u v
noncomputable section
variable {X : Type u} {Y : Type v} [Fintype X] [Fintype Y]
local instance : DecidableEq Y := Classical.decEq _

def tuples (S : Finset Y) (k : ℕ) : Finset (Fin k → Y) :=
  univ.filter (fun f => Function.Injective f ∧ ∀ i, f i∈S)

lemma tuples_card (S : Finset Y) (k : ℕ) :
    (tuples S k).card=(univ.filter (fun f : Fin k → S => Function.Injective f)).card := by
  classical
  apply card_bij (fun f hf i => (⟨f i,(mem_filter.mp hf).2.2 i⟩ : S))
  · intro f hf
    exact mem_filter.mpr ⟨mem_univ _,fun i j h => (mem_filter.mp hf).2.1 (congrArg Subtype.val h)⟩
  · intro f hf g hg h
    funext i
    exact congrArg Subtype.val (congrFun h i)
  · intro f hf
    refine ⟨fun i => (f i).val,mem_filter.mpr ⟨mem_univ _,?_,fun i => (f i).property⟩,rfl⟩
    intro i j h
    exact (mem_filter.mp hf).2 (Subtype.ext h)

lemma tuples_lower (S : Finset Y) (k d : ℕ) (hk : 0<k)
    (hd : 2*k^2≤d) (hS : d≤S.card) : d^k≤2*(tuples S k).card := by
  classical
  rw [tuples_card]
  have hb := KSTUpper.noninjective_count (V := S) k
  have hs := card_filter_add_card_filter_not (s := (univ : Finset (Fin k → S))) Function.Injective
  simp only [card_univ,Fintype.card_fun,Fintype.card_fin,Fintype.card_coe] at hb hs
  have hm := Nat.mul_le_mul_right (S.card^(k-1)) (hd.trans hS)
  have hp : S.card*S.card^(k-1)=S.card^k := by rw [← pow_succ',Nat.sub_add_cancel hk]
  have hl : d^k≤S.card^k := Nat.pow_le_pow_left hS k
  nlinarith only [hb,hs,hm,hp,hl]

variable (N : X → Finset Y) (w : X → ℕ)

def weight (k : ℕ) (f : Fin k → Y) : ℕ :=
  ∑ x, if ∀ i, f i∈N x then w x else 0

lemma weighted_count (k : ℕ) :
    (∑ f ∈ univ.filter (fun f : Fin k → Y => Function.Injective f), weight N w k f)=
      ∑ x, w x*(tuples (N x) k).card := by
  classical
  simp only [weight]
  rw [sum_comm]
  apply sum_congr rfl
  intro x _
  rw [tuples,card_filter,mul_sum]
  simp only [sum_filter]
  apply sum_congr rfl
  intro f _
  split_ifs <;> simp_all

lemma exists_weight (k d K : ℕ) (hk : 0<k) (hd : 2*k^2≤d)
    (hN : ∀ x, 0<w x → d≤(N x).card)
    (hlarge : 2*K*Fintype.card Y^k < d^k*(∑ x, w x)) :
    ∃ f : Fin k → Y, Function.Injective f ∧ K<weight N w k f := by
  classical
  by_contra hn
  push_neg at hn
  have hup : (∑ f ∈ univ.filter (fun f : Fin k → Y => Function.Injective f), weight N w k f)≤
      Fintype.card Y^k*K := by
    calc
      _ ≤ ∑ _f ∈ univ.filter (fun f : Fin k → Y => Function.Injective f), K :=
        sum_le_sum (fun f hf => hn f (mem_filter.mp hf).2)
      _ ≤ Fintype.card Y^k*K := by
        simp only [sum_const,nsmul_eq_mul]
        exact Nat.mul_le_mul_right K (card_filter_le _ _ |>.trans_eq (by simp))
  have hlo : d^k*(∑ x, w x)≤2*(∑ x, w x*(tuples (N x) k).card) := by
    rw [mul_sum,mul_sum]
    apply sum_le_sum
    intro x _
    by_cases hw : w x=0
    · simp [hw]
    · have hh := Nat.mul_le_mul_left (w x) (tuples_lower (N x) k d hk hd (hN x (Nat.pos_of_ne_zero hw)))
      nlinarith only [hh]
  rw [weighted_count] at hup
  nlinarith only [hup,hlo,hlarge]

end
end FiniteWeightedCommon

end -- FiniteWeightedCommon

section -- FiniteDenseWeightedLink

/- A dense weighted bipartite relation has a useful weighted fan. -/
open Finset
namespace FiniteDenseWeightedLink
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {A : Type u} {Z : Type v} [Fintype A] [Fintype Z]
local instance : DecidableEq Z := Classical.decEq _

lemma select (N : Z → Finset A) (m : Z → ℕ) (j d D : ℕ) (hj : 2≤j)
    (hA : Fintype.card A≤D) (hm : (∑ z, m z)≤D^(j-1))
    (hE : 2*d*D^(j-1)<∑ z, m z*(N z).card) :
    ∃ a : A, ∃ T : Finset Z,
      (∀ z∈T, a∈N z ∧ d≤((N z).erase a).card) ∧
      d*D^(j-2)<∑ z∈T, m z := by
  let w (a : A) (z : Z) := if d<(N z).card ∧ a∈N z then m z else 0
  have hrow : (∑ a, ∑ z, w a z)=∑ z, if d<(N z).card then m z*(N z).card else 0 := by
    rw [sum_comm]
    apply sum_congr rfl
    intro z _
    by_cases hz : d<(N z).card
    · simp only [w,hz,true_and,if_true]
      rw [sum_ite_mem]
      simp [mul_comm]
    · simp [w,hz]
  have hpoint (z : Z) : m z*(N z).card≤d*m z+(if d<(N z).card then m z*(N z).card else 0) := by
    split_ifs with hz
    · omega
    · have hh := Nat.mul_le_mul_left (m z) (Nat.le_of_not_gt hz)
      nlinarith only [hh]
  have hb := sum_le_sum (s := (univ : Finset Z)) (fun z _ => hpoint z)
  rw [sum_add_distrib,← mul_sum,← hrow] at hb
  have hm' := Nat.mul_le_mul_left d hm
  have hhigh : d*D^(j-1)<∑ a, ∑ z, w a z := by nlinarith only [hE,hb,hm']
  have hex : ∃ a : A, d*D^(j-2)<∑ z, w a z := by
    by_contra hn
    push_neg at hn
    have hh : (∑ a, ∑ z, w a z)≤Fintype.card A*(d*D^(j-2)) := by
      calc
        _ ≤ ∑ _a : A, d*D^(j-2) := sum_le_sum (fun a _ => hn a)
        _ = _ := by simp
    have hscale := Nat.mul_le_mul_right (d*D^(j-2)) hA
    have he : D*(d*D^(j-2))=d*D^(j-1) := by
      rw [mul_left_comm,← pow_succ']
      congr 2
      omega
    rw [he] at hscale
    omega
  obtain ⟨a,ha⟩ := hex
  let T := univ.filter (fun z => d<(N z).card ∧ a∈N z)
  refine ⟨a,T,?_,?_⟩
  · intro z hz
    have hz' := (mem_filter.mp hz).2
    refine ⟨hz'.2,?_⟩
    have he := card_erase_add_one hz'.2
    omega
  · simpa only [T,sum_filter,w] using ha

end
end FiniteDenseWeightedLink

end -- FiniteDenseWeightedLink

section -- WeightedAdmissibleSelection

/- Threshold normalization for weighted common-neighborhood selection. -/
open Finset
namespace WeightedAdmissibleSelection
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {A : Type u} {Z : Type v} [Fintype A] [Fintype Z]
local instance : DecidableEq Z := Classical.decEq _

lemma normalize (s d D κ K L J : ℕ) (hd : 0<d) (hD : D≤κ*d)
    (hJ : 2*K*κ^(s+1)*L^2<J) :
    2*K*L^2*D^(s+1)<J*d^(s+1) := by
  have hp := Nat.pow_le_pow_left hD (s+1)
  rw [mul_pow] at hp
  have hh := Nat.mul_lt_mul_of_pos_right hJ (Nat.pow_pos (n := s+1) hd)
  have hm := Nat.mul_le_mul_left (2*K*L^2) hp
  nlinarith only [hh,hm]

lemma select (N : Z → Finset A) (m w : Z → ℕ) (T : Finset Z)
    (j s d D κ K L J : ℕ) (hj : 2≤j) (hs : 0<s) (hDpos : 0<D) (hL : 0<L)
    (hd : 2*s^2≤d) (hA : Fintype.card A≤D) (hD : D≤κ*d)
    (hJ : 2*K*κ^(s+1)*L^2<J)
    (hm : ∀ z∈T, m z≤L) (hw : ∀ z∈T, J≤w z)
    (hN : ∀ z∈T, d≤(N z).card)
    (hT : d*D^(j-2)<∑ z∈T, m z) :
    ∃ f : Fin s → A, Function.Injective f ∧
      K*L*D^(j-1)<∑ z∈T, if ∀ i, f i∈N z then w z else 0 := by
  let w' (z : Z) := if z∈T then w z else 0
  have hdpos : 0<d := by nlinarith
  have hweight : J*(∑ z∈T, m z)≤L*(∑ z, w' z) := by
    rw [mul_sum,show (∑ z, w' z)=∑ z∈T, w z by simp [w',← sum_filter],mul_sum]
    apply sum_le_sum
    intro z hz
    have hh := Nat.mul_le_mul (hm z hz) (hw z hz)
    nlinarith only [hh]
  have hnorm := normalize s d D κ K L J hdpos hD hJ
  have hnorm' := Nat.mul_lt_mul_of_pos_right hnorm (Nat.pow_pos (n := j-2) hDpos)
  have hT' := Nat.mul_le_mul_left J hT.le
  have hT'' := Nat.mul_le_mul_left (d^s) (hT'.trans hweight)
  have hpow : D^(s+1)*D^(j-2)=D^(j-1)*D^s := by
    rw [← pow_add,← pow_add]
    congr 1
    omega
  have hdpow : d^(s+1)=d^s*d := pow_succ _ _
  have hlargeD : (2*(K*L*D^(j-1))*D^s)*L < (d^s*(∑ z, w' z))*L := by
    rw [mul_assoc (2*K*L^2) (D^(s+1)),hpow,hdpow] at hnorm'
    nlinarith only [hnorm',hT'']
  have hlarge : 2*(K*L*D^(j-1))*Fintype.card A^s<d^s*(∑ z, w' z) := by
    have hh := (Nat.mul_lt_mul_right hL).mp hlargeD
    exact (Nat.mul_le_mul_left _ (Nat.pow_le_pow_left hA s)).trans_lt hh
  obtain ⟨f,hf,hwf⟩ := FiniteWeightedCommon.exists_weight N w' s d (K*L*D^(j-1)) hs hd
    (by
      intro z hz
      have hzT : z∈T := by by_contra hn; simp [w',hn] at hz
      exact hN z hzT) hlarge
  refine ⟨f,hf,?_⟩
  have he : FiniteWeightedCommon.weight N w' s f=∑ z∈T, if ∀ i, f i∈N z then w z else 0 := by
    calc
      _ = ∑ z, if z∈T then (if ∀ i, f i∈N z then w z else 0) else 0 := by
        apply sum_congr rfl
        intro z _
        dsimp only [w']
        split_ifs <;> rfl
      _ = _ := by rw [sum_ite_mem]; simp
  rwa [he] at hwf

end
end WeightedAdmissibleSelection

end -- WeightedAdmissibleSelection

section -- AdmissibleHeavyLinks

/- Weighted local links of admissible heavy paths. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace AdmissibleHeavyLinks
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _
local instance (v : V) : DecidableEq (H.neighborSet v) := Classical.decEq _

def bad (B j : ℕ) : Finset (Chain H j) := by
  classical
  exact univ.filter (fun p => Admissible H (threshold B) j p ∧
    HeavyShadow.heavy H B j (p.val 0) (p.val (Fin.last j)))

lemma mem_bad (B j : ℕ) (p : Chain H j) : p∈bad H B j ↔
    Admissible H (threshold B) j p ∧ HeavyShadow.heavy H B j (p.val 0) (p.val (Fin.last j)) := by
  classical
  simp only [bad,mem_filter,mem_univ,true_and]

def neighbors (B j : ℕ) (v z : V) : Finset (H.neighborSet v) := by
  classical
  exact univ.filter (fun a => HeavyShadow.heavy H B j a.val z)

def multiplicity (B j : ℕ) (v z : V) : ℕ :=
  (goodFiber H (threshold B) (j-1) v z).card

def mass (B j : ℕ) (v : V) : ℕ := ∑ z, multiplicity H B j v z*(neighbors H B j v z).card

lemma multiplicity_le (B j : ℕ) (v z : V) : multiplicity H B j v z≤threshold B (j-1) :=
  goodFiber_le H (threshold B) _ _ _

lemma multiplicity_sum (B j D : ℕ) (hD : ∀ v, H.degree v≤D) (v : V) :
    (∑ z, multiplicity H B j v z)≤D^(j-1)  := by
  classical
  let Q := Σ z : V, {q // q∈goodFiber H (threshold B) (j-1) v z}
  let f : Q → From H v (j-1) := fun q =>
    ⟨q.2.val,((mem_goodFiber H (threshold B) (j-1) v q.1 q.2.val).mp q.2.property).2.1⟩
  have hf : Function.Injective f := by
    rintro ⟨z,p⟩ ⟨w,q⟩ he
    have hpq : p.val=q.val := congrArg Subtype.val he
    have hz := ((mem_goodFiber H (threshold B) (j-1) v z p.val).mp p.property).2.2
    have hw := ((mem_goodFiber H (threshold B) (j-1) v w q.val).mp q.property).2.2
    have hzw : z=w := hz.symm.trans ((congrArg (fun p : Chain H (j-1) => p.val (Fin.last (j-1))) hpq).trans hw)
    subst w
    exact congrArg (Sigma.mk z) (Subtype.ext hpq)
  have hh := (Fintype.card_le_of_injective f hf).trans (from_le H D hD _ _)
  simpa only [Q,Fintype.card_sigma,Fintype.card_coe,multiplicity] using hh

lemma bad_le_mass (B j : ℕ) (hj : 2≤j) : (bad H B j).card≤∑ v, mass H B j v  := by
  classical
  let Bad := bad H B j
  let Q := Σ v : V, Σ z : V, {q // q∈goodFiber H (threshold B) (j-1) v z} × (neighbors H B j v z)
  let f (p : Bad) : Q := by
    let v := p.val.val ⟨1,by omega⟩
    let z := p.val.val (Fin.last j)
    have hp := (mem_filter.mp (show p.val∈bad H B j from p.property)).2
    refine ⟨v,z,⟨segment H p.val 1 (j-1) (by omega),?_⟩,⟨⟨p.val.val 0,?_⟩,?_⟩⟩
    · apply (mem_goodFiber H (threshold B) (j-1) v z _).mpr
      refine ⟨hp.1.2 1 (j-1) (by omega) (by omega),rfl,?_⟩
      apply congrArg p.val.val
      apply Fin.ext
      change 1+(j-1)=j
      omega
    · exact (p.val.property ⟨0,by omega⟩).symm
    · exact mem_filter.mpr ⟨mem_univ _,hp.2⟩
  have hf : Function.Injective f := by
    intro p q he
    apply Subtype.ext
    apply Subtype.ext
    funext i
    have hfirst := congrArg (fun z : Q => z.2.2.2.val.val) he
    have htail := congrArg (fun z : Q => z.2.2.1.val) he
    by_cases hi : i.val=0
    · have hi' : i=0 := Fin.ext hi
      simpa only [hi'] using hfirst
    · have hh := congrArg (fun p : Chain H (j-1) => p.val ⟨i.val-1,by omega⟩) htail
      change p.val.val ⟨1+(i.val-1),by omega⟩=q.val.val ⟨1+(i.val-1),by omega⟩ at hh
      simpa only [show 1+(i.val-1)=i.val by omega] using hh
  have hh := Fintype.card_le_of_injective f hf
  simpa only [Bad,Q,Fintype.card_coe,Fintype.card_sigma,Fintype.card_prod,mass,multiplicity] using hh

lemma dense_fan (B j d D : ℕ) (hj : 2≤j) (hD : ∀ v, H.degree v≤D) (v : V)
    (hlarge : 2*d*D^(j-1)< mass H B j v) :
    ∃ a : H.neighborSet v, ∃ T : Finset V,
      (∀ z∈T, HeavyShadow.heavy H B j a.val z ∧ d≤((neighbors H B j v z).erase a).card) ∧
      d*D^(j-2)<∑ z∈T, multiplicity H B j v z  := by
  classical
  obtain ⟨a,T,hT,hweight⟩ := FiniteDenseWeightedLink.select (neighbors H B j v) (multiplicity H B j v)
    j d D hj (by simpa only [H.card_neighborSet_eq_degree] using hD v) (multiplicity_sum H B j D hD v) hlarge
  refine ⟨a,T,?_,hweight⟩
  intro z hz
  refine ⟨(mem_filter.mp (hT z hz).1).2,?_⟩
  exact (hT z hz).2

end
end AdmissibleHeavyLinks

end -- AdmissibleHeavyLinks

section -- AdmissibleHubLightCount

/- Partition long injective paths into truncated-good paths and extensions of heavy subpaths. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace AdmissibleHubLightCount
set_option maxHeartbeats 2500000
universe u
noncomputable section
variable {V : Type u} [Fintype V]
local instance : DecidableEq V := Classical.decEq _
variable (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

def badAt (k B : ℕ) (ij : Fin (k+4) × Fin (k+2)) : Finset (HubLightPaths.Path H k) :=
  if h : ij.1.val+ij.2.val≤k+3 then
    extensions H (k+3) ij.1.val ij.2.val h (AdmissibleHeavyLinks.bad H B ij.2.val)
  else ∅

lemma partition (k B : ℕ) :
    (GeneralThetaCounting.paths H (k+3)).card≤(HubLightPaths.good H k (threshold B)).card+
      ∑ ij : Fin (k+4) × Fin (k+2), (badAt H k B ij).card := by
  classical
  have hsub : GeneralThetaCounting.paths H (k+3)⊆HubLightPaths.good H k (threshold B) ∪
      univ.biUnion (badAt H k B) := by
    intro p hp
    have hinj := (mem_filter.mp hp).2
    by_cases hg : HubLightPaths.Good H k (threshold B) p
    · exact mem_union_left _ (mem_filter.mpr ⟨mem_univ _,hg⟩)
    · have hbad : ¬∀ a j : ℕ, (hj : j≤k+1) → (hlen : a+j≤k+3) →
          GoodChains.Good H (threshold B) j (segment H p a j hlen) := fun h => hg ⟨hinj,h⟩
      push_neg at hbad
      obtain ⟨a,j,hj,hlen,hbad⟩ := hbad
      obtain ⟨b,l,hbl,hadm,hheavy⟩ := bad_witness H (threshold B) j (segment H p a j hlen)
        (segment_injective H hinj a j hlen) hbad
      have hl : 2≤l := GeneralThetaCounting.heavy_length H B l _ _ hheavy
      have hlen' : a+b+l≤k+3 := by omega
      have hbad' : segment H p (a+b) l hlen'∈AdmissibleHeavyLinks.bad H B l := by
        apply (AdmissibleHeavyLinks.mem_bad H B l _).mpr
        have hinj' := segment_injective H hinj (a+b) l hlen'
        refine ⟨?_,hinj'.ne ?_,?_⟩
        · simpa only [segment_segment] using hadm
        · intro he
          have hh := congrArg Fin.val he
          change 0=l at hh
          omega
        · simpa only [segment_segment] using hheavy
      apply mem_union_right
      apply mem_biUnion.mpr
      refine ⟨(⟨a+b,by omega⟩,⟨l,by omega⟩),mem_univ _,?_⟩
      simp only [badAt,dif_pos hlen']
      exact mem_filter.mpr ⟨mem_univ _,hbad'⟩
  exact (card_le_card hsub).trans ((card_union_le _ _).trans (Nat.add_le_add_left card_biUnion_le _))

lemma badAt_le (k B D : ℕ) (hD : ∀ v, H.degree v≤D) (ij : Fin (k+4) × Fin (k+2)) :
    (badAt H k B ij).card≤(AdmissibleHeavyLinks.bad H B ij.2.val).card*D^(k+3-ij.2.val) := by
  dsimp only [badAt]
  split_ifs with h
  · exact extensions_le H D (k+3) ij.1.val ij.2.val hD h _
  · exact Nat.zero_le _

lemma count (k B d D : ℕ) (hd : ∀ v, d+(k+3)≤H.degree v) (hD : ∀ v, H.degree v≤D) :
    Fintype.card V*d^(k+3)≤(HubLightPaths.good H k (threshold B)).card+
      (k+4)*∑ j : Fin (k+2), (AdmissibleHeavyLinks.bad H B j.val).card*D^(k+3-j.val) := by
  have hh := (GeneralThetaCounting.paths_lower H d (k+3) hd).trans (partition H k B)
  have hs : (∑ ij : Fin (k+4) × Fin (k+2), (badAt H k B ij).card)≤
      (k+4)*∑ j : Fin (k+2), (AdmissibleHeavyLinks.bad H B j.val).card*D^(k+3-j.val) := by
    calc
      _ ≤ ∑ ij : Fin (k+4) × Fin (k+2), (AdmissibleHeavyLinks.bad H B ij.2.val).card*D^(k+3-ij.2.val) :=
        sum_le_sum (fun ij _ => badAt_le H k B D hD ij)
      _ = _ := by rw [Fintype.sum_prod_type]; simp
  exact hh.trans (Nat.add_le_add_left hs _)

lemma bad_small (B j : ℕ) (hj : j≤1) : AdmissibleHeavyLinks.bad H B j=∅ := by
  apply eq_empty_iff_forall_notMem.mpr
  intro p hp
  have hh := ((AdmissibleHeavyLinks.mem_bad H B j p).mp hp).2.2
  have hl := GeneralThetaCounting.heavy_length H B j _ _ hh
  omega

end
end AdmissibleHubLightCount

end -- AdmissibleHubLightCount

section -- HubLightSelection

/- Select paths with distinct core endpoint pairs and pairwise disjoint core interiors. -/
open Finset SimpleGraph ChainCounting
namespace HubLightSelection
open HubLightPaths
set_option maxHeartbeats 2500000
universe u
noncomputable section
variable {V : Type u} [Fintype V]
local instance : DecidableEq V := Classical.decEq _
variable (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

def labels (k : ℕ) (p : Path H k) : Finset ((V × V) ⊕ V) :=
  insert (Sum.inl (first H k p,last H k p)) (univ.image (fun i : Fin k => Sum.inr (middle H k p i)))

lemma labels_nonempty (k : ℕ) (p : Path H k) : (labels H k p).Nonempty := insert_nonempty _ _

lemma labels_card (k : ℕ) (p : Path H k) : (labels H k p).card≤k+1 := by
  apply (card_insert_le _ _).trans
  have hh := card_image_le (s := (univ : Finset (Fin k))) (f := fun i => (Sum.inr (middle H k p i) : (V × V) ⊕ V))
  simpa only [card_univ,Fintype.card_fin] using Nat.add_le_add_right hh 1

lemma pair_mem (k : ℕ) (p : Path H k) : Sum.inl (first H k p,last H k p)∈labels H k p := mem_insert_self _ _

lemma middle_mem (k : ℕ) (p : Path H k) (i : Fin k) : Sum.inr (middle H k p i)∈labels H k p :=
  mem_insert_of_mem (mem_image.mpr ⟨i,mem_univ _,rfl⟩)

lemma incidence (k : ℕ) (L : ℕ → ℕ) (hL : Monotone L) (x y : V) (z : (V × V) ⊕ V) :
    ((links H k L x y).filter (fun p => z∈labels H k p)).card≤L (k+1)+k*(L (k+1))^2 := by
  cases z with
  | inl z =>
    have he : (links H k L x y).filter (fun p => Sum.inl z∈labels H k p)=
        (links H k L x y).filter (fun p => (first H k p,last H k p)=z) := by
      ext p
      simp [labels,eq_comm]
    rw [he]
    exact (pair_bound H k L x y z).trans (Nat.le_add_right _ _)
  | inr z =>
    let P (i : Fin k) := (links H k L x y).filter (fun p => middle H k p i=z)
    have hsub : (links H k L x y).filter (fun p => Sum.inr z∈labels H k p)⊆univ.biUnion P := by
      intro p hp
      have hmem := (mem_filter.mp hp).2
      simp only [labels,mem_insert,Sum.inr_ne_inl,false_or,mem_image,mem_univ,true_and,Sum.inr.injEq] at hmem
      obtain ⟨i,hi⟩ := hmem
      exact mem_biUnion.mpr ⟨i,mem_univ _,mem_filter.mpr ⟨(mem_filter.mp hp).1,hi⟩⟩
    have hh : ((links H k L x y).filter (fun p => Sum.inr z∈labels H k p)).card≤k*(L (k+1))^2 := by
      calc
        _ ≤ (univ.biUnion P).card := card_le_card hsub
        _ ≤ ∑ i, (P i).card := card_biUnion_le
        _ ≤ ∑ _i : Fin k, (L (k+1))^2 := sum_le_sum (fun i _ => coordinate_le H k L hL x y z i)
        _ = _ := by simp
    exact hh.trans (Nat.le_add_left _ _)

lemma select (k : ℕ) (L : ℕ → ℕ) (hL : Monotone L) (x y : V)
    (P : Finset (Path H k)) (hP : P⊆links H k L x y) :
    ∃ Q : Finset (Path H k), Q⊆P ∧
      Set.InjOn (fun p : Path H k => (first H k p,last H k p)) Q ∧
      (∀ p∈Q, ∀ q∈Q, ∀ i j : Fin k, middle H k p i=middle H k q j → p=q ∧ i=j) ∧
      P.card≤((k+1)*(L (k+1)+k*(L (k+1))^2))*Q.card := by
  obtain ⟨Q,hQ,hdis,hcard⟩ := FiniteDisjointSubfamily.select P (labels H k) (k+1)
    (L (k+1)+k*(L (k+1))^2) (fun p _ => labels_nonempty H k p) (fun p _ => labels_card H k p)
    (fun z => (card_le_card (filter_subset_filter _ hP)).trans (incidence H k L hL x y z))
  refine ⟨Q,hQ,?_,?_,hcard⟩
  · intro p hp q hq he
    dsimp only at he
    by_contra hn
    apply disjoint_left.mp (hdis p hp q hq hn) (pair_mem H k p)
    rw [he]
    exact pair_mem H k q
  · intro p hp q hq i j he
    have hpq : p=q := by
      by_contra hn
      apply disjoint_left.mp (hdis p hp q hq hn) (middle_mem H k p i)
      rw [he]
      exact middle_mem H k q j
    subst q
    refine ⟨rfl,?_⟩
    have hinj := ((mem_links H k L x y p).mp (hP (hQ hp))).1.1
    have hh := congrArg Fin.val (hinj he)
    apply Fin.ext
    change i.val+2=j.val+2 at hh
    omega

end
end HubLightSelection

end -- HubLightSelection

section -- SelectedHubLink

/- A selected family of pinned paths supplies a copy of the corresponding hub replacement. -/
open Finset SimpleGraph ChainCounting
namespace SelectedHubLink
set_option maxHeartbeats 3000000
universe u
noncomputable section
variable {V : Type u} [Fintype V]
local instance : DecidableEq V := Classical.decEq _
variable (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _
variable (k : ℕ) (Q : Finset (HubLightPaths.Path H k))

def X : Finset V := Q.image (HubLightPaths.first H k)
def Y : Finset V := Q.image (HubLightPaths.last H k)
abbrev Vertex := X H k Q ⊕ Y H k Q

def first (p : Q) : X H k Q := ⟨HubLightPaths.first H k p.val,mem_image.mpr ⟨p.val,p.property,rfl⟩⟩
def last (p : Q) : Y H k Q := ⟨HubLightPaths.last H k p.val,mem_image.mpr ⟨p.val,p.property,rfl⟩⟩
def eval : Vertex H k Q → V := Sum.elim Subtype.val Subtype.val

def relation (a : X H k Q) (b : Y H k Q) : Prop :=
  ∃ p∈Q, a.val=HubLightPaths.first H k p ∧ b.val=HubLightPaths.last H k p

def graph : SimpleGraph (Vertex H k Q) := SuspensionBounds.biGraph (relation H k Q)
def color : (graph H k Q).Coloring (Fin 2) := SuspensionBounds.biColor _

def edge (p : Q) : GraphSubdivision.Edge (graph H k Q) :=
  ⟨s(Sum.inl (first H k Q p),Sum.inr (last H k Q p)),p.val,p.property,rfl,rfl⟩

lemma edge_injective (hp : Set.InjOn (fun p : HubLightPaths.Path H k =>
      (HubLightPaths.first H k p,HubLightPaths.last H k p)) Q) : Function.Injective (edge H k Q) := by
  intro p q he
  have hh := congrArg Subtype.val he
  rcases Sym2.eq_iff.mp hh with ⟨hl,hr⟩ | ⟨hl,hr⟩
  · apply Subtype.ext
    exact hp p.property q.property (Prod.ext
      (congrArg Subtype.val (Sum.inl.inj hl)) (congrArg Subtype.val (Sum.inr.inj hr)))
  · exact (Sum.inl_ne_inr hl).elim

lemma edge_surjective : Function.Surjective (edge H k Q) := by
  intro e
  have hout : s(e.val.out.1,e.val.out.2)=e.val := e.val.out_eq
  have ha : (graph H k Q).Adj e.val.out.1 e.val.out.2 := by
    change s(e.val.out.1,e.val.out.2)∈(graph H k Q).edgeSet
    rw [hout]
    exact e.property
  cases h₁ : e.val.out.1 with
  | inl a => cases h₂ : e.val.out.2 with
    | inl b => rw [h₁,h₂] at ha; exact ha.elim
    | inr b =>
      rw [h₁,h₂] at ha
      obtain ⟨p,hp,hl,hr⟩ := ha
      refine ⟨⟨p,hp⟩,Subtype.ext ?_⟩
      apply Eq.trans _ hout
      rw [h₁,h₂]
      exact congrArg₂ (fun a b => s(a,b)) (congrArg Sum.inl (Subtype.ext hl.symm))
        (congrArg Sum.inr (Subtype.ext hr.symm))
  | inr a => cases h₂ : e.val.out.2 with
    | inl b =>
      rw [h₁,h₂] at ha
      obtain ⟨p,hp,hl,hr⟩ := ha
      refine ⟨⟨p,hp⟩,Subtype.ext ?_⟩
      apply Eq.trans _ hout
      rw [h₁,h₂]
      exact Sym2.eq_iff.mpr (Or.inr
        ⟨congrArg Sum.inl (Subtype.ext hl.symm),congrArg Sum.inr (Subtype.ext hr.symm)⟩)
    | inr b => rw [h₁,h₂] at ha; exact ha.elim

def edgeEquiv (hp : Set.InjOn (fun p : HubLightPaths.Path H k =>
      (HubLightPaths.first H k p,HubLightPaths.last H k p)) Q) :
    Q ≃ GraphSubdivision.Edge (graph H k Q) :=
  Equiv.ofBijective _ ⟨edge_injective H k Q hp,edge_surjective H k Q⟩

variable (L : ℕ → ℕ) (x y : V) (hQ : Q⊆HubLightPaths.links H k L x y)

include hQ in
lemma prop (p : Q) : HubLightPaths.Good H k L p.val ∧ p.val.val 0=x ∧ p.val.val (Fin.last (k+3))=y :=
  (HubLightPaths.mem_links H k L x y p.val).mp (hQ p.property)

include hQ in
lemma first_adj (p : Q) : H.Adj x (first H k Q p).val := by
  have hh := prop H k Q L x y hQ p
  rw [← hh.2.1]
  exact p.val.property 0

include hQ in
lemma last_adj (p : Q) : H.Adj y (last H k Q p).val := by
  have hh := prop H k Q L x y hQ p
  rw [← hh.2.2]
  exact (p.val.property ⟨k+2,by omega⟩).symm

include hQ in
lemma old_avoids (p : Q) :
    x≠(first H k Q p).val ∧ y≠(first H k Q p).val ∧
    x≠(last H k Q p).val ∧ y≠(last H k Q p).val := by
  have hh := prop H k Q L x y hQ p
  have hn0 : (0 : Fin (k+4))≠⟨1,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  have hn1 : (Fin.last (k+3) : Fin (k+4))≠⟨1,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  have hn2 : (0 : Fin (k+4))≠⟨k+2,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  have hn3 : (Fin.last (k+3) : Fin (k+4))≠⟨k+2,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  refine ⟨?_,?_,?_,?_⟩
  · exact fun h => hh.1.1.ne hn0 (hh.2.1.trans h)
  · exact fun h => hh.1.1.ne hn1 (hh.2.2.trans h)
  · exact fun h => hh.1.1.ne hn2 (hh.2.1.trans h)
  · exact fun h => hh.1.1.ne hn3 (hh.2.2.trans h)

include hQ in
lemma middle_avoids (p : Q) (i : Fin k) :
    x≠HubLightPaths.middle H k p.val i ∧ y≠HubLightPaths.middle H k p.val i := by
  have hh := prop H k Q L x y hQ p
  have hn0 : (0 : Fin (k+4))≠⟨i.val+2,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  have hn1 : (Fin.last (k+3) : Fin (k+4))≠⟨i.val+2,by omega⟩ := by intro h; have hh := congrArg Fin.val h; simp only [Fin.val_zero,Fin.val_mk,Fin.val_last] at hh; omega
  exactfun h => hh.1.1.ne hn0 (hh.2.1.trans h),fun h => hh.1.1.ne hn1 (hh.2.2.trans h)⟩

include hQ in
lemma copy (hne : Q.Nonempty) (b : V → Fin 2)
    (hb : ∀ p∈Q, b (HubLightPaths.first H k p)=0 ∧ b (HubLightPaths.last H k p)=1)
    (hp : Set.InjOn (fun p : HubLightPaths.Path H k => (HubLightPaths.first H k p,HubLightPaths.last H k p)) Q)
    (hm : ∀ p∈Q, ∀ q∈Q, ∀ i j : Fin k, HubLightPaths.middle H k p i=HubLightPaths.middle H k q j → p=q ∧ i=j)
    (hsep : ∀ p∈Q, ∀ q∈Q, ∀ i : Fin k,
      HubLightPaths.first H k p≠HubLightPaths.middle H k q i ∧
      HubLightPaths.last H k p≠HubLightPaths.middle H k q i) :
    HubPathSubdivision.graph (color H k Q) k ⊑ H := by
  let e := edgeEquiv H k Q hp
  let ev := eval H k Q
  let hubs : Fin 2 → V := fun i => if i=0 then x else y
  let p (a : GraphSubdivision.Edge (graph H k Q)) : Chain H (k+1) := HubLightPaths.core H k (e.symm a).val
  have hmid (a : GraphSubdivision.Edge (graph H k Q)) (i : Fin k) :
      (p a).val i.succ.castSucc=HubLightPaths.middle H k (e.symm a).val i := by
    simp only [p,HubLightPaths.core,segment_apply,Fin.val_castSucc,Fin.val_succ,HubLightPaths.middle]
    apply congrArg (e.symm a).val.val
    apply Fin.ext
    change 1+(i.val+1)=i.val+2
    omega
  have hevinj : Function.Injective ev := Subtype.val_injective.sumElim Subtype.val_injective (by
    intro a d he
    obtain ⟨r,hr,her⟩ := mem_image.mp a.property
    obtain ⟨s,hs,hes⟩ := mem_image.mp d.property
    have hh := congrArg b (her.trans (he.trans hes.symm))
    rw [(hb r hr).1,(hb s hs).2] at hh
    exact (by decide : (0 : Fin 2)≠1) hh)
  obtain ⟨p₀,hp₀⟩ := hne
  have hh₀ := prop H k Q L x y hQ ⟨p₀,hp₀⟩
  have hxy : x≠y := by
    intro he
    have hh := congrArg Fin.val (hh₀.1.1 (hh₀.2.1.trans (he.trans hh₀.2.2.symm)))
    change 0=k+3 at hh
    omega
  have hzinj : Function.Injective hubs := by
    intro i j he
    fin_cases i <;> fin_cases j
    · rfl
    · exact (hxy he).elim
    · exact (hxy he.symm).elim
    · rfl
  have hminj : Function.Injective (fun a : GraphSubdivision.Edge (graph H k Q) × Fin k => (p a.1).val a.2.succ.castSucc) := by
    rintro ⟨a,i⟩ ⟨d,j⟩ he
    dsimp only at he
    rw [hmid,hmid] at he
    have hh := hm (e.symm a).val (e.symm a).property (e.symm d).val (e.symm d).property i j he
    exact Prod.ext (e.symm.injective (Subtype.ext hh.1)) hh.2
  have hzf (i : Fin 2) (w : Vertex H k Q) : hubs i≠ev w := by
    cases w with
    | inl w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      have hh := old_avoids H k Q L x y hQ ⟨q,hq⟩
      fin_cases i
      · exact fun h => hh.1 (h.trans he.symm)
      · exact fun h => hh.2.1 (h.trans he.symm)
    | inr w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      have hh := old_avoids H k Q L x y hQ ⟨q,hq⟩
      fin_cases i
      · exact fun h => hh.2.2.1 (h.trans he.symm)
      · exact fun h => hh.2.2.2 (h.trans he.symm)
  have hzm (i : Fin 2) (a : GraphSubdivision.Edge (graph H k Q)) (j : Fin k) : hubs i≠(p a).val j.succ.castSucc := by
    rw [hmid]
    have hh := middle_avoids H k Q L x y hQ (e.symm a) j
    fin_cases i
    · exact hh.1
    · exact hh.2
  have hfm (w : Vertex H k Q) (a : GraphSubdivision.Edge (graph H k Q)) (j : Fin k) : ev w≠(p a).val j.succ.castSucc := by
    rw [hmid]
    cases w with
    | inl w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      exact fun h => (hsep q hq (e.symm a).val (e.symm a).property j).1 (he.trans h)
    | inr w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      exact fun h => (hsep q hq (e.symm a).val (e.symm a).property j).2 (he.trans h)
  have hend (a : GraphSubdivision.Edge (graph H k Q)) :
      ev (ColoredEdges.left (color H k Q) a)=HubLightPaths.first H k (e.symm a).val ∧
      ev (ColoredEdges.right (color H k Q) a)=HubLightPaths.last H k (e.symm a).val := by
    have hl := ColoredEdges.left_unique (color H k Q) (e (e.symm a))
      (Sym2.mem_mk_left (Sum.inl (first H k Q (e.symm a))) (Sum.inr (last H k Q (e.symm a)))) rfl
    have hr := ColoredEdges.right_unique (color H k Q) (e (e.symm a))
      (Sym2.mem_mk_right (Sum.inl (first H k Q (e.symm a))) (Sum.inr (last H k Q (e.symm a)))) rfl
    rw [e.apply_symm_apply] at hl hr
    exact ⟨(congrArg ev hl).symm,(congrArg ev hr).symm⟩
  refine ⟨HubPathCopies.copyOfChains (color H k Q) H k hubs ev p hzinj hevinj hminj hzf hzm hfm ?_ ?_ ?_⟩
  · intro a
    exact (hend a).1.symm
  · intro a
    have hh := (hend a).2.symm
    simpa only [p,HubLightPaths.core,segment_apply,Fin.val_last,HubLightPaths.last,Nat.add_comm,Nat.add_left_comm,Nat.add_assoc] using hh
  · intro i w hw
    cases w with
    | inl w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      have hi : i=0 := hw.symm
      subst i
      change H.Adj x w.val
      rw [← he]
      exact first_adj H k Q L x y hQ ⟨q,hq⟩
    | inr w =>
      obtain ⟨q,hq,he⟩ := mem_image.mp w.property
      have hi : i=1 := hw.symm
      subst i
      change H.Adj y w.val
      rw [← he]
      exact last_adj H k Q L x y hQ ⟨q,hq⟩

include hQ in
lemma vertices_card (D : ℕ) (hD : ∀ v, H.degree v≤D) : Fintype.card (Vertex H k Q)≤2*D := by
  have hx : (X H k Q).card≤H.degree x := by
    rw [← H.card_neighborFinset_eq_degree]
    apply card_le_card
    intro w hw
    obtain ⟨p,hp,rfl⟩ := mem_image.mp hw
    exact (H.mem_neighborFinset _ _).mpr (first_adj H k Q L x y hQ ⟨p,hp⟩)
  have hy : (Y H k Q).card≤H.degree y := by
    rw [← H.card_neighborFinset_eq_degree]
    apply card_le_card
    intro w hw
    obtain ⟨p,hp,rfl⟩ := mem_image.mp hw
    exact (H.mem_neighborFinset _ _).mpr (last_adj H k Q L x y hQ ⟨p,hp⟩)
  simp only [Fintype.card_sum,Fintype.card_coe]
  have hdx := hD x
  have hdy := hD y
  omega

end
end SelectedHubLink

end -- SelectedHubLink

section -- OrientedRolePartition

/- A quarter of any finite family of ordered distinct pairs has prescribed
roles under a suitable two-class vertex partition. -/
open Finset
namespace OrientedRolePartition
set_option maxHeartbeats 1500000
universe u v
noncomputable section
variable {A : Type u} {V : Type v} [Fintype V]
local instance : DecidableEq V := Classical.decEq _

lemma differing (P : Finset A) (x y : A → V) (hxy : ∀ a∈P, x a≠y a) :
    ∃ c : V → Bool, P.card≤2*(P.filter (fun a => c (x a)≠c (y a))).card := by
  have hs : (∑ c : V → Bool, 2*(P.filter (fun a => c (x a)≠c (y a))).card)=
      Fintype.card (V → Bool)*P.card := by
    calc
      _ = ∑ c : V → Bool, ∑ a∈P, 2*(if c (x a)≠c (y a) then 1 else 0) := by
        simp only [card_filter,mul_sum]
      _ = ∑ a∈P, ∑ c : V → Bool, 2*(if c (x a)≠c (y a) then 1 else 0) := sum_comm
      _ = ∑ _a∈P, Fintype.card (V → Bool) := by
        apply sum_congr rfl
        intro a ha
        rw [← mul_sum,← card_filter]
        exact MaxCut.half_colorings (x a) (y a) (hxy a ha)
      _ = _ := by simp; ring
  have hh : (∑ _c : V → Bool, P.card)≤∑ c : V → Bool, 2*(P.filter (fun a => c (x a)≠c (y a))).card := by
    rw [hs]
    simp
  obtain ⟨c,_,hc⟩ := exists_le_of_sum_le (by simp : (univ : Finset (V → Bool)).Nonempty) hh
  exact ⟨c,hc⟩

lemma exists_roles (P : Finset A) (x y : A → V) (hxy : ∀ a∈P, x a≠y a) :
    ∃ b : V → Fin 2, P.card≤4*(P.filter (fun a => b (x a)=0 ∧ b (y a)=1)).card := by
  obtain ⟨c,hc⟩ := differing P x y hxy
  let A₀ := P.filter (fun a => c (x a)=false ∧ c (y a)=true)
  let A₁ := P.filter (fun a => c (x a)=true ∧ c (y a)=false)
  have hs : P.filter (fun a => c (x a)≠c (y a))⊆A₀∪A₁ := by
    intro a ha
    obtain ⟨ha,hn⟩ := mem_filter.mp ha
    by_cases hx : c (x a)=false
    · have hy : c (y a)=true := by cases h : c (y a) <;> simp_all
      exact mem_union_left _ (mem_filter.mpr ⟨ha,hx,hy⟩)
    · have hx' : c (x a)=true := by cases h : c (x a) <;> simp_all
      have hy : c (y a)=false := by cases h : c (y a) <;> simp_all
      exact mem_union_right _ (mem_filter.mpr ⟨ha,hx',hy⟩)
  have hcount := (card_le_card hs).trans (card_union_le _ _)
  by_cases h : A₀.card≤A₁.card
  · let b : V → Fin 2 := fun v => if c v then 0 else 1
    have he : P.filter (fun a => b (x a)=0 ∧ b (y a)=1)=A₁ := by
      ext a
      simp only [A₁,mem_filter,b]
      cases c (x a) <;> cases c (y a) <;> simp
    refine ⟨b,?_⟩
    rw [he]
    omega
  · let b : V → Fin 2 := fun v => if c v then 1 else 0
    have he : P.filter (fun a => b (x a)=0 ∧ b (y a)=1)=A₀ := by
      ext a
      simp only [A₀,mem_filter,b]
      cases c (x a) <;> cases c (y a) <;> simp
    refine ⟨b,?_⟩
    rw [he]
    omega
end
end OrientedRolePartition

end -- OrientedRolePartition

section -- FiniteRolePartitions

/- Simultaneous role separation using independently chosen two-class partitions. -/
open Finset
namespace FiniteRolePartitions
set_option maxHeartbeats 1500000
universe u v w
variable {A : Type u} {V : Type v} [Fintype V]

lemma select_nat (n : ℕ) (P : Finset A) (x y : Fin n → A → V)
    (hxy : ∀ i a, a∈P → x i a≠y i a) :
    ∃ (b : Fin n → V → Fin 2) (Q : Finset A), Q⊆P ∧
      (∀ i a, a∈Q → b i (x i a)=0 ∧ b i (y i a)=1) ∧ P.card≤4^n*Q.card := by
  classical
  induction n generalizing P with
  | zero => exact ⟨Fin.elim0,P,subset_rfl,(fun i => Fin.elim0 i),by simp⟩
  | succ n ih =>
    obtain ⟨b0,h0⟩ := OrientedRolePartition.exists_roles P (x 0) (y 0) (hxy 0)
    let P0 := P.filter (fun a => b0 (x 0 a)=0 ∧ b0 (y 0 a)=1)
    obtain ⟨b,Q,hQ,hroles,hcard⟩ := ih P0 (fun i => x i.succ) (fun i => y i.succ)
      (fun i a ha => hxy i.succ a (mem_filter.mp ha).1)
    refine ⟨Fin.cons b0 b,Q,hQ.trans (filter_subset _ _),?_,?_⟩
    · intro i
      refine Fin.cases ?_ (fun i => ?_) i
      · intro a ha
        exact (mem_filter.mp (hQ ha)).2
      · exact hroles i
    · have hh := h0.trans (Nat.mul_le_mul_left 4 hcard)
      simpa only [pow_succ,Nat.mul_assoc,Nat.mul_comm,Nat.mul_left_comm] using hh

lemma select {I : Type w} [Fintype I] (P : Finset A) (x y : I → A → V)
    (hxy : ∀ i a, a∈P → x i a≠y i a) :
    ∃ (b : I → V → Fin 2) (Q : Finset A), Q⊆P ∧
      (∀ i a, a∈Q → b i (x i a)=0 ∧ b i (y i a)=1) ∧ P.card≤4^(Fintype.card I)*Q.card := by
  classical
  let e := Fintype.equivFin I
  obtain ⟨b,Q,hQ,hr,hcard⟩ := select_nat (Fintype.card I) P
    (fun i => x (e.symm i)) (fun i => y (e.symm i)) (fun i a ha => hxy _ a ha)
  refine ⟨(fun i => b (e i)),Q,hQ,?_,hcard⟩
  intro i a ha
  simpa only [Equiv.symm_apply_apply] using hr (e i) a ha

end FiniteRolePartitions

end -- FiniteRolePartitions

section -- HubPathRoleSelection

/- Separate the two old-vertex roles from one another and from every core-interior coordinate. -/
open Finset SimpleGraph ChainCounting
namespace HubPathRoleSelection
open HubLightPaths
set_option maxHeartbeats 2000000
universe u
noncomputable section
variable {V : Type u} [Fintype V]
variable (H : SimpleGraph V)

lemma select (k : ℕ) (L : ℕ → ℕ) (x y : V) :
    ∃ (b : V → Fin 2) (Q : Finset (Path H k)), Q⊆links H k L x y ∧
      (∀ p∈Q, b (first H k p)=0 ∧ b (last H k p)=1) ∧
      (∀ p∈Q, ∀ q∈Q, ∀ i : Fin k,
        first H k p≠middle H k q i ∧ last H k p≠middle H k q i) ∧
      (links H k L x y).card≤4^(1+2*k)*Q.card := by
  let I := Unit ⊕ (Fin 2 × Fin k)
  let l : I → Path H k → V := Sum.elim (fun _ => first H k)
    (fun ij p => if ij.1=0 then first H k p else last H k p)
  let r : I → Path H k → V := Sum.elim (fun _ => last H k) (fun ij p => middle H k p ij.2)
  have hneq (i : I) (p : Path H k) (hp : p∈links H k L x y) : l i p≠r i p := by
    have hinj := ((mem_links H k L x y p).mp hp).1.1
    cases i with
    | inl a =>
      change first H k p≠last H k p
      apply hinj.ne
      intro he
      have hh := congrArg Fin.val he
      change 1=k+2 at hh
      omega
    | inr ij =>
      dsimp only [l,r,Sum.elim_inr]
      split_ifs
      · apply hinj.ne
        intro he
        have hh := congrArg Fin.val he
        change 1=ij.2.val+2 at hh
        omega
      · apply hinj.ne
        intro he
        have hh := congrArg Fin.val he
        change k+2=ij.2.val+2 at hh
        have := ij.2.isLt
        omega
  obtain ⟨b,Q,hQ,hroles,hcard⟩ := FiniteRolePartitions.select (links H k L x y) l r hneq
  refine ⟨b (Sum.inl ()),Q,hQ,?_,?_,?_⟩
  · intro p hp
    exact hroles (Sum.inl ()) p hp
  · intro p hp q hq i
    constructor
    · have hp' := (hroles (Sum.inr (0,i)) p hp).1
      have hq' := (hroles (Sum.inr (0,i)) q hq).2
      change b (Sum.inr (0,i)) (first H k p)=0 at hp'
      change b (Sum.inr (0,i)) (middle H k q i)=1 at hq'
      intro he
      rw [he,hq'] at hp'
      exact (by decide : (1 : Fin 2)≠0) hp'
    · have hp' := (hroles (Sum.inr (1,i)) p hp).1
      have hq' := (hroles (Sum.inr (1,i)) q hq).2
      change b (Sum.inr (1,i)) (last H k p)=0 at hp'
      change b (Sum.inr (1,i)) (middle H k q i)=1 at hq'
      intro he
      rw [he,hq'] at hp'
      exact (by decide : (1 : Fin 2)≠0) hp'
  · simpa only [I,Fintype.card_sum,Fintype.card_prod,Fintype.card_unit,Fintype.card_fin] using hcard

end
end HubPathRoleSelection

end -- HubPathRoleSelection

section -- HubLightBounds

/- The full truncated-good path bound, for an arbitrary replacement length. -/
open Finset SimpleGraph ChainCounting HubLightPaths
namespace HubLightBounds
set_option maxHeartbeats 3000000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] (F : SimpleGraph W) (c : F.Coloring (Fin 2))
variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

def loss (k : ℕ) (L : ℕ → ℕ) : ℕ := 4^(1+2*k)*((k+1)*(L (k+1)+k*(L (k+1))^2))

lemma selected_bound (hF : F.Connected) (k D : ℕ) (L : ℕ → ℕ) (x y : V)
    (Q : Finset (Path H k)) (hQ : Q⊆links H k L x y)
    (b : V → Fin 2) (hb : ∀ p∈Q, b (first H k p)=0 ∧ b (last H k p)=1)
    (hp : Set.InjOn (fun p : Path H k => (first H k p,last H k p)) Q)
    (hm : ∀ p∈Q, ∀ q∈Q, ∀ i j : Fin k, middle H k p i=middle H k q j → p=q ∧ i=j)
    (hsep : ∀ p∈Q, ∀ q∈Q, ∀ i : Fin k, first H k p≠middle H k q i ∧ last H k p≠middle H k q i)
    (hD : ∀ v, H.degree v≤D) (hfree : (HubPathSubdivision.graph c k).Free H)
    (C α : ℝ) (hC : 0≤C) (hα : 0≤α)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α) :
    (Q.card : ℝ)≤C*(2*(D : ℝ))^α := by
  by_cases hne : Q.Nonempty
  · let J := SelectedHubLink.graph H k Q
    have hJfree : F.Free J := by
      rintro ⟨f⟩
      have h1 := HubPathCopyTransport.copy_of_copy hF c (SelectedHubLink.color H k Q) f k
      have h2 := SelectedHubLink.copy H k Q L x y hQ hne b hb hp hm hsep
      exact hfree (h1.trans h2)
    have he : Q.card=Nat.card J.edgeSet := by
      rw [Nat.card_eq_fintype_card,← Fintype.card_coe Q]
      exact Fintype.card_congr (SelectedHubLink.edgeEquiv H k Q hp)
    have hj := SimpleGraph.card_edgeFinset_le_extremalNumber hJfree
    have hh : (Nat.card J.edgeSet : ℝ)≤(extremalNumber (Fintype.card (SelectedHubLink.Vertex H k Q)) F : ℝ) := by
      simpa only [← SimpleGraph.card_edgeSet,← Nat.card_eq_fintype_card] using (show
        (J.edgeFinset.card : ℝ)≤(extremalNumber (Fintype.card (SelectedHubLink.Vertex H k Q)) F : ℝ) by exact_mod_cast hj)
    have hn : (Fintype.card (SelectedHubLink.Vertex H k Q) : ℝ)≤2*(D : ℝ) := by
      exact_mod_cast SelectedHubLink.vertices_card H k Q L x y hQ D hD
    rw [he]
    exact (hh.trans (hbound _)).trans (mul_le_mul_of_nonneg_left (Real.rpow_le_rpow (by positivity) hn hα) hC)
  · rw [not_nonempty_iff_eq_empty.mp hne,card_empty,Nat.cast_zero]
    positivity

lemma link_bound (hF : F.Connected) (k D : ℕ) (L : ℕ → ℕ) (hL : Monotone L)
    (x y : V) (hD : ∀ v, H.degree v≤D) (hfree : (HubPathSubdivision.graph c k).Free H)
    (C α : ℝ) (hC : 0≤C) (hα : 0≤α)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α) :
    ((links H k L x y).card : ℝ)≤(loss k L : ℝ)*(C*(2*(D : ℝ))^α) := by
  obtain ⟨b,P,hP,hb,hsep,hcard⟩ := HubPathRoleSelection.select H k L x y
  obtain ⟨Q,hQ,hpair,hmid,hcount⟩ := HubLightSelection.select H k L hL x y P hP
  have hQbound := selected_bound F c H hF k D L x y Q (hQ.trans hP) b
    (fun p hp => hb p (hQ hp)) hpair hmid (fun p hp q hq i => hsep p (hQ hp) q (hQ hq) i)
    hD hfree C α hC hα hbound
  have hnat : (links H k L x y).card≤loss k L*Q.card := by
    exact (hcard.trans (Nat.mul_le_mul_left _ hcount)).trans_eq (by dsimp only [loss]; ring)
  have hreal : ((links H k L x y).card : ℝ)≤(loss k L : ℝ)*Q.card := by exact_mod_cast hnat
  exact hreal.trans (mul_le_mul_of_nonneg_left hQbound (Nat.cast_nonneg _))

lemma good_bound (hF : F.Connected) (k D : ℕ) (L : ℕ → ℕ) (hL : Monotone L)
    (hD : ∀ v, H.degree v≤D) (hfree : (HubPathSubdivision.graph c k).Free H)
    (C α : ℝ) (hC : 0≤C) (hα : 0≤α)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α) :
    ((good H k L).card : ℝ)≤(loss k L : ℝ)*(Fintype.card V : ℝ)^2*(C*(2*(D : ℝ))^α) := by
  have he : (good H k L).card=∑ xy : V × V, (links H k L xy.1 xy.2).card := by
    have hh := card_eq_sum_card_fiberwise (s := good H k L) (t := (univ : Finset (V × V)))
      (fun p _ => mem_univ (p.val 0,p.val (Fin.last (k+3))))
    apply hh.trans
    apply sum_congr rfl
    rintro ⟨x,y⟩ _
    congr 1
    ext p
    simp only [links,mem_filter,Prod.mk.injEq]
  rw [he,Nat.cast_sum]
  apply (sum_le_sum (fun xy _ => link_bound F c H hF k D L hL xy.1 xy.2 hD hfree C α hC hα hbound)).trans_eq
  simp only [sum_const,card_univ,Fintype.card_prod,nsmul_eq_mul,Nat.cast_mul]
  ring

end
end HubLightBounds

end -- HubLightBounds

section -- HubAdmissibleCount

/- The general hub path count with only an absorbable constant error. -/
open Finset SimpleGraph ChainCounting
namespace HubAdmissibleCount
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] (F : SimpleGraph W) (c : F.Coloring (Fin 2))
variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

lemma count (hF : F.Connected) (k B d D : ℕ) (hd : ∀ v, d+(k+3)≤H.degree v)
    (hD : ∀ v, H.degree v≤D) (hfree : (HubPathSubdivision.graph c k).Free H)
    (C α ε : ℝ) (hC : 0≤C) (hα : 0≤α) (hε : 0≤ε)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α)
    (hsmall : ∀ j : ℕ, 2≤j → j≤k+1 → ((AdmissibleHeavyLinks.bad H B j).card : ℝ)≤
      ε*Fintype.card V*(D : ℝ)^j) :
    (Fintype.card V : ℝ)*(d : ℝ)^(k+3)≤
      (HubLightBounds.loss k (ThetaChains.threshold B) : ℝ)*C*2^α*(Fintype.card V : ℝ)^2*(D : ℝ)^α+
      (k+4 : ℕ)*(k+2 : ℕ)*ε*Fintype.card V*(D : ℝ)^(k+3) := by
  have hc : (Fintype.card V : ℝ)*(d : ℝ)^(k+3)≤(HubLightPaths.good H k (ThetaChains.threshold B)).card+
      (k+4 : ℕ)*∑ j : Fin (k+2), ((AdmissibleHeavyLinks.bad H B j.val).card : ℝ)*(D : ℝ)^(k+3-j.val) := by
    exact_mod_cast AdmissibleHubLightCount.count H k B d D hd hD
  have hgood := HubLightBounds.good_bound F c H hF k D (ThetaChains.threshold B) (ThetaChains.threshold_mono B)
    hD hfree C α hC hα hbound
  have hsum : (∑ j : Fin (k+2), ((AdmissibleHeavyLinks.bad H B j.val).card : ℝ)*(D : ℝ)^(k+3-j.val))≤
      (k+2 : ℕ)*(ε*Fintype.card V*(D : ℝ)^(k+3)) := by
    calc
      _ ≤ ∑ _j : Fin (k+2), ε*Fintype.card V*(D : ℝ)^(k+3) := by
        apply sum_le_sum
        intro j _
        by_cases hj : 2≤j.val
        · have hh := mul_le_mul_of_nonneg_right (hsmall j.val hj (by omega))
            (pow_nonneg (Nat.cast_nonneg D) (k+3-j.val))
          have he : (D : ℝ)^j.val*(D : ℝ)^(k+3-j.val)=(D : ℝ)^(k+3) := by
            rw [← pow_add,Nat.add_sub_of_le (by omega : j.val≤k+3)]
          simpa only [mul_assoc,he] using hh
        · rw [AdmissibleHubLightCount.bad_small H B j.val (by omega),card_empty,Nat.cast_zero,zero_mul]
          positivity
      _ = _ := by simp
  have hm := mul_le_mul_of_nonneg_left hsum (Nat.cast_nonneg (k+4))
  rw [Real.mul_rpow (by norm_num : (0 : ℝ)≤2) (Nat.cast_nonneg D)] at hgood
  nlinarith only [hc,hgood,hm]

end
end HubAdmissibleCount

end -- HubAdmissibleCount

section -- BipartiteReservoirPaths

/- Fixed-length paths inside two complete bipartite reservoirs, avoiding
an arbitrary finite set at all internal vertices. -/
open Finset SimpleGraph ChainCounting
namespace BipartiteReservoirPaths
set_option maxHeartbeats 2500000
universe u
noncomputable section
variable {V : Type u} (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _

def pool (A B : Finset V) (i : ℕ) : Finset V := if i%2=0 then A else B

lemma exists_path (A B S : Finset V) (m : ℕ) (hm : 0 < m) (x y : V)
    (hx : x∈A) (hy : y∈pool A B m) (hxy : x≠y)
    (hA : S.card+m+2≤A.card) (hB : S.card+m+2≤B.card)
    (hcomplete : ∀ a∈A, ∀ b∈B, H.Adj a b) :
    ∃ p : Chain H m, Function.Injective p.val ∧ p.val 0=x ∧ p.val (Fin.last m)=y ∧
      Disjoint (interior H p) S ∧ ∀ i, p.val i∈pool A B i.val := by
  classical
  let P (i : Fin (m-1)) : Set V := {v | v∈pool A B (i.val+1) ∧ v∉S ∧ v≠x ∧ v≠y}
  obtain ⟨g,hg,hdis⟩ := FiniteLabelPacking.select_fintype 1 P (fun v => ({v} : Finset V))
    (fun _ _ _ => by simp) (by
      intro i T hT
      have hT' : T.card≤ m-1 := by simpa using hT
      let U := S∪({x,y}∪T)
      have hU : U.card<S.card+m+2 := by
        have h₁ := card_union_le S ({x,y}∪T)
        have h₂ := card_union_le ({x,y} : Finset V) T
        have h₃ : ({x,y} : Finset V).card≤2 := (card_insert_le x {y}).trans (by simp)
        dsimp only [U]
        omega
      have hpool : S.card+m+2≤(pool A B (i.val+1)).card := by
        dsimp only [pool]
        split_ifs <;> assumption
      obtain ⟨v,hv,hvU⟩ := exists_mem_notMem_of_card_lt_card (hU.trans_le hpool)
      have hvS : v∉S := fun h => hvU (mem_union_left _ h)
      have hvx : v≠x := fun h => hvU (mem_union_right _ (mem_union_left _ (mem_insert.mpr (Or.inl h))))
      have hvy : v≠y := fun h => hvU (mem_union_right _ (mem_union_left _ (mem_insert_of_mem (mem_singleton.mpr h))))
      have hvT : v∉T := fun h => hvU (mem_union_right _ (mem_union_right _ h))
      exact ⟨v,⟨hv,hvS,hvx,hvy⟩,by simpa only [disjoint_singleton_left] using hvT⟩)
  have hgi : Function.Injective g := by
    intro i j he
    by_contra hn
    exact Finset.disjoint_left.mp (hdis i j hn) (mem_singleton_self _) (mem_singleton.mpr he)
  let f (i : Fin (m+1)) : V :=
    if h0 : i.val=0 then x else if hl : i.val=m then y else g ⟨i.val-1,by omega⟩
  have hf0 : f 0=x := by simp [f]
  have hflast : f (Fin.last m)=y := by simp [f,hm.ne']
  have hfm (i : Fin (m-1)) : f ⟨i.val+1,by omega⟩=g i := by
    dsimp only [f]
    rw [dif_neg (by omega),dif_neg (by omega)]
    congr 1
  have hfi : Function.Injective f := by
    intro i j he
    dsimp only [f] at he
    split_ifs at he with hi0 him hj0 hjm hj0 hjm
    · exact Fin.ext (by omega)
    · exact (hxy he).elim
    · exact ((hg _).2.2.1 he.symm).elim
    · exact (hxy he.symm).elim
    · exact Fin.ext (by omega)
    · exact ((hg _).2.2.2 he.symm).elim
    · exact ((hg _).2.2.1 he).elim
    · exact ((hg _).2.2.2 he).elim
    · have hh := congrArg Fin.val (hgi he)
      apply Fin.ext
      dsimp only [Fin.val_mk] at hh
      omega
  have hpool (i : Fin (m+1)) : f i∈pool A B i.val := by
    dsimp only [f]
    split_ifs with hi0 him
    · simpa [hi0,pool] using hx
    · simpa only [him] using hy
    · have hh := (hg ⟨i.val-1,by omega⟩).1
      simpa only [show i.val-1+1=i.val by omega] using hh
  have hchain : IsChain H f := by
    intro i
    have h₀ := hpool i.castSucc
    have h₁ := hpool i.succ
    have hi : i.val%2=0 ∨ i.val%2=1 := by omega
    rcases hi with hi | hi
    · have hnext : (i.val+1)%2≠0 := by omega
      simp only [pool,Fin.val_castSucc,Fin.val_succ,hi,if_pos rfl,if_neg hnext] at h₀ h₁
      exact hcomplete _ h₀ _ h₁
    · have hnext : (i.val+1)%2=0 := by omega
      simp only [pool,Fin.val_castSucc,Fin.val_succ,hi,hnext,if_pos rfl,show (1 : ℕ)≠0 by omega,if_false] at h₀ h₁
      exact (hcomplete _ h₁ _ h₀).symm
  refine ⟨⟨f,hchain⟩,hfi,hf0,hflast,?_,hpool⟩
  apply Finset.disjoint_left.mpr
  intro v hv hvS
  obtain ⟨i,hi0,him,he⟩ := (mem_interior H ⟨f,hchain⟩ v).mp hv
  have hi : (⟨(i.val-1)+1,by omega⟩ : Fin (m+1))=i := Fin.ext (by dsimp; omega)
  have hfg : f i=g ⟨i.val-1,by omega⟩ := by simpa only [hi] using hfm ⟨i.val-1,by omega⟩
  have he' : f i=v := he
  exact (hg ⟨i.val-1,by omega⟩).2.1 ((hfg.symm.trans he').symm ▸ hvS)


lemma select_paths {E : Type*} [Fintype E] (A B S : Finset V) (m : ℕ) (hm : 0 < m)
    (x y : E → V) (hx : ∀ e, x e∈A) (hy : ∀ e, y e∈pool A B m) (hxy : ∀ e, x e≠y e)
    (hA : S.card+(m-1)*Fintype.card E+m+2≤A.card)
    (hB : S.card+(m-1)*Fintype.card E+m+2≤B.card)
    (hcomplete : ∀ a∈A, ∀ b∈B, H.Adj a b) :
    ∃ p : E → Chain H m,
      (∀ e, Function.Injective (p e).val ∧ (p e).val 0=x e ∧ (p e).val (Fin.last m)=y e ∧
        Disjoint (interior H (p e)) S ∧ ∀ i, (p e).val i∈pool A B i.val) ∧
      ∀ e f, e≠f → Disjoint (interior H (p e)) (interior H (p f)) := by
  classical
  let P (e : E) : Set (Chain H m) := {p | Function.Injective p.val ∧ p.val 0=x e ∧
    p.val (Fin.last m)=y e ∧ Disjoint (interior H p) S ∧ ∀ i, p.val i∈pool A B i.val}
  obtain ⟨p,hp,hdis⟩ := FiniteLabelPacking.select_fintype (m-1) P (interior H)
    (fun _ p _ => interior_card_le H p) (by
      intro e T hT
      have hST : (S∪T).card+m+2≤S.card+(m-1)*Fintype.card E+m+2 := by
        have hh := card_union_le S T
        omega
      obtain ⟨q,hq,hq0,hql,hqS,hqp⟩ := exists_path H A B (S∪T) m hm (x e) (y e) (hx e) (hy e) (hxy e)
        (hST.trans hA) (hST.trans hB) hcomplete
      exact ⟨q,⟨hq,hq0,hql,hqS.mono_right subset_union_left,hqp⟩,hqS.mono_right subset_union_right⟩)
  exact ⟨p,hp,hdis⟩

end
end BipartiteReservoirPaths

end -- BipartiteReservoirPaths

section -- HeavyChainBundle

/- Lift a whole internally disjoint bundle of shadow paths, keeping a
prescribed finite set out of all new path interiors. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace HeavyChainBundle
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u v
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
variable {E : Type v} [Fintype E]

lemma lift (B j m : ℕ) (hj : 0<j) (S : Finset V) (b : E → Chain (HeavyShadow.graph H B j) m)
    (hbinj : ∀ e, Function.Injective (b e).val)
    (hbS : ∀ e, Disjoint (interior (HeavyShadow.graph H B j) (b e)) S)
    (hbdis : ∀ e f, e≠f → Disjoint (interior (HeavyShadow.graph H B j) (b e))
      (interior (HeavyShadow.graph H B j) (b f)))
    (hB : (j-1)*(Fintype.card E*m)+S.card+Fintype.card E*(m+1)≤B) :
    ∃ p : E → Chain H (m*j),
      (∀ e, Function.Injective (p e).val ∧ (p e).val 0=(b e).val 0 ∧
        (p e).val (Fin.last (m*j))=(b e).val (Fin.last m) ∧ Disjoint (interior H (p e)) S) ∧
      ∀ e f, e≠f → Disjoint (interior H (p e)) (interior H (p f)) := by
  classical
  let Branches := univ.image (fun z : E × Fin (m+1) => (b z.1).val z.2)
  let U := S∪Branches
  have hBranches : Branches.card≤Fintype.card E*(m+1) := card_image_le.trans_eq (by simp)
  have hU : U.card≤S.card+Fintype.card E*(m+1) := (card_union_le S Branches).trans (Nat.add_le_add_left hBranches _)
  let P (e : E × Fin m) : Set (Chain H j) := {q |
    q∈fiber H (threshold B) j ((b e.1).val e.2.castSucc) ((b e.1).val e.2.succ) ∧
      Disjoint (interior H q) U}
  obtain ⟨r,hr,hrdis⟩ := FiniteLabelPacking.select_fintype (j-1) P (interior H)
    (fun _ q _ => interior_card_le H q) (by
      intro e T hT
      have hsize : (T∪U).card≤B := by
        have hh := card_union_le T U
        simp only [Fintype.card_prod,Fintype.card_fin] at hT
        omega
      obtain ⟨q,hq,hqdis⟩ := fiber_avoiding H B j hj _ _ ((b e.1).property e.2).2 (T∪U) hsize
      exact ⟨q,⟨hq,hqdis.mono_right subset_union_right⟩,hqdis.mono_right subset_union_left⟩)
  have hr' (e : E × Fin m) := (mem_fiber H (threshold B) j _ _ (r e)).mp (hr e).1
  have hbranch (e : E) (i : Fin (m+1)) : (b e).val i∈U :=
    mem_union_right _ (mem_image.mpr ⟨(e,i),mem_univ _,rfl⟩)
  have hconcat (e : E) : ∃ q : Chain H (m*j), Function.Injective q.val ∧ q.val 0=(b e).val 0 ∧
      q.val (Fin.last (m*j))=(b e).val (Fin.last m) ∧
      ∀ i, (∃ a, q.val i=(b e).val a) ∨ ∃ a, q.val i∈interior H (r (e,a)) := by
    exact concatenate H j m (b e).val (fun a => r (e,a)) (hbinj e)
      (fun a => ⟨(hr' (e,a)).1.1,(hr' (e,a)).2⟩)
      (fun a i hi => Finset.disjoint_left.mp (hr (e,a)).2 hi (hbranch e i))
      (fun a c hac => hrdis (e,a) (e,c) (fun h => hac (congrArg Prod.snd h)))
  choose p hp hp0 hplast hcover using hconcat
  have hmidcover (e : E) (v : V) (hv : v∈interior H (p e)) :
      v∈interior (HeavyShadow.graph H B j) (b e) ∨ ∃ a, v∈interior H (r (e,a)) := by
    obtain ⟨i,hi0,hil,he⟩ := (mem_interior H (p e) v).mp hv
    rcases hcover e i with ⟨a,ha⟩ | ⟨a,ha⟩
    · have hv0 : v≠(b e).val 0 := by
        intro h
        have hh := congrArg Fin.val ((hp e) (he.trans (h.trans (hp0 e).symm)))
        simp only [Fin.val_zero] at hh
        omega
      have hvl : v≠(b e).val (Fin.last m) := by
        intro h
        have hh := congrArg Fin.val ((hp e) (he.trans (h.trans (hplast e).symm)))
        simp only [Fin.val_last] at hh
        omega
      rcases vertex_cases (HeavyShadow.graph H B j) (b e) a with h0 | hl | hm
      · exact (hv0 (he.symm.trans (ha.trans h0))).elim
      · exact (hvl (he.symm.trans (ha.trans hl))).elim
      · exact Or.inl ((ha.symm.trans he) ▸ hm)
    · exact Or.inr ⟨a,he ▸ ha⟩
  have hav (e : E × Fin m) : Disjoint (interior H (r e)) S := (hr e).2.mono_right subset_union_left
  refine ⟨p,fun e => ⟨hp e,hp0 e,hplast e,?_⟩,?_⟩
  · apply Finset.disjoint_left.mpr
    intro v hv hvS
    rcases hmidcover e v hv with hv | ⟨a,ha⟩
    · exact Finset.disjoint_left.mp (hbS e) hv hvS
    · exact Finset.disjoint_left.mp (hav (e,a)) ha hvS
  · intro e f hef
    apply Finset.disjoint_left.mpr
    intro v hve hvf
    rcases hmidcover e v hve with he | ⟨a,ha⟩ <;>
      rcases hmidcover f v hvf with hf | ⟨c,hc⟩
    · exact Finset.disjoint_left.mp (hbdis e f hef) he hf
    · obtain ⟨i,_,_,hi⟩ := (mem_interior (HeavyShadow.graph H B j) (b e) v).mp he
      exact Finset.disjoint_left.mp (hr (f,c)).2 hc (hi ▸ hbranch e i)
    · obtain ⟨i,_,_,hi⟩ := (mem_interior (HeavyShadow.graph H B j) (b f) v).mp hf
      exact Finset.disjoint_left.mp (hr (e,a)).2 ha (hi ▸ hbranch f i)
    · exact Finset.disjoint_left.mp (hrdis (e,a) (f,c) (fun h => hef (congrArg Prod.fst h))) ha hc

end
end HeavyChainBundle

end -- HeavyChainBundle

section -- AppendChainBundle

/- Append disjoint tails to an internally disjoint path bundle. -/
open Finset SimpleGraph ChainCounting
namespace AppendChainBundle
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {V : Type u} (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
variable {E : Type v}

def cotail {l : ℕ} (q : Chain H l) : Finset V := insert (q.val 0) (interior H q)

lemma append_bundle (n l : ℕ) (p : E → Chain H n) (q : E → Chain H l)
    (hp : ∀ e, Function.Injective (p e).val) (hq : ∀ e, Function.Injective (q e).val)
    (hjoin : ∀ e, (p e).val (Fin.last n)=(q e).val 0)
    (hstart : ∀ e f i, (p e).val 0≠(q f).val i)
    (havoid : ∀ e f i, (q f).val i∉interior H (p e))
    (hpdis : ∀ e f, e≠f → Disjoint (interior H (p e)) (interior H (p f)))
    (hqdis : ∀ e f, e≠f → Disjoint (cotail H (q e)) (cotail H (q f))) :
    ∃ r : E → Chain H (n+l),
      (∀ e, Function.Injective (r e).val ∧ (r e).val 0=(p e).val 0 ∧
        (r e).val (Fin.last (n+l))=(q e).val (Fin.last l) ∧
        interior H (r e)⊆interior H (p e)∪cotail H (q e)) ∧
      ∀ e f, e≠f → Disjoint (interior H (r e)) (interior H (r f)) := by
  let r (e : E) := append H (p e) (q e) (hjoin e)
  have hr (e : E) : Function.Injective (r e).val := by
    apply append_injective H (p e) (q e) (hjoin e) (hp e) (hq e)
    intro i j he
    rcases vertex_cases H (p e) i with h0 | hl | hm
    · exact (hstart e e j (h0.symm.trans he)).elim
    · exact ⟨(hp e) hl,(hq e) (he.symm.trans (hl.trans (hjoin e)))⟩
    · exact (havoid e e j (he ▸ hm)).elim
  have hsub (e : E) : interior H (r e)⊆interior H (p e)∪cotail H (q e) := by
    intro v hv
    obtain ⟨i,hi0,hil,he⟩ := (mem_interior H (r e) v).mp hv
    have hv0 : v≠(p e).val 0 := by
      intro hv0
      have hh := congrArg Fin.val (hr e (he.trans (hv0.trans (append_start H (p e) (q e) (hjoin e)).symm)))
      simp only [Fin.val_zero] at hh
      omega
    have hvl : v≠(q e).val (Fin.last l) := by
      intro hvl
      have hh := congrArg Fin.val (hr e (he.trans (hvl.trans (append_last H (p e) (q e) (hjoin e)).symm)))
      simp only [Fin.val_last] at hh
      omega
    rcases append_vertex H (p e) (q e) (hjoin e) i with ⟨a,ha⟩ | ⟨a,ha⟩
    · rcases vertex_cases H (p e) a with h0 | hl | hm
      · exact (hv0 (he.symm.trans (ha.trans h0))).elim
      · exact mem_union_right _ (mem_insert.mpr (Or.inl (he.symm.trans (ha.trans (hl.trans (hjoin e))))))
      · exact mem_union_left _ ((ha.symm.trans he) ▸ hm)
    · rcases vertex_cases H (q e) a with h0 | hl | hm
      · exact mem_union_right _ (mem_insert.mpr (Or.inl (he.symm.trans (ha.trans h0))))
      · exact (hvl (he.symm.trans (ha.trans hl))).elim
      · exact mem_union_right _ (mem_insert_of_mem ((ha.symm.trans he) ▸ hm))
  have hcross (e f : E) : Disjoint (interior H (p e)) (cotail H (q f)) := by
    apply Finset.disjoint_left.mpr
    intro v hpv hqv
    rcases mem_insert.mp hqv with h0 | hm
    · exact havoid e f 0 (h0 ▸ hpv)
    · obtain ⟨i,_,_,he⟩ := (mem_interior H (q f) v).mp hm
      exact havoid e f i (he.symm ▸ hpv)
  refine ⟨r,fun e => ⟨hr e,append_start H (p e) (q e) (hjoin e),append_last H (p e) (q e) (hjoin e),hsub e⟩,?_⟩
  intro e f hef
  apply Finset.disjoint_left.mpr
  intro v hve hvf
  rcases mem_union.mp (hsub e hve) with he | he <;> rcases mem_union.mp (hsub f hvf) with hf | hf
  · exact Finset.disjoint_left.mp (hpdis e f hef) he hf
  · exact Finset.disjoint_left.mp (hcross e f) he hf
  · exact Finset.disjoint_left.mp (hcross f e) hf he
  · exact Finset.disjoint_left.mp (hqdis e f hef) he hf

end
end AppendChainBundle

end -- AppendChainBundle

section -- ChainFront

/- All vertices of a path except its final endpoint, also for zero length. -/
open Finset SimpleGraph ChainCounting
namespace ChainFront
set_option maxHeartbeats 2000000
universe u v
noncomputable section
variable {V : Type u} (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _

def front {l : ℕ} (p : Chain H l) : Finset V := univ.image (fun i : Fin l => p.val i.castSucc)

lemma card_le {l : ℕ} (p : Chain H l) : (front H p).card≤l := card_image_le.trans_eq (by simp)

lemma mem_front {l : ℕ} (p : Chain H l) (v : V) :
    v∈front H p ↔ ∃ i : Fin (l+1), i.val<l ∧ p.val i=v := by
  constructor
  · rintro hv
    obtain ⟨i,_,hi⟩ := mem_image.mp hv
    exact ⟨i.castSucc,i.isLt,hi⟩
  · rintro ⟨i,hi,he⟩
    exact mem_image.mpr ⟨⟨i.val,hi⟩,mem_univ _,he⟩

lemma eq_cotail {l : ℕ} (hl : 0<l) (p : Chain H l) : front H p=AppendChainBundle.cotail H p := by
  ext v
  simp only [AppendChainBundle.cotail,mem_insert,mem_front,mem_interior]
  constructor
  · rintro ⟨i,hi,he⟩
    by_cases hi0 : i.val=0
    · left
      exact he.symm.trans (congrArg p.val (Fin.ext hi0))
    · right
      exact ⟨i,by omega,hi,he⟩
  · rintro (he | ⟨i,hi0,hi,he⟩)
    · exact ⟨0,hl,he.symm⟩
    · exact ⟨i,hi,he⟩


lemma append_bundle {E : Type v} (n l : ℕ) (p : E → Chain H n) (q : E → Chain H l)
    (hp : ∀ e, Function.Injective (p e).val) (hq : ∀ e, Function.Injective (q e).val)
    (hjoin : ∀ e, (p e).val (Fin.last n)=(q e).val 0)
    (hstart : ∀ e f i, (p e).val 0≠(q f).val i)
    (havoid : ∀ e f i, (q f).val i∉interior H (p e))
    (hpdis : ∀ e f, e≠f → Disjoint (interior H (p e)) (interior H (p f)))
    (hqdis : ∀ e f, e≠f → Disjoint (front H (q e)) (front H (q f))) :
    ∃ r : E → Chain H (n+l),
      (∀ e, Function.Injective (r e).val ∧ (r e).val 0=(p e).val 0 ∧
        (r e).val (Fin.last (n+l))=(q e).val (Fin.last l) ∧
        interior H (r e)⊆interior H (p e)∪front H (q e)) ∧
      ∀ e f, e≠f → Disjoint (interior H (r e)) (interior H (r f)) := by
  by_cases hl : l=0
  · subst l
    simp only [Nat.add_zero]
    exact ⟨p,fun e => ⟨hp e,rfl,hjoin e,subset_union_left⟩,hpdis⟩
  · have hlp : 0<l := by omega
    simp_rw [eq_cotail H hlp] at hqdis ⊢
    exact AppendChainBundle.append_bundle H n l p q hp hq hjoin hstart havoid hpdis hqdis

end
end ChainFront

end -- ChainFront

section -- HubPathBundleCopy

/- The bundle formulation of a hub-subdivision copy. -/
open Finset SimpleGraph ChainCounting
namespace HubPathBundleCopy
set_option maxHeartbeats 2000000
universe u v
variable {W : Type u} {F : SimpleGraph W} (c : F.Coloring (Fin 2))
variable {V : Type v} (H : SimpleGraph V) (k : ℕ)
noncomputable section
local instance : DecidableEq V := Classical.decEq _

lemma copy (z : Fin 2 → V) (f : W → V) (p : GraphSubdivision.Edge F → Chain H (k+1))
    (hz : Function.Injective z) (hf : Function.Injective f) (hzf : ∀ i w, z i≠f w)
    (hp : ∀ e, Function.Injective (p e).val)
    (hpdis : ∀ e d, e≠d → Disjoint (interior H (p e)) (interior H (p d)))
    (hzp : ∀ i e, z i∉interior H (p e)) (hfp : ∀ w e, f w∉interior H (p e))
    (hstart : ∀ e, (p e).val 0=f (ColoredEdges.left c e))
    (hend : ∀ e, (p e).val (Fin.last (k+1))=f (ColoredEdges.right c e))
    (hhub : ∀ i w, c w=i → H.Adj (z i) (f w)) : HubPathSubdivision.graph c k ⊑ H := by
  let m (e : GraphSubdivision.Edge F × Fin k) : V := (p e.1).val e.2.succ.castSucc
  have hm_mem (e : GraphSubdivision.Edge F × Fin k) : m e∈interior H (p e.1) := by
    apply (mem_interior H (p e.1) _).mpr
    exact ⟨e.2.succ.castSucc,by simp,by simp only [Fin.val_castSucc,Fin.val_succ]; omega,rfl⟩
  have hm : Function.Injective m := by
    intro e d he
    have hfirst : e.1=d.1 := by
      by_contra hn
      exact Finset.disjoint_left.mp (hpdis e.1 d.1 hn) (hm_mem e) (he.symm ▸ hm_mem d)
    have hsecond : e.2=d.2 := by
      have hh := hp d.1 (by simpa only [m,hfirst] using he)
      have hn := congrArg Fin.val hh
      apply Fin.ext
      change e.2.val+1=d.2.val+1 at hn
      omega
    exact Prod.ext hfirst hsecond
  have hzm (i : Fin 2) (e : GraphSubdivision.Edge F × Fin k) : z i≠m e := by
    intro he
    exact hzp i e.1 (he.symm ▸ hm_mem e)
  have hfm (w : W) (e : GraphSubdivision.Edge F × Fin k) : f w≠m e := by
    intro he
    exact hfp w e.1 (he.symm ▸ hm_mem e)
  exact ⟨HubPathCopies.copyOfChains c H k z f p hz hf hm hzf
    (fun i e j => hzm i (e,j)) (fun w e j => hfm w (e,j)) hstart hend hhub⟩

end
end HubPathBundleCopy

end -- HubPathBundleCopy

section -- HubReservoirAssembly

/- Assemble a hub-subdivision from heavy complete bipartite reservoirs and
an externally selected disjoint tail bundle. -/
open Finset SimpleGraph ChainCounting
namespace HubReservoirAssembly
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] {F : SimpleGraph W} (c : F.Coloring (Fin 2))
variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : Fintype (GraphSubdivision.Edge F) := Fintype.ofFinite _

lemma copy (B j m l k : ℕ) (hj : 0<j) (hm : 0 < m) (hlen : m*j+l=k+1)
    (A C S : Finset V) (z : Fin 2 → V) (f : W → V) (q : GraphSubdivision.Edge F → Chain H l)
    (hz : Function.Injective z) (hf : Function.Injective f) (hzf : ∀ i w, z i≠f w)
    (hspoke : ∀ i w, c w=i → H.Adj (z i) (f w))
    (hqinj : ∀ e, Function.Injective (q e).val)
    (hqend : ∀ e, (q e).val (Fin.last l)=f (ColoredEdges.right c e))
    (hqdis : ∀ e d, e≠d → Disjoint (ChainFront.front H (q e)) (ChainFront.front H (q d)))
    (hqold : ∀ w e, f w∉ChainFront.front H (q e))
    (hqhub : ∀ i e, z i∉ChainFront.front H (q e))
    (hleft : ∀ e, f (ColoredEdges.left c e)∈A)
    (hright : ∀ e, (q e).val 0∈BipartiteReservoirPaths.pool A C m)
    (hstart : ∀ e d i, f (ColoredEdges.left c e)≠(q d).val i)
    (hcomplete : ∀ a∈A, ∀ b∈C, (HeavyShadow.graph H B j).Adj a b)
    (hfS : ∀ w, f w∈S) (hzS : ∀ i, z i∈S) (hqS : ∀ e i, (q e).val i∈S)
    (hA : S.card+(m-1)*Nat.card (GraphSubdivision.Edge F)+m+2≤A.card)
    (hC : S.card+(m-1)*Nat.card (GraphSubdivision.Edge F)+m+2≤C.card)
    (hB : (j-1)*(Nat.card (GraphSubdivision.Edge F)*m)+S.card+Nat.card (GraphSubdivision.Edge F)*(m+1)≤B) :
    HubPathSubdivision.graph c k ⊑ H := by
  classical
  let E := GraphSubdivision.Edge F
  have hA' : S.card+(m-1)*Fintype.card E+m+2≤A.card := by simpa only [Nat.card_eq_fintype_card] using hA
  have hC' : S.card+(m-1)*Fintype.card E+m+2≤C.card := by simpa only [Nat.card_eq_fintype_card] using hC
  obtain ⟨b,hb,hbdis⟩ := BipartiteReservoirPaths.select_paths (HeavyShadow.graph H B j) A C S m hm
    (fun e : E => f (ColoredEdges.left c e)) (fun e : E => (q e).val 0)
    hleft hright (fun e => hstart e e 0) hA' hC' hcomplete
  obtain ⟨p,hp,hpdis⟩ := HeavyChainBundle.lift H B j m hj S b (fun e => (hb e).1)
    (fun e => (hb e).2.2.2.1) hbdis (by simpa only [Nat.card_eq_fintype_card] using hB)
  have hp0 (e : E) : (p e).val 0=f (ColoredEdges.left c e) := (hp e).2.1.trans (hb e).2.1
  have hpjoin (e : E) : (p e).val (Fin.last (m*j))=(q e).val 0 :=
    (hp e).2.2.1.trans (hb e).2.2.1
  have hpstart (e d : E) (i : Fin (l+1)) : (p e).val 0≠(q d).val i := by
    rw [hp0]
    exact hstart e d i
  have hpavoid (e d : E) (i : Fin (l+1)) : (q d).val i∉interior H (p e) := by
    intro hi
    exact Finset.disjoint_left.mp (hp e).2.2.2 hi (hqS d i)
  have hbundle := ChainFront.append_bundle H (m*j) l p q (fun e => (hp e).1) hqinj
    hpjoin hpstart hpavoid hpdis hqdis
  rw [hlen] at hbundle
  obtain ⟨r,hr,hrdis⟩ := hbundle
  apply HubPathBundleCopy.copy c H k z f r hz hf hzf (fun e => (hr e).1) hrdis
  · intro i e hi
    rcases mem_union.mp ((hr e).2.2.2 hi) with hpv | hqv
    · exact Finset.disjoint_left.mp (hp e).2.2.2 hpv (hzS i)
    · exact hqhub i e hqv
  · intro w e hw
    rcases mem_union.mp ((hr e).2.2.2 hw) with hpv | hqv
    · exact Finset.disjoint_left.mp (hp e).2.2.2 hpv (hfS w)
    · exact hqold w e hqv
  · intro e
    exact (hr e).2.1.trans (hp0 e)
  · intro e
    exact (hr e).2.2.1.trans (hqend e)
  · exact hspoke

end
end HubReservoirAssembly

end -- HubReservoirAssembly

section -- AdmissibleSuffixCounts

/- Labels beyond a pinned coordinate of an admissible path. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace AdmissibleSuffixCounts
set_option maxHeartbeats 2000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

def labels {n : ℕ} (a : Fin (n+1)) (p : Chain H n) : Finset V :=
  univ.image (fun i : Fin (n-a.val) => p.val ⟨a.val+i.val+1,by omega⟩)

lemma labels_card {n : ℕ} (a : Fin (n+1)) (p : Chain H n) : (labels H a p).card≤n-a.val :=
  card_image_le.trans_eq (by simp)

lemma mem_labels {n : ℕ} (a : Fin (n+1)) (p : Chain H n) (v : V) :
    v∈labels H a p ↔ ∃ i : Fin (n+1), a.val < i.val ∧ p.val i=v := by
  constructor
  · intro hv
    obtain ⟨i,_,hi⟩ := mem_image.mp hv
    exact ⟨⟨a.val+i.val+1,by omega⟩,by dsimp; omega,hi⟩
  · rintro ⟨i,hi,hiv⟩
    refine mem_image.mpr ⟨⟨i.val-a.val-1,by omega⟩,mem_univ _,?_⟩
    convert hiv using 1
    apply congrArg p.val
    apply Fin.ext
    dsimp
    omega

lemma pinned_notMem {n : ℕ} (a : Fin (n+1)) (p : Chain H n) (hp : Function.Injective p.val) :
    p.val a∉labels H a p := by
  intro hv
  obtain ⟨i,hi,he⟩ := (mem_labels H a p _).mp hv
  have hh := congrArg Fin.val (hp he)
  omega

lemma labels_succ {n : ℕ} (a : Fin (n+1)) (ha : a.val<n) (p : Chain H n) :
    labels H a p=insert (p.val ⟨a.val+1,by omega⟩) (labels H ⟨a.val+1,by omega⟩ p) := by
  ext v
  simp only [mem_insert,mem_labels]
  constructor
  · rintro ⟨i,hi,he⟩
    by_cases h : i.val=a.val+1
    · left
      exact he.symm.trans (congrArg p.val (Fin.ext h))
    · right
      exact ⟨i,by omega,he⟩
  · rintro (he | ⟨i,hi,he⟩)
    · exact ⟨⟨a.val+1,by omega⟩,by dsimp; omega,he.symm⟩
    · exact ⟨i,by omega,he⟩

lemma incidence (L : ℕ → ℕ) (n D : ℕ) (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (a : Fin (n+1)) (ha : a.val<n) (z v : V) :
    ((P.filter (fun p => p.val a=z)).filter (fun p => v∈labels H a p)).card≤
      (n-a.val)*(L a.val*D^(n-a.val-1)) := by
  let E (i : Fin (n-a.val)) := P.filter (fun p => p.val a=z ∧ p.val ⟨a.val+i.val+1,by omega⟩=v)
  have hsub : (P.filter (fun p => p.val a=z)).filter (fun p => v∈labels H a p) ⊆ univ.biUnion E := by
    intro p hp
    obtain ⟨i,_,hi⟩ := mem_image.mp (mem_filter.mp hp).2
    exact mem_biUnion.mpr ⟨i,mem_univ _,mem_filter.mpr ⟨(mem_filter.mp (mem_filter.mp hp).1).1,
      (mem_filter.mp (mem_filter.mp hp).1).2,hi⟩⟩
  calc
    _ ≤ (univ.biUnion E).card := card_le_card hsub
    _ ≤ ∑ i, (E i).card := card_biUnion_le
    _ ≤ ∑ _i : Fin (n-a.val), L a.val*D^(n-a.val-1) := by
      apply sum_le_sum
      intro i _
      exact AdmissibleChainCounts.two_coordinates_bound H L n D x P hP hD a
        ⟨a.val+i.val+1,by omega⟩ (by dsimp; omega) z v
    _ = _ := by simp

lemma next_image (n D : ℕ) (P : Finset (Chain H n)) (hD : ∀ v, H.degree v≤D)
    (a : Fin (n+1)) (ha : a.val<n) (z : V) :
    ((P.filter (fun p => p.val a=z)).image (fun p => p.val ⟨a.val+1,by omega⟩)).card≤D := by
  have hsub : (P.filter (fun p => p.val a=z)).image (fun p => p.val ⟨a.val+1,by omega⟩) ⊆ H.neighborFinset z := by
    intro v hv
    obtain ⟨p,hp,rfl⟩ := mem_image.mp hv
    apply (H.mem_neighborFinset _ _).mpr
    have hh := p.property ⟨a.val,ha⟩
    change H.Adj (p.val a) _ at hh
    rwa [(mem_filter.mp hp).2] at hh
  exact (card_le_card hsub).trans ((H.card_neighborFinset_eq_degree z).trans_le (hD z))

end
end AdmissibleSuffixCounts

end -- AdmissibleSuffixCounts

section -- AdmissiblePinnedSelection

/- A large admissible path family has a large fiber at a permitted hub. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace AdmissiblePinnedSelection
set_option maxHeartbeats 2500000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

lemma select (L : ℕ → ℕ) (hL : Monotone L) (n D K : ℕ) (hDpos : 1≤D)
    (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (a : Fin (n+1)) (ha : a.val<n)
    (S : Finset V) (hx : x∉S)
    (hlarge : (S.card+K)*L (n-1)*D^(n-1)<P.card) :
    ∃ z : V, z∉S ∧ K*L (n-1)*D^(n-a.val-1)<(P.filter (fun p => p.val a=z)).card := by
  let Bad := P.filter (fun p => p.val a∈S)
  let Q := P.filter (fun p => p.val a∉S)
  have hbad : Bad.card≤S.card*L (n-1)*D^(n-1) := by
    by_cases ha0 : a.val=0
    · have ha' : a=0 := Fin.ext ha0
      have he : Bad=∅ := by
        apply eq_empty_iff_forall_notMem.mpr
        intro p hp
        have hh := (mem_filter.mp hp).2
        rw [ha',(hP p (mem_filter.mp hp).1).2] at hh
        exact hx hh
      rw [he,card_empty]
      exact Nat.zero_le _
    · have hsub : Bad⊆S.biUnion (fun v => P.filter (fun p => p.val a=v)) := by
        intro p hp
        exact mem_biUnion.mpr ⟨p.val a,(mem_filter.mp hp).2,mem_filter.mpr ⟨(mem_filter.mp hp).1,rfl⟩⟩
      have hb (v : V) : (P.filter (fun p => p.val a=v)).card≤L (n-1)*D^(n-1) := by
        exact (AdmissibleChainCounts.prefix_bound H L n D x P hP hD a ha v).trans
          (Nat.mul_le_mul (hL (by omega)) (Nat.pow_le_pow_right hDpos (by omega)))
      calc
        _ ≤ _ := card_le_card hsub
        _ ≤ ∑ v∈S, (P.filter (fun p => p.val a=v)).card := card_biUnion_le
        _ ≤ ∑ _v∈S, L (n-1)*D^(n-1) := sum_le_sum (fun v _ => hb v)
        _ = _ := by simp [mul_assoc]
  have hsplit : Bad.card+Q.card=P.card := card_filter_add_card_filter_not (s := P) (fun p => p.val a∈S)
  have hQ : K*L (n-1)*D^(n-1)<Q.card := by nlinarith only [hbad,hsplit,hlarge]
  have himage : (Q.image (fun p => p.val a)).card≤D^a.val :=
    AdmissibleChainCounts.index_image_bound H n D x Q
      (fun p hp => (hP p (mem_filter.mp hp).1).2) hD a
  by_contra hn
  push_neg at hn
  have hfiber (z : V) (hz : z∈Q.image (fun p => p.val a)) :
      (Q.filter (fun p => p.val a=z)).card≤K*L (n-1)*D^(n-a.val-1) := by
    obtain ⟨p,hp,he⟩ := mem_image.mp hz
    have hzS : z∉S := he ▸ (mem_filter.mp hp).2
    exact (card_le_card (by intro q hq; exact mem_filter.mpr ⟨(mem_filter.mp (mem_filter.mp hq).1).1,(mem_filter.mp hq).2⟩)).trans (hn z hzS)
  have hb := card_le_mul_card_image_of_maps_to (s := Q) (t := Q.image (fun p => p.val a))
    (f := fun p => p.val a) (fun p hp => mem_image.mpr ⟨p,hp,rfl⟩)
    (K*L (n-1)*D^(n-a.val-1)) hfiber
  have hm := Nat.mul_le_mul_left (K*L (n-1)*D^(n-a.val-1)) himage
  have he : (K*L (n-1)*D^(n-a.val-1))*D^a.val=K*L (n-1)*D^(n-1) := by
    rw [mul_assoc,← pow_add]
    congr 2
    omega
  rw [he] at hm
  omega

end
end AdmissiblePinnedSelection

end -- AdmissiblePinnedSelection

section -- FiniteRowFans

/- Pack disjoint stars whose rays are finite labelled objects. -/
open Finset
namespace FiniteRowFans
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {A : Type u} {V : Type v} [Fintype A]
local instance : DecidableEq V := Classical.decEq _

abbrev Star (A : Type u) (s : ℕ) := Fin s → A

def whole (row : A → V) (label : A → Finset V) (p : A) : Finset V := insert (row p) (label p)

def starLabels (row : A → V) (label : A → Finset V) (s : ℕ) (f : Star A s) : Finset V :=
  univ.biUnion (fun i => whole row label (f i))

def Valid (P : Finset A) (row : A → V) (label : A → Finset V) (s : ℕ) (f : Star A s) : Prop :=
  (∀ i, f i∈P) ∧ (∀ i j, row (f i)=row (f j)) ∧
    ∀ i j, i≠j → Disjoint (label (f i)) (label (f j))

lemma starLabels_card (row : A → V) (label : A → Finset V) (s ℓ : ℕ) (f : Star A s)
    (hcard : ∀ i, (label (f i)).card≤ℓ) (hrow : ∀ i j, row (f i)=row (f j)) :
    (starLabels row label s f).card≤1+s*ℓ := by
  by_cases hs : 0<s
  · have hsub : starLabels row label s f ⊆ insert (row (f ⟨0,hs⟩)) (univ.biUnion (fun i => label (f i))) := by
      intro v hv
      obtain ⟨i,_,hi⟩ := mem_biUnion.mp hv
      rcases mem_insert.mp hi with he | he
      · exact mem_insert.mpr (Or.inl (he.trans (hrow i ⟨0,hs⟩)))
      · exact mem_insert.mpr (Or.inr (mem_biUnion.mpr ⟨i,mem_univ _,he⟩))
    have hh := card_biUnion_le (s := (univ : Finset (Fin s))) (t := fun i => label (f i))
    have hb : (∑ i, (label (f i)).card)≤s*ℓ := by
      calc
        _ ≤ ∑ _i : Fin s, ℓ := sum_le_sum (fun i _ => hcard i)
        _ = _ := by simp
    exact (card_le_card hsub).trans ((card_insert_le _ _).trans (by omega))
  · have he : s=0 := by omega
    subst s
    simp [starLabels]

lemma avoid (P : Finset A) (row : A → V) (label : A → Finset V) (s ℓ N M R : ℕ)
    (hs : 0<s) (hcard : ∀ p∈P, (label p).card≤ℓ)
    (hN : (P.image row).card≤N)
    (hM : ∀ v, (P.filter (fun p => v∈whole row label p)).card≤M)
    (hR : ∀ y v, ((P.filter (fun p => row p=y)).filter (fun p => v∈label p)).card≤R)
    (S : Finset V) (hP : N*(ℓ*s*R)+S.card*M<P.card) :
    ∃ f : Star A s, Valid P row label s f ∧ Disjoint (starLabels row label s f) S := by
  let Q := P.filter (fun p => Disjoint (whole row label p) S)
  have hbad := FiniteLabelPacking.hit_le P (whole row label) M hM S
  have hsplit := card_filter_add_card_filter_not (s := P) (fun p => Disjoint (whole row label p) S)
  have hQ : N*(ℓ*s*R)<Q.card := by dsimp only [Q]; omega
  have hrow : ∃ y∈P.image row, ℓ*s*R<(Q.filter (fun p => row p=y)).card := by
    by_contra hn
    push_neg at hn
    have hb := card_le_mul_card_image_of_maps_to (s := Q) (t := P.image row) (f := row)
      (fun p hp => mem_image.mpr ⟨p,(mem_filter.mp hp).1,rfl⟩) (ℓ*s*R) hn
    have hm := Nat.mul_le_mul_right (ℓ*s*R) hN
    nlinarith only [hb,hm,hQ]
  obtain ⟨y,hy,hlarge⟩ := hrow
  let T := Q.filter (fun p => row p=y)
  have hTR (v : V) : (T.filter (fun p => v∈label p)).card≤R := by
    apply (card_le_card ?_).trans (hR y v)
    intro p hp
    exact mem_filter.mpr ⟨mem_filter.mpr ⟨(mem_filter.mp (mem_filter.mp (mem_filter.mp hp).1).1).1,
      (mem_filter.mp (mem_filter.mp hp).1).2⟩,(mem_filter.mp hp).2⟩
  obtain ⟨f,hf,hdis⟩ := FiniteLabelPacking.select ℓ s (fun _ => (↑T : Set A)) label
    (fun _ p hp => hcard p (mem_filter.mp (mem_filter.mp hp).1).1) (by
      intro i U hU
      apply FiniteLabelPacking.avoid_of_card T label R hTR U
      exact (Nat.mul_le_mul_right R hU).trans_lt hlarge)
  refine ⟨f,⟨fun i => (mem_filter.mp (mem_filter.mp (hf i)).1).1,?_,hdis⟩,?_⟩
  · intro i j
    exact (mem_filter.mp (hf i)).2.trans (mem_filter.mp (hf j)).2.symm
  · apply Finset.disjoint_left.mpr
    intro v hv hvS
    obtain ⟨i,_,hi⟩ := mem_biUnion.mp hv
    exact Finset.disjoint_left.mp (mem_filter.mp (mem_filter.mp (hf i)).1).2 hi hvS

lemma select (P : Finset A) (row : A → V) (label : A → Finset V) (s t ℓ N M R : ℕ)
    (hs : 0<s) (hcard : ∀ p∈P, (label p).card≤ℓ)
    (hN : (P.image row).card≤N)
    (hM : ∀ v, (P.filter (fun p => v∈whole row label p)).card≤M)
    (hR : ∀ y v, ((P.filter (fun p => row p=y)).filter (fun p => v∈label p)).card≤R)
    (S : Finset V) (hP : N*(ℓ*s*R)+(S.card+(1+s*ℓ)*t)*M<P.card) :
    ∃ f : Fin t → Star A s, (∀ i, Valid P row label s (f i)) ∧
      (∀ i, Disjoint (starLabels row label s (f i)) S) ∧
      ∀ i j, i≠j → Disjoint (starLabels row label s (f i)) (starLabels row label s (f j)) := by
  let T : Set (Star A s) := {f | Valid P row label s f ∧ Disjoint (starLabels row label s f) S}
  obtain ⟨f,hf,hdis⟩ := FiniteLabelPacking.select (1+s*ℓ) t (fun _ => T) (starLabels row label s)
    (fun _ f hf => starLabels_card row label s ℓ f (fun i => hcard _ (hf.1.1 i)) hf.1.2.1) (by
      intro i U hU
      have hSU : (S∪U).card≤S.card+(1+s*ℓ)*t := (card_union_le _ _).trans (Nat.add_le_add_left hU _)
      obtain ⟨g,hg,hdis⟩ := avoid P row label s ℓ N M R hs hcard hN hM hR (S∪U)
        ((Nat.add_le_add_left (Nat.mul_le_mul_right M hSU) _).trans_lt hP)
      exact ⟨g,⟨hg,hdis.mono_right (subset_union_left)⟩,hdis.mono_right (subset_union_right)⟩)
  exact ⟨f,fun i => (hf i).1,fun i => (hf i).2,hdis⟩

end
end FiniteRowFans

end -- FiniteRowFans

section -- AdmissibleSuffixFans

/- Disjoint suffix fans of any positive arm length, selected from many
admissible paths with a common initial vertex. -/
open Finset SimpleGraph ChainCounting GoodChains AdmissibleSuffixCounts
namespace AdmissibleSuffixFans
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

def cost (n s t q : ℕ) : ℕ := s*n^2+(q+(1+s*n)*t)*n

lemma select_at (L : ℕ → ℕ) (hL : Monotone L) (n D s t : ℕ) (hs : 0<s)
    (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (a : Fin (n+1)) (ha : a.val+1<n) (z : V) (S : Finset V)
    (hlarge : cost n s t S.card*L (n-1)*D^(n-a.val-1)<(P.filter (fun p => p.val a=z)).card) :
    ∃ f : Fin t → Fin s → Chain H n,
      (∀ i, FiniteRowFans.Valid (P.filter (fun p => p.val a=z))
        (fun p => p.val ⟨a.val+1,by omega⟩) (labels H ⟨a.val+1,by omega⟩) s (f i)) ∧
      (∀ i, Disjoint (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f i)) S) ∧
      ∀ i j, i≠j → Disjoint (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f i)) (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f j)) := by
  let b : Fin (n+1) := ⟨a.val+1,by omega⟩
  let Q := P.filter (fun p => p.val a=z)
  let r := n-a.val-1
  let M := (n-a.val)*(L a.val*D^(n-a.val-1))
  let R := r*(L b.val*D^(r-1))
  have hr : 0<r := by dsimp [r]; omega
  have hcard (p : Chain H n) (hp : p∈Q) : (labels H b p).card≤r := by
    simpa only [b,r,Nat.sub_add_eq] using labels_card H b p
  have hN : (Q.image (fun p => p.val b)).card≤D := next_image H n D P hD a (by omega) z
  have hM (v : V) : (Q.filter (fun p => v∈FiniteRowFans.whole (fun p => p.val b) (labels H b) p)).card≤M := by
    have he (p : Chain H n) : FiniteRowFans.whole (fun p => p.val b) (labels H b) p=labels H a p :=
      (labels_succ H a (by omega) p).symm
    simp_rw [he]
    exact incidence H L n D x P hP hD a (by omega) z v
  have hR (y v : V) : ((Q.filter (fun p => p.val b=y)).filter (fun p => v∈labels H b p)).card≤R := by
    have hh := incidence H L n D x P hP hD b (by dsimp [b]; omega) y v
    have hsub : (Q.filter (fun p => p.val b=y)).filter (fun p => v∈labels H b p) ⊆
        (P.filter (fun p => p.val b=y)).filter (fun p => v∈labels H b p) := by
      intro p hp
      exact mem_filter.mpr ⟨mem_filter.mpr ⟨(mem_filter.mp (mem_filter.mp (mem_filter.mp hp).1).1).1,
        (mem_filter.mp (mem_filter.mp hp).1).2⟩,(mem_filter.mp hp).2⟩
    apply (card_le_card hsub).trans
    simpa only [R,r,b,Nat.sub_add_eq] using hh
  have hLa : L a.val≤L (n-1) := hL (by omega)
  have hLb : L b.val≤L (n-1) := hL (by dsimp [b]; omega)
  have hrn : r≤n := by dsimp [r]; omega
  have hDpow : D*D^(r-1)=D^r := by rw [← pow_succ',Nat.sub_add_cancel hr]
  have hterm₁ : D*(r*s*R)≤s*n^2*L (n-1)*D^r := by
    calc
      _ = s*r^2*L b.val*(D*D^(r-1)) := by dsimp only [R]; ring
      _ = s*r^2*L b.val*D^r := by rw [hDpow]
      _ ≤ _ := by gcongr
  have hterm₂ : (S.card+(1+s*r)*t)*M≤(S.card+(1+s*n)*t)*n*L (n-1)*D^r := by
    dsimp only [M]
    change (S.card+(1+s*r)*t)*((n-a.val)*(L a.val*D^r))≤_
    calc
      _ = (S.card+(1+s*r)*t)*(n-a.val)*L a.val*D^r := by ring
      _ ≤ _ := by gcongr; exact Nat.sub_le n a.val
  have hbound : D*(r*s*R)+(S.card+(1+s*r)*t)*M≤cost n s t S.card*L (n-1)*D^r := by
    dsimp only [cost]
    nlinarith only [hterm₁,hterm₂]
  exact FiniteRowFans.select Q (fun p => p.val b) (labels H b) s t r D M R hs hcard hN hM hR S
    (hbound.trans_lt hlarge)

lemma select (L : ℕ → ℕ) (hL : Monotone L) (n D s t : ℕ) (hs : 0<s) (hDpos : 1≤D)
    (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (a : Fin (n+1)) (ha : a.val+1<n) (S : Finset V) (hx : x∉S)
    (hlarge : (S.card+cost n s t S.card)*L (n-1)*D^(n-1)<P.card) :
    ∃ z : V, z∉S ∧ ∃ f : Fin t → Fin s → Chain H n,
      (∀ i, FiniteRowFans.Valid (P.filter (fun p => p.val a=z))
        (fun p => p.val ⟨a.val+1,by omega⟩) (labels H ⟨a.val+1,by omega⟩) s (f i)) ∧
      (∀ i, Disjoint (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f i)) S) ∧
      ∀ i j, i≠j → Disjoint (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f i)) (FiniteRowFans.starLabels (fun p => p.val ⟨a.val+1,by omega⟩)
        (labels H ⟨a.val+1,by omega⟩) s (f j)) := by
  obtain ⟨z,hz,hl⟩ := AdmissiblePinnedSelection.select H L hL n D (cost n s t S.card) hDpos
    x P hP hD a (by omega) S hx hlarge
  obtain ⟨f,hf⟩ := select_at H L hL n D s t hs x P hP hD a ha z S hl
  exact ⟨z,hz,f,hf⟩

end
end AdmissibleSuffixFans

end -- AdmissibleSuffixFans

section -- AdmissibleEndSelection

/- Zero-length tails: select distinct last vertices adjacent to a common hub. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace AdmissibleEndSelection
set_option maxHeartbeats 2500000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

lemma select (L : ℕ → ℕ) (hL : Monotone L) (n D t : ℕ) (hn : 2≤n) (hDpos : 1≤D)
    (x : V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hD : ∀ v, H.degree v≤D) (S : Finset V) (hx : x∉S)
    (hlarge : (S.card+(S.card+t))*L (n-1)*D^(n-1)<P.card) :
    ∃ z : V, z∉S ∧ ∃ f : Fin t → Chain H n,
      (∀ i, f i∈P ∧ (f i).val ⟨n-1,by omega⟩=z ∧ (f i).val (Fin.last n)∉S) ∧
      Function.Injective (fun i => (f i).val (Fin.last n)) := by
  let a : Fin (n+1) := ⟨n-1,by omega⟩
  obtain ⟨z,hz,hlarge'⟩ := AdmissiblePinnedSelection.select H L hL n D (S.card+t) hDpos x P hP hD
    a (by dsimp [a]; omega) S hx hlarge
  let Q := P.filter (fun p => p.val a=z)
  let Y := Q.image (fun p => p.val (Fin.last n))
  have hlocal : (S.card+t)*L (n-1)<Q.card := by
    simpa only [a,show n-(n-1)-1=0 by omega,pow_zero,mul_one] using hlarge'
  have hfiber (y : V) : (Q.filter (fun p => p.val (Fin.last n)=y)).card≤L (n-1) := by
    have he : Q.filter (fun p => p.val (Fin.last n)=y)=P.filter (fun p => p.val a=z ∧ p.val (Fin.last n)=y) := by
      ext p
      simp only [Q,mem_filter,and_assoc]
    rw [he]
    have hh := AdmissibleChainCounts.two_coordinates_bound H L n D x P hP hD a (Fin.last n)
      (by dsimp [a]; omega) z y
    simpa only [a,show n-(n-1)-1=0 by omega,pow_zero,mul_one] using hh
  have hb := card_le_mul_card_image_of_maps_to (s := Q) (t := Y) (f := fun p => p.val (Fin.last n))
    (fun p hp => mem_image.mpr ⟨p,hp,rfl⟩) (L (n-1)) (fun y _ => hfiber y)
  have hY : t≤(Y\S).card := by
    have hsplit := card_le_card_sdiff_add_card (s := Y) (t := S)
    by_contra ht
    have hm := Nat.mul_le_mul_left (L (n-1)) (show Y.card≤S.card+t by omega)
    nlinarith only [hlocal,hb,hm]
  obtain ⟨g⟩ : Nonempty (Fin t ↪ ↑(Y\S)) := Function.Embedding.nonempty_of_card_le (by simpa only [Fintype.card_fin,Fintype.card_coe] using hY)
  have hex (i : Fin t) : ∃ p∈Q, p.val (Fin.last n)=(g i).val :=
    mem_image.mp (mem_sdiff.mp (g i).property).1
  choose f hf hend using hex
  refine ⟨z,hz,f,fun i => ⟨(mem_filter.mp (hf i)).1,(mem_filter.mp (hf i)).2,?_⟩,?_⟩
  · rw [hend i]
    exact (mem_sdiff.mp (g i).property).2
  · intro i j he
    apply g.injective
    apply Subtype.ext
    exact (hend i).symm.trans (he.trans (hend j))

end
end AdmissibleEndSelection

end -- AdmissibleEndSelection

section -- SuffixFanData

/- A uniform interface for selected suffix fans, including zero-length arms. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace SuffixFanData
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} (H : SimpleGraph V)

structure Data (l s t : ℕ) (S : Finset V) (x : V) (Z : Set V) where
  hub : V
  old : Fin t → V
  tail : Fin t × Fin s → Chain H l
  old_injective : Function.Injective old
  spoke : ∀ i, H.Adj hub (old i)
  tail_injective : ∀ e, Function.Injective (tail e).val
  tail_end : ∀ e, (tail e).val (Fin.last l)=old e.1
  tail_start : ∀ e, (tail e).val 0∈Z
  front_disjoint : ∀ e f, e≠f → Disjoint (ChainFront.front H (tail e)) (ChainFront.front H (tail f))
  old_not_front : ∀ i e, old i∉ChainFront.front H (tail e)
  hub_not_tail : ∀ e i, hub≠(tail e).val i
  hub_avoid : hub∉S
  old_avoid : ∀ i, old i∉S
  tail_avoid : ∀ e i, (tail e).val i∉S
  initial_not_old : ∀ i, x≠old i
  initial_not_tail : ∀ e i, x≠(tail e).val i

variable [Fintype V]
local instance : DecidableRel H.Adj := Classical.decRel _

lemma zero (L : ℕ → ℕ) (hL : Monotone L) (n D s t : ℕ) (hn : 2≤n) (hDpos : 1≤D)
    (x : V) (Z : Set V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hZ : ∀ p∈P, p.val (Fin.last n)∈Z)
    (hD : ∀ v, H.degree v≤D) (S : Finset V) (hx : x∉S)
    (hlarge : (S.card+(S.card+t))*L (n-1)*D^(n-1)<P.card) (ht : 0<t) :
    ∃ F : Data H 0 s t S x Z, F.hub≠x := by
  obtain ⟨z,hz,f,hf,hinj⟩ := AdmissibleEndSelection.select H L hL n D t hn hDpos x P hP hD S hx hlarge
  let old (i : Fin t) := (f i).val (Fin.last n)
  let tail (e : Fin t × Fin s) : Chain H 0 := ⟨fun _ => old e.1,fun i => Fin.elim0 i⟩
  have hspoke (i : Fin t) : H.Adj z (old i) := by
    have hh := (f i).property ⟨n-1,by omega⟩
    change H.Adj ((f i).val ⟨n-1,by omega⟩) ((f i).val ⟨(n-1)+1,by omega⟩) at hh
    rw [(hf i).2.1] at hh
    simpa only [old,Nat.sub_add_cancel (by omega : 1≤n),Fin.last] using hh
  have hxi (i : Fin t) : x≠old i := by
    intro he
    have hh := congrArg Fin.val ((hP (f i) (hf i).1).1.1 ((hP (f i) (hf i).1).2.trans he))
    simp only [Fin.val_zero,Fin.val_last] at hh
    omega
  have hfront (e : Fin t × Fin s) : ChainFront.front H (tail e)=∅ := by simp [ChainFront.front]
  let F : Data H 0 s t S x Z := {
    hub := z
    old := old
    tail := tail
    old_injective := hinj
    spoke := hspoke
    tail_injective := fun e i j _ => Fin.ext (by omega)
    tail_end := fun _ => rfl
    tail_start := fun e => hZ (f e.1) (hf e.1).1
    front_disjoint := fun e f _ => by rw [hfront e,hfront f]; exact disjoint_empty_left _
    old_not_front := fun i e => by rw [hfront e]; exact notMem_empty _
    hub_not_tail := fun e i => (hspoke e.1).ne
    hub_avoid := hz
    old_avoid := fun i => (hf i).2.2
    tail_avoid := fun e _ => (hf e.1).2.2
    initial_not_old := hxi
    initial_not_tail := fun e _ => hxi e.1 }
  refine ⟨F,?_⟩
  intro he
  let i : Fin t := ⟨0,ht⟩
  have hh := congrArg Fin.val ((hP (f i) (hf i).1).1.1 ((hf i).2.1.trans (he.trans (hP (f i) (hf i).1).2.symm)))
  change n-1=0 at hh
  omega

end
end SuffixFanData

end -- SuffixFanData

section -- PositiveSuffixFanData

/- Convert selected admissible suffix stars into the uniform tail-data interface. -/
open Finset SimpleGraph ChainCounting GoodChains AdmissibleSuffixCounts
namespace SuffixFanData
set_option maxHeartbeats 3500000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

lemma positive (L : ℕ → ℕ) (hL : Monotone L) (n l D s t : ℕ) (hl : 0<l) (hln : l<n)
    (hs : 0<s) (hDpos : 1≤D) (x : V) (Z : Set V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hZ : ∀ p∈P, p.val (Fin.last n)∈Z)
    (hD : ∀ v, H.degree v≤D) (S : Finset V) (hx : x∉S)
    (hlarge : (S.card+AdmissibleSuffixFans.cost n s t S.card)*L (n-1)*D^(n-1)<P.card) :
    Nonempty (Data H l s t S x Z) := by
  classical
  let a : Fin (n+1) := ⟨n-l-1,by omega⟩
  have ha : a.val+1<n := by dsimp [a]; omega
  let b : Fin (n+1) := ⟨a.val+1,by omega⟩
  have hbl : b.val+l=n := by dsimp [a,b]; omega
  obtain ⟨z,hz,f,hf,hfS,hfdis⟩ := AdmissibleSuffixFans.select H L hL n D s t hs hDpos x P hP hD a ha S hx hlarge
  let row (p : Chain H n) := p.val b
  let star (i : Fin t) := FiniteRowFans.starLabels row (labels H b) s (f i)
  let old (i : Fin t) := row (f i ⟨0,hs⟩)
  let q (e : Fin t × Fin s) := reverse H (segment H (f e.1 e.2) b.val l (by omega))
  have hfp (i : Fin t) (j : Fin s) : f i j∈P := (mem_filter.mp ((hf i).1 j)).1
  have hfa (i : Fin t) (j : Fin s) : (f i j).val a=z := (mem_filter.mp ((hf i).1 j)).2
  have hadm (i : Fin t) (j : Fin s) := (hP (f i j) (hfp i j)).1
  have hrow (i : Fin t) (j : Fin s) : (f i j).val b=old i := (hf i).2.1 j ⟨0,hs⟩
  have hlabelstar (i : Fin t) (j : Fin s) : labels H b (f i j)⊆star i := by
    intro v hv
    exact mem_biUnion.mpr ⟨j,mem_univ _,mem_insert_of_mem hv⟩
  have holdstar (i : Fin t) : old i∈star i :=
    mem_biUnion.mpr ⟨⟨0,hs⟩,mem_univ _,mem_insert_self _ _⟩
  have hqstart (e : Fin t × Fin s) : (q e).val 0=(f e.1 e.2).val (Fin.last n) := by
    dsimp only [q]
    rw [reverse_start]
    simp only [segment_apply,Fin.val_last,hbl]
    rfl
  have hqend (e : Fin t × Fin s) : (q e).val (Fin.last l)=old e.1 := by
    dsimp only [q]
    rw [reverse_last]
    simpa only [segment_apply,Fin.val_zero,Nat.add_zero] using hrow e.1 e.2
  have hqinj (e : Fin t × Fin s) : Function.Injective (q e).val :=
    reverse_injective H (segment_injective H (hadm e.1 e.2).1 b.val l (by omega))
  have hqfront (e : Fin t × Fin s) : ChainFront.front H (q e)⊆labels H b (f e.1 e.2) := by
    intro v hv
    obtain ⟨i,hi,he⟩ := (ChainFront.mem_front H (q e) v).mp hv
    apply (mem_labels H b (f e.1 e.2) v).mpr
    refine ⟨⟨b.val+i.rev.val,by omega⟩,?_,he⟩
    simp only [Fin.val_rev]
    omega
  have hqstar (e : Fin t × Fin s) (i : Fin (l+1)) : (q e).val i∈star e.1 := by
    have hm : (q e).val i∈labels H a (f e.1 e.2) := by
      apply (mem_labels H a (f e.1 e.2) _).mpr
      refine ⟨⟨b.val+i.rev.val,by omega⟩,?_,rfl⟩
      dsimp only [b]
      omega
    rw [labels_succ H a (by omega)] at hm
    exact mem_biUnion.mpr ⟨e.2,mem_univ _,hm⟩
  have holdinj : Function.Injective old := by
    intro i j he
    by_contra hij
    exact Finset.disjoint_left.mp (hfdis i j hij) (holdstar i) (he.symm ▸ holdstar j)
  have hspoke (i : Fin t) : H.Adj z (old i) := by
    have hh := (f i ⟨0,hs⟩).property ⟨a.val,by omega⟩
    change H.Adj ((f i ⟨0,hs⟩).val a) ((f i ⟨0,hs⟩).val b) at hh
    rwa [hfa i ⟨0,hs⟩,hrow i ⟨0,hs⟩] at hh
  have hdis (e d : Fin t × Fin s) (hed : e≠d) : Disjoint (ChainFront.front H (q e)) (ChainFront.front H (q d)) := by
    rcases e with ⟨i,j⟩
    rcases d with ⟨i',j'⟩
    by_cases hii : i=i'
    · subst i'
      have hjj : j≠j' := fun h => hed (Prod.ext rfl h)
      exact ((hf i).2.2 j j' hjj).mono (hqfront (i,j)) (hqfront (i,j'))
    · exact (hfdis i i' hii).mono ((hqfront (i,j)).trans (hlabelstar i j))
        ((hqfront (i',j')).trans (hlabelstar i' j'))
  have holdnot (i : Fin t) (e : Fin t × Fin s) : old i∉ChainFront.front H (q e) := by
    intro hv
    by_cases hie : i=e.1
    · have hh := pinned_notMem H b (f e.1 e.2) (hadm e.1 e.2).1
      rw [hrow e.1 e.2] at hh
      exact hh (hie ▸ hqfront e hv)
    · exact Finset.disjoint_left.mp (hfdis i e.1 hie) (holdstar i)
        (hqfront e hv |> hlabelstar e.1 e.2)
  have hzq (e : Fin t × Fin s) (i : Fin (l+1)) : z≠(q e).val i := by
    intro he
    have hh := congrArg Fin.val ((hadm e.1 e.2).1 ((hfa e.1 e.2).trans he))
    change a.val=b.val+i.rev.val at hh
    dsimp only [b] at hh
    omega
  have hxq (e : Fin t × Fin s) (i : Fin (l+1)) : x≠(q e).val i := by
    intro he
    have hh := congrArg Fin.val ((hadm e.1 e.2).1 ((hP (f e.1 e.2) (hfp e.1 e.2)).2.trans he))
    change 0=b.val+i.rev.val at hh
    dsimp only [b] at hh
    omega
  have hxold (i : Fin t) : x≠old i := by
    intro he
    exact hxq (i,⟨0,hs⟩) (Fin.last l) (he.trans (hqend (i,⟨0,hs⟩)).symm)
  exact ⟨{
    hub := z
    old := old
    tail := q
    old_injective := holdinj
    spoke := hspoke
    tail_injective := hqinj
    tail_end := hqend
    tail_start := fun e => (hqstart e).symm ▸ hZ (f e.1 e.2) (hfp e.1 e.2)
    front_disjoint := hdis
    old_not_front := holdnot
    hub_not_tail := hzq
    hub_avoid := hz
    old_avoid := fun i hi => Finset.disjoint_left.mp (hfS i) (holdstar i) hi
    tail_avoid := fun e i hi => Finset.disjoint_left.mp (hfS e.1) (hqstar e i) hi
    initial_not_old := hxold
    initial_not_tail := hxq }⟩

end
end SuffixFanData

end -- PositiveSuffixFanData

section -- SuffixFanDataProperties

/- Vertex sets and uniform budgets for suffix fan data. -/
open Finset SimpleGraph ChainCounting GoodChains
namespace SuffixFanData
set_option maxHeartbeats 2500000
universe u
noncomputable section
variable {V : Type u} (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _

variable {l s t : ℕ} {S : Finset V} {x : V} {Z : Set V}

def Data.vertices (F : Data H l s t S x Z) : Finset V :=
  insert F.hub (univ.image F.old ∪ univ.biUnion (fun e => ChainFront.front H (F.tail e)))

lemma Data.hub_mem (F : Data H l s t S x Z) : F.hub∈F.vertices H := mem_insert_self _ _

lemma Data.old_mem (F : Data H l s t S x Z) (i : Fin t) : F.old i∈F.vertices H :=
  mem_insert_of_mem (mem_union_left _ (mem_image.mpr ⟨i,mem_univ _,rfl⟩))


lemma Data.vertices_card (F : Data H l s t S x Z) : (F.vertices H).card≤1+t+t*s*l := by
  have h₁ := card_insert_le F.hub (univ.image F.old ∪ univ.biUnion (fun e => ChainFront.front H (F.tail e)))
  have h₂ := card_union_le (univ.image F.old) (univ.biUnion (fun e => ChainFront.front H (F.tail e)))
  have h₃ : (univ.image F.old).card≤t := card_image_le.trans_eq (by simp)
  have h₄ : (univ.biUnion (fun e => ChainFront.front H (F.tail e))).card≤t*s*l := by
    calc
      _ ≤ ∑ e, (ChainFront.front H (F.tail e)).card := card_biUnion_le
      _ ≤ ∑ _e : Fin t × Fin s, l := sum_le_sum (fun e _ => ChainFront.card_le H (F.tail e))
      _ = _ := by simp
  change (insert F.hub (univ.image F.old ∪ univ.biUnion (fun e => ChainFront.front H (F.tail e)))).card≤_
  omega

lemma Data.initial_not_vertices (F : Data H l s t S x Z) (hxh : F.hub≠x) : x∉F.vertices H := by
  intro hx
  rcases mem_insert.mp hx with he | he
  · exact hxh he.symm
  · rcases mem_union.mp he with he | he
    · obtain ⟨i,_,hi⟩ := mem_image.mp he
      exact F.initial_not_old i hi.symm
    · obtain ⟨e,_,he⟩ := mem_biUnion.mp he
      obtain ⟨i,_,hi⟩ := (ChainFront.mem_front H (F.tail e) x).mp he
      exact F.initial_not_tail e i hi.symm

lemma Data.zero_old_allowed {s t : ℕ} (F : Data H 0 s t S x Z) (hs : 0<s) (i : Fin t) : F.old i∈Z := by
  have hh := F.tail_start (i,⟨0,hs⟩)
  have he := F.tail_end (i,⟨0,hs⟩)
  change (F.tail (i,⟨0,hs⟩)).val 0=F.old i at he
  rwa [he] at hh

variable [Fintype V]
local instance : DecidableRel H.Adj := Classical.decRel _

def budget (n s t q : ℕ) : ℕ := 2*q+t+AdmissibleSuffixFans.cost n s t q


lemma choose (L : ℕ → ℕ) (hL : Monotone L) (n l D s t : ℕ) (hn : 2≤n) (hln : l<n)
    (hs : 0<s) (ht : 0<t) (hDpos : 1≤D) (x : V) (Z : Set V) (P : Finset (Chain H n))
    (hP : ∀ p∈P, Admissible H L n p ∧ p.val 0=x)
    (hZ : ∀ p∈P, p.val (Fin.last n)∈Z)
    (hD : ∀ v, H.degree v≤D) (S : Finset V) (hx : x∉S)
    (hlarge : budget n s t S.card*L (n-1)*D^(n-1)<P.card) : Nonempty (Data H l s t S x Z) := by
  by_cases hl : l=0
  · subst l
    obtain ⟨F,hF⟩ := zero H L hL n D s t hn hDpos x Z P hP hZ hD S hx (by
      apply lt_of_le_of_lt _ hlarge
      gcongr
      unfold budget
      omega) ht
    exact ⟨F⟩
  · apply positive H L hL n l D s t (by omega) hln hs hDpos x Z P hP hZ hD S hx
    apply lt_of_le_of_lt _ hlarge
    gcongr
    unfold budget
    omega

end
end SuffixFanData

end -- SuffixFanDataProperties

section -- TwoColorPlacement

/- Place the two color classes in two disjoint injective copies of the old vertex set. -/
namespace TwoColorPlacement
universe u v
variable {W : Type u} {V : Type v}

def place (c : W → Fin 2) (f g : W → V) (w : W) : V := if c w=0 then f w else g w

def hubs (x y : V) (i : Fin 2) : V := if i=0 then x else y

lemma place_zero (c : W → Fin 2) (f g : W → V) (w : W) (hw : c w=0) : place c f g w=f w := by
  simp only [place,if_pos hw]

lemma place_one (c : W → Fin 2) (f g : W → V) (w : W) (hw : c w=1) : place c f g w=g w := by
  simp [place,hw]

lemma place_injective (c : W → Fin 2) (f g : W → V) (hf : Function.Injective f)
    (hg : Function.Injective g) (hfg : ∀ a b, f a≠g b) : Function.Injective (place c f g) := by
  intro a b he
  dsimp only [place] at he
  split_ifs at he
  · exact hf he
  · exact (hfg a b he).elim
  · exact (hfg b a he.symm).elim
  · exact hg he

lemma hubs_injective (x y : V) (hxy : x≠y) : Function.Injective (hubs x y) := by
  intro i j he
  fin_cases i <;> fin_cases j <;> simp_all [hubs]

lemma hubs_ne_place (c : W → Fin 2) (f g : W → V) (x y : V)
    (hxf : ∀ w, x≠f w) (hxg : ∀ w, x≠g w) (hyf : ∀ w, y≠f w) (hyg : ∀ w, y≠g w) :
    ∀ i w, hubs x y i≠place c f g w := by
  intro i w
  dsimp only [hubs,place]
  split_ifs <;> first | exact hxf w | exact hxg w | exact hyf w | exact hyg w

lemma spoke (H : SimpleGraph V) (c : W → Fin 2) (f g : W → V) (x y : V)
    (hxf : ∀ w, H.Adj x (f w)) (hyg : ∀ w, H.Adj y (g w)) :
    ∀ i w, c w=i → H.Adj (hubs x y i) (place c f g w) := by
  intro i w hi
  dsimp only [hubs,place]
  rw [hi]
  split_ifs
  · exact hxf w
  · exact hyg w

end TwoColorPlacement

end -- TwoColorPlacement

section -- HubFanReservoirCopy

/- A selected suffix fan and two heavy reservoirs force a hub subdivision. -/
open Finset SimpleGraph ChainCounting
namespace HubFanReservoirCopy
set_option maxHeartbeats 3500000
set_option synthInstance.maxHeartbeats 200000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] {F : SimpleGraph W} (c : F.Coloring (Fin 2))
variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : Fintype (GraphSubdivision.Edge F) := Fintype.ofFinite _

lemma copy (B j m l k s t : ℕ) (hj : 0<j) (hm : 0 < m) (hlen : m*j+l=k+1)
    (S : Finset V) (x : V) (Z : Set V) (T : SuffixFanData.Data H l s t S x Z)
    (wi : W ↪ Fin t) (ei : GraphSubdivision.Edge F ↪ Fin s)
    (u : W → V) (z₀ : V) (hu : Function.Injective u) (hzu : ∀ w, H.Adj z₀ (u w))
    (huS : ∀ w, u w∈S) (hzS : z₀∈S)
    (A C : Finset V) (huA : ∀ w, u w∈A)
    (hqC : ∀ e, (T.tail (wi (ColoredEdges.right c e),ei e)).val 0∈BipartiteReservoirPaths.pool A C m)
    (hcomplete : ∀ a∈A, ∀ b∈C, (HeavyShadow.graph H B j).Adj a b)
    (hA : Fintype.card W+2+Nat.card (GraphSubdivision.Edge F)*(l+1)+
      (m-1)*Nat.card (GraphSubdivision.Edge F)+m+2≤A.card)
    (hC : Fintype.card W+2+Nat.card (GraphSubdivision.Edge F)*(l+1)+
      (m-1)*Nat.card (GraphSubdivision.Edge F)+m+2≤C.card)
    (hB : (j-1)*(Nat.card (GraphSubdivision.Edge F)*m)+
      (Fintype.card W+2+Nat.card (GraphSubdivision.Edge F)*(l+1))+Nat.card (GraphSubdivision.Edge F)*(m+1)≤B) :
    HubPathSubdivision.graph c k ⊑ H := by
  classical
  let E := GraphSubdivision.Edge F
  let g (w : W) := T.old (wi w)
  let f := TwoColorPlacement.place c u g
  let z := TwoColorPlacement.hubs z₀ T.hub
  let q (e : E) := T.tail (wi (ColoredEdges.right c e),ei e)
  have hg : Function.Injective g := T.old_injective.comp wi.injective
  have hug (a b : W) : u a≠g b := by
    intro he
    apply T.old_avoid (wi b)
    change g b∈S
    exact he ▸ huS a
  have hzu' (w : W) : z₀≠u w := (hzu w).ne
  have hzg (w : W) : z₀≠g w := by
    intro he
    apply T.old_avoid (wi w)
    change g w∈S
    exact he ▸ hzS
  have hTu (w : W) : T.hub≠u w := by intro he; exact T.hub_avoid (he.symm ▸ huS w)
  have hTg (w : W) : T.hub≠g w := (T.spoke (wi w)).ne
  have hzz : z₀≠T.hub := by intro he; exact T.hub_avoid (he ▸ hzS)
  have hfi : Function.Injective f := TwoColorPlacement.place_injective c u g hu hg hug
  have hzi : Function.Injective z := TwoColorPlacement.hubs_injective z₀ T.hub hzz
  have hzf : ∀ i w, z i≠f w := TwoColorPlacement.hubs_ne_place c u g z₀ T.hub hzu' hzg hTu hTg
  have hspoke : ∀ i w, c w=i → H.Adj (z i) (f w) :=
    TwoColorPlacement.spoke H c u g z₀ T.hub hzu (fun w => T.spoke (wi w))
  have hfleft (e : E) : f (ColoredEdges.left c e)=u (ColoredEdges.left c e) :=
    TwoColorPlacement.place_zero c u g _ (ColoredEdges.left_color c e)
  have hfright (e : E) : f (ColoredEdges.right c e)=g (ColoredEdges.right c e) :=
    TwoColorPlacement.place_one c u g _ (ColoredEdges.right_color c e)
  have hqend (e : E) : (q e).val (Fin.last l)=f (ColoredEdges.right c e) := by
    rw [hfright]
    exact T.tail_end _
  have hqdis (e d : E) (hed : e≠d) : Disjoint (ChainFront.front H (q e)) (ChainFront.front H (q d)) :=
    T.front_disjoint _ _ (fun h => hed (ei.injective (congrArg Prod.snd h)))
  have hqold (w : W) (e : E) : f w∉ChainFront.front H (q e) := by
    dsimp only [f,TwoColorPlacement.place]
    split_ifs
    · intro hw
      obtain ⟨i,_,hi⟩ := (ChainFront.mem_front H (q e) _).mp hw
      exact T.tail_avoid _ i (hi.symm ▸ huS w)
    · exact T.old_not_front (wi w) _
  have hqhub (i : Fin 2) (e : E) : z i∉ChainFront.front H (q e) := by
    intro hv
    obtain ⟨a,_,ha⟩ := (ChainFront.mem_front H (q e) _).mp hv
    by_cases hi : i=0
    · have hh : (q e).val a=z₀ := by simpa only [z,TwoColorPlacement.hubs,if_pos hi] using ha
      exact T.tail_avoid _ a (hh.symm ▸ hzS)
    · have hh : (q e).val a=T.hub := by simpa only [z,TwoColorPlacement.hubs,if_neg hi] using ha
      exact T.hub_not_tail _ a hh.symm
  have hstart (e d : E) (i : Fin (l+1)) : f (ColoredEdges.left c e)≠(q d).val i := by
    rw [hfleft]
    intro he
    exact T.tail_avoid _ i (he ▸ huS _)
  let TailVertices := univ.biUnion (fun e : E => univ.image (q e).val)
  let S' := univ.image f ∪ (univ.image z ∪ TailVertices)
  have hTail : TailVertices.card≤Fintype.card E*(l+1) := by
    calc
      _ ≤ ∑ e, (univ.image (q e).val).card := card_biUnion_le
      _ ≤ ∑ _e : E, (l+1) := sum_le_sum (fun e _ => card_image_le.trans_eq (by simp))
      _ = _ := by simp
  have hS' : S'.card≤Fintype.card W+2+Nat.card E*(l+1) := by
    have h₁ := card_union_le (univ.image f) (univ.image z ∪ TailVertices)
    have h₂ := card_union_le (univ.image z) TailVertices
    have hf' : (univ.image f).card≤Fintype.card W := card_image_le.trans_eq (by simp)
    have hz' : (univ.image z).card≤2 := card_image_le.trans_eq (by simp)
    rw [Nat.card_eq_fintype_card]
    dsimp only [S']
    omega
  have hfS' (w : W) : f w∈S' := mem_union_left _ (mem_image.mpr ⟨w,mem_univ _,rfl⟩)
  have hzS' (i : Fin 2) : z i∈S' := mem_union_right _ (mem_union_left _ (mem_image.mpr ⟨i,mem_univ _,rfl⟩))
  have hqS' (e : E) (i : Fin (l+1)) : (q e).val i∈S' :=
    mem_union_right _ (mem_union_right _ (mem_biUnion.mpr ⟨e,mem_univ _,mem_image.mpr ⟨i,mem_univ _,rfl⟩⟩))
  apply HubReservoirAssembly.copy c H B j m l k hj hm hlen A C S' z f q hzi hfi hzf hspoke
    (fun e => T.tail_injective _) hqend hqdis hqold hqhub
    (fun e => by rw [hfleft]; exact huA _) hqC hstart hcomplete hfS' hzS' hqS'
  · exact (Nat.add_le_add_right (Nat.add_le_add_right (Nat.add_le_add_right hS' _) _) _).trans hA
  · exact (Nat.add_le_add_right (Nat.add_le_add_right (Nat.add_le_add_right hS' _) _) _).trans hC
  · exact (Nat.add_le_add_right (Nat.add_le_add_left hS' _) _).trans hB

end
end HubFanReservoirCopy

end -- HubFanReservoirCopy

section -- AdmissibleHeavyCommon

/- Many admissible heavy paths give a large family of admissible paths whose
endpoints are heavy-adjacent to a fixed set of ordinary neighbors. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace AdmissibleHeavyCommon
set_option maxHeartbeats 3000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _
local instance (v : V) : DecidableEq (H.neighborSet v) := Classical.decEq _

lemma threshold_room (B j s κ K : ℕ) (hj : 0<j) (hB : 2*K*κ^(s+1)≤B) :
    2*K*κ^(s+1)*(threshold B (j-1))^2<threshold B j := by
  have hh := threshold_large B j hj
  have hjB : B≤j*B := by nlinarith
  exact (Nat.mul_le_mul_right _ (hB.trans hjB)).trans_lt hh

lemma local_select (B j d D κ s K : ℕ) (hj : 2≤j) (hs : 0<s) (hDpos : 0<D)
    (hd : 2*s^2≤d) (hκ : D≤κ*d) (hB : 2*K*κ^(s+1)≤B)
    (hD : ∀ w, H.degree w≤D) (v : V)
    (hlarge : 2*d*D^(j-1)<AdmissibleHeavyLinks.mass H B j v) :
    ∃ a : H.neighborSet v, ∃ f : Fin s → H.neighborSet v,
      Function.Injective f ∧ (∀ i, f i≠a) ∧ ∃ P : Finset (Chain H j),
      (∀ p∈P, Admissible H (threshold B) j p ∧ p.val 0=a.val ∧
        ∀ i, HeavyShadow.heavy H B j (f i).val (p.val (Fin.last j))) ∧
      K*threshold B (j-1)*D^(j-1)<P.card := by
  classical
  obtain ⟨a,T,hT,hmass⟩ := AdmissibleHeavyLinks.dense_fan H B j d D hj hD v hlarge
  let N (z : V) := (AdmissibleHeavyLinks.neighbors H B j v z).erase a
  let w (z : V) := (fiber H (threshold B) j a.val z).card
  have hw (z : V) (hz : z∈T) : threshold B j≤w z := (hT z hz).1.2.le
  obtain ⟨f,hf,hweight⟩ := WeightedAdmissibleSelection.select N
    (AdmissibleHeavyLinks.multiplicity H B j v) w T j s d D κ K (threshold B (j-1)) (threshold B j)
    hj hs hDpos (threshold_pos B (j-1)) hd
    (by simpa only [H.card_neighborSet_eq_degree] using hD v) hκ
    (threshold_room B j s κ K (by omega) hB)
    (fun z _ => AdmissibleHeavyLinks.multiplicity_le H B j v z) hw
    (fun z hz => (hT z hz).2) hmass
  let E (z : V) : Finset (Chain H j) := if ∀ i, f i∈N z then fiber H (threshold B) j a.val z else ∅
  let P := T.biUnion E
  have hE (z : V) (p : Chain H j) (hp : p∈E z) :
      (∀ i, f i∈N z) ∧ p∈fiber H (threshold B) j a.val z := by
    by_cases hz : ∀ i, f i∈N z
    · exact ⟨hz,by simpa only [E,if_pos hz] using hp⟩
    · simp only [E,if_neg hz,notMem_empty] at hp
  have hdis : ∀ z∈T, ∀ y∈T, z≠y → Disjoint (E z) (E y) := by
    intro z _ y _ hzy
    apply Finset.disjoint_left.mpr
    intro p hp hq
    have hz := ((mem_fiber H (threshold B) j a.val z p).mp (hE z p hp).2).2.2
    have hy := ((mem_fiber H (threshold B) j a.val y p).mp (hE y p hq).2).2.2
    exact hzy (hz.symm.trans hy)
  have hcard : P.card=∑ z∈T, if ∀ i, f i∈N z then w z else 0 := by
    rw [show P=T.biUnion E from rfl,card_biUnion hdis]
    apply sum_congr rfl
    intro z _
    dsimp only [E,w]
    split_ifs <;> simp only [card_empty]
  have hP : ∀ p∈P, Admissible H (threshold B) j p ∧ p.val 0=a.val ∧
      ∀ i, HeavyShadow.heavy H B j (f i).val (p.val (Fin.last j)) := by
    intro p hp
    obtain ⟨z,hz,hpz⟩ := mem_biUnion.mp hp
    obtain ⟨hfz,hpf⟩ := hE z p hpz
    obtain ⟨hadm,hstart,hend⟩ := (mem_fiber H (threshold B) j a.val z p).mp hpf
    refine ⟨hadm,hstart,?_⟩
    intro i
    rw [hend]
    exact (mem_filter.mp (mem_erase.mp (hfz i)).2).2
  have hPlarge : K*threshold B (j-1)*D^(j-1)<P.card := by rwa [hcard]
  have hfa (i : Fin s) : f i≠a := by
    obtain ⟨p,hp⟩ := card_pos.mp (lt_of_le_of_lt (Nat.zero_le _) hPlarge)
    obtain ⟨z,hz,hpz⟩ := mem_biUnion.mp hp
    exact (mem_erase.mp ((hE z p hpz).1 i)).1
  exact ⟨a,f,hf,hfa,P,hP,hPlarge⟩

lemma global (B j d D κ s K : ℕ) (hj : 2≤j) (hs : 0<s) (hDpos : 0<D)
    (hd : 2*s^2≤d) (hκ : D≤κ*d) (hB : 2*K*κ^(s+1)≤B)
    (hD : ∀ w, H.degree w≤D)
    (hlarge : Fintype.card V*(2*d*D^(j-1))<(AdmissibleHeavyLinks.bad H B j).card) :
    ∃ v : V, ∃ a : H.neighborSet v, ∃ f : Fin s → H.neighborSet v,
      Function.Injective f ∧ (∀ i, f i≠a) ∧ ∃ P : Finset (Chain H j),
      (∀ p∈P, Admissible H (threshold B) j p ∧ p.val 0=a.val ∧
        ∀ i, HeavyShadow.heavy H B j (f i).val (p.val (Fin.last j))) ∧
      K*threshold B (j-1)*D^(j-1)<P.card := by
  have hh := hlarge.trans_le (AdmissibleHeavyLinks.bad_le_mass H B j hj)
  have hex : ∃ v : V, 2*d*D^(j-1)<AdmissibleHeavyLinks.mass H B j v := by
    by_contra hn
    push_neg at hn
    have hb : (∑ v, AdmissibleHeavyLinks.mass H B j v)≤Fintype.card V*(2*d*D^(j-1)) := by
      calc
        _ ≤ ∑ _v : V, 2*d*D^(j-1) := sum_le_sum (fun v _ => hn v)
        _ = _ := by simp
    omega
  obtain ⟨v,hv⟩ := hex
  obtain ⟨a,f,hf,hfa,P,hP,hPlarge⟩ := local_select H B j d D κ s K hj hs hDpos hd hκ hB hD v hv
  exact ⟨v,a,f,hf,hfa,P,hP,hPlarge⟩

end
end AdmissibleHeavyCommon

end -- AdmissibleHeavyCommon

section -- HubHeavyConfiguration

/- Force an arbitrary longer two-hub subdivision from the common-heavy
configuration supplied by admissible-path averaging. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace HubHeavyConfiguration
set_option maxHeartbeats 4000000
set_option synthInstance.maxHeartbeats 200000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] {F : SimpleGraph W} (c : F.Coloring (Fin 2))

def reserve (F : SimpleGraph W) (r : ℕ) : ℕ :=
  Fintype.card W+2+Nat.card (GraphSubdivision.Edge F)*(r+1)+r*Nat.card (GraphSubdivision.Edge F)+r+3

def cost (F : SimpleGraph W) (r : ℕ) : ℕ :=
  2*(reserve F r+1)+reserve F r+
    SuffixFanData.budget r (Nat.card (GraphSubdivision.Edge F)+1) (Fintype.card W+1) (2+2*reserve F r)

def liftBudget (F : SimpleGraph W) (r : ℕ) : ℕ :=
  r*(Nat.card (GraphSubdivision.Edge F)*r)+(Fintype.card W+2+Nat.card (GraphSubdivision.Edge F)*(r+1))+
    Nat.card (GraphSubdivision.Edge F)*(r+1)

lemma reserve_pos (F : SimpleGraph W) (r : ℕ) : 0<reserve F r := by unfold reserve; omega
lemma reserve_vertices (F : SimpleGraph W) (r : ℕ) : Fintype.card W≤reserve F r := by unfold reserve; omega

lemma budget_mono (n n' s t q q' : ℕ) (hn : n≤n') (hq : q≤q') :
    SuffixFanData.budget n s t q≤SuffixFanData.budget n' s t q' := by
  unfold SuffixFanData.budget AdmissibleSuffixFans.cost
  gcongr

variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _
local instance : Fintype (GraphSubdivision.Edge F) := Fintype.ofFinite _

lemma copy (r j m l B D : ℕ) (hj : 2≤j) (hjr : j≤r) (hm : 0 < m) (hl : l<j)
    (hr : m*j+l=r) (hDpos : 1≤D) (hD : ∀ v, H.degree v≤D) (hB : liftBudget F r≤B)
    (v : V) (a : H.neighborSet v) (f : Fin (reserve F r) → H.neighborSet v)
    (hf : Function.Injective f) (hfa : ∀ i, f i≠a) (P : Finset (Chain H j))
    (hP : ∀ p∈P, Admissible H (threshold B) j p ∧ p.val 0=a.val ∧
      ∀ i, HeavyShadow.heavy H B j (f i).val (p.val (Fin.last j)))
    (hlarge : cost F r*threshold B (j-1)*D^(j-1)<P.card) :
    HubPathSubdivision.graph c (r-1) ⊑ H := by
  classical
  let E := GraphSubdivision.Edge F
  let N := reserve F r
  let A := univ.image (fun i => (f i).val)
  let S₀ := insert v A
  let Z : Set V := {z | ∀ i, HeavyShadow.heavy H B j (f i).val z}
  have hfval : Function.Injective (fun i => (f i).val) := Subtype.val_injective.comp hf
  have hAcard : A.card=N := by dsimp only [A]; rw [card_image_of_injective _ hfval]; simp [N]
  have hS₀card : S₀.card≤N+1 := (card_insert_le v A).trans (by omega)
  have haS₀ : a.val∉S₀ := by
    intro ha
    rcases mem_insert.mp ha with he | he
    · exact a.property.ne he.symm
    · obtain ⟨i,_,hi⟩ := mem_image.mp he
      exact hfa i (Subtype.ext hi)
  have hadm (p : Chain H j) (hp : p∈P) : Admissible H (threshold B) j p ∧ p.val 0=a.val :=
    ⟨(hP p hp).1,(hP p hp).2.1⟩
  have hZ (p : Chain H j) (hp : p∈P) : p.val (Fin.last j)∈Z := (hP p hp).2.2
  have hzero : (S₀.card+(S₀.card+N))*threshold B (j-1)*D^(j-1)<P.card := by
    apply lt_of_le_of_lt _ hlarge
    gcongr
    dsimp only [cost,N]
    omega
  obtain ⟨T₀,hT₀a⟩ := SuffixFanData.zero H (threshold B) (threshold_mono B) j D 1 N hj hDpos
    a.val Z P hadm hZ hD S₀ haS₀ hzero (reserve_pos F r)
  let S₁ := S₀∪T₀.vertices H
  have hS₁card : S₁.card≤2+2*N := by
    have hh := T₀.vertices_card H
    simp only [mul_zero,add_zero] at hh
    have hu := card_union_le S₀ (T₀.vertices H)
    dsimp only [S₁]
    omega
  have haS₁ : a.val∉S₁ := by
    intro ha
    rcases mem_union.mp ha with ha | ha
    · exact haS₀ ha
    · exact T₀.initial_not_vertices H hT₀a ha
  have htailcost : SuffixFanData.budget j (Nat.card E+1) (Fintype.card W+1) S₁.card≤cost F r := by
    have hh := budget_mono j r (Nat.card E+1) (Fintype.card W+1) S₁.card (2+2*N) hjr hS₁card
    exact hh.trans (by dsimp only [cost,N,E]; omega)
  obtain ⟨T₁⟩ := SuffixFanData.choose H (threshold B) (threshold_mono B) j l D (Nat.card E+1)
    (Fintype.card W+1) hj hl (by omega) (by omega) hDpos a.val Z P hadm hZ hD S₁ haS₁ (by
      exact (Nat.mul_le_mul_right _ (Nat.mul_le_mul_right _ htailcost)).trans_lt hlarge)
  obtain ⟨wn⟩ : Nonempty (W ↪ Fin N) := Function.Embedding.nonempty_of_card_le (by
    simpa only [Fintype.card_fin] using reserve_vertices F r)
  let wi : W ↪ Fin (Fintype.card W+1) := (Fintype.equivFin W).toEmbedding.trans
    ⟨Fin.castSucc,Fin.castSucc_injective _⟩
  obtain ⟨ei⟩ : Nonempty (E ↪ Fin (Nat.card E+1)) := Function.Embedding.nonempty_of_card_le (by
    simp only [Fintype.card_fin,Nat.card_eq_fintype_card]; omega)
  let C := univ.image T₀.old ∪ univ.image (fun e : E => (T₁.tail (wi (ColoredEdges.right c e),ei e)).val 0)
  have hCcard : N≤C.card := by
    have hh : (univ.image T₀.old).card=N := by rw [card_image_of_injective _ T₀.old_injective]; simp
    rw [← hh]
    exact card_le_card subset_union_left
  have hCZ (z : V) (hz : z∈C) : z∈Z := by
    rcases mem_union.mp hz with hz | hz
    · obtain ⟨i,_,rfl⟩ := mem_image.mp hz
      exact T₀.zero_old_allowed H (by omega) i
    · obtain ⟨e,_,rfl⟩ := mem_image.mp hz
      exact T₁.tail_start _
  have hcomplete : ∀ u∈A, ∀ z∈C, (HeavyShadow.graph H B j).Adj u z := by
    intro u hu z hz
    obtain ⟨i,_,rfl⟩ := mem_image.mp hu
    exact hCZ z hz i
  have hstartC (e : E) : (T₁.tail (wi (ColoredEdges.right c e),ei e)).val 0∈C :=
    mem_union_right _ (mem_image.mpr ⟨e,mem_univ _,rfl⟩)
  have hmr : m≤r := by nlinarith only [hr,hj,Nat.zero_le l]
  have hlr : l≤r := by omega
  have hneed : Fintype.card W+2+Nat.card E*(l+1)+(m-1)*Nat.card E+m+2≤N := by
    calc
      _ ≤ Fintype.card W+2+Nat.card E*(r+1)+r*Nat.card E+r+2 := by gcongr; omega
      _ ≤ N := by dsimp only [N,reserve,E]; omega
  have hneedA := hneed.trans_eq hAcard.symm
  have hneedC := hneed.trans hCcard
  have hbudget : (j-1)*(Nat.card E*m)+(Fintype.card W+2+Nat.card E*(l+1))+Nat.card E*(m+1)≤B := by
    apply le_trans _ hB
    dsimp only [liftBudget,E]
    gcongr <;> omega
  have hlen : m*j+l=(r-1)+1 := by omega
  by_cases hm0 : m%2=0
  · let u (w : W) := T₀.old (wn w)
    have hu : Function.Injective u := T₀.old_injective.comp wn.injective
    have huS (w : W) : u w∈S₁ := mem_union_right _ (T₀.old_mem H (wn w))
    have hzS : T₀.hub∈S₁ := mem_union_right _ (T₀.hub_mem H)
    have huC (w : W) : u w∈C := mem_union_left _ (mem_image.mpr ⟨wn w,mem_univ _,rfl⟩)
    apply HubFanReservoirCopy.copy c H B j m l (r-1) (Nat.card E+1) (Fintype.card W+1)
      (by omega) hm hlen S₁ a.val Z T₁ wi ei u T₀.hub hu (fun w => T₀.spoke (wn w)) huS hzS C A huC
      (fun e => by simpa [BipartiteReservoirPaths.pool,hm0] using hstartC e)
      (fun z hz u hu => (hcomplete u hu z hz).symm) hneedC hneedA hbudget
  · let u (w : W) := (f (wn w)).val
    have hu : Function.Injective u := hfval.comp wn.injective
    have huA (w : W) : u w∈A := mem_image.mpr ⟨wn w,mem_univ _,rfl⟩
    have huS (w : W) : u w∈S₁ := mem_union_left _ (mem_insert_of_mem (huA w))
    have hzS : v∈S₁ := mem_union_left _ (mem_insert_self _ _)
    apply HubFanReservoirCopy.copy c H B j m l (r-1) (Nat.card E+1) (Fintype.card W+1)
      (by omega) hm hlen S₁ a.val Z T₁ wi ei u v hu (fun w => (f (wn w)).property) huS hzS A C huA
      (fun e => by simpa only [BipartiteReservoirPaths.pool,if_neg hm0] using hstartC e)
      hcomplete hneedA hneedC hbudget

end
end HubHeavyConfiguration

end -- HubHeavyConfiguration

section -- AdmissibleFiberDegree

/- Elementary endpoint bounds and the small-degree empty-heavy case. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace AdmissibleFiberDegree
set_option maxHeartbeats 2000000
set_option synthInstance.maxHeartbeats 200000
universe u
noncomputable section
variable {V : Type u} [Fintype V] (H : SimpleGraph V)
local instance : DecidableEq V := Classical.decEq _
local instance : DecidableRel H.Adj := Classical.decRel _

lemma fiber_le (L : ℕ → ℕ) (j D : ℕ) (hj : 0<j) (hD : ∀ v, H.degree v≤D) (x y : V) :
    (fiber H L j x y).card≤D^(j-1) := by
  classical
  let i : Fin j := ⟨j-1,by omega⟩
  let f (p : fiber H L j x y) : {q : From H x j // q.val.val i.succ=y} := by
    have hp := (mem_fiber H L j x y p.val).mp p.property
    refine ⟨⟨p.val,hp.2.1⟩,?_⟩
    have he : i.succ=Fin.last j := by apply Fin.ext; dsimp [i]; omega
    simpa only [he] using hp.2.2
  have hf : Function.Injective f := by
    intro p q he
    apply Subtype.ext
    exact congrArg (fun z : {q : From H x j // q.val.val i.succ=y} => z.val.val) he
  have hh := (Fintype.card_le_of_injective f hf).trans (ChainCounting.coordinate_le H D hD j x y i)
  simpa only [Fintype.card_coe] using hh

lemma budget_le_threshold (B j : ℕ) (hj : 0<j) : B≤threshold B j := by
  have hh := threshold_large B j hj
  have hL := threshold_pos B (j-1)
  have hm : 1≤j*(threshold B (j-1))^2 := by nlinarith
  have hb := Nat.mul_le_mul_left B hm
  nlinarith only [hh,hb]

lemma bad_empty (B j D : ℕ) (hj : 0<j) (hD : ∀ v, H.degree v≤D)
    (hsmall : D^(j-1)≤threshold B j) : AdmissibleHeavyLinks.bad H B j=∅ := by
  classical
  apply eq_empty_iff_forall_notMem.mpr
  intro p hp
  have hh := (mem_filter.mp hp).2.2.2
  exact (Nat.not_lt_of_ge ((fiber_le H (threshold B) j D hj hD _ _).trans hsmall)) hh

end
end AdmissibleFiberDegree

end -- AdmissibleFiberDegree

section -- HubAdmissiblePruning

/- Uniform pruning of admissible heavy paths at EVERY length up to the
replacement length in a forbidden two-hub subdivision. -/
open Finset SimpleGraph ChainCounting GoodChains ThetaChains
namespace HubAdmissiblePruning
set_option maxHeartbeats 3500000
set_option synthInstance.maxHeartbeats 200000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] {F : SimpleGraph W} (c : F.Coloring (Fin 2))
variable {V : Type v} [Fintype V] (H : SimpleGraph V)
local instance : DecidableRel H.Adj := Classical.decRel _

lemma scaled (r κ B D : ℕ) (hr : 2≤r) (hκ : 0<κ)
    (hB₀ : HubHeavyConfiguration.liftBudget F r≤B)
    (hB₁ : (4*κ*(HubHeavyConfiguration.reserve F r)^2)^(r-1)≤B)
    (hB₂ : 2*HubHeavyConfiguration.cost F r*(4*κ)^(HubHeavyConfiguration.reserve F r+1)≤B)
    (hfree : (HubPathSubdivision.graph c (r-1)).Free H) (hD : ∀ v, H.degree v≤D)
    (j : ℕ) (hj : 2≤j) (hjr : j≤r) :
    κ*(AdmissibleHeavyLinks.bad H B j).card≤Fintype.card V*D^j := by
  classical
  let N := HubHeavyConfiguration.reserve F r
  have hN : 0<N := HubHeavyConfiguration.reserve_pos F r
  by_cases hsmall : D<4*κ*N^2
  · have hbase : 1≤4*κ*N^2 := by nlinarith
    have hpow : D^(j-1)≤B := by
      calc
        _ ≤ (4*κ*N^2)^(j-1) := Nat.pow_le_pow_left hsmall.le _
        _ ≤ (4*κ*N^2)^(r-1) := Nat.pow_le_pow_right hbase (by omega)
        _ ≤ B := hB₁
    have he := AdmissibleFiberDegree.bad_empty H B j D (by omega) hD
      (hpow.trans (AdmissibleFiberDegree.budget_le_threshold B j (by omega)))
    rw [he,card_empty,mul_zero]
    exact Nat.zero_le _
  · have hlarge : 4*κ*N^2≤D := by omega
    let d := D/(2*κ)
    have hκ₂ : 0<2*κ := by omega
    have hd : 2*N^2≤d := by
      apply (Nat.le_div_iff_mul_le hκ₂).mpr
      nlinarith only [hlarge]
    have hdpos : 0<d := by nlinarith
    have hDpos : 0<D := by nlinarith only [hlarge,hκ,hN]
    have hrem : D<2*κ*(d+1) := by simpa only [d] using Nat.lt_mul_div_succ D hκ₂
    have hratio : D≤(4*κ)*d := by nlinarith only [hrem,hdpos]
    have hbound : (AdmissibleHeavyLinks.bad H B j).card≤Fintype.card V*(2*d*D^(j-1)) := by
      by_contra hn
      obtain ⟨v,a,f,hf,hfa,P,hP,hPcard⟩ := AdmissibleHeavyCommon.global H B j d D (4*κ) N
        (HubHeavyConfiguration.cost F r) hj hN hDpos hd hratio hB₂ hD (Nat.lt_of_not_ge hn)
      let m := r/j
      let l := r%j
      have hm : 0 < m := Nat.div_pos hjr (by omega)
      have hl : l<j := Nat.mod_lt r (by omega)
      have he : m*j+l=r := by dsimp only [m,l]; simpa only [Nat.mul_comm] using Nat.div_add_mod r j
      exact hfree (HubHeavyConfiguration.copy c H r j m l B D hj hjr hm hl he (by omega) hD hB₀
        v a f hf hfa P hP hPcard)
    have hdiv : 2*κ*d≤D := by simpa only [d] using Nat.mul_div_le D (2*κ)
    have hmul := Nat.mul_le_mul_left κ hbound
    have hmax := Nat.mul_le_mul_left (Fintype.card V*D^(j-1)) hdiv
    have hpow : D*D^(j-1)=D^j := by rw [← pow_succ',Nat.sub_add_cancel (by omega : 0<j)]
    nlinarith only [hmul,hmax,hpow]

lemma pruning (r : ℕ) (hr : 2≤r) (ε : ℝ) (hε : 0<ε) (B₀ : ℕ) :
    ∃ B : ℕ, B₀≤B ∧ ∀ (V : Type v) [Fintype V] (H : SimpleGraph V) (D : ℕ),
      (HubPathSubdivision.graph c (r-1)).Free H → (∀ v, Nat.card (H.neighborSet v)≤D) →
      ∀ j : ℕ, 2≤j → j≤r → ((AdmissibleHeavyLinks.bad H B j).card : ℝ)≤
        ε*Fintype.card V*(D : ℝ)^j := by
  obtain ⟨κ,hκR⟩ := exists_nat_gt (1/ε)
  have hκRpos : (0 : ℝ)<κ := (by positivity : (0 : ℝ)<1/ε).trans hκR
  have hκ : 0<κ := by exact_mod_cast hκRpos
  have hεκ : 1≤ε*κ := by
    have hh := (div_lt_iff₀ hε).mp hκR
    nlinarith only [hh]
  let N := HubHeavyConfiguration.reserve F r
  let B := B₀+HubHeavyConfiguration.liftBudget F r+(4*κ*N^2)^(r-1)+
    2*HubHeavyConfiguration.cost F r*(4*κ)^(N+1)
  refine ⟨B,by dsimp only [B]; omega,?_⟩
  intro V _ H D hfree hD j hj hjr
  classical
  have hdeg : ∀ v, H.degree v≤D := by simpa only [Nat.card_eq_fintype_card,H.card_neighborSet_eq_degree] using hD
  have hh := scaled c H r κ B D hr hκ (by dsimp only [B]; omega)
    (by dsimp only [B,N]; omega) (by dsimp only [B,N]; omega) hfree hdeg j hj hjr
  have hhR : (κ : ℝ)*(AdmissibleHeavyLinks.bad H B j).card≤Fintype.card V*(D : ℝ)^j := by exact_mod_cast hh
  have hm := mul_le_mul_of_nonneg_left hhR hε.le
  have hb := mul_le_mul_of_nonneg_right hεκ (Nat.cast_nonneg (AdmissibleHeavyLinks.bad H B j).card : (0 : ℝ)≤_)
  nlinarith only [hm,hb]

end
end HubAdmissiblePruning

end -- HubAdmissiblePruning

section -- PowerErrorAbsorption

/- Absorbing a strict power-saving error in a degree moment bound. -/
namespace PowerErrorAbsorption
set_option maxHeartbeats 1000000

noncomputable def constant (C E b ε : ℝ) : ℝ := (2*E)^(1/ε)+(2*C)^(1/b)

lemma constant_nonneg (C E b ε : ℝ) (hC : 0 ≤ C) (hE : 0 ≤ E) :
    0 ≤ constant C E b ε := by unfold constant; positivity

lemma bound (x N a b ε C E : ℝ) (hx : 0 < x) (hN : 1 ≤ N)
    (ha : 0 ≤ a) (hb : 0 < b) (hε : 0 < ε) (hC : 0 ≤ C) (hE : 0 ≤ E)
    (hmain : x^b ≤ C*N^a+E*x^(b-ε)) :
    x ≤ constant C E b ε * N^(a/b) := by
  have hNr : 1 ≤ N^(a/b) := Real.one_le_rpow hN (by positivity)
  have hconst := constant_nonneg C E b ε hC hE
  by_cases hsmall : x^ε ≤ 2*E
  · have hr := Real.rpow_le_rpow (Real.rpow_nonneg hx.le _) hsmall (by positivity : 0 ≤ 1/ε)
    rw [← Real.rpow_mul hx.le,show ε*(1/ε) = 1 by field_simp,Real.rpow_one] at hr
    have hc : (2*E)^(1/ε) ≤ constant C E b ε :=
      le_add_of_nonneg_right (Real.rpow_nonneg (by positivity) _)
    exact hr.trans (hc.trans (le_mul_of_one_le_right hconst hNr))
  · have hp := mul_le_mul_of_nonneg_right (le_of_lt (lt_of_not_ge hsmall))
      (Real.rpow_nonneg hx.le (b-ε))
    rw [← Real.rpow_add hx,show ε+(b-ε) = b by ring] at hp
    have hc : x^b ≤ 2*C*N^a := by nlinarith only [hmain,hp]
    have hr := Real.rpow_le_rpow (Real.rpow_nonneg hx.le _) hc (by positivity : 0 ≤ 1/b)
    rw [← Real.rpow_mul hx.le,show b*(1/b) = 1 by field_simp,Real.rpow_one,
      Real.mul_rpow (show 0 ≤ 2*C by positivity) (Real.rpow_nonneg (by linarith) a),
      ← Real.rpow_mul (show 0 ≤ N by linarith),show a*(1/b) = a/b by ring] at hr
    apply hr.trans
    apply mul_le_mul_of_nonneg_right _ (Real.rpow_nonneg (by linarith) _)
    exact le_add_of_nonneg_left (Real.rpow_nonneg (by positivity) _)

end PowerErrorAbsorption

end -- PowerErrorAbsorption

section -- HubPathDegree

/- General almost-regular degree bound for arbitrary-length two-hub replacements. -/
open Finset SimpleGraph
namespace HubPathDegree
set_option maxHeartbeats 3500000
set_option synthInstance.maxHeartbeats 200000
universe u v

lemma absorb (p : ℕ) (n d δ U α : ℝ) (hn : 0<n) (hd : 0<d) (hhalf : d≤2*δ)
    (hcount : n*δ^p≤n^2*U*d^α+(1/(2 : ℝ)^(p+1))*n*d^p) :
    d^((p : ℝ)-α)≤(2 : ℝ)^(p+1)*U*n := by
  have hp := pow_le_pow_left₀ hd.le hhalf p
  rw [mul_pow] at hp
  have hp' := mul_le_mul_of_nonneg_left hp (show 0≤2*n by positivity)
  have hh := mul_le_mul_of_nonneg_left hcount (show 0≤(2 : ℝ)^(p+1) by positivity)
  rw [mul_add] at hh
  have he : (2 : ℝ)^(p+1)*((1/(2 : ℝ)^(p+1))*n*d^p)=n*d^p := by
    field_simp
  rw [he] at hh
  have ht : (2 : ℝ)^(p+1)=2*(2 : ℝ)^p := by rw [pow_succ]; ring
  have hmain : n*d^p≤n*((2 : ℝ)^(p+1)*U*n*d^α) := by rw [ht] at hh ⊢; nlinarith only [hp',hh]
  have hpower : d^p≤(2 : ℝ)^(p+1)*U*n*d^α := (mul_le_mul_iff_right₀ hn).mp hmain
  have hid : d^((p : ℝ)-α)*d^α=d^p := by rw [← Real.rpow_add hd,sub_add_cancel,Real.rpow_natCast]
  apply (mul_le_mul_iff_left₀ (Real.rpow_pos_of_pos hd α)).mp
  simpa only [hid] using hpower

noncomputable section
variable {W : Type u} [Fintype W] (F : SimpleGraph W) (c : F.Coloring (Fin 2))

lemma almost_regular (hF : F.Connected) (k : ℕ) (hk : 1≤k) (α C : ℝ)
    (hα : 0≤α) (hα₂ : α<2) (hC : 0≤C)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α) (R : ℕ) (hR : 0<R) :
    ∃ A : ℝ, 0≤A ∧ ∀ (V : Type v) [Fintype V] [Nonempty V] (H : SimpleGraph V) (δ : ℕ),
      0<δ → (HubPathSubdivision.graph c k).Free H →
      (∀ w, δ≤Nat.card (H.neighborSet w)) → (∀ w, Nat.card (H.neighborSet w)≤R*δ) →
      (δ : ℝ)≤A*(Nat.card V : ℝ)^(1/(((k+3 : ℕ) : ℝ)-α)) := by
  let ε : ℝ := 1/((2 : ℝ)^(k+4)*(k+4 : ℕ)*(k+2 : ℕ)*(R : ℝ)^(k+3))
  have hRR : (0 : ℝ)<R := by exact_mod_cast hR
  have hε : 0<ε := by dsimp [ε]; positivity
  have hcoef : (k+4 : ℕ)*(k+2 : ℕ)*ε*(R : ℝ)^(k+3)=1/(2 : ℝ)^(k+4) := by
    dsimp only [ε]
    have hR0 : (R : ℝ)≠0 := hRR.ne'
    have hk4 : ((k+4 : ℕ) : ℝ)≠0 := by positivity
    have hk2 : ((k+2 : ℕ) : ℝ)≠0 := by positivity
    field_simp
  obtain ⟨B,hB,hprune⟩ := HubAdmissiblePruning.pruning.{u,v} c (k+1) (by omega) ε hε 0
  let U : ℝ := (HubLightBounds.loss k (ThetaChains.threshold B) : ℝ)*C*2^α*(R : ℝ)^α
  let A : ℝ := 2*(k+3 : ℕ)+PowerErrorAbsorption.constant ((2 : ℝ)^(k+4)*U) 0 (((k+3 : ℕ) : ℝ)-α) 1
  have hU : 0≤U := by dsimp [U]; positivity
  have hA : 0≤A := by
    exact add_nonneg (by positivity) (PowerErrorAbsorption.constant_nonneg _ _ _ _ (by positivity) le_rfl)
  refine ⟨A,hA,?_⟩
  intro V _ _ H δ hδ hfree hmin hmax
  classical
  have hn : (0 : ℝ)<Fintype.card V := by exact_mod_cast Fintype.card_pos
  have hn1 : (1 : ℝ)≤Fintype.card V := by exact_mod_cast Fintype.card_pos
  have hdR : (0 : ℝ)<δ := by exact_mod_cast hδ
  have hkR : (1 : ℝ)≤k := by exact_mod_cast hk
  have hden : 0<((k+3 : ℕ) : ℝ)-α := by push_cast; linarith
  have hnr : 1≤(Fintype.card V : ℝ)^(1/(((k+3 : ℕ) : ℝ)-α)) := Real.one_le_rpow hn1 (by positivity)
  rw [Nat.card_eq_fintype_card]
  by_cases hsmall : δ<2*(k+3)
  · have hdsmall : (δ : ℝ)≤2*(k+3 : ℕ) := by exact_mod_cast hsmall.le
    have hbase : (2*(k+3 : ℕ) : ℝ)≤A := le_add_of_nonneg_right
      (PowerErrorAbsorption.constant_nonneg _ _ _ _ (by positivity) le_rfl)
    exact hdsmall.trans (hbase.trans (le_mul_of_one_le_right hA hnr))
  have hlarge : 2*(k+3)≤δ := by omega
  have hD : ∀ w, H.degree w≤R*δ := by simpa only [Nat.card_eq_fintype_card,H.card_neighborSet_eq_degree] using hmax
  have hm : ∀ w, δ-(k+3)+(k+3)≤H.degree w := by
    simpa only [Nat.sub_add_cancel (by omega : k+3≤δ),Nat.card_eq_fintype_card,H.card_neighborSet_eq_degree] using hmin
  have hpr := hprune V H (R*δ) (by simpa using hfree) hmax
  have hc := HubAdmissibleCount.count F c H hF k B (δ-(k+3)) (R*δ) hm hD hfree C α ε hC hα hε.le hbound hpr
  have he : (((R*δ : ℕ) : ℝ)^α)=(R : ℝ)^α*(δ : ℝ)^α := by
    rw [Nat.cast_mul,Real.mul_rpow hRR.le hdR.le]
  have herr : (k+4 : ℕ)*(k+2 : ℕ)*ε*Fintype.card V*(((R*δ : ℕ) : ℝ)^(k+3))=
      (1/(2 : ℝ)^(k+4))*Fintype.card V*(δ : ℝ)^(k+3) := by
    rw [Nat.cast_mul,mul_pow]
    calc
      _ = ((k+4 : ℕ)*(k+2 : ℕ)*ε*(R : ℝ)^(k+3))*Fintype.card V*(δ : ℝ)^(k+3) := by ring
      _ = _ := by rw [hcoef]
  rw [he,herr] at hc
  have hcount : (Fintype.card V : ℝ)*((δ-(k+3) : ℕ) : ℝ)^(k+3)≤
      (Fintype.card V : ℝ)^2*U*(δ : ℝ)^α+(1/(2 : ℝ)^(k+4))*Fintype.card V*(δ : ℝ)^(k+3) := by
    dsimp only [U]
    nlinarith only [hc]
  have hhalf : (δ : ℝ)≤2*((δ-(k+3) : ℕ) : ℝ) := by exact_mod_cast (by omega : δ≤2*(δ-(k+3)))
  have hp := absorb (k+3) (Fintype.card V) δ (δ-(k+3) : ℕ) U α hn hdR hhalf hcount
  have hp' : (δ : ℝ)^(((k+3 : ℕ) : ℝ)-α)≤((2 : ℝ)^(k+4)*U)*(Fintype.card V : ℝ)^(1 : ℝ)+
      0*(δ : ℝ)^((((k+3 : ℕ) : ℝ)-α)-1) := by simpa only [Real.rpow_one,zero_mul,add_zero] using hp
  have hh := PowerErrorAbsorption.bound δ (Fintype.card V) 1 (((k+3 : ℕ) : ℝ)-α) 1 ((2 : ℝ)^(k+4)*U) 0
    hdR hn1 (by norm_num) hden (by norm_num) (by positivity) le_rfl hp'
  apply hh.trans
  exact mul_le_mul_of_nonneg_right (le_add_of_nonneg_left (by positivity : (0 : ℝ)≤2*(k+3 : ℕ))) (by positivity)

end
end HubPathDegree

end -- HubPathDegree

section -- BipartiteRegularization

/- Bipartite almost-regular tests suffice for a general edge bound. -/
open Finset SimpleGraph
namespace BipartiteRegularization
set_option maxHeartbeats 1500000
universe u


lemma bound (γ A : ℝ) (L : ℕ) (hγ : 1 < γ) (hA : 0 ≤ A)
    (hL : 4*(2 : ℝ)^γ ≤ (L : ℝ)^(γ-1))
    (P : ∀ (V : Type u) [Fintype V], SimpleGraph V → Prop)
    (hered : ∀ (V W : Type u) [Fintype V] [Fintype W] (H : SimpleGraph V) (G : SimpleGraph W),
      Copy G H → P V H → P W G)
    (hbound : ∀ (W : Type u) [Fintype W] [Nonempty W] (G : SimpleGraph W),
      G.Coloring (Fin 2) → P W G → ∀ d : ℕ,
      0 < d → (∀ v, d ≤ Nat.card (G.neighborSet v)) →
      (∀ v, Nat.card (G.neighborSet v) ≤ 8*L*d) →
      (d : ℝ) ≤ A*(Nat.card W : ℝ)^(γ-1)) :
    ∀ (V : Type u) [Fintype V] (H : SimpleGraph V), P V H →
      (Nat.card H.edgeSet : ℝ) ≤ 8*A*(Nat.card V : ℝ)^γ := by
  intro V _ H hP
  classical
  have he : Nat.card H.edgeSet = H.edgeFinset.card := by rw [Nat.card_eq_fintype_card]; exact H.card_edgeSet
  rw [he,Nat.card_eq_fintype_card]
  cases isEmpty_or_nonempty V with
  | inl h =>
    have hzero : H.edgeFinset.card = 0 := by
      have hh := H.card_edgeFinset_le_card_choose_two
      simpa using hh
    rw [hzero,Nat.cast_zero]
    positivity
  | inr h =>
    obtain ⟨J,hJ,hJH,hJB,heJ⟩ := MaxCut.exists_bipartite_subgraph H
    letI := hJ
    let cJ : J.Coloring (Fin 2) := Classical.choice hJB
    have hPJ := hered V V H J (Copy.ofLE J H hJH) hP
    have hreg : (J.edgeFinset.card : ℝ) ≤ 4*A*(Fintype.card V : ℝ)^γ := by
      apply Regularization.edge_bound_of_almost_regular J γ A L hγ hA hL
      intro W _ _ G _ f d hdpos hd hD
      let cG : G.Coloring (Fin 2) := Coloring.mk (fun v => cJ (f v))
        (fun h => cJ.valid (f.toHom.map_rel' h))
      have hh := hbound W G cG (hered V W J G f hPJ) d hdpos
        (fun v => by simpa only [Nat.card_eq_fintype_card,G.card_neighborSet_eq_degree] using hd v)
        (fun v => by simpa only [Nat.card_eq_fintype_card,G.card_neighborSet_eq_degree] using hD v)
      simpa only [Nat.card_eq_fintype_card] using hh
    have heJ' : (H.edgeFinset.card : ℝ) ≤ 2*J.edgeFinset.card := by exact_mod_cast heJ
    nlinarith only [hreg,heJ']

end BipartiteRegularization

end -- BipartiteRegularization

section -- HubPathBounds

/- The general upper transformation alpha -> 1+1/(k+3-alpha) for the two-hub
(k+1)-edge subdivision of a connected bipartite graph. -/
open Finset SimpleGraph Filter
namespace HubPathBounds
set_option maxHeartbeats 2500000
universe u v
noncomputable section
variable {W : Type u} [Fintype W] (F : SimpleGraph W) (c : F.Coloring (Fin 2))

lemma edge_bound (hF : F.Connected) (k : ℕ) (hk : 1≤k) (α C : ℝ) (hα : 0≤α) (hα₂ : α<2) (hC : 0≤C)
    (hbound : ∀ n : ℕ, (extremalNumber n F : ℝ)≤C*(n : ℝ)^α) :
    ∃ B : ℝ, 0≤B ∧ ∀ (V : Type v) [Fintype V] (H : SimpleGraph V),
      (HubPathSubdivision.graph c k).Free H →
      (Nat.card H.edgeSet : ℝ)≤B*(Nat.card V : ℝ)^(1+1/(((k+3 : ℕ) : ℝ)-α)) := by
  let γ : ℝ := 1+1/(((k+3 : ℕ) : ℝ)-α)
  have hkR : (1 : ℝ)≤k := by exact_mod_cast hk
  have hden : 0<((k+3 : ℕ) : ℝ)-α := by push_cast; linarith
  have hγ : 1<γ := by dsimp only [γ]; have := one_div_pos.mpr hden; linarith
  have hγ' : 0≤γ-1 := by linarith
  obtain ⟨M,hM⟩ := Regularization.exists_regularization_constant γ hγ
  have hM' : 4*(2 : ℝ)^γ≤((M+1 : ℕ) : ℝ)^(γ-1) := by
    exact hM.trans (Real.rpow_le_rpow (Nat.cast_nonneg _) (by exact_mod_cast Nat.le_succ M) hγ')
  obtain ⟨A,hA,hdegree⟩ := HubPathDegree.almost_regular.{u,v} F c hF k hk α C hα hα₂ hC hbound (8*(M+1)) (by omega)
  refine ⟨8*A,mul_nonneg (by norm_num) hA,?_⟩
  apply BipartiteRegularization.bound γ A (M+1) hγ hA hM'
    (fun V _ H => (HubPathSubdivision.graph c k).Free H)
  · intro V V' _ _ H G f hfree h
    exact hfree (h.trans ⟨f⟩)
  · intro V _ _ H d hfree δ hδ hmin hmax
    have hh := hdegree V H δ hδ hfree hmin hmax
    simpa only [γ,add_sub_cancel_left] using hh

lemma upper_isBigO (hF : F.Connected) (k : ℕ) (hk : 1≤k) (α : ℝ) (hα : 0≤α) (hα₂ : α<2)
    (hupper : Asymptotics.IsBigO atTop (fun n : ℕ => (extremalNumber n F : ℝ))
      (fun n : ℕ => (n : ℝ)^α)) :
    Asymptotics.IsBigO atTop (fun n : ℕ => (extremalNumber n (HubPathSubdivision.graph c k) : ℝ))
      (fun n : ℕ => (n : ℝ)^(1+1/(((k+3 : ℕ) : ℝ)-α))) := by
  obtain ⟨C,hC,hbound⟩ := SuspensionBounds.uniform_bound_of_isBigO F α hα hupper
  obtain ⟨B,hB,hgraph⟩ := edge_bound.{u,0} F c hF k hk α C hα hα₂ hC hbound
  have hpoint (n : ℕ) : (extremalNumber n (HubPathSubdivision.graph c k) : ℝ)≤B*(n : ℝ)^(1+1/(((k+3 : ℕ) : ℝ)-α)) := by
    classical
    rw [← Fintype.card_fin n,extremalNumber_le_iff_of_nonneg _ (by positivity)]
    intro H _ hfree
    have hh := hgraph (Fin n) H hfree
    simpa only [Nat.card_eq_fintype_card,← SimpleGraph.edgeFinset_card] using hh
  apply Asymptotics.isBigO_iff.mpr
  refine ⟨B,Eventually.of_forall ?_⟩
  intro n
  simpa only [Real.norm_eq_abs,Nat.abs_cast,abs_of_nonneg (Real.rpow_nonneg (Nat.cast_nonneg n) _)] using hpoint n

end
end HubPathBounds

end -- HubPathBounds

section -- RootedModelFacts

/- The verified rooted-model transformation (a,b) -> (a+b,a+2*b). -/
open Finset SimpleGraph
namespace RootedModelFacts
open RootedUpperModels
set_option maxHeartbeats 2000000

lemma model_has_edge {a b : ℕ} (M : Model a b) (hb : 0<b) : ∃ x y, M.G.Adj x y := by
  classical
  letI := M.fintypeA
  letI := M.fintypeR
  letI := M.nonemptyA
  let x := Classical.choice M.nonemptyA
  have hh := M.balance {x}
  rw [card_singleton,mul_one] at hh
  have hc : 0<(RootedUnionDensity.incident M.G {x}).card := by
    by_contra hn
    have hz : (RootedUnionDensity.incident M.G {x}).card=0 := by omega
    rw [hz,mul_zero] at hh
    omega
  obtain ⟨e,he⟩ := card_pos.mp hc
  have hadj := (mem_filter.mp he).1
  induction e using Sym2.inductionOn with
  | _ u v => exact ⟨u,v,mem_edgeFinset.mp hadj⟩

lemma color_surjective {W : Type*} (F : SimpleGraph W) (c : F.Coloring (Fin 2))
    (hedge : ∃ x y, F.Adj x y) : Function.Surjective c := by
  obtain ⟨x,y,hxy⟩ := hedge
  have hc := c.valid hxy
  intro i
  by_cases hx : c x=i
  · exact ⟨x,hx⟩
  · exact ⟨y,by change c x≠c y at hc; omega⟩

end RootedModelFacts

end -- RootedModelFacts

section -- RootedHubPathModels

/- The arbitrary rooted-model closure (a,b) -> (a+k*b,a+(k+1)*b). -/
open Finset SimpleGraph
namespace RootedHubPathModels
open RootedUpperModels
set_option maxHeartbeats 2500000

noncomputable def model {a b : ℕ} (M : Model a b) (ha : 0<a) (hab : a≤b) (k : ℕ) (hk : 1≤k) :
    Model (a+k*b) (a+(k+1)*b) := by
  classical
  letI := M.fintypeA
  letI := M.fintypeR
  letI := M.nonemptyA
  letI : Fintype (RootedSubdivision.E M.G) := Fintype.ofFinite _
  letI : Fintype (RootedHubPath.I M.G) := Fintype.ofFinite _
  letI : Fintype (RootedHubPath.J M.G) := Fintype.ofFinite _
  have hb : 0<b := ha.trans_le hab
  have hedge := RootedModelFacts.model_has_edge M hb
  refine {
    A := RootedHubPath.Internal M.G k
    R := RootedHubPath.Roots M.G k
    G := RootedHubPath.graph M.G k M.color
    color := RootedHubPath.color M.G k M.color
    balance := RootedHubPath.balanced M.G k M.color a b M.balance
    connected := ?_
    upper := ?_ }
  · intro t ht
    have he : ∃ x y, (RootedPowers.graph M.G t).Adj x y := by
      obtain ⟨x,y,hxy⟩ := hedge
      exact ⟨RootedPowers.layer M.G t ⟨0,ht⟩ x,RootedPowers.layer M.G t ⟨0,ht⟩ y,
        (RootedPowers.layer M.G t ⟨0,ht⟩).toHom.map_rel' hxy⟩
    exact (RootedHubPath.powerIso M.G k M.color t ⟨0,ht⟩).connected_iff.mpr
      (HubPathSubdivision.connected _ k (M.connected t ht) (RootedModelFacts.color_surjective _ _ he))
  · intro t ht
    have haR : (0 : ℝ)<a := by exact_mod_cast ha
    have hbR : (0 : ℝ)<b := by exact_mod_cast hb
    have habR : (a : ℝ)≤b := by exact_mod_cast hab
    have hα : 0≤2-(a : ℝ)/b := by have := (div_le_one hbR).mpr habR; linarith
    have hα₂ : 2-(a : ℝ)/b<2 := by have := div_pos haR hbR; linarith
    have hu := HubPathBounds.upper_isBigO (RootedPowers.graph M.G t) (RootedSuspension.powerColor M.color t)
      (M.connected t ht) k hk (2-(a : ℝ)/b) hα hα₂ (M.upper t ht)
    have he : 1+1/(((k+3 : ℕ) : ℝ)-(2-(a : ℝ)/b))=2-((a+k*b : ℕ) : ℝ)/(a+(k+1)*b : ℕ) := by
      have hd : (a : ℝ)+((k : ℝ)+1)*b≠0 := by positivity
      have hden : ((k+3 : ℕ) : ℝ)-(2-(a : ℝ)/b)=((a : ℝ)+((k : ℝ)+1)*b)/b := by
        push_cast
        field_simp
        ring
      rw [hden,one_div_div]
      push_cast
      field_simp
      ring
    simpa only [extremalNumber_congr_right (RootedHubPath.powerIso M.G k M.color t ⟨0,ht⟩),he] using hu

end RootedHubPathModels

end -- RootedHubPathModels

section -- UniversalHubModels

/- The arbitrary two-hub closure and suspension generate all rational
extremal exponents between one and two. -/
open Finset SimpleGraph
namespace UniversalHubModels
open RootedUpperModels
set_option maxHeartbeats 2500000

noncomputable def initial_scaled (a : ℕ) (ha : 0<a) : Model a a := by
  let M := RootedUpperModels.initial
  letI := M.fintypeA
  letI := M.fintypeR
  letI := M.nonemptyA
  exact {
    A := M.A
    R := M.R
    G := M.G
    color := M.color
    balance := fun S => by
      have hh := Nat.mul_le_mul_left a (M.balance S)
      simpa only [mul_one,one_mul] using hh
    connected := M.connected
    upper := fun t ht => by
      have haR : (a : ℝ)≠0 := by exact_mod_cast ha.ne'
      simpa only [Nat.cast_one,div_self haR,div_one,sub_self] using M.upper t ht }

noncomputable def transform {a b : ℕ} (M : Model a b) (ha : 0<a) (hab : a≤b) (k : ℕ) :
    Model (a+k*b) (a+(k+1)*b) := by
  by_cases hk : k=0
  · subst k
    simpa only [zero_mul,add_zero,zero_add,one_mul,Nat.add_comm] using RootedUpperModels.suspension M ha hab
  · exact RootedHubPathModels.model M ha hab k (by omega)

/-- The inverse negative-continued-fraction step, written without rational division. -/
lemma negative_step (a b : ℕ) (ha : 0<a) (hab : a<b) :
    ∃ k r : ℕ, r<a ∧ b+r=(k+2)*a := by
  let q := b/a
  have hdiv := Nat.mod_add_div b a
  have hrem : b%a<a := Nat.mod_lt b ha
  by_cases hz : b%a=0
  · have hmul : q*a=b := by dsimp only [q]; nlinarith only [hdiv,hz]
    have hq : 2≤q := by nlinarith only [hmul,hab,ha]
    refine ⟨q-2,0,ha,?_⟩
    rw [Nat.sub_add_cancel hq,Nat.add_zero]
    exact hmul.symm
  · have hq : 0<q := Nat.div_pos hab.le ha
    have hsub := Nat.sub_add_cancel hrem.le
    refine ⟨q-1,a-b%a,by omega,?_⟩
    have he : q-1+2=q+1 := by omega
    rw [he]
    dsimp only [q] at *
    nlinarith only [hdiv,hsub]

lemma all_models : ∀ b a : ℕ, 0<a → a≤b → Nonempty (Model a b) := by
  intro b
  induction b using Nat.strong_induction_on with
  | h b ih =>
    intro a ha hab
    by_cases he : a=b
    · subst a
      exact ⟨initial_scaled b ha⟩
    have hab' : a<b := by omega
    let p := b-a
    have hp : 0<p := by dsimp only [p]; omega
    have hpb : p<b := by dsimp only [p]; omega
    have hpa : p+a=b := by dsimp only [p]; omega
    obtain ⟨k,r,hr,hkr⟩ := negative_step p b hp hpb
    have hprev : p-r+r=p := Nat.sub_add_cancel hr.le
    obtain ⟨M⟩ := ih p hpb (p-r) (by omega) (Nat.sub_le p r)
    have M' := transform M (by omega) (Nat.sub_le p r) k
    have hnewA : p-r+k*p=a := by nlinarith only [hkr,hpa,hprev]
    have hnewB : p-r+(k+1)*p=b := by nlinarith only [hkr,hprev]
    rw [hnewA,hnewB] at M'
    exact ⟨M'⟩

lemma result (α : ℚ) (hα : 1≤α) (hα₂ : α<2) :
    ∃ q : ℕ, ∃ G : SimpleGraph (Fin q), G.IsBipartite ∧
      Asymptotics.IsTheta Filter.atTop
        (fun n : ℕ => (extremalNumber n G : ℝ))
        (fun n : ℕ => (n : ℝ)^(α : ℝ)) := by
  let x : ℚ := 2-α
  have hx : 0<x := by dsimp only [x]; linarith
  have hx1 : x≤1 := by dsimp only [x]; linarith
  have hnum : 0<x.num := Rat.num_pos.mpr hx
  have hxcast : (x.num.natAbs : ℚ)/x.den=x := by
    have hn : (x.num.natAbs : ℚ)=x.num := by rw [← Int.cast_natCast,Int.natAbs_of_nonneg hnum.le]
    rw [hn,Rat.num_div_den]
  have ha : 0<x.num.natAbs := Int.natAbs_pos.mpr hnum.ne'
  have hab : x.num.natAbs≤x.den := by
    have hd : (0 : ℚ)<x.den := by exact_mod_cast x.den_pos
    have hh : (x.num.natAbs : ℚ)≤x.den := (div_le_one hd).mp (by rwa [hxcast])
    exact_mod_cast hh
  obtain ⟨M⟩ := all_models x.den x.num.natAbs ha hab
  have he : α=2-(x.num.natAbs : ℚ)/x.den := by rw [hxcast]; dsimp only [x]; ring
  rw [he]
  exact RootedUpperModels.realization M ha hab

end UniversalHubModels

end -- UniversalHubModels

open Filter SimpleGraph

namespace Erdos571

/--
Show that for any rational $\alpha \in [1,2)$ there exists a bipartite graph $G$ such that\[\mathrm{ex}(n;G)\asymp n^{\alpha}.\]
-/
theorem erdos_571 :
    ∀ α : ℚ, 1 ≤ α → α < 2 →
      ∃ q : ℕ, ∃ G : SimpleGraph (Fin q), G.IsBipartite ∧
        Asymptotics.IsTheta atTop
          (fun n : ℕ => (extremalNumber n G : ℝ))
          (fun n : ℕ => (n : ℝ) ^ (α : ℝ)) := by
  exact UniversalHubModels.result

end Erdos571


/- Canonical Jig330 formulation and an independently checked equivalence bridge. -/

namespace Jig330Canonical
open SimpleGraph Filter

def HasTuranExponent (α : ℝ) : Prop :=
  ∃ v : ℕ, ∃ G : SimpleGraph (Fin v),
    G.IsBipartite ∧
    ∃ c C : ℝ, 0 < c ∧ 0 < C ∧
      ∃ N : ℕ, ∀ n : ℕ, N ≤ n →
        (∀ H : SimpleGraph (Fin n), ¬G ⊑ H →
          (H.edgeSet.ncard : ℝ) ≤ C * (n : ℝ) ^ α) ∧
        ∃ H : SimpleGraph (Fin n), ¬G ⊑ H ∧
          c * (n : ℝ) ^ α ≤ (H.edgeSet.ncard : ℝ)

abbrev statement : Prop :=
  ∀ α : ℚ, 1 ≤ α → α < 2 → HasTuranExponent (α : ℝ)

lemma hasTuranExponent_of_theta {α : ℝ} {v : ℕ} (G : SimpleGraph (Fin v))
    (hG : G.IsBipartite)
    (hΘ : Asymptotics.IsTheta atTop
      (fun n : ℕ => (extremalNumber n G : ℝ)) (fun n : ℕ => (n : ℝ) ^ α)) :
    HasTuranExponent α := by
  classical
  obtain ⟨C, hC, hu⟩ := hΘ.1.exists_pos
  obtain ⟨D, hD, hl⟩ := hΘ.2.exists_pos
  obtain ⟨N, hN⟩ := eventually_atTop.mp (hu.bound.and hl.bound)
  refine ⟨v, G, hG, (2 * D)⁻¹, C, by positivity, hC, max N 1, ?_⟩
  intro n hn
  obtain ⟨hu, hl⟩ := hN n (le_trans (le_max_left _ _) hn)
  have hn1 : 1 ≤ n := le_trans (le_max_right _ _) hn
  have hnpos : (0 : ℝ) < n := by exact_mod_cast hn1
  have hpow : 0 < (n : ℝ) ^ α := Real.rpow_pos_of_pos hnpos _
  simp only [Real.norm_eq_abs, Nat.abs_cast,
    abs_of_pos hpow] at hu hl
  constructor
  · intro H hH
    have he : H.edgeFinset.card ≤ extremalNumber n G := by
      simpa only [Fintype.card_fin] using card_edgeFinset_le_extremalNumber hH
    have hncard : H.edgeSet.ncard = H.edgeFinset.card := by
      rw [← coe_edgeFinset, Set.ncard_coe_finset]
    rw [hncard]
    exact le_trans (by exact_mod_cast he) hu
  · have hlt : (2 * D)⁻¹ * (n : ℝ) ^ α < (extremalNumber n G : ℝ) := by
      have hhalf : (2 * D)⁻¹ * (n : ℝ) ^ α < D⁻¹ * (n : ℝ) ^ α := by
        apply mul_lt_mul_of_pos_right _ hpow
        exact (inv_lt_inv₀ (by positivity) hD).mpr (by nlinarith)
      exact lt_of_lt_of_le hhalf ((inv_mul_le_iff₀ hD).mpr hl)
    obtain ⟨H, inst, hfree, hedge⟩ :=
      (lt_extremalNumber_iff_of_nonneg (V := Fin n) G
        (show (0 : ℝ) ≤ (2 * D)⁻¹ * (n : ℝ) ^ α by positivity)).mp
          (by simpa only [Fintype.card_fin] using hlt)
    refine ⟨H, hfree, ?_⟩
    rw [← coe_edgeFinset, Set.ncard_coe_finset]
    exact hedge.le

end Jig330Canonical


namespace Jig330Canonical

theorem target : statement := by
  intro α hα hα₂
  obtain ⟨v, G, hG, hTheta⟩ := Erdos571.erdos_571 α hα hα₂
  exact hasTuranExponent_of_theta G hG hTheta

end Jig330Canonical



/-
UPSTREAM NOTICE (retained verbatim)

Erdős problem #571 (rational exponents for Turán numbers of bipartite graphs): proof
Copyright 2026 Tom Adamczewski / Epoch AI

The formal statement was given to the AI system by the FrontierMath Erdős benchmark of Tom Adamczewski and
Thomas F. Bloom (LeanOpenProblems,
https://github.com/epoch-research/LeanOpenProblems, commit 77882c437ca1dfefab3b27fa00f1d29788100311), Epoch AI, MIT License.
The Lean proofs were produced by a pre-release version of GPT-6 Astra (OpenAI) running in that benchmark.

UPSTREAM APACHE-2.0 LICENSE (retained verbatim)

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

-/

namespace Submissions.Erdos571TuranExponents.EpochPort
theorem proof : Jig330Canonical.statement := Jig330Canonical.target
end Submissions.Erdos571TuranExponents.EpochPort
EpochPort.lean
StatementUserModelHarnessTime
Kernel-checked
2)V2The rational endpoint α=1 lies in the conjecture's interval [1,2).
@woshuajolk
GPT 5.6 Sol
Cursor
8/25/26
Prior art
1)V3For every rational α with 1≤α<2, there is one finite bipartite graph G and positive constants c,C such that e…
@woshuajolk
+1
GPT 5.6 Sol
Cursor
8/25/26