Documentation

HexBerlekampZassenhaus.FactorizationResult

theorem Hex.ZPoly.QuadraticMultifactorLiftInvariant_of_choosePrimeData (core : ZPoly) (B : Nat) (primeData : PrimeChoiceData) (hp_prime : Nat.Prime primeData.p) (hp : 1 < primeData.p) (hB : 1 B) (hcore_monic : DensePoly.Monic core) (hfactors_monic : ∀ (g : FpPoly primeData.p), g primeData.factorsModPDensePoly.Monic g) (hproduct_mod_p : (Array.map FpPoly.liftToZ primeData.factorsModP).polyProduct.congr core primeData.p) (hcoprime : QuadraticMultifactorCoprimeSplits primeData.p primeData.factorsModP.toList) (hnonempty : primeData.factorsModP.toList []) :

PrimeChoiceData-shaped wrapper around Hex.ZPoly.quadraticMultifactorLiftInvariant_of_factorsModP.

Given monic core, an admissible 1 ≤ B, and the minimal modular boundary facts about primeData.factorsModP -- per-factor monicness, product congruence modulo primeData.p, sequential split coprimality, and a nonempty witness -- this produces the recursive quadratic multifactor lift invariant on the lifted modular factors that henselLiftData consumes.

The Mathlib-free downstream theorem HexBerlekampZassenhausMathlib.henselLiftData_liftedFactor_monic already feeds this invariant into Hex.ZPoly.multifactorLiftQuadratic_each_monic.

def Hex.bhksCoeffBound (f : ZPoly) (j : Nat) :

Integer coefficient bound B_j used by the BHKS all-coefficients CLD lattice.

Equations
Instances For

    Twice the largest per-column CLD coefficient bound of f.

    Equations
    Instances For

      Integer upper bound for the production BHKS resultant contradiction.

      Writing n = degree f, the components are deliberately coarse:

      • R = 4n + n³ bounds the cut radius;

      • V = 2n · 2^(2n) · R bounds a retained LLL row coordinate;

      • E = V + V·R + 2^n·R bounds every coordinate after the full-lattice true-support adjustment;

      • C = 500 · (bhksColumnFloor f + 1) bounds every cut power and low residue, using the production selector's p ≤ 500;

      • M = (n+1)·E·C bounds every coefficient of the reconstructed auxiliary;

      • the final power term bounds the Leibniz expansion of a Sylvester matrix of size at most 2n (using (2n)! ≤ (2n)^(2n)).

      The leading 1 makes the bound strictly larger than the absolute resultant. Unlike the former paper-shaped placeholder, every component here is tied directly to the executable lattice, selector, and resultant proof.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        def Hex.ceilLogPAux (p target : Nat) :
        NatNatNatNat

        Bounded iteration finding the least exponent whose p-power reaches target.

        Equations
        Instances For
          def Hex.ceilLogP (p target : Nat) :

          Small executable ceil_log_p helper.

          For 1 < p, ceilLogP p target searches for the least visible exponent whose p-power is at least target. The degenerate p ≤ 1 case returns zero because the BHKS fast path is only used with admissible primes.

          Equations
          Instances For
            def Hex.bhksCoeffCutThreshold (p : Nat) (f : ZPoly) (j : Nat) :

            Per-coordinate BHKS precision threshold ell_j := ceil_log_p (2 * B_j + 1).

            Equations
            Instances For

              Global cap on direct classical recombination candidates.

              Shared between the engine that spends it and the prime planner that prices it: Hex.scoutPays bounds a plan's remaining recombination by this, because beyond it the direct search declines rather than continuing.

              Equations
              Instances For

                Hensel precision exponent for a Mignotte coefficient bound.

                For the Mignotte criterion p^a > 2·B, returns the smallest exponent a with p^a ≥ 2·B + 1 (equivalently p^a > 2·B). The two quantities are different; B is a magnitude on integer coefficients, a is the small exponent on the Hensel modulus p^a; and must not be conflated.

                Equations
                Instances For
                  theorem Hex.le_pow_ceilLogP {p : Nat} (hp : 2 p) (target : Nat) :
                  target p ^ ceilLogP p target

                  Correctness of ceilLogP: when 2 ≤ p, the returned exponent satisfies target ≤ p ^ ceilLogP p target.

                  This bound is consumed by precisionForCoeffBound_spec below; the strict-inequality Mignotte side condition 2 * B < p ^ precisionForCoeffBound B p follows by chaining this with the target target = 2 * B + 1.

                  theorem Hex.ceilLogP_le_of_le_pow {p : Nat} (hp : 2 p) (target a : Nat) (h : target p ^ a) :
                  ceilLogP p target a

                  Minimality of ceilLogP: when 2 ≤ p and target ≤ p ^ a, the least exponent returned by ceilLogP is at most a.

                  This is the upper-bound companion to le_pow_ceilLogP. Together they pin ceilLogP p target between the least admissible exponent and any witness a, which the BHKS period rows need to know the cut threshold ℓ_j does not exceed the ambient Hensel precision a (ℓ_j ≤ a, so the diagonal exponent a − ℓ_j is a genuine subtraction).

                  theorem Hex.pow_ceilLogP_le_mul {p target : Nat} (hp : 2 p) (htarget : 0 < target) :
                  p ^ ceilLogP p target p * target

                  The power selected by ceilLogP overshoots a positive target by at most one factor of the base. This is the upper-bound companion needed when a BHKS proof reconstructs ordinary coefficients from the high-bit lattice columns.

                  Every in-range CLD column bound is dominated by bhksColumnFloor.

                  theorem Hex.pow_bhksCoeffCutThreshold_le (f : ZPoly) {p j : Nat} (hp2 : 2 p) (hp500 : p 500) (hj : j DensePoly.natDegree f) :

                  For the production selector range p ≤ 500, every in-range cut power is bounded by the explicit C component of bhksBound.

                  theorem Hex.precisionForCoeffBound_spec {p : Nat} (hp : 2 p) (B : Nat) :

                  The executable Mignotte precision exponent satisfies the Mignotte side condition 2 * B < p ^ precisionForCoeffBound B p whenever the modulus is at least 2.

                  This is the reusable bound consumed by ForwardRecoveryInputs constructors that need to discharge the mignotte_precision field at the actual executable precision returned by henselLiftData f (precisionForCoeffBound B p).

                  Enumerate every way to partition a list of polynomials into a (selected, unselected) pair while preserving the original order in each component. Used by the exhaustive recombination search to drive the slow path.

                  Equations
                  Instances For

                    Variant of subsetSplits that forces the first element of the input list into the selected component. This is what the recombination search actually iterates over, since the head of the remaining local factors must end up in some recovered factor and tracking that explicitly avoids enumerating the same subset twice through different traversal orders.

                    Equations
                    Instances For
                      def Hex.firstSome {α β : Type} :
                      List α(αOption β)Option β

                      Return the first some produced by applying f to elements of xs in order, or none if every application is none.

                      Equations
                      Instances For

                        Public wrapper for the reassembly membership split used by downstream factor-output classifiers.

                        The repeated-part expansion fully consumed the normalization residual, so reassemblePolynomialFactors uses its expanded branch rather than the non-decomposed repeated-part fallback.

                        Equations
                        Instances For
                          theorem Hex.reassemblePolynomialFactors_mem_xPower_or_core_of_expansionComplete (d : FactorNormalizationData) (coreFactors : Array ZPoly) (factor : ZPoly) (hcomplete : reassemblyExpansionComplete d coreFactors) (hmem : factor (reassemblePolynomialFactors d coreFactors).toList) :
                          factor (xPowerFactorArray d.xPower).toList factor coreFactors.toList

                          Sharp membership split for the complete-expansion branch of reassembly.

                          When the repeated part has been completely expanded by the supplied square-free part factors, a reassembled raw factor is either an extracted X-power factor or one of the supplied factors of the square-free part. In particular, it cannot be the non-decomposed repeatedPartFactorArray fallback.

                          Sign normalization preserves nonzeroness.

                          Every collected (factor, multiplicity) entry comes from some raw factor after sign normalization. This is the theorem-level wrapper for the collectFactorMultiplicities step.

                          Every collected factorization entry has positive multiplicity.

                          Every collected factorization entry passed the recorded-factor filter.

                          The collector emits no duplicate polynomial keys.

                          theorem Hex.factorizationOfFactors_entry_mem_normalized_raw (f : ZPoly) (factors : Array ZPoly) (entry : ZPoly × Nat) (hmem : entry (factorizationOfFactors f factors).factors.toList) :
                          (raw : ZPoly), raw factors.toList entry.fst = normalizeFactorSign raw

                          Membership in a Factorization built from a raw factor array descends to membership in that raw array, up to sign normalization.

                          theorem Hex.factorizationOfFactors_entry_multiplicity_pos (f : ZPoly) (factors : Array ZPoly) (entry : ZPoly × Nat) (hmem : entry (factorizationOfFactors f factors).factors.toList) :
                          0 < entry.snd

                          Entries in a Factorization built from raw factors have positive multiplicity.

                          A Factorization built from raw factors has no duplicate polynomial keys.

                          theorem Hex.factorizationOfFactors_product_of_raw_product_of_all_recorded_normalized (f : ZPoly) (factors : Array ZPoly) (hraw : DensePoly.C (signedContentScalar f) * factors.polyProduct = f) (hnormalized : ∀ (factor : ZPoly), factor factors.toListnormalizeFactorSign factor = factor) (hrecorded : ∀ (factor : ZPoly), factor factors.toListshouldRecordPolynomialFactor factor = true) :

                          Packing a sign-normalized, fully recorded raw factor array preserves its known product.

                          Packing any raw factor array against the zero input has product zero, because the packed scalar is zero.

                          The sign-normalisation of 1 is 1. Exposed publicly so Mathlib-side per-branch umbrellas (in particular the fast-path constant arm, where the singleton primitive square-free part collapses to 1) can normalise the unit factor without re-deriving the leading-coefficient computation inline.

                          The shouldRecordPolynomialFactor filter rejects the unit 1. Exposed publicly so Mathlib-side per-branch umbrellas can contradict factorize_entry_shouldRecord directly when an entry collapses to a unit (in particular the fast-path constant arm, where the singleton primitive square-free part is 1).

                          Sign normalization fixes a polynomial with nonnegative leading coefficient.

                          Sign normalization produces a nonnegative leading coefficient.

                          Sign normalisation preserves primitivity: the if_neg branch is the identity, and the if_pos branch scales by -1, which preserves content by DensePoly.content_scale_neg_one.

                          Collected factor entries are fixed points of normalizeFactorSign.

                          Collected factor entries have positive leading coefficient.

                          Entries in a Factorization built from raw factors are fixed points of normalizeFactorSign.

                          Entries in a Factorization built from raw factors have positive leading coefficient.

                          theorem Hex.exactQuotient?_eq_some_of_mul_eq_monic_of_pos_degree {target candidate quotient : ZPoly} (hmonic : DensePoly.Monic candidate) (hdegree : 0 < DensePoly.natDegree candidate) (hmul : quotient * candidate = target) :
                          exactQuotient? target candidate = some quotient

                          Converse to exactQuotient?_product: if candidate is monic with positive degree and quotient * candidate = target, then exactQuotient? target candidate returns some quotient.

                          theorem Hex.exactQuotient?_eq_some_of_divMod_eq_of_shouldRecord {target candidate quotient : ZPoly} (hrecord : shouldRecordPolynomialFactor candidate = true) (_hdivMod : DensePoly.divMod target candidate = (quotient, 0)) (hmul : quotient * candidate = target) :
                          exactQuotient? target candidate = some quotient

                          Non-monic packaging companion for exactQuotient?_product.

                          For non-monic integer polynomials, an exact product equation alone does not identify the executable quotient: DensePoly.divMod performs coefficient division in , so downstream proofs must also supply the concrete divMod result. This lemma records the remaining wrapper logic of exactQuotient?: a recorded non-unit candidate with zero executable remainder and the checked product equation is accepted with the witnessed quotient.