Skip to content

Commit 4953abd

Browse files
committed
Create MLE eval component
1 parent e67c1c5 commit 4953abd

File tree

5 files changed

+543
-100
lines changed

5 files changed

+543
-100
lines changed

crates/prover/src/constraint_framework/component.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub struct TraceLocationAllocator {
3131
}
3232

3333
impl TraceLocationAllocator {
34-
fn next_for_structure<T>(
34+
pub fn next_for_structure<T>(
3535
&mut self,
3636
structure: &TreeVec<ColumnVec<T>>,
3737
) -> TreeVec<TreeColumnSpan> {
@@ -75,14 +75,18 @@ pub struct FrameworkComponent<C: FrameworkEval> {
7575
}
7676

7777
impl<E: FrameworkEval> FrameworkComponent<E> {
78-
pub fn new(provider: &mut TraceLocationAllocator, eval: E) -> Self {
78+
pub fn new(location_allocator: &mut TraceLocationAllocator, eval: E) -> Self {
7979
let eval_tree_structure = eval.evaluate(InfoEvaluator::default()).mask_offsets;
80-
let trace_locations = provider.next_for_structure(&eval_tree_structure);
80+
let trace_locations = location_allocator.next_for_structure(&eval_tree_structure);
8181
Self {
8282
eval,
8383
trace_locations,
8484
}
8585
}
86+
87+
pub fn trace_locations(&self) -> &[TreeColumnSpan] {
88+
&self.trace_locations
89+
}
8690
}
8791

8892
impl<E: FrameworkEval> Component for FrameworkComponent<E> {
@@ -95,26 +99,20 @@ impl<E: FrameworkEval> Component for FrameworkComponent<E> {
9599
}
96100

97101
fn trace_log_degree_bounds(&self) -> TreeVec<ColumnVec<u32>> {
98-
TreeVec::new(
99-
self.eval
100-
.evaluate(InfoEvaluator::default())
101-
.mask_offsets
102-
.iter()
103-
.map(|tree_masks| vec![self.eval.log_size(); tree_masks.len()])
104-
.collect(),
105-
)
102+
let InfoEvaluator { mask_offsets, .. } = self.eval.evaluate(InfoEvaluator::default());
103+
mask_offsets.map(|tree_offsets| vec![self.eval.log_size(); tree_offsets.len()])
106104
}
107105

108106
fn mask_points(
109107
&self,
110108
point: CirclePoint<SecureField>,
111109
) -> TreeVec<ColumnVec<Vec<CirclePoint<SecureField>>>> {
112-
let info = self.eval.evaluate(InfoEvaluator::default());
113110
let trace_step = CanonicCoset::new(self.eval.log_size()).step();
114-
info.mask_offsets.map_cols(|col_mask| {
115-
col_mask
111+
let InfoEvaluator { mask_offsets, .. } = self.eval.evaluate(InfoEvaluator::default());
112+
mask_offsets.map_cols(|col_offsets| {
113+
col_offsets
116114
.iter()
117-
.map(|off| point + trace_step.mul_signed(*off).into_ef())
115+
.map(|offset| point + trace_step.mul_signed(*offset).into_ef())
118116
.collect()
119117
})
120118
}
@@ -139,6 +137,10 @@ impl<E: FrameworkEval> ComponentProver<SimdBackend> for FrameworkComponent<E> {
139137
trace: &Trace<'_, SimdBackend>,
140138
evaluation_accumulator: &mut DomainEvaluationAccumulator<SimdBackend>,
141139
) {
140+
if self.n_constraints() == 0 {
141+
return;
142+
}
143+
142144
let eval_domain = CanonicCoset::new(self.max_constraint_log_degree_bound()).circle_domain();
143145
let trace_domain = CanonicCoset::new(self.eval.log_size());
144146

crates/prover/src/constraint_framework/constant_columns.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ use crate::core::utils::{bit_reverse_index, coset_index_to_circle_domain_index};
88

99
/// Generates a column with a single one at the first position, and zeros elsewhere.
1010
pub fn gen_is_first<B: Backend>(log_size: u32) -> CircleEvaluation<B, BaseField, BitReversedOrder> {
11+
gen_is_offset(log_size, 0)
12+
}
13+
14+
/// Generates a column with a single one at the `offset`, and zeros elsewhere.
15+
pub fn gen_is_offset<B: Backend>(
16+
log_size: u32,
17+
offset: isize,
18+
) -> CircleEvaluation<B, BaseField, BitReversedOrder> {
1119
let mut col = Col::<B, BaseField>::zeros(1 << log_size);
12-
col.set(0, BaseField::one());
20+
let offset = offset.rem_euclid(col.len() as isize) as usize;
21+
let circle_domain_offset = coset_index_to_circle_domain_index(offset, log_size);
22+
col.set(circle_domain_offset, BaseField::one());
1323
CircleEvaluation::new(CanonicCoset::new(log_size).circle_domain(), col)
1424
}
1525

crates/prover/src/core/air/accumulation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::core::utils::generate_secure_powers;
1818
/// Accumulates N evaluations of u_i(P0) at a single point.
1919
/// Computes f(P0), the combined polynomial at that point.
2020
/// For n accumulated evaluations, the i'th evaluation is multiplied by alpha^(N-1-i).
21+
#[derive(Debug, Clone, Copy)]
2122
pub struct PointEvaluationAccumulator {
2223
random_coeff: SecureField,
2324
accumulation: SecureField,

crates/prover/src/examples/xor/gkr_lookups/accumulation.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ pub const MIN_LOG_BLOWUP_FACTOR: u32 = 1;
1818
/// IOP for multilinear eval at point.
1919
pub const MAX_MLE_N_VARIABLES: u32 = M31_CIRCLE_LOG_ORDER - MIN_LOG_BLOWUP_FACTOR;
2020

21-
/// Accumulates [`Mle`]s grouped by their number of variables.
21+
/// Collection of [`Mle`]s grouped by their number of variables.
2222
pub struct MleCollection<B: Backend> {
2323
mles_by_n_variables: Vec<Option<Vec<DynMle<B>>>>,
2424
}
2525

2626
impl<B: Backend> MleCollection<B> {
27-
/// Appends an [`Mle`] to the collection.
27+
/// Appends an [`Mle`] to the back of the collection.
2828
pub fn push(&mut self, mle: impl Into<DynMle<B>>) {
2929
let mle = mle.into();
3030
let mles = self.mles_by_n_variables[mle.n_variables()].get_or_insert(Vec::new());
@@ -35,6 +35,7 @@ impl<B: Backend> MleCollection<B> {
3535
impl MleCollection<SimdBackend> {
3636
/// Performs a random linear combination of all MLEs, grouped by their number of variables.
3737
///
38+
/// For `n` accumulated MLEs in a group, the `i`th MLE is multiplied by `alpha^(n-1-i)`.
3839
/// MLEs are returned in ascending order by number of variables.
3940
pub fn random_linear_combine_by_n_variables(
4041
self,
@@ -53,13 +54,15 @@ impl MleCollection<SimdBackend> {
5354
/// Panics if `mles` is empty or all MLEs don't have the same number of variables.
5455
fn mle_random_linear_combination(
5556
mles: Vec<DynMle<SimdBackend>>,
56-
alpha: SecureField,
57+
random_coeff: SecureField,
5758
) -> Mle<SimdBackend, SecureField> {
5859
assert!(!mles.is_empty());
5960
let n_variables = mles[0].n_variables();
6061
assert!(mles.iter().all(|mle| mle.n_variables() == n_variables));
61-
let alpha_powers = generate_secure_powers(alpha, mles.len()).into_iter().rev();
62-
let mut mle_and_coeff = zip(mles, alpha_powers);
62+
let coeff_powers = generate_secure_powers(random_coeff, mles.len())
63+
.into_iter()
64+
.rev();
65+
let mut mle_and_coeff = zip(mles, coeff_powers);
6366

6467
// The last value can initialize the accumulator.
6568
let (mle, coeff) = mle_and_coeff.next_back().unwrap();

0 commit comments

Comments
 (0)