Lean sources / SurfaceBlowup / Algebra / FactorInvariant.lean

Invariance of factor invariants and uniqueness of algebra types

324 lines · 6 public declarations · raw file · declaration index

1/-2Copyright (c) 2026 Asvin G, Claude (Anthropic), GPT-6-Astra (OpenAI). All rights reserved.3Released under Apache 2.0 license as described in the file LICENSE.4Authors: Asvin G, Claude (Anthropic), GPT-6-Astra (OpenAI)5-/6import SurfaceBlowup.Measure.PrimitiveLocus7import SurfaceBlowup.Unramified.FactorCells8 9/-!10# Invariance of factor invariants and uniqueness of algebra types11 12Over a complete DVR `O` with finite residue field and fraction field `K = BaseField O`, the13invariants `(e, f)` of the integral closure of `O` in a finite extension `L/K` depend only on the14`K`-isomorphism class of `L`. Consequences: polynomial types are invariant under normalized15reversal `g ↦ g(0)⁻¹ · reverse g`, algebra types are unique, and a monic `F ∈ O[X]` has polynomial16type `σ` over `K` exactly when `O[X]/(F)` has algebra type `σ`.17 18## Main results19 20* `SurfaceBlowup.field_invariant_algEquiv`, `SurfaceBlowup.factor_invariant_algEquiv`21* `SurfaceBlowup.reverse_normalized_irreducible`, `SurfaceBlowup.reverse_polynomial_type_iff`22* `SurfaceBlowup.algebra_type_unique`, `SurfaceBlowup.polynomial_type_iff_algebra_type`23 24Provenance: Thm_SurfaceBlowupV2_{factor_invariant_algEquiv, reverse_normalized_irreducible,25reverse_polynomial_type_iff, field_invariant_algEquiv, algebra_type_unique,26polynomial_type_iff_algebra_type}.27-/28 29namespace SurfaceBlowup30 31open Polynomial32 33/-! ### Invariance under isomorphism -/34 35/-- The invariants `(e, f)` of the integral closure of `O` in a finite extension `L/K` (assumed36finite over `O`) depend only on the `K`-isomorphism class of `L`. -/37theorem field_invariant_algEquiv (O : Type) [CommRing O] [IsDomain O]38    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]39    [Finite (IsLocalRing.ResidueField O)] (L L' : Type) [Field L] [Field L']40    [Algebra (BaseField O) L] [Algebra O L] [IsScalarTower O (BaseField O) L]41    [FiniteDimensional (BaseField O) L] [Algebra (BaseField O) L'] [Algebra O L']42    [IsScalarTower O (BaseField O) L'] [FiniteDimensional (BaseField O) L']43    (e : L ≃ₐ[BaseField O] L') (hfin : Module.Finite O (integralClosure O L)) :44    fieldInvariant O L = fieldInvariant O L' := by45  obtain ⟨φ, -⟩ := integral_closure_algEquiv O L L' (e.restrictScalars O)46  have : Module.Finite O (integralClosure O L') := .equiv φ.toLinearEquiv47  have h1 := integral_closure_is_local O (BaseField O) L48  have h2 := integral_closure_is_local O (BaseField O) L'49  have := integral_closure_is_dvr O (BaseField O) L50  have := integral_closure_is_dvr O (BaseField O) L'51  obtain ⟨hr, hi⟩ := dvr_algEquiv_ramification_inertia O _ _52    (algebraMap_injective_of_tower O _ L) (algebraMap_injective_of_tower O _ L') φ53  unfold fieldInvariant54  rw [dif_pos h1, dif_pos h2, hr, hi]55 56/-- `K`-isomorphic root fields of monic irreducibles `g, g'` (with finite closure) have the same57factor invariant. -/58theorem factor_invariant_algEquiv (O : Type) [CommRing O] [IsDomain O]59    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]60    [Finite (IsLocalRing.ResidueField O)] (g g' : Polynomial (BaseField O)) (hg : g.Monic)61    (hirr : Irreducible g) (hg' : g'.Monic) (hirr' : Irreducible g')62    (e : AdjoinRoot g ≃ₐ[BaseField O] AdjoinRoot g')63    (hfin : Module.Finite O (integralClosure O (AdjoinRoot g))) :64    factorInvariant O g = factorInvariant O g' := by65  have : Fact (Irreducible g) := ⟨hirr⟩66  have : Fact (Irreducible g') := ⟨hirr'⟩67  have : Module.Finite (BaseField O) (AdjoinRoot g) := hg.finite_adjoinRoot68  have : Module.Finite (BaseField O) (AdjoinRoot g') := hg'.finite_adjoinRoot69  exact field_invariant_algEquiv O _ _ e hfin70 71/-! ### Normalized reversal -/72 73section Reverse74 75variable {K : Type} [Field K]76 77/-- The normalized reversal `f(0)⁻¹ · reverse f`. -/78private noncomputable def rho (f : K[X]) : K[X] := C (f.coeff 0)⁻¹ * f.reverse79 80private theorem rho_mul (f g : K[X]) : rho (f * g) = rho f * rho g := by81  unfold rho82  rw [mul_coeff_zero, reverse_mul_of_domain, mul_inv, C_mul]83  ring84 85private theorem rho_prod (gs : List K[X]) : rho gs.prod = (gs.map rho).prod := by86  induction gs with87  | nil => simp [rho, reverse]88  | cons g gs ih => rw [List.prod_cons, rho_mul, ih, List.map_cons, List.prod_cons]89 90private theorem reverse_reverse_of (f : K[X]) (h0 : f.coeff 0 ≠ 0) : f.reverse.reverse = f := by91  have hd : f.reverse.natDegree = f.natDegree := by92    rw [reverse_natDegree, natTrailingDegree_eq_zero_of_constantCoeff_ne_zero h0, Nat.sub_zero]93  ext n94  rw [coeff_reverse, coeff_reverse, hd, revAt_invol]95 96private theorem rho_coeff_zero {f : K[X]} (hf : f.Monic) : (rho f).coeff 0 = (f.coeff 0)⁻¹ := by97  rw [rho, coeff_C_mul, coeff_zero_reverse, hf.leadingCoeff, mul_one]98 99private theorem rho_rho (f : K[X]) (hf : f.Monic) (h0 : f.coeff 0 ≠ 0) : rho (rho f) = f := by100  rw [rho, rho_coeff_zero hf, inv_inv, rho, reverse_mul_of_domain, reverse_reverse_of f h0,101    show (C (f.coeff 0)⁻¹).reverse = C (f.coeff 0)⁻¹ by simp [reverse], ← mul_assoc, ← C_mul,102    mul_inv_cancel₀ h0, C_1, one_mul]103 104end Reverse105 106/-- For a monic irreducible `g` with `g(0) ≠ 0` and finite closure, its normalized reversal107`h = g(0)⁻¹ · reverse g` is monic irreducible of the same degree with `h(0) = g(0)⁻¹`, has the108same factor invariant and finite closure, and normalized reversal of `h` gives back `g`. -/109theorem reverse_normalized_irreducible (O : Type) [CommRing O] [IsDomain O]110    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]111    [Finite (IsLocalRing.ResidueField O)] (g : Polynomial (BaseField O)) (hg : g.Monic)112    (hgi : Irreducible g) (h0 : g.coeff 0 ≠ 0)113    (hfin : Module.Finite O (integralClosure O (AdjoinRoot g))) :114    (C (g.coeff 0)⁻¹ * g.reverse).Monic115      ∧ Irreducible (C (g.coeff 0)⁻¹ * g.reverse)116      ∧ (C (g.coeff 0)⁻¹ * g.reverse).natDegree = g.natDegree117      ∧ (C (g.coeff 0)⁻¹ * g.reverse).coeff 0 = (g.coeff 0)⁻¹118      ∧ factorInvariant O (C (g.coeff 0)⁻¹ * g.reverse) = factorInvariant O g119      ∧ C ((C (g.coeff 0)⁻¹ * g.reverse).coeff 0)⁻¹ * (C (g.coeff 0)⁻¹ * g.reverse).reverse =120        g121      ∧ Module.Finite O (integralClosure O (AdjoinRoot (C (g.coeff 0)⁻¹ * g.reverse))) := by122  set K := BaseField O123  set c := g.coeff 0124  set h := C c⁻¹ * g.reverse with hh125  have hr : 0 < g.natDegree := natDegree_pos_iff_degree_pos.mpr (degree_pos_of_irreducible hgi)126  have hrevdeg : g.reverse.natDegree = g.natDegree := by127    rw [reverse_natDegree, natTrailingDegree_eq_zero_of_constantCoeff_ne_zero h0, Nat.sub_zero]128  have hdeg : h.natDegree = g.natDegree := by rw [hh, natDegree_C_mul (inv_ne_zero h0), hrevdeg]129  have hmon : h.Monic := by130    rw [Monic, hh, leadingCoeff_mul, leadingCoeff_C, reverse_leadingCoeff,131      trailingCoeff_eq_coeff_zero h0, inv_mul_cancel₀ h0]132  have hcoeff0 : h.coeff 0 = c⁻¹ := rho_coeff_zero hg133  have hgrev : g.reverse = C c * h := by134    rw [hh, ← mul_assoc, ← C_mul, mul_inv_cancel₀ h0, C_1, one_mul]135  -- the root field `K[X]/(h)` is isomorphic to `K[X]/(g)`, via the inverse of the root of `h`136  have hne : h ≠ 0 := hmon.ne_zero137  have : Nontrivial (AdjoinRoot h) := AdjoinRoot.nontrivial h (by138    rw [degree_eq_natDegree hne, hdeg]; exact_mod_cast hr.ne')139  set L := AdjoinRoot h140  set β : L := AdjoinRoot.root h141  have hβ : h.eval₂ (algebraMap K L) β = 0 := AdjoinRoot.eval₂_root h142  have hβinv : β * (-(algebraMap K L c) * (divX h).eval₂ (algebraMap K L) β) = 1 := by143    have e1 := congrArg (fun p ↦ p.eval₂ (algebraMap K L) β) (X_mul_divX_add h)144    simp only [eval₂_add, eval₂_mul, eval₂_X, eval₂_C, hβ, hcoeff0] at e1145    calc β * (-(algebraMap K L c) * (divX h).eval₂ (algebraMap K L) β)146        = -(algebraMap K L c) * (β * (divX h).eval₂ (algebraMap K L) β) := by ring147      _ = algebraMap K L (c * c⁻¹) := by rw [eq_neg_of_add_eq_zero_left e1, map_mul]; ring148      _ = 1 := by rw [mul_inv_cancel₀ h0, map_one]149  let _ : Invertible β := invertibleOfRightInverse _ _ hβinv150  have hgβ : g.eval₂ (algebraMap K L) (⅟β) = 0 := by151    have : Invertible (⅟β) := invertibleInvOf152    rw [← eval₂_reverse_eq_zero_iff, invOf_invOf, hgrev, eval₂_mul, hβ, mul_zero]153  have : Fact (Irreducible g) := ⟨hgi⟩154  let φ : AdjoinRoot g →ₐ[K] L := AdjoinRoot.liftAlgHom g (Algebra.ofId K L) (⅟β) hgβ155  have hinj : Function.Injective φ := φ.toRingHom.injective156  have : FiniteDimensional K (AdjoinRoot g) := (AdjoinRoot.powerBasis hg.ne_zero).finite157  have : FiniteDimensional K L := (AdjoinRoot.powerBasis hne).finite158  have hsurj : Function.Surjective φ :=159    (LinearMap.injective_iff_surjective_of_finrank_eq_finrank (f := φ.toLinearMap) (by160      rw [(AdjoinRoot.powerBasis hg.ne_zero).finrank, AdjoinRoot.powerBasis_dim,161        (AdjoinRoot.powerBasis hne).finrank, AdjoinRoot.powerBasis_dim, hdeg])).mp hinj162  let e : AdjoinRoot g ≃ₐ[K] L := AlgEquiv.ofBijective φ ⟨hinj, hsurj⟩163  have hirr : Irreducible h := (Ideal.irreducible_iff_isMaximal_span_singleton hne).mpr164    (Ideal.Quotient.maximal_of_isField _165      (MulEquiv.isField (Field.toIsField (AdjoinRoot g)) e.symm.toMulEquiv))166  obtain ⟨φ', -⟩ := integral_closure_algEquiv O _ _ (e.restrictScalars O)167  exact ⟨hmon, hirr, hdeg, hcoeff0, (factor_invariant_algEquiv O g h hg hgi hmon hirr e hfin).symm,168    rho_rho g hg h0, .equiv φ'.toLinearEquiv⟩169 170private theorem rev_type_forward (O : Type) [CommRing O] [IsDomain O]171    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]172    [Finite (IsLocalRing.ResidueField O)] (P : Polynomial (BaseField O)) (h0 : P.coeff 0 ≠ 0)173    (τ : FactorType) : HasPolynomialTypeF O P τ → HasPolynomialTypeF O (rho P) τ := by174  rintro ⟨gs, hmem, hpw, hprod, hτ, hfin⟩175  have hg0 : ∀ g ∈ gs, g.coeff 0 ≠ 0 := fun g hg hz ↦ by176    obtain ⟨Q, hQ⟩ := List.dvd_prod hg177    exact h0 (by rw [hprod, hQ, mul_coeff_zero, hz, zero_mul])178  have hrev : ∀ g ∈ gs, _ := fun g hg ↦179    reverse_normalized_irreducible O g (hmem g hg).1 (hmem g hg).2 (hg0 g hg) (hfin g hg)180  refine ⟨gs.map rho, ?_, ?_, by rw [hprod, rho_prod], ?_, ?_⟩181  · simp only [List.mem_map]182    rintro _ ⟨g, hg, rfl⟩183    exact ⟨(hrev g hg).1, (hrev g hg).2.1⟩184  · refine List.Nodup.map_on (fun a ha b hb hab ↦ ?_) hpw185    rw [← (hrev a ha).2.2.2.2.2.1, ← (hrev b hb).2.2.2.2.2.1]186    exact congrArg rho hab187  · rw [hτ, List.map_map]188    exact congrArg _ (List.map_congr_left fun g hg ↦ ((hrev g hg).2.2.2.2.1).symm)189  · simp only [List.mem_map]190    rintro _ ⟨g, hg, rfl⟩191    exact (hrev g hg).2.2.2.2.2.2192 193/-- A monic `P` with `P(0) ≠ 0` has type `τ` iff its normalized reversal does. -/194theorem reverse_polynomial_type_iff (O : Type) [CommRing O] [IsDomain O]195    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]196    [Finite (IsLocalRing.ResidueField O)] (P : Polynomial (BaseField O)) (hP : P.Monic)197    (h0 : P.coeff 0 ≠ 0) (τ : FactorType) :198    HasPolynomialTypeF O P τ ↔ HasPolynomialTypeF O (Polynomial.C (P.coeff 0)⁻¹ * P.reverse) τ :=199  ⟨rev_type_forward O P h0 τ, fun h ↦ rho_rho P hP h0 ▸200    rev_type_forward O (rho P) (by rw [rho_coeff_zero hP]; exact inv_ne_zero h0) τ h⟩201 202/-! ### Uniqueness of algebra types -/203 204/-- A `K`-algebra isomorphism between finite products of fields `∏ Lᵢ ≃ ∏ L'ⱼ` yields an injection205`φ : ι → ι'` with `Lᵢ ≃ L'_{φ i}`. -/206private theorem pi_field_matching (K : Type) [Field K] (ι ι' : Type) [Finite ι] [Finite ι']207    (L : ι → Type) [∀ i, Field (L i)] [∀ i, Algebra K (L i)]208    (L' : ι' → Type) [∀ i, Field (L' i)] [∀ i, Algebra K (L' i)]209    (f : (∀ i, L i) ≃ₐ[K] (∀ j, L' j)) :210    ∃ φ : ι → ι', Function.Injective φ ∧ ∀ i, Nonempty (L i ≃ₐ[K] L' (φ i)) := by211  classical212  have := Fintype.ofFinite ι213  have := Fintype.ofFinite ι'214  have hs : ∀ i, Function.Surjective ((Pi.evalAlgHom K L i).comp f.symm.toAlgHom) :=215    fun i x ↦ ⟨f (Pi.single i x), by simp⟩216  have hker : ∀ i, ∃ j, RingHom.ker ((Pi.evalAlgHom K L i).comp f.symm.toAlgHom) =217      RingHom.ker (Pi.evalAlgHom K L' j) := fun i ↦218    (pi_field_maximal_ideals ι' L' _).1.1 (RingHom.ker_isMaximal_of_surjective _ (hs i))219  choose φ hφ using hker220  refine ⟨φ, fun i i' h ↦ ?_, fun i ↦ ?_⟩221  · have h1 := hφ i222    rw [h] at h1223    apply (pi_field_maximal_ideals ι L ⊥).2 i i'224    ext x225    simpa [RingHom.mem_ker] using Ideal.ext_iff.1 (h1.trans (hφ i').symm) (f x)226  · exact ⟨(Ideal.quotientKerAlgEquivOfSurjective (hs i)).symm.trans227      ((Ideal.quotientEquivAlgOfEq K (hφ i)).trans228        (Ideal.quotientKerAlgEquivOfSurjective fun x ↦ ⟨Pi.single (φ i) x, by simp⟩))⟩229 230/-- The algebra type of an `O`-algebra, if it exists, is unique. -/231theorem algebra_type_unique (O : Type) [CommRing O] [IsDomain O] [IsDiscreteValuationRing O]232    [IsAdicComplete (IsLocalRing.maximalIdeal O) O] [Finite (IsLocalRing.ResidueField O)]233    (B : Type) [CommRing B] [Algebra O B] (σ τ : FactorType) (hσ : HasAlgebraType O B σ)234    (hτ : HasAlgebraType O B τ) : σ = τ := by235  obtain ⟨ι, _, L, _, _, _, _, _, e, rfl, hfinL⟩ := hσ236  obtain ⟨ι', _, L', _, _, _, _, _, e', rfl, -⟩ := hτ237  obtain ⟨φ, hφi, hφ⟩ := pi_field_matching _ ι ι' L L' (e.symm.trans e')238  obtain ⟨ψ, hψi, -⟩ := pi_field_matching _ ι' ι L' L (e'.symm.trans e)239  have hb : Function.Bijective φ := (Fintype.bijective_iff_injective_and_card φ).2240    ⟨hφi, le_antisymm (Fintype.card_le_of_injective φ hφi) (Fintype.card_le_of_injective ψ hψi)⟩241  refine (Finset.sum_congr rfl fun i _ ↦ ?_).trans (Fintype.sum_bijective φ hb _ _ fun _ ↦ rfl)242  obtain ⟨g⟩ := hφ i243  rw [field_invariant_algEquiv O (L i) (L' (φ i)) g (hfinL i)]244 245/-! ### Polynomial types versus algebra types -/246 247private theorem sum_singleton_get {α β : Type} (f : α → β) (l : List α) :248    ∑ i : Fin l.length, ({f (l.get i)} : Multiset β) = ((l.map f : List β) : Multiset β) := by249  induction l with250  | nil => simp251  | cons a l ih =>252    refine (Fin.sum_univ_succ253      (fun i : Fin (l.length + 1) ↦ ({f ((a :: l).get i)} : Multiset β))).trans ?_254    rw [show ∑ i : Fin l.length, ({f ((a :: l).get i.succ)} : Multiset β) = _ from ih]255    rfl256 257private theorem type_forward (O : Type) [CommRing O] [IsDomain O] (F : Polynomial O)258    (σ : FactorType) (h : HasPolynomialTypeF O (F.map (algebraMap O (BaseField O))) σ) :259    HasAlgebraType O (AdjoinRoot F) σ := by260  obtain ⟨gs, hgs, hd, hprod, hσ, hfinG⟩ := h261  obtain ⟨e₁, -⟩ := polynomial_quotient_product_equiv (BaseField O) gs hgs hd262  obtain ⟨e₀, -⟩ := adjoinRoot_base_change O F263  rw [hprod] at e₀264  have : ∀ i : Fin gs.length, Fact (Irreducible (gs.get i)) :=265    fun i ↦ ⟨(hgs _ (List.get_mem gs i)).2⟩266  refine ⟨Fin gs.length, inferInstance, fun i ↦ AdjoinRoot (gs.get i),267    fun i ↦ AdjoinRoot.instField, fun i ↦ inferInstance, fun i ↦ inferInstance,268    fun i ↦ inferInstance, fun i ↦ (hgs _ (List.get_mem gs i)).1.finite_adjoinRoot, e₀.trans e₁,269    ?_, fun i ↦ hfinG _ (List.get_mem gs i)⟩270  rw [hσ, ← sum_singleton_get]271  rfl272 273/-- For monic `F ∈ O[X]`, the image of `F` in `K[X]` has polynomial type `σ` iff `O[X]/(F)` has274algebra type `σ`. -/275theorem polynomial_type_iff_algebra_type (O : Type) [CommRing O] [IsDomain O]276    [IsDiscreteValuationRing O] [IsAdicComplete (IsLocalRing.maximalIdeal O) O]277    [Finite (IsLocalRing.ResidueField O)] (F : Polynomial O) (hF : F.Monic) (σ : FactorType) :278    HasPolynomialTypeF O (F.map (algebraMap O (BaseField O))) σ ↔279      HasAlgebraType O (AdjoinRoot F) σ := by280  classical281  open UniqueFactorizationMonoid in282  refine ⟨type_forward O F σ, fun h ↦ ?_⟩283  obtain ⟨e₀, -⟩ := adjoinRoot_base_change O F284  -- `K[X]/(F)` is reduced (a product of fields), so the image `G` of `F` is squarefree285  set G := F.map (algebraMap O (BaseField O))286  have hGm : G.Monic := hF.map _287  have h0 : G ≠ 0 := hGm.ne_zero288  have hsq : Squarefree G := by289    obtain ⟨ι, _, L, _, _, _, _, _, e, -, -⟩ := h290    exact squarefree_of_isReduced_adjoinRoot _ _ h0291      (isReduced_of_injective (e₀.symm.trans e).toRingHom (e₀.symm.trans e).injective)292  -- closure finiteness of each irreducible factor is read off by matching factors with the `Lᵢ`293  have hmon : ∀ g ∈ normalizedFactors G, g.Monic := fun g hg ↦ by294    rw [← normalize_normalized_factor g hg]295    exact monic_normalize (irreducible_of_normalized_factor g hg).ne_zero296  set l := (normalizedFactors G).toList with hl297  have hlm : ∀ g ∈ l, g.Monic ∧ Irreducible g := fun g hg ↦ by298    rw [hl, Multiset.mem_toList] at hg299    exact ⟨hmon g hg, irreducible_of_normalized_factor g hg⟩300  have hlnd : l.Pairwise (fun g h ↦ g ≠ h) := by301    change l.Nodup302    rw [hl, ← Multiset.coe_nodup, Multiset.coe_toList]303    exact (squarefree_iff_nodup_normalizedFactors h0).1 hsq304  have hlprod : G = l.prod := by305    rw [hl, Multiset.prod_toList]306    exact (eq_of_monic_of_associated (by simpa using monic_multiset_prod_of_monic _ id hmon) hGm307      (prod_normalizedFactors h0)).symm308  obtain ⟨e₁, -⟩ := polynomial_quotient_product_equiv (BaseField O) l hlm hlnd309  rw [hlprod] at e₀310  obtain ⟨ι, _, L, _, _, _, _, _, e, -, hfinL⟩ := id h311  have : ∀ i : Fin l.length, Fact (Irreducible (l.get i)) := fun i ↦ ⟨(hlm _ (List.get_mem l i)).2⟩312  obtain ⟨φ, -, hφ⟩ := pi_field_matching (BaseField O) (Fin l.length) ι313    (fun i ↦ AdjoinRoot (l.get i)) L (e₁.symm.trans (e₀.symm.trans e))314  have hfac : ∀ g ∈ normalizedFactors G, Module.Finite O (integralClosure O (AdjoinRoot g)) := by315    intro g hg316    obtain ⟨j, rfl⟩ := List.mem_iff_get.1 (show g ∈ l by rwa [hl, Multiset.mem_toList])317    obtain ⟨ψ⟩ := hφ j318    obtain ⟨χ, -⟩ := integral_closure_algEquiv O _ _ (ψ.restrictScalars O)319    have := hfinL (φ j)320    exact .equiv χ.symm.toLinearEquiv321  obtain ⟨τ, hτ⟩ := squarefree_monic_has_polynomial_type O G hGm hsq hfac322  rwa [algebra_type_unique O (AdjoinRoot F) σ τ h (type_forward O F τ hτ)]323 324end SurfaceBlowup