mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 15:23:06 +00:00
Try to simplify open_plonk and fri_combine_initial a bit more (#59)
* Try to simplify open_plonk and fri_combine_initial a bit more - Use `alpha.powers()` in `open_plonk` instead of the more "manual" approach - No more "manually" reducing with `alpha_powers`; now using helper methods for that. - Renaming & other small tweaks * Remove type hint * Feedback
This commit is contained in:
parent
72c2e19bc5
commit
60f3773a23
@ -1,5 +1,4 @@
|
||||
use anyhow::{ensure, Result};
|
||||
use itertools::izip;
|
||||
|
||||
use crate::field::extension_field::{flatten, Extendable, FieldExtension, OEF};
|
||||
use crate::field::field::Field;
|
||||
@ -156,31 +155,29 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
|
||||
let mut sum = F::Extension::ZERO;
|
||||
|
||||
// We will add three terms to `sum`:
|
||||
// - one for polynomials opened at `x` only
|
||||
// - one for polynomials opened at `x` and `g x`
|
||||
// - one for polynomials opened at `x` and its conjugate
|
||||
// - one for various polynomials which are opened at a single point `x`
|
||||
// - one for Zs, which are opened at `x` and `g x`
|
||||
// - one for wire polynomials, which are opened at `x` and its conjugate
|
||||
|
||||
let evals = [0, 1, 4]
|
||||
let single_evals = [0, 1, 4]
|
||||
.iter()
|
||||
.flat_map(|&i| proof.unsalted_evals(i, config))
|
||||
.map(|&e| F::Extension::from_basefield(e));
|
||||
let openings = os
|
||||
let single_openings = os
|
||||
.constants
|
||||
.iter()
|
||||
.chain(&os.plonk_s_sigmas)
|
||||
.chain(&os.quotient_polys);
|
||||
let numerator = izip!(evals, openings, &mut alpha_powers)
|
||||
.map(|(e, &o, a)| a * (e - o))
|
||||
.sum::<F::Extension>();
|
||||
let denominator = subgroup_x - zeta;
|
||||
sum += numerator / denominator;
|
||||
let single_diffs = single_evals.zip(single_openings).map(|(e, &o)| e - o);
|
||||
let single_numerator = reduce_with_iter(single_diffs, &mut alpha_powers);
|
||||
let single_denominator = subgroup_x - zeta;
|
||||
sum += single_numerator / single_denominator;
|
||||
|
||||
let ev: F::Extension = proof
|
||||
let zs_evals = proof
|
||||
.unsalted_evals(3, config)
|
||||
.iter()
|
||||
.zip(alpha_powers.clone())
|
||||
.map(|(&e, a)| a * e.into())
|
||||
.sum();
|
||||
.map(|&e| F::Extension::from_basefield(e));
|
||||
let zs_composition_eval = reduce_with_iter(zs_evals, alpha_powers.clone());
|
||||
let zeta_right = F::Extension::primitive_root_of_unity(degree_log) * zeta;
|
||||
let zs_interpol = interpolant(&[
|
||||
(zeta, reduce_with_iter(&os.plonk_zs, alpha_powers.clone())),
|
||||
@ -189,25 +186,24 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
|
||||
reduce_with_iter(&os.plonk_zs_right, &mut alpha_powers),
|
||||
),
|
||||
]);
|
||||
let numerator = ev - zs_interpol.eval(subgroup_x);
|
||||
let denominator = (subgroup_x - zeta) * (subgroup_x - zeta_right);
|
||||
sum += numerator / denominator;
|
||||
let zs_numerator = zs_composition_eval - zs_interpol.eval(subgroup_x);
|
||||
let zs_denominator = (subgroup_x - zeta) * (subgroup_x - zeta_right);
|
||||
sum += zs_numerator / zs_denominator;
|
||||
|
||||
let ev: F::Extension = proof
|
||||
let wire_evals = proof
|
||||
.unsalted_evals(2, config)
|
||||
.iter()
|
||||
.zip(alpha_powers.clone())
|
||||
.map(|(&e, a)| a * e.into())
|
||||
.sum();
|
||||
.map(|&e| F::Extension::from_basefield(e));
|
||||
let wire_composition_eval = reduce_with_iter(wire_evals, alpha_powers.clone());
|
||||
let zeta_frob = zeta.frobenius();
|
||||
let wire_evals_frob = os.wires.iter().map(|e| e.frobenius()).collect::<Vec<_>>();
|
||||
let wire_evals_frob = os.wires.iter().map(|e| e.frobenius());
|
||||
let wires_interpol = interpolant(&[
|
||||
(zeta, reduce_with_iter(&os.wires, alpha_powers.clone())),
|
||||
(zeta_frob, reduce_with_iter(&wire_evals_frob, alpha_powers)),
|
||||
(zeta_frob, reduce_with_iter(wire_evals_frob, alpha_powers)),
|
||||
]);
|
||||
let numerator = ev - wires_interpol.eval(subgroup_x);
|
||||
let denominator = (subgroup_x - zeta) * (subgroup_x - zeta_frob);
|
||||
sum += numerator / denominator;
|
||||
let wires_numerator = wire_composition_eval - wires_interpol.eval(subgroup_x);
|
||||
let wires_denominator = (subgroup_x - zeta) * (subgroup_x - zeta_frob);
|
||||
sum += wires_numerator / wires_denominator;
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::circuit_data::CommonCircuitData;
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::GateRef;
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
|
||||
@ -209,13 +212,26 @@ pub(crate) fn reduce_with_powers_recursive<F: Extendable<D>, const D: usize>(
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub(crate) fn reduce_with_iter<F: Field, I>(terms: &[F], coeffs: I) -> F
|
||||
where
|
||||
I: IntoIterator<Item = F>,
|
||||
{
|
||||
let mut sum = F::ZERO;
|
||||
for (&term, coeff) in terms.iter().zip(coeffs) {
|
||||
sum += coeff * term;
|
||||
}
|
||||
sum
|
||||
/// Reduce a sequence of field elements by the given coefficients.
|
||||
pub(crate) fn reduce_with_iter<F: Field>(
|
||||
terms: impl IntoIterator<Item = impl Borrow<F>>,
|
||||
coeffs: impl IntoIterator<Item = impl Borrow<F>>,
|
||||
) -> F {
|
||||
terms
|
||||
.into_iter()
|
||||
.zip(coeffs)
|
||||
.map(|(t, c)| *t.borrow() * *c.borrow())
|
||||
.sum()
|
||||
}
|
||||
|
||||
/// Reduce a sequence of polynomials by the given coefficients.
|
||||
pub(crate) fn reduce_polys_with_iter<F: Field>(
|
||||
polys: impl IntoIterator<Item = impl Borrow<PolynomialCoeffs<F>>>,
|
||||
coeffs: impl IntoIterator<Item = impl Borrow<F>>,
|
||||
) -> PolynomialCoeffs<F> {
|
||||
polys
|
||||
.into_iter()
|
||||
.zip(coeffs)
|
||||
.map(|(p, c)| p.borrow() * *c.borrow())
|
||||
.sum()
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::field::lagrange::interpolant;
|
||||
use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
||||
use crate::merkle_tree::MerkleTree;
|
||||
use crate::plonk_challenger::Challenger;
|
||||
use crate::plonk_common::reduce_with_powers;
|
||||
use crate::plonk_common::{reduce_polys_with_iter, reduce_with_iter};
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::proof::{FriProof, Hash, OpeningSet};
|
||||
use crate::timed;
|
||||
@ -90,7 +90,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
assert!(D > 1, "Not implemented for D=1.");
|
||||
let degree_log = log2_strict(commitments[0].degree);
|
||||
let g = F::Extension::primitive_root_of_unity(degree_log);
|
||||
for &p in &[zeta, g * zeta] {
|
||||
for p in &[zeta, g * zeta] {
|
||||
assert_ne!(
|
||||
p.exp(1 << degree_log as u64),
|
||||
F::Extension::ONE,
|
||||
@ -110,45 +110,34 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
challenger.observe_opening_set(&os);
|
||||
|
||||
let alpha = challenger.get_extension_challenge();
|
||||
let mut cur_alpha = F::Extension::ONE;
|
||||
let mut alpha_powers = alpha.powers();
|
||||
|
||||
// Final low-degree polynomial that goes into FRI.
|
||||
let mut final_poly = PolynomialCoeffs::empty();
|
||||
// Count the total number of polynomials accumulated into `final_poly`.
|
||||
let mut poly_count = 0;
|
||||
|
||||
// Polynomials opened at a single point.
|
||||
let composition_poly = [0, 1, 4]
|
||||
let single_polys = [0, 1, 4]
|
||||
.iter()
|
||||
.flat_map(|&i| &commitments[i].polynomials)
|
||||
.rev()
|
||||
.fold(PolynomialCoeffs::empty(), |acc, p| {
|
||||
poly_count += 1;
|
||||
&(&acc * alpha) + &p.to_extension()
|
||||
});
|
||||
let composition_eval = [&os.constants, &os.plonk_s_sigmas, &os.quotient_polys]
|
||||
.iter()
|
||||
.flat_map(|v| v.iter())
|
||||
.rev()
|
||||
.fold(F::Extension::ZERO, |acc, &e| acc * alpha + e);
|
||||
.map(|p| p.to_extension());
|
||||
let single_os = [&os.constants, &os.plonk_s_sigmas, &os.quotient_polys];
|
||||
let single_evals = single_os.iter().flat_map(|v| v.iter());
|
||||
let single_composition_poly = reduce_polys_with_iter(single_polys, alpha_powers.clone());
|
||||
let single_composition_eval = reduce_with_iter(single_evals, &mut alpha_powers);
|
||||
|
||||
let quotient = Self::compute_quotient(&[zeta], &[composition_eval], &composition_poly);
|
||||
final_poly = &final_poly + &("ient * cur_alpha);
|
||||
cur_alpha = alpha.exp(poly_count);
|
||||
let single_quotient = Self::compute_quotient(
|
||||
&[zeta],
|
||||
&[single_composition_eval],
|
||||
&single_composition_poly,
|
||||
);
|
||||
final_poly = &final_poly + &single_quotient;
|
||||
|
||||
// Zs polynomials are opened at `zeta` and `g*zeta`.
|
||||
let zs_composition_poly =
|
||||
commitments[3]
|
||||
.polynomials
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(PolynomialCoeffs::empty(), |acc, p| {
|
||||
poly_count += 1;
|
||||
&(&acc * alpha) + &p.to_extension()
|
||||
});
|
||||
let zs_polys = commitments[3].polynomials.iter().map(|p| p.to_extension());
|
||||
let zs_composition_poly = reduce_polys_with_iter(zs_polys, alpha_powers.clone());
|
||||
let zs_composition_evals = [
|
||||
reduce_with_powers(&os.plonk_zs, alpha),
|
||||
reduce_with_powers(&os.plonk_zs_right, alpha),
|
||||
reduce_with_iter(&os.plonk_zs, alpha_powers.clone()),
|
||||
reduce_with_iter(&os.plonk_zs_right, &mut alpha_powers),
|
||||
];
|
||||
|
||||
let zs_quotient = Self::compute_quotient(
|
||||
@ -156,33 +145,25 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
&zs_composition_evals,
|
||||
&zs_composition_poly,
|
||||
);
|
||||
final_poly = &final_poly + &(&zs_quotient * cur_alpha);
|
||||
cur_alpha = alpha.exp(poly_count);
|
||||
final_poly = &final_poly + &zs_quotient;
|
||||
|
||||
// When working in an extension field, need to check that wires are in the base field.
|
||||
// Check this by opening the wires polynomials at `zeta` and `zeta.frobenius()` and using the fact that
|
||||
// a polynomial `f` is over the base field iff `f(z).frobenius()=f(z.frobenius())` with high probability.
|
||||
let wires_composition_poly =
|
||||
commitments[2]
|
||||
.polynomials
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(PolynomialCoeffs::empty(), |acc, p| {
|
||||
poly_count += 1;
|
||||
&(&acc * alpha) + &p.to_extension()
|
||||
});
|
||||
let wire_polys = commitments[2].polynomials.iter().map(|p| p.to_extension());
|
||||
let wire_composition_poly = reduce_polys_with_iter(wire_polys, alpha_powers.clone());
|
||||
let wire_evals_frob = os.wires.iter().map(|e| e.frobenius()).collect::<Vec<_>>();
|
||||
let wires_composition_evals = [
|
||||
reduce_with_powers(&os.wires, alpha),
|
||||
reduce_with_powers(&wire_evals_frob, alpha),
|
||||
let wire_composition_evals = [
|
||||
reduce_with_iter(&os.wires, alpha_powers.clone()),
|
||||
reduce_with_iter(&wire_evals_frob, alpha_powers),
|
||||
];
|
||||
|
||||
let wires_quotient = Self::compute_quotient(
|
||||
&[zeta, zeta.frobenius()],
|
||||
&wires_composition_evals,
|
||||
&wires_composition_poly,
|
||||
&wire_composition_evals,
|
||||
&wire_composition_poly,
|
||||
);
|
||||
final_poly = &final_poly + &(&wires_quotient * cur_alpha);
|
||||
final_poly = &final_poly + &wires_quotient;
|
||||
|
||||
let lde_final_poly = final_poly.lde(config.rate_bits);
|
||||
let lde_final_values = lde_final_poly
|
||||
@ -275,9 +256,9 @@ impl<F: Field + Extendable<D>, const D: usize> OpeningProof<F, D> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
use rand::Rng;
|
||||
|
||||
use super::*;
|
||||
use rand::Rng;
|
||||
|
||||
fn gen_random_test_case<F: Field + Extendable<D>, const D: usize>(
|
||||
k: usize,
|
||||
@ -359,8 +340,10 @@ mod tests {
|
||||
}
|
||||
|
||||
mod quadratic {
|
||||
use super::*;
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment() -> Result<()> {
|
||||
check_batch_polynomial_commitment::<CrandallField, 2>()
|
||||
@ -368,8 +351,10 @@ mod tests {
|
||||
}
|
||||
|
||||
mod quartic {
|
||||
use super::*;
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment() -> Result<()> {
|
||||
check_batch_polynomial_commitment::<CrandallField, 4>()
|
||||
|
||||
@ -5,6 +5,7 @@ use crate::field::extension_field::Extendable;
|
||||
use crate::field::fft::{fft, ifft};
|
||||
use crate::field::field::Field;
|
||||
use crate::util::log2_strict;
|
||||
use std::iter::Sum;
|
||||
|
||||
/// A polynomial in point-value form.
|
||||
///
|
||||
@ -222,6 +223,12 @@ impl<F: Field> Add for &PolynomialCoeffs<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> Sum for PolynomialCoeffs<F> {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::empty(), |acc, p| &acc + &p)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> Sub for &PolynomialCoeffs<F> {
|
||||
type Output = PolynomialCoeffs<F>;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user