-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Composition Polynomial #26
base: master
Are you sure you want to change the base?
Changes from 6 commits
820f81f
028e1d2
77442dd
719f7bc
e440669
ba9e534
c7f91eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "composition_polynomial" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "MIT" | ||
|
||
[dependencies] | ||
ark-ff = { workspace = true } | ||
ark-poly ={ workspace = true } | ||
fri = { path = "../fri" } | ||
|
||
[dev-dependencies] | ||
rand.workspace = true | ||
num-bigint.workspace = true | ||
felt = { path = "../felt" } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
use crate::composition_polynomial::{batch_pow, CompositionPolynomial}; | ||
use crate::periodic_columns::PeriodicColumn; | ||
use ark_ff::PrimeField; | ||
use std::collections::HashMap; | ||
use std::sync::Arc; | ||
|
||
pub trait Air<F: PrimeField> { | ||
fn create_composition_polynomial( | ||
&self, | ||
trace_generator: &F, | ||
random_coefficients: &[F], | ||
) -> CompositionPolynomial<F>; | ||
|
||
fn trace_length(&self) -> usize; | ||
|
||
fn get_composition_polynomial_degree_bound(&self) -> usize; | ||
|
||
fn num_random_coefficients(&self) -> usize; | ||
|
||
fn get_num_constraints(&self) -> usize { | ||
self.num_random_coefficients() | ||
} | ||
|
||
fn constraints_eval( | ||
&self, | ||
neighbors: &[F], | ||
periodic_columns: &[F], | ||
random_coefficients: &[F], | ||
point: &F, | ||
gen_powers: &[F], | ||
precomp_domains: &[F], | ||
) -> F; | ||
|
||
fn get_mask(&self) -> &[(usize, usize)]; | ||
|
||
fn num_columns(&self) -> usize; | ||
|
||
fn domain_evals_at_point(&self, point_powers: &[F], shifts: &[F]) -> Vec<F>; | ||
|
||
fn parse_dynamic_params(&self, params: &HashMap<String, usize>) -> Vec<usize>; | ||
|
||
fn with_interaction_elements(&self, _interaction_elms: &[F]) -> Box<dyn Air<F>> { | ||
panic!("Calling with_interaction_elements in an air with no interaction."); | ||
} | ||
|
||
fn get_interaction_params(&self) -> Option<InteractionParams>; | ||
|
||
fn get_n_columns_first(&self) -> usize { | ||
match self.get_interaction_params() { | ||
Some(params) => params.n_columns_first, | ||
None => self.num_columns(), | ||
} | ||
} | ||
|
||
fn precompute_domain_evals_on_coset( | ||
&self, | ||
point: &F, | ||
generator: &F, | ||
point_exponents: &[usize], | ||
shifts: &[F], | ||
) -> Vec<Vec<F>>; | ||
} | ||
|
||
pub struct InteractionParams { | ||
pub n_columns_first: usize, | ||
pub n_columns_second: usize, | ||
pub n_interaction_elements: usize, | ||
} | ||
|
||
type ConstraintFunction<F> = Arc<dyn Fn(&[F], &[F], &[F], &F, &[F], &[F]) -> F>; | ||
|
||
// DummyAir struct definition | ||
#[derive(Clone)] | ||
pub struct DummyAir<F: PrimeField> { | ||
pub trace_length: usize, | ||
pub n_constraints: usize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this different from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its the same, removed |
||
pub n_columns: usize, | ||
pub mask: Vec<(usize, usize)>, | ||
pub periodic_columns: Vec<PeriodicColumn<F>>, | ||
pub point_exponents: Vec<usize>, | ||
pub gen_exponents: Vec<usize>, | ||
pub constraints: Vec<ConstraintFunction<F>>, | ||
pub composition_polynomial_degree_bound: Option<usize>, | ||
} | ||
|
||
impl<F: PrimeField> DummyAir<F> { | ||
pub fn new(trace_length: usize) -> Self { | ||
assert!(trace_length.is_power_of_two()); | ||
Self { | ||
trace_length, | ||
n_constraints: 0, | ||
n_columns: 0, | ||
mask: vec![], | ||
periodic_columns: vec![], | ||
point_exponents: vec![], | ||
gen_exponents: vec![], | ||
constraints: vec![], | ||
composition_polynomial_degree_bound: None, | ||
} | ||
} | ||
} | ||
|
||
impl<F: PrimeField> Air<F> for DummyAir<F> { | ||
fn trace_length(&self) -> usize { | ||
self.trace_length | ||
} | ||
|
||
fn get_composition_polynomial_degree_bound(&self) -> usize { | ||
assert!( | ||
self.composition_polynomial_degree_bound.is_some(), | ||
"composition_polynomial_degree_bound wasn't initialized." | ||
); | ||
self.composition_polynomial_degree_bound.unwrap() | ||
} | ||
|
||
fn num_random_coefficients(&self) -> usize { | ||
self.n_constraints | ||
} | ||
|
||
fn num_columns(&self) -> usize { | ||
self.n_columns | ||
} | ||
|
||
fn get_interaction_params(&self) -> Option<InteractionParams> { | ||
None | ||
} | ||
|
||
fn constraints_eval( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this just be a method on e.g. it takes |
||
&self, | ||
neighbors: &[F], | ||
periodic_columns: &[F], | ||
random_coefficients: &[F], | ||
point: &F, | ||
gen_powers: &[F], | ||
precomp_domains: &[F], | ||
) -> F { | ||
assert!( | ||
random_coefficients.len() == self.constraints.len(), | ||
"This is a bug in the test." | ||
); | ||
|
||
let mut res = F::ZERO; | ||
for constraint in self.constraints.iter() { | ||
res += constraint( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought the |
||
neighbors, | ||
periodic_columns, | ||
random_coefficients, | ||
point, | ||
gen_powers, | ||
precomp_domains, | ||
); | ||
} | ||
res | ||
} | ||
|
||
fn domain_evals_at_point(&self, point_powers: &[F], _shifts: &[F]) -> Vec<F> { | ||
if point_powers.len() <= 1 { | ||
return vec![]; | ||
} | ||
vec![point_powers[1] - F::ONE] | ||
} | ||
|
||
fn create_composition_polynomial( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this take ownership of the Air? i.e. fn into_composition_polynomial(
self,
trace_generator,
random_coefficients
) -> CompositionPolynomial<F> That way we avoid the Box and Clone? |
||
&self, | ||
trace_generator: &F, | ||
random_coefficients: &[F], | ||
) -> CompositionPolynomial<F> { | ||
let shifts = batch_pow(trace_generator, &self.gen_exponents); | ||
CompositionPolynomial::new( | ||
Box::new(self.clone()), | ||
*trace_generator, | ||
self.trace_length(), | ||
self.periodic_columns.clone(), | ||
random_coefficients, | ||
&self.point_exponents, | ||
&shifts, | ||
) | ||
} | ||
|
||
fn get_mask(&self) -> &[(usize, usize)] { | ||
&self.mask | ||
} | ||
|
||
fn parse_dynamic_params( | ||
&self, | ||
_params: &std::collections::HashMap<String, usize>, | ||
) -> Vec<usize> { | ||
vec![] | ||
} | ||
|
||
fn precompute_domain_evals_on_coset( | ||
&self, | ||
point: &F, | ||
generator: &F, | ||
point_exponents: &[usize], | ||
_shifts: &[F], | ||
) -> Vec<Vec<F>> { | ||
assert!(point_exponents[0] != 0); | ||
assert!(self.trace_length % point_exponents[0] == 0); | ||
let size = self.trace_length / point_exponents[0]; | ||
|
||
let mut point_powers = Vec::with_capacity(size); | ||
let mut power = point.pow([point_exponents[0] as u64]); | ||
let gen_power = generator.pow([point_exponents[0] as u64]); | ||
|
||
point_powers.push(power); | ||
for _ in 1..size { | ||
power *= gen_power; | ||
point_powers.push(power); | ||
} | ||
|
||
let mut precomp_domains = vec![Vec::with_capacity(size)]; | ||
for p in point_powers.iter() { | ||
precomp_domains[0].push(*p - F::ONE); | ||
} | ||
precomp_domains | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider introducing a struct for the argument: that way they are named and it is easy to see what a
ConstraintFunction
takes e.g.