Documentation

HexNumberFieldTowerMathlib.FactorGeneric.Trager

Rebuilding a raw dense polynomial from its flattened coordinate arrays is the identity: Factor.polyCoords is a section of Factor.rawPoly.

theorem Hex.NumberTower.rawPoly_shiftTop (level : Level) (lower : List Level) (f : Array (Array )) (c : ) :
Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f c) = (Factor.rawPoly (level :: lower) f).compose (DensePoly.ofCoeffs #[-(Arithmetic.Coeff.ofData (level :: lower) #[c] * Factor.topGenerator level lower), 1])

The executable top-generator shift is composition with the affine polynomial X - c * α over the extended coefficient field.

theorem Hex.NumberTower.polyCoords_rawPoly_shiftTop (level : Level) (lower : List Level) (f : Array (Array )) (c : ) :
Factor.polyCoords (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f c)) = Factor.shiftTop level lower f c

Shifted coordinate arrays are already canonical: rebuilding and re-flattening a Factor.shiftTop output returns it unchanged.

theorem Hex.NumberTower.rawPoly_embedLower (level : Level) (lower : List Level) (f : Array (Array )) :
Factor.rawPoly (level :: lower) (Factor.embedLower level lower f) = DensePoly.ofCoeffs (Array.map (fun (coefficient : Array ) => Arithmetic.Coeff.ofData (level :: lower) coefficient) f)

Rebuilding an embedLower output reads its coefficients through the canonical coordinate injection into the extended tower.

theorem Hex.NumberTower.ofData_lower_eq_lowerHom (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (a : Arithmetic.Coeff lower) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; Arithmetic.Coeff.ofData (level :: lower) a.data = (Norm.lowerHom level lower hvalid hinjectiveTop) a

Zero-padding lower-tower coordinate data into the extended tower agrees with the bundled lower-coefficient embedding Norm.lowerHom.

theorem Hex.NumberTower.rawPoly_embedLower_polyCoords (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (q : DensePoly (Arithmetic.Coeff lower)) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; Factor.rawPoly (level :: lower) (Factor.embedLower level lower (Factor.polyCoords q)) = HexPolyMathlib.ofPolynomial (Polynomial.map (Norm.lowerHom level lower hvalid hinjectiveTop) (HexPolyMathlib.toPolynomial q))

Lifting a lower-tower polynomial by embedLower is, semantically, coefficientwise mapping through Norm.lowerHom.

The two-coefficient array #[-delta, 1] interprets to the affine polynomial X - C delta.

theorem Hex.NumberTower.toPolynomial_shiftTop (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : Array (Array )) (c : ) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have delta := Arithmetic.Coeff.ofData (level :: lower) #[c] * Factor.topGenerator level lower; HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f c)) = (Polynomial.taylor (-delta)) (HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) f))

Semantic polynomial translation performed by the executable top-level shift.

theorem Hex.NumberTower.shiftDelta_neg (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (c : ) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have deltaNeg := Arithmetic.Coeff.ofData (level :: lower) #[-c] * Factor.topGenerator level lower; have delta := Arithmetic.Coeff.ofData (level :: lower) #[c] * Factor.topGenerator level lower; -deltaNeg = delta

Negating the integer shift negates the shift delta c * α, so opposite shifts translate by opposite amounts.

theorem Hex.NumberTower.irreducible_shiftTop_iff (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : Array (Array )) (c : ) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; Irreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f c))) Irreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) f))

Shifting by the top generator preserves irreducibility: translation by a fixed element is a ring automorphism of the polynomial ring.

theorem Hex.NumberTower.ofData_zero_eq_zero (levels : List Level) (hvalid : LevelsValid levels) (hinjective : LevelSemantics.DenoteInjective levels) :

The canonical coordinate representative of rational zero is the coefficient-field zero.

theorem Hex.NumberTower.rawPoly_shiftTop_zero (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : DensePoly (Arithmetic.Coeff (level :: lower))) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; Factor.rawPoly (level :: lower) (Factor.shiftTop level lower (Factor.polyCoords f) 0) = f

The zero shift is the identity on rebuilt polynomials.

theorem Hex.NumberTower.toPolynomial_shiftTop_zero (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : Array (Array )) :
have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f 0)) = HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) f)

The zero shift leaves the represented polynomial unchanged.

def Hex.NumberTower.tragerNorm (level : Level) (lower : List Level) (f : DensePoly (Arithmetic.Coeff (level :: lower))) :

The lower-field polynomial produced by one unshifted Trager elimination.

Equations
Instances For
    theorem Hex.NumberTower.tragerNorm_shiftTop (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : Array (Array )) (c : ) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; tragerNorm level lower (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower f c)) = Factor.rawPoly lower (Norm.oneLevel level lower f c)

    Norming after an executable shift agrees with the shifted one-level resultant Norm.oneLevel … c, identifying the two routes to the shifted Trager norm.

    theorem Hex.NumberTower.tragerNorm_mul (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (a b : DensePoly (Arithmetic.Coeff (level :: lower))) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; tragerNorm level lower (a * b) = tragerNorm level lower a * tragerNorm level lower b

    The one-level Trager norm is multiplicative.

    theorem Hex.NumberTower.tragerNorm_lift (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (q : DensePoly (Arithmetic.Coeff lower)) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have lifted := HexPolyMathlib.ofPolynomial (Polynomial.map (Norm.lowerHom level lower hvalid hinjectiveTop) (HexPolyMathlib.toPolynomial q)); HexPolyMathlib.toPolynomial (tragerNorm level lower lifted) = HexPolyMathlib.toPolynomial q ^ level.degree

    The norm of a polynomial lifted from the lower tower is its level.degree-th power: every conjugate of the top generator contributes the same factor.

    theorem Hex.NumberTower.tragerNorm_dvd (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) {a b : DensePoly (Arithmetic.Coeff (level :: lower))} :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; HexPolyMathlib.toPolynomial a HexPolyMathlib.toPolynomial bHexPolyMathlib.toPolynomial (tragerNorm level lower a) HexPolyMathlib.toPolynomial (tragerNorm level lower b)

    The one-level Trager norm preserves divisibility of interpreted polynomials.

    theorem Hex.NumberTower.tragerNorm_not_isUnit (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : DensePoly (Arithmetic.Coeff (level :: lower))) (hdegree : 0 < f.natDegree) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; ¬IsUnit (HexPolyMathlib.toPolynomial (tragerNorm level lower f))

    The Trager norm of a nonconstant polynomial is nonconstant: a unit norm would force the input itself to be a unit.

    Monic normalisation only rescales by a unit: the interpretation of Norm.monic f is associated to the interpretation of f.

    Monic normalisation preserves the degree, including at zero.

    The monic normalisation of a nonzero executable polynomial interprets to a monic polynomial.

    Monic normalisation fixes polynomials that already interpret to monic polynomials.

    theorem Hex.NumberTower.not_two_nonunits_of_squarefree_primePower {K : Type u_1} [Field K] {N q a b : Polynomial K} {d : } (hN : Squarefree N) (hq : Irreducible q) (hNdiv : a * b N) (hqdiv : a * b q ^ d) (haUnit : ¬IsUnit a) (hbUnit : ¬IsUnit b) :

    Core counting argument for gcd recovery: a product of two nonunits cannot simultaneously divide a squarefree polynomial and a power of one irreducible, since both its irreducible factors would collapse onto that irreducible and square it inside the squarefree divisor.

    theorem Hex.NumberTower.recoveredCommon_irreducible (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (P : DensePoly (Arithmetic.Coeff (level :: lower))) (q : DensePoly (Arithmetic.Coeff lower)) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have lifted := Factor.rawPoly (level :: lower) (Factor.embedLower level lower (Factor.polyCoords q)); have common := Norm.monic (P.gcd lifted); Squarefree (HexPolyMathlib.toPolynomial (tragerNorm level lower P))Irreducible (HexPolyMathlib.toPolynomial q)0 < common.natDegreeIrreducible (HexPolyMathlib.toPolynomial common)

    Irreducibility of one recovered gcd: when the Trager norm of P is squarefree and q is an irreducible lower factor, any nonconstant monic gcd of P with the lift of q is irreducible, because its norm divides both the squarefree norm of P and the prime power q ^ level.degree.

    theorem Hex.NumberTower.recoveredFactor_irreducible (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (component lowerFactor : Array (Array )) (shift : ) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have shifted := Factor.rawPoly (level :: lower) (Factor.shiftTop level lower component shift); have q := Factor.rawPoly lower lowerFactor; have lifted := Factor.rawPoly (level :: lower) (Factor.embedLower level lower lowerFactor); have common := Norm.monic (shifted.gcd lifted); have unshifted := Factor.rawPoly (level :: lower) (Factor.shiftTop level lower (Factor.polyCoords common) (-shift)); have result := Norm.monic unshifted; Squarefree (HexPolyMathlib.toPolynomial (tragerNorm level lower shifted))Irreducible (HexPolyMathlib.toPolynomial q)Factor.polyCoords q = lowerFactor0 < common.natDegreeIrreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) (Factor.polyCoords result)))

    Irreducibility survives un-shifting and renormalising: the recovered factor produced from one accepted lower factor interprets to an irreducible polynomial over the extended tower.

    theorem Hex.NumberTower.findSquarefreeShiftAux_squarefree (level : Level) (lower : List Level) (f : Array (Array )) (start fuel : ) {shift : } {norm : Array (Array )} (h : Norm.findSquarefreeShiftAux level lower f start fuel = some (shift, norm)) :

    Any shift accepted by the bounded search passes the executable squarefreeness check on its one-level norm.

    theorem Hex.NumberTower.findSquarefreeShiftAux_norm (level : Level) (lower : List Level) (f : Array (Array )) (start fuel : ) {shift : } {norm : Array (Array )} (h : Norm.findSquarefreeShiftAux level lower f start fuel = some (shift, norm)) :
    norm = Norm.oneLevel level lower f shift

    The norm returned by the bounded search is the one-level resultant at the returned shift.

    theorem Hex.NumberTower.findSquarefreeShift_squarefree (level : Level) (lower : List Level) (f : Array (Array )) {shift : } {norm : Array (Array )} (h : Norm.findSquarefreeShift level lower f = some (shift, norm)) :

    A successful Norm.findSquarefreeShift returns a norm passing the executable squarefreeness check.

    theorem Hex.NumberTower.findSquarefreeShift_norm (level : Level) (lower : List Level) (f : Array (Array )) {shift : } {norm : Array (Array )} (h : Norm.findSquarefreeShift level lower f = some (shift, norm)) :
    norm = Norm.oneLevel level lower f shift

    A successful Norm.findSquarefreeShift returns the one-level resultant at the returned shift.

    theorem Hex.NumberTower.array_degree_pos_of_raw_degree_pos (levels : List Level) (f : Array (Array )) (hdegree : 0 < (Factor.rawPoly levels f).natDegree) :
    0 < f.size - 1

    Positive rebuilt degree forces the flattened coefficient array to have at least two entries.

    theorem Hex.NumberTower.oneLevel_degree_pos (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (f : Array (Array )) (shift : ) (hdegree : 0 < (Factor.rawPoly (level :: lower) f).natDegree) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; Squarefree (HexPolyMathlib.toPolynomial (Factor.rawPoly lower (Norm.oneLevel level lower f shift)))0 < (Factor.rawPoly lower (Norm.oneLevel level lower f shift)).natDegree

    A squarefree one-level norm of a nonconstant input is itself nonconstant, so the recursion below the top level receives a genuine factorization problem.

    The executable squarefreeness certificate is semantically sound: a polynomial passing Norm.isSquarefree interprets to a squarefree polynomial over the tower coefficient field.

    theorem Hex.NumberTower.mem_foldl_push_if {α : Type u_1} {β : Type u_2} (p : αProp) [DecidablePred p] (g : αβ) (items : List α) (init : Array β) (x : β) :
    x List.foldl (fun (out : Array β) (item : α) => if p item then out.push (g item) else out) init itemsx init itemitems, p item g item = x

    Membership inversion for a filtered push fold: an element of the result is either in the initial accumulator or the image of a passing input.

    theorem Hex.NumberTower.foldl_push_if_toList {α : Type u_1} {β : Type u_2} (p : αProp) [DecidablePred p] (g : αβ) (items : List α) (init : Array β) :
    (List.foldl (fun (out : Array β) (item : α) => if p item then out.push (g item) else out) init items).toList = init.toList ++ List.filterMap (fun (item : α) => if p item then some (g item) else none) items

    A filtered push fold materialises as the initial accumulator followed by a filterMap over the inputs.

    theorem Hex.NumberTower.filterMap_prod_associated {K : Type u_1} {α : Type u_2} [Field K] (p : αProp) [DecidablePred p] (result common : αPolynomial K) (hpass : ∀ (item : α), p itemAssociated (result item) (common item)) (hskip : ∀ (item : α), ¬p itemIsUnit (common item)) (items : List α) :
    Associated (List.filterMap (fun (item : α) => if p item then some (result item) else none) items).prod (List.map common items).prod

    Dropping unit contributions preserves the product up to a unit: if passing items have associated images and failing items map to units, the filtered product is associated to the full product.

    theorem Hex.NumberTower.taylor_list_prod {K : Type u_1} [CommRing K] (c : K) (ps : List (Polynomial K)) :

    Taylor translation distributes over a list product.

    theorem Hex.NumberTower.polynomial_squarefree_map {K : Type u_1} {L : Type u_2} [Field K] [Field L] [CharZero K] [CharZero L] (f : K →+* L) {p : Polynomial K} (hp : Squarefree p) :

    Squarefreeness transfers along field embeddings in characteristic zero, via separability.

    theorem Hex.NumberTower.recoveryGcd_eq (levels : List Level) (hvalid : LevelsValid levels) (hinjective : LevelSemantics.DenoteInjective levels) (p q : DensePoly (Arithmetic.Coeff levels)) :

    Monic recovery division preserves the exact unnormalised gcd.

    theorem Hex.NumberTower.recover_mem (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjective : LevelSemantics.DenoteInjective (level :: lower)) (shift : ) (component : Array (Array )) (lowerFactors : Array (Array (Array ))) {factor : Array (Array )} (hfactor : factor Factor.recover level lower shift component lowerFactors) :
    lowerFactorlowerFactors, have shifted := Factor.rawPoly (level :: lower) (Factor.shiftTop level lower component shift); have lifted := Factor.rawPoly (level :: lower) (Factor.embedLower level lower lowerFactor); have common := Norm.monic (shifted.gcd lifted); 0 < common.natDegree Factor.polyCoords (Norm.monic (Factor.rawPoly (level :: lower) (Factor.shiftTop level lower (Factor.polyCoords common) (-shift)))) = factor

    Membership inversion for Factor.recover: every recovered factor arises from some lower factor whose lifted gcd with the shifted component is nonconstant, by un-shifting and renormalising that gcd.

    theorem Hex.NumberTower.recover_mem_sound (level : Level) (lower : List Level) (hvalid : LevelsValid (level :: lower)) (hinjectiveTop : LevelSemantics.DenoteInjective (level :: lower)) (component : Array (Array )) (shift : ) (lowerFactors : Array (Array (Array ))) :
    have hinjectiveLower := ; have hinvLower := ; have hinvTop := ; have shifted := Factor.rawPoly (level :: lower) (Factor.shiftTop level lower component shift); Squarefree (HexPolyMathlib.toPolynomial (tragerNorm level lower shifted))(∀ lowerFactorlowerFactors, Factor.polyCoords (Factor.rawPoly lower lowerFactor) = lowerFactor Irreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly lower lowerFactor)))factorFactor.recover level lower shift component lowerFactors, Factor.polyCoords (Factor.rawPoly (level :: lower) factor) = factor Irreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly (level :: lower) factor))

    Every factor produced by Factor.recover from canonical irreducible lower factors is canonical and interprets to an irreducible polynomial over the extended tower.

    Wrapping rational coefficients as singleton coordinate arrays and reading them back is the identity.

    Over the empty tower, ofRatPoly outputs canonical coordinate arrays: rebuilding and re-flattening them is the identity for nonzero inputs.

    Rescaling a nonzero rational polynomial by the inverse of its leading coefficient interprets to a monic polynomial.

    Rescaling by the inverse leading coefficient changes the interpretation only by a unit.

    The monic rational polynomial obtained from an integer factor by reading it rationally and dividing by its leading coefficient.

    Equations
    Instances For

      The rational reading of a nonzero integer polynomial is nonzero.

      The product of monically rescaled integer factors is monic and associated to the product of their plain rational readings.

      The executable integer factor power reads rationally as the polynomial power.

      Rational reading of integer polynomials is multiplicative.

      theorem Hex.NumberTower.factorizationProduct_toPolyℚ_foldl (entries : List (ZPoly × )) (init : ZPoly) :
      HexPolyZMathlib.toPolyℚ (List.foldl (fun (product : ZPoly) (entry : ZPoly × ) => product * Factorization.factorPower entry.1 entry.2) init entries) = HexPolyZMathlib.toPolyℚ init * (List.flatMap (fun (entry : ZPoly × ) => List.replicate entry.2 (HexPolyZMathlib.toPolyℚ entry.1)) entries).prod

      The executable fold multiplying labelled integer factor powers reads rationally as the initial value times the multiplicity-expanded product of the factors.

      A Hex.Factorization reads rationally as its scalar times the multiplicity-expanded product of its factors.

      Monically rescaling the multiplicity-expanded Berlekamp-Zassenhaus factors of a nonzero integer polynomial yields a monic product associated to its rational reading.

      theorem Hex.NumberTower.normalizedRatFactor_irreducible (integer : ZPoly) (hinteger : integer 0) (entry : ZPoly × ) (hentry : entry integer.factorize.factors) :

      Each Berlekamp-Zassenhaus factor stays irreducible after monic rational rescaling: primitivity transfers integer irreducibility to by Gauss's lemma, and rescaling is associated.

      The empty-tower coordinate encoding of a monically rescaled Berlekamp-Zassenhaus factor interprets to an irreducible polynomial.

      theorem Hex.NumberTower.generatedRatFactors_sound (integer : ZPoly) (hinteger : integer 0) :
      have rawFactors := Array.flatMap (fun (entry : ZPoly × ) => Array.replicate entry.2 entry.1) integer.factorize.factors; have factors := Array.map (fun (factor : ZPoly) => have q := DensePoly.scale factor.toRatPoly.leadingCoeff⁻¹ factor.toRatPoly; Factor.ofRatPoly q) rawFactors; factorfactors, Factor.polyCoords (Factor.rawPoly [] factor) = factor Irreducible (HexPolyMathlib.toPolynomial (Factor.rawPoly [] factor))

      Every multiplicity-expanded, monically rescaled Berlekamp-Zassenhaus factor is a canonical coordinate array interpreting to an irreducible polynomial over the empty tower.

      theorem Hex.NumberTower.factorRat_mem_sound (input : DensePoly ) {factors : Array (Array (Array ))} (hresult : Factor.factorRat? input = some factors) (factor : Array (Array )) :

      Base-case soundness of the rational factorizer: every factor returned by Factor.factorRat? is canonical and interprets to an irreducible polynomial.