Skip to content

Commit 74a942d

Browse files
authored
refactor: simplify drawing of composition coefficients (#381)
1 parent 74246b2 commit 74a942d

File tree

1 file changed

+65
-116
lines changed

1 file changed

+65
-116
lines changed

air/src/air/coefficients.rs

Lines changed: 65 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use alloc::vec::Vec;
77

88
use crypto::{RandomCoin, RandomCoinError};
9-
use math::{get_power_series, get_power_series_with_offset, FieldElement};
9+
use math::{get_power_series, FieldElement};
1010

1111
// CONSTRAINT COMPOSITION COEFFICIENTS
1212
// ================================================================================================
@@ -43,27 +43,28 @@ pub struct ConstraintCompositionCoefficients<E: FieldElement> {
4343
}
4444

4545
impl<E: FieldElement> ConstraintCompositionCoefficients<E> {
46+
/// Returns new [ConstraintCompositionCoefficients] constructed by splitting the provided
47+
/// coefficients into transition and boundary coefficients.
48+
///
49+
/// The first `num_transition_constraints` values in the `coefficients` vector are assigned
50+
/// to the transition coefficients and the remaining coefficients are assigned to boundary
51+
/// coefficients.
52+
fn new(mut coefficients: Vec<E>, num_transition_constraints: usize) -> Self {
53+
let boundary = coefficients.split_off(num_transition_constraints);
54+
let transition = coefficients;
55+
Self { transition, boundary }
56+
}
57+
4658
/// Generates the random values used in the construction of the constraint composition
4759
/// polynomial when linear batching is used.
4860
pub fn draw_linear(
4961
public_coin: &mut impl RandomCoin<BaseField = E::BaseField>,
5062
num_transition_constraints: usize,
5163
num_boundary_constraints: usize,
5264
) -> Result<Self, RandomCoinError> {
53-
let mut t_coefficients = Vec::with_capacity(num_transition_constraints);
54-
for _ in 0..num_transition_constraints {
55-
t_coefficients.push(public_coin.draw()?);
56-
}
57-
58-
let mut b_coefficients = Vec::with_capacity(num_boundary_constraints);
59-
for _ in 0..num_boundary_constraints {
60-
b_coefficients.push(public_coin.draw()?);
61-
}
62-
63-
Ok(ConstraintCompositionCoefficients {
64-
transition: t_coefficients,
65-
boundary: b_coefficients,
66-
})
65+
let num_coefficients = num_transition_constraints + num_boundary_constraints;
66+
let coefficients = draw_linear_coefficients(public_coin, num_coefficients)?;
67+
Ok(Self::new(coefficients, num_transition_constraints))
6768
}
6869

6970
/// Generates the random values used in the construction of the constraint composition
@@ -73,26 +74,9 @@ impl<E: FieldElement> ConstraintCompositionCoefficients<E> {
7374
num_transition_constraints: usize,
7475
num_boundary_constraints: usize,
7576
) -> Result<Self, RandomCoinError> {
76-
let mut t_coefficients = Vec::with_capacity(num_transition_constraints);
77-
let alpha: E = public_coin.draw()?;
78-
t_coefficients.extend_from_slice(&get_power_series(alpha, num_transition_constraints));
79-
80-
let mut b_coefficients = Vec::with_capacity(num_boundary_constraints);
81-
82-
let alpha_pow_num_transition_constraints =
83-
alpha.exp((num_transition_constraints as u32).into());
84-
b_coefficients.extend_from_slice(&get_power_series_with_offset(
85-
alpha,
86-
alpha_pow_num_transition_constraints,
87-
num_boundary_constraints,
88-
));
89-
90-
assert_eq!(t_coefficients[num_transition_constraints - 1] * alpha, b_coefficients[0]);
91-
92-
Ok(ConstraintCompositionCoefficients {
93-
transition: t_coefficients,
94-
boundary: b_coefficients,
95-
})
77+
let num_coefficients = num_transition_constraints + num_boundary_constraints;
78+
let coefficients = draw_algebraic_coefficients(public_coin, num_coefficients)?;
79+
Ok(Self::new(coefficients, num_transition_constraints))
9680
}
9781

9882
/// Generates the random values used in the construction of the constraint composition
@@ -102,35 +86,10 @@ impl<E: FieldElement> ConstraintCompositionCoefficients<E> {
10286
num_transition_constraints: usize,
10387
num_boundary_constraints: usize,
10488
) -> Result<Self, RandomCoinError> {
105-
let mut res = Self::draw_algebraic(
106-
public_coin,
107-
num_transition_constraints,
108-
num_boundary_constraints,
109-
)?;
110-
res.reverse();
111-
Ok(res)
112-
}
113-
114-
/// Reverses the order of coefficients.
115-
fn reverse(&mut self) {
116-
let num_constraints = self.transition.len() + self.boundary.len();
117-
let mut coefficients = Vec::with_capacity(num_constraints);
118-
119-
coefficients.extend_from_slice(&self.transition);
120-
coefficients.extend_from_slice(&self.boundary);
121-
89+
let num_coefficients = num_transition_constraints + num_boundary_constraints;
90+
let mut coefficients = draw_algebraic_coefficients(public_coin, num_coefficients)?;
12291
coefficients.reverse();
123-
124-
let b_coefficients = coefficients.split_off(self.transition.len());
125-
let t_coefficients = coefficients;
126-
127-
assert_eq!(
128-
t_coefficients[self.transition.len() - 1],
129-
b_coefficients[0] * self.transition[1]
130-
);
131-
132-
self.transition = t_coefficients;
133-
self.boundary = b_coefficients;
92+
Ok(Self::new(coefficients, num_transition_constraints))
13493
}
13594
}
13695

@@ -184,27 +143,27 @@ pub struct DeepCompositionCoefficients<E: FieldElement> {
184143
}
185144

186145
impl<E: FieldElement> DeepCompositionCoefficients<E> {
146+
/// Returns new [DeepCompositionCoefficients] constructed by splitting the provided
147+
/// coefficients into transition and boundary coefficients.
148+
///
149+
/// The first `trace_width` values in the `coefficients` vector are assigned to the trace
150+
/// coefficients and the remaining coefficients are assigned to constraint coefficients.
151+
fn new(mut coefficients: Vec<E>, trace_width: usize) -> Self {
152+
let constraints = coefficients.split_off(trace_width);
153+
let trace = coefficients;
154+
Self { trace, constraints }
155+
}
156+
187157
/// Generates the random values used in the construction of the DEEP polynomial when linear
188158
/// batching is used.
189159
pub fn draw_linear(
190160
public_coin: &mut impl RandomCoin<BaseField = E::BaseField>,
191161
trace_width: usize,
192162
num_constraint_composition_columns: usize,
193163
) -> Result<Self, RandomCoinError> {
194-
let mut t_coefficients = Vec::with_capacity(trace_width);
195-
for _ in 0..trace_width {
196-
t_coefficients.push(public_coin.draw()?);
197-
}
198-
199-
let mut c_coefficients = Vec::with_capacity(num_constraint_composition_columns);
200-
for _ in 0..num_constraint_composition_columns {
201-
c_coefficients.push(public_coin.draw()?);
202-
}
203-
204-
Ok(DeepCompositionCoefficients {
205-
trace: t_coefficients,
206-
constraints: c_coefficients,
207-
})
164+
let num_coefficients = trace_width + num_constraint_composition_columns;
165+
let coefficients = draw_linear_coefficients(public_coin, num_coefficients)?;
166+
Ok(Self::new(coefficients, trace_width))
208167
}
209168

210169
/// Generates the random values used in the construction of the DEEP polynomial when algebraic
@@ -214,25 +173,9 @@ impl<E: FieldElement> DeepCompositionCoefficients<E> {
214173
trace_width: usize,
215174
num_constraint_composition_columns: usize,
216175
) -> Result<Self, RandomCoinError> {
217-
let mut t_coefficients = Vec::with_capacity(trace_width);
218-
let alpha: E = public_coin.draw()?;
219-
t_coefficients.extend_from_slice(&get_power_series(alpha, trace_width));
220-
221-
let mut c_coefficients = Vec::with_capacity(num_constraint_composition_columns);
222-
223-
let alpha_pow_trace_width = alpha.exp((trace_width as u32).into());
224-
c_coefficients.extend_from_slice(&get_power_series_with_offset(
225-
alpha,
226-
alpha_pow_trace_width,
227-
num_constraint_composition_columns,
228-
));
229-
230-
assert_eq!(t_coefficients[trace_width - 1] * alpha, c_coefficients[0]);
231-
232-
Ok(DeepCompositionCoefficients {
233-
trace: t_coefficients,
234-
constraints: c_coefficients,
235-
})
176+
let num_coefficients = trace_width + num_constraint_composition_columns;
177+
let coefficients = draw_algebraic_coefficients(public_coin, num_coefficients)?;
178+
Ok(Self::new(coefficients, trace_width))
236179
}
237180

238181
/// Generates the random values used in the construction of the DEEP polynomial when Horner-type
@@ -242,28 +185,34 @@ impl<E: FieldElement> DeepCompositionCoefficients<E> {
242185
trace_width: usize,
243186
num_constraint_composition_columns: usize,
244187
) -> Result<Self, RandomCoinError> {
245-
let mut res =
246-
Self::draw_algebraic(public_coin, trace_width, num_constraint_composition_columns)?;
247-
res.reverse();
248-
Ok(res)
249-
}
250-
251-
/// Reverses the order of coefficients.
252-
fn reverse(&mut self) {
253-
let num_constraints = self.trace.len() + self.constraints.len();
254-
let mut coefficients = Vec::with_capacity(num_constraints);
255-
256-
coefficients.extend_from_slice(&self.trace);
257-
coefficients.extend_from_slice(&self.constraints);
258-
188+
let num_coefficients = trace_width + num_constraint_composition_columns;
189+
let mut coefficients = draw_algebraic_coefficients(public_coin, num_coefficients)?;
259190
coefficients.reverse();
191+
Ok(Self::new(coefficients, trace_width))
192+
}
193+
}
260194

261-
let c_coefficients = coefficients.split_off(self.trace.len());
262-
let t_coefficients = coefficients;
195+
// HELPER FUNCTIONS
196+
// ================================================================================================
263197

264-
assert_eq!(t_coefficients[self.trace.len() - 1], c_coefficients[0] * self.trace[1]);
198+
/// Returns a vector of coefficients built from the provided public coin.
199+
///
200+
/// The returned coefficients are drawn uniformly from the provided coin.
201+
fn draw_linear_coefficients<E: FieldElement>(
202+
public_coin: &mut impl RandomCoin<BaseField = E::BaseField>,
203+
num_coefficients: usize,
204+
) -> Result<Vec<E>, RandomCoinError> {
205+
(0..num_coefficients).map(|_| public_coin.draw()).collect()
206+
}
265207

266-
self.trace = t_coefficients;
267-
self.constraints = c_coefficients;
268-
}
208+
/// Returns a vector of coefficients built from the provided public coin.
209+
///
210+
/// A single random value alpha is drawn from the public coin, and the coefficients are computed as
211+
/// successive powers of this alpha.
212+
fn draw_algebraic_coefficients<E: FieldElement>(
213+
public_coin: &mut impl RandomCoin<BaseField = E::BaseField>,
214+
num_coefficients: usize,
215+
) -> Result<Vec<E>, RandomCoinError> {
216+
let alpha: E = public_coin.draw()?;
217+
Ok(get_power_series(alpha, num_coefficients))
269218
}

0 commit comments

Comments
 (0)