Documentation

Complexity.Computability.Circuit.Rational.Runtime.HermiteCramer

Executable confluent Hermite Cramer recovery #

Executable list-of-rows builders and plain Turing.MultiTapeTM.ComputableInPolyTime certificates for recovering the integer constant term H(0) = (H_zero : ℚ) of a rational polynomial H ∈ ℚ[X] with H.natDegree < N (N = nodes.length * J) from a nodes.length × J table jets (jets.length = nodes.length, each row of length J) of integer-scaled order-J Taylor jets Ω · [z ^ j] H(t_i + z) with nonzero scale Ω ≠ 0 at distinct integer nodes nodes = [t_0, …, t_{Q-1}] (nodes.Nodup).

Following Appendix B.3, equation (B.1), of [OAI26c], hermiteRows nodes J tabulates the N × N integer confluent Vandermonde matrix V (Polynomial.hermiteMatrix), cramerColZeroRows replaces column 0 with the flattened scaled jet vector b = Ω y to form V_{(0)}, and hermiteRecoverZero evaluates N_H = detRows V_{(0)} and D_H = detRows V via the division-free staged determinant of Complexity/Computability/Circuit/Rational/Runtime/Determinant.lean before performing the single total integer division N_H / (Ω · D_H) (Int.ediv, exact when nodes.Nodup and Ω ≠ 0, and returning 0 when Ω = 0 or D_H = 0). hermiteRecoverModPowTwo composes this recovery with Int.modPowTwo to extract bounded counts modulo 2 ^ ℓ.

Main definitions #

Main results #

References #

Executable list-of-rows builders #

The (nodes.length * J) × (nodes.length * J) integer confluent Vandermonde (Hermite) matrix at nodes of uniform order J, stored in row-major (node, jet-order) order: row i * J + j and column m holds (m.choose j : ℤ) * nodes[i] ^ (m - j), which vanishes for m < j.

Instances For

    Replace column 0 of each row k of mat with rhs.getD k 0, keeping the tail of each row unchanged.

    Instances For
      def Cslib.Circuits.Rational.hermiteRecoverZero (nodes : List ℤ) (J : ℕ) (Ω : ℤ) (jets : List (List ℤ)) :

      Recover the integer value H(0) = (H_zero : ℚ) of H ∈ ℚ[X] with H.natDegree < nodes.length * J from a nodes.length × J table jets (jets.length = nodes.length, each row of length J) of its Ω-scaled order-J Taylor jets with nonzero scale Ω ≠ 0 at distinct integer nodes (nodes.Nodup), via Cramer's rule, detRows, and total Int.ediv (returning 0 when Ω = 0 or detRows (hermiteRows nodes J) = 0; see hermiteRecoverZero_eq).

      Instances For
        def Cslib.Circuits.Rational.hermiteRecoverModPowTwo (nodes : List ℤ) (J ℓ : ℕ) (Ω : ℤ) (jets : List (List ℤ)) :

        Recover the least nonnegative residue of integer H(0) modulo 2 ^ ℓ from Ω-scaled order-J Taylor jets jets under the hypotheses of hermiteRecoverZero_eq (nodes.Nodup, Ω ≠ 0, H.natDegree < nodes.length * J, integer H(0), and nodes.length × J jet shape; see hermiteRecoverModPowTwo_eq).

        Instances For

          Shape and well-formedness #

          @[simp]

          hermiteRows nodes J has nodes.length * J rows.

          theorem Cslib.Circuits.Rational.length_of_mem_hermiteRows {nodes : List ℤ} {J : ℕ} {row : List ℤ} (hrow : row ∈ hermiteRows nodes J) :
          row.length = nodes.length * J

          Every row of hermiteRows nodes J has length nodes.length * J.

          @[simp]

          cramerColZeroRows mat rhs preserves the number of rows of mat.

          theorem Cslib.Circuits.Rational.length_of_mem_cramerColZeroRows {mat : List (List ℤ)} {rhs : List ℤ} (hmat : ∀ r ∈ mat, r.length = mat.length) {row : List ℤ} (hrow : row ∈ cramerColZeroRows mat rhs) :
          row.length = mat.length

          If every row of mat has length mat.length, then every row of cramerColZeroRows mat rhs has length mat.length.

          theorem Cslib.Circuits.Rational.length_of_mem_cramerColZeroRows_hermiteRows {nodes : List ℤ} {J : ℕ} {rhs row : List ℤ} (hrow : row ∈ cramerColZeroRows (hermiteRows nodes J) rhs) :
          row.length = nodes.length * J

          Every row of cramerColZeroRows (hermiteRows nodes J) rhs has length nodes.length * J.

          Agreement with Polynomial.hermiteMatrix and Matrix.updateCol #

          theorem Cslib.Circuits.Rational.rowEntry_hermiteRows (nodes : List ℤ) (J : ℕ) (r c : Fin nodes.length × Fin J) :
          rowEntry (hermiteRows nodes J) ↑(finProdFinEquiv r) ↑(finProdFinEquiv c) = Polynomial.hermiteMatrix (fun (i : Fin nodes.length) => nodes[i]) J r c

          Entry (finProdFinEquiv r, finProdFinEquiv c) of hermiteRows nodes J equals entry (r, c) of Polynomial.hermiteMatrix.

          ofRows (hermiteRows nodes J) is Polynomial.hermiteMatrix reindexed along finProdFinEquiv.

          theorem Cslib.Circuits.Rational.detRows_hermiteRows (nodes : List ℤ) (J : ℕ) :
          detRows (hermiteRows nodes J) = (Polynomial.hermiteMatrix (fun (i : Fin nodes.length) => nodes[i]) J).det

          detRows (hermiteRows nodes J) equals the determinant of Polynomial.hermiteMatrix.

          theorem Cslib.Circuits.Rational.detRows_hermiteRows_ne_zero {nodes : List ℤ} (hnodup : nodes.Nodup) (J : ℕ) :
          detRows (hermiteRows nodes J) ≠ 0

          At distinct integer nodes (nodes.Nodup), detRows (hermiteRows nodes J) is nonzero.

          theorem Cslib.Circuits.Rational.rowEntry_cramerColZeroRows (mat : List (List ℤ)) (rhs : List ℤ) {i : ℕ} (hi : i < mat.length) (j : ℕ) :
          rowEntry (cramerColZeroRows mat rhs) i j = if j = 0 then rhs.getD i 0 else rowEntry mat i j

          Looking up entry (i, j) of cramerColZeroRows mat rhs for i < mat.length returns rhs.getD i 0 in column 0 and rowEntry mat i j in columns j > 0.

          theorem Cslib.Circuits.Rational.ofRows_cramerColZeroRows (mat : List (List ℤ)) (rhs : List ℤ) (h0 : 0 < mat.length) :
          ofRows (cramerColZeroRows mat rhs) = (Matrix.reindex (finCongr ⋯) (finCongr ⋯)) ((ofRows mat).updateCol ⟨0, h0⟩ fun (i : Fin mat.length) => rhs.getD (↑i) 0)

          For nonempty mat, ofRows (cramerColZeroRows mat rhs) is (ofRows mat).updateCol 0 reindexed along length_cramerColZeroRows.

          theorem Cslib.Circuits.Rational.detRows_cramerColZeroRows (mat : List (List ℤ)) (rhs : List ℤ) (h0 : 0 < mat.length) :
          detRows (cramerColZeroRows mat rhs) = ((ofRows mat).updateCol ⟨0, h0⟩ fun (i : Fin mat.length) => rhs.getD (↑i) 0).det

          detRows (cramerColZeroRows mat rhs) is the determinant of ofRows mat with column 0 replaced by rhs.

          theorem Cslib.Circuits.Rational.detRows_cramerColZeroRows_hermiteRows (nodes : List ℤ) (J : ℕ) (jets : List (List ℤ)) (hQ : 0 < nodes.length) (hJ : 0 < J) (hjets_len : jets.length = nodes.length) (hjets_row : ∀ row ∈ jets, row.length = J) :
          detRows (cramerColZeroRows (hermiteRows nodes J) jets.flatten) = ((Polynomial.hermiteMatrix (fun (i : Fin nodes.length) => nodes[i]) J).updateCol (⟨0, hQ⟩, ⟨0, hJ⟩) fun (r : Fin nodes.length × Fin J) => rowEntry jets ↑r.1 ↑r.2).det

          detRows of cramerColZeroRows (hermiteRows nodes J) jets.flatten equals the determinant of Polynomial.hermiteMatrix with column (0, 0) replaced by (i, j) ↦ rowEntry jets i j.

          Exact Cramer recovery of H(0) #

          theorem Cslib.Circuits.Rational.detRows_cramerColZeroRows_eq_mul_eval_zero {nodes : List ℤ} {J : ℕ} {Ω H_zero : ℤ} {jets : List (List ℤ)} {H : Polynomial ℚ} (hdeg : H.natDegree < nodes.length * J) (hH0 : Polynomial.eval 0 H = ↑H_zero) (hjets_len : jets.length = nodes.length) (hjets_row : ∀ row ∈ jets, row.length = J) (hjets : ∀ (i : Fin nodes.length) (j : Fin J), ↑(rowEntry jets ↑i ↑j) = ↑Ω * ((Polynomial.taylor ↑nodes[i]) H).coeff ↑j) :
          detRows (cramerColZeroRows (hermiteRows nodes J) jets.flatten) = Ω * detRows (hermiteRows nodes J) * H_zero

          Exact integer Cramer identity for scaled Taylor jets: without any distinctness or nonzero-scale assumption, detRows (cramerColZeroRows (hermiteRows nodes J) jets.flatten) equals (Ω * detRows (hermiteRows nodes J)) * H_zero.

          theorem Cslib.Circuits.Rational.hermiteRecoverZero_eq_of_rowEntry {nodes : List ℤ} {J : ℕ} {Ω H_zero : ℤ} {jets : List (List ℤ)} {H : Polynomial ℚ} (hnodup : nodes.Nodup) (hΩ : Ω ≠ 0) (hdeg : H.natDegree < nodes.length * J) (hH0 : Polynomial.eval 0 H = ↑H_zero) (hjets_len : jets.length = nodes.length) (hjets_row : ∀ row ∈ jets, row.length = J) (hjets : ∀ (i : Fin nodes.length) (j : Fin J), ↑(rowEntry jets ↑i ↑j) = ↑Ω * ((Polynomial.taylor ↑nodes[i]) H).coeff ↑j) :
          hermiteRecoverZero nodes J Ω jets = H_zero

          Exact confluent Hermite Cramer recovery (rowEntry form). When nodes are distinct, Ω ≠ 0, H ∈ ℚ[X] has natDegree < nodes.length * J and integer value H(0) = H_zero, and jets holds the Ω-scaled order-J Taylor jets at nodes, hermiteRecoverZero returns H_zero.

          theorem Cslib.Circuits.Rational.hermiteRecoverZero_eq {nodes : List ℤ} {J : ℕ} {Ω H_zero : ℤ} {jets : List (List ℤ)} {H : Polynomial ℚ} (hnodup : nodes.Nodup) (hΩ : Ω ≠ 0) (hdeg : H.natDegree < nodes.length * J) (hH0 : Polynomial.eval 0 H = ↑H_zero) (hjets_len : jets.length = nodes.length) (hjets_row : ∀ row ∈ jets, row.length = J) (hjets : ∀ (i : Fin nodes.length) (j : Fin J), have hi := ⋯; have hj := ⋯; ↑jets[↑i][↑j] = ↑Ω * ((Polynomial.taylor ↑nodes[i]) H).coeff ↑j) :
          hermiteRecoverZero nodes J Ω jets = H_zero

          Exact confluent Hermite Cramer recovery (getElem form, [OAI26c] eq. (B.1)).

          theorem Cslib.Circuits.Rational.hermiteRecoverModPowTwo_eq {nodes : List ℤ} {J ℓ : ℕ} {Ω H_zero count : ℤ} {jets : List (List ℤ)} {H : Polynomial ℚ} (hnodup : nodes.Nodup) (hΩ : Ω ≠ 0) (hdeg : H.natDegree < nodes.length * J) (hH0 : Polynomial.eval 0 H = ↑H_zero) (hjets_len : jets.length = nodes.length) (hjets_row : ∀ row ∈ jets, row.length = J) (hjets : ∀ (i : Fin nodes.length) (j : Fin J), ↑(rowEntry jets ↑i ↑j) = ↑Ω * ((Polynomial.taylor ↑nodes[i]) H).coeff ↑j) (hcount₀ : 0 ≤ count) (hcount₁ : count < 2 ^ ℓ) (hdvd : 2 ^ ℓ ∣ H_zero - count) :
          hermiteRecoverModPowTwo nodes J ℓ Ω jets = count

          Modular recovery of a count count ∈ [0, 2 ^ ℓ) congruent to H(0) modulo 2 ^ ℓ.

          theorem Cslib.Circuits.Rational.modPowTwo_sum_hermiteRecoverZero_eq {nodes : List ℤ} {J ℓ : ℕ} {Ω count : ℤ} {coordJets : List (List (List ℤ))} {Hs : List (Polynomial ℚ)} {H_zeros : List ℤ} (hnodup : nodes.Nodup) (hΩ : Ω ≠ 0) (hlen_H : Hs.length = coordJets.length) (hlen_Z : H_zeros.length = coordJets.length) (hcoord : ∀ (s : Fin coordJets.length), have hsH := ⋯; have hsZ := ⋯; Hs[↑s].natDegree < nodes.length * J ∧ Polynomial.eval 0 Hs[↑s] = ↑H_zeros[↑s] ∧ coordJets[s].length = nodes.length ∧ (∀ row ∈ coordJets[s], row.length = J) ∧ ∀ (i : Fin nodes.length) (j : Fin J), ↑(rowEntry coordJets[s] ↑i ↑j) = ↑Ω * ((Polynomial.taylor ↑nodes[i]) Hs[↑s]).coeff ↑j) (hcount₀ : 0 ≤ count) (hcount₁ : count < 2 ^ ℓ) (hdvd : 2 ^ ℓ ∣ H_zeros.sum - count) :
          (List.map (hermiteRecoverZero nodes J Ω) coordJets).sum.modPowTwo ℓ = count

          Multi-coordinate count recovery modulo 2 ^ ℓ ([OAI26c], Appendix B.3): summing the recovered integer constant terms H_s(0) across coordinates and reducing modulo 2 ^ ℓ yields count whenever 0 ≤ count < 2 ^ ℓ and 2 ^ ℓ ∣ ∑_s H_s(0) - count.

          Entry magnitude and bit-length bounds #

          Truncated integer division never increases the sign-magnitude bit length of the dividend.

          Euclidean integer division never increases the sign-magnitude bit length of the dividend.

          For a nonzero divisor b, the Euclidean remainder a.emod b has sign-magnitude bit length at most intBits b.

          For a nonzero divisor b, intBits (a.emod b) ≤ intBits b + 1.

          Unconditionally on b (including b = 0), intBits (a.emod b) ≤ max (intBits a) (intBits b).

          Reducing modulo 2 ^ ℓ produces an integer of sign-magnitude bit length at most ℓ + 1.

          theorem Cslib.Circuits.Rational.natAbs_lt_of_mem_hermiteRows {nodes : List ℤ} {J b : ℕ} (hnodes : ∀ t ∈ nodes, t.natAbs < 2 ^ b) {row : List ℤ} (hrow : row ∈ hermiteRows nodes J) {z : ℤ} (hz : z ∈ row) :
          z.natAbs < 2 ^ (nodes.length * J * (b + 1))

          If every node in nodes has magnitude below 2 ^ b, then every entry of hermiteRows nodes J has magnitude strictly below 2 ^ ((nodes.length * J) * (b + 1)).

          theorem Cslib.Circuits.Rational.intBits_le_of_mem_hermiteRows {nodes : List ℤ} {J b : ℕ} (hnodes : ∀ t ∈ nodes, intBits t ≤ b + 1) {row : List ℤ} (hrow : row ∈ hermiteRows nodes J) {z : ℤ} (hz : z ∈ row) :
          intBits z ≤ nodes.length * J * (b + 1) + 1

          Entry bit-length bound for hermiteRows: if every node has intBits t ≤ b + 1, then every entry z of hermiteRows nodes J satisfies intBits z ≤ (nodes.length * J) * (b + 1) + 1.

          theorem Cslib.Circuits.Rational.intBits_le_of_mem_cramerColZeroRows {mat : List (List ℤ)} {rhs : List ℤ} {B : ℕ} (hmat : ∀ row ∈ mat, ∀ z ∈ row, intBits z ≤ B + 1) (hrhs : ∀ w ∈ rhs, intBits w ≤ B + 1) {row : List ℤ} (hrow : row ∈ cramerColZeroRows mat rhs) {z : ℤ} (hz : z ∈ row) :
          intBits z ≤ B + 1

          Entry bit-length bound for cramerColZeroRows: replacing column 0 with rhs preserves any common bit-length bound on mat and rhs.

          Plain polynomial-time certificates #

          Constructing hermiteRows (nodes x) (J x) from binary integer nodes and a unary order J is computable in polynomial time.

          Recovering a coordinate sum ∑_s H_s(0) mod 2 ^ ℓ across a list of scaled jet tables sharing nodes, J, and Ω ([OAI26c], Appendix B.3) is computable in polynomial time.