From ca9eb4bfcbab767cfc730e4048936037b38a7858 Mon Sep 17 00:00:00 2001 From: Alon Haramati Date: Tue, 18 Jun 2024 11:48:31 +0300 Subject: [PATCH] Add final lookup constraint. --- .../src/examples/wide_fibonacci/component.rs | 31 +++++++- .../wide_fibonacci/constraint_eval.rs | 75 ++++++++++++++----- 2 files changed, 84 insertions(+), 22 deletions(-) diff --git a/crates/prover/src/examples/wide_fibonacci/component.rs b/crates/prover/src/examples/wide_fibonacci/component.rs index a7247ee1f..114055b97 100644 --- a/crates/prover/src/examples/wide_fibonacci/component.rs +++ b/crates/prover/src/examples/wide_fibonacci/component.rs @@ -89,13 +89,14 @@ impl WideFibComponent { } } - fn evaluate_lookup_boundary_constraint_at_point( + fn evaluate_lookup_boundary_constraints_at_point( &self, point: CirclePoint, mask: &ColumnVec>, evaluation_accumulator: &mut PointEvaluationAccumulator, constraint_zero_domain: Coset, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) { let (alpha, z) = (interaction_elements[ALPHA_ID], interaction_elements[Z_ID]); let value = @@ -111,6 +112,29 @@ impl WideFibComponent { - shifted_secure_combination(&[mask[0][0], mask[1][0]], alpha, z); let denom = point_vanishing(constraint_zero_domain.at(0), point); evaluation_accumulator.accumulate(numerator / denom); + + let numerator = (value + * shifted_secure_combination( + &[ + lookup_values[LOOKUP_VALUE_N_MINUS_2_ID], + lookup_values[LOOKUP_VALUE_N_MINUS_1_ID], + ], + alpha, + z, + )) + - shifted_secure_combination( + &[ + lookup_values[LOOKUP_VALUE_0_ID], + lookup_values[LOOKUP_VALUE_1_ID], + ], + alpha, + z, + ); + let denom = point_vanishing( + constraint_zero_domain.at(constraint_zero_domain.size()), + point, + ); + evaluation_accumulator.accumulate(numerator / denom); } fn evaluate_lookup_step_constraints_at_point( @@ -155,7 +179,7 @@ impl Air for WideFibAir { impl Component for WideFibComponent { fn n_constraints(&self) -> usize { - self.n_columns() + 4 + self.n_columns() + 5 } fn max_constraint_log_degree_bound(&self) -> u32 { @@ -211,12 +235,13 @@ impl Component for WideFibComponent { constraint_zero_domain, interaction_elements, ); - self.evaluate_lookup_boundary_constraint_at_point( + self.evaluate_lookup_boundary_constraints_at_point( point, mask, evaluation_accumulator, constraint_zero_domain, interaction_elements, + lookup_values, ); self.evaluate_trace_step_constraints_at_point( point, diff --git a/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs b/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs index 472e055a9..287482e09 100644 --- a/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs +++ b/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs @@ -87,14 +87,14 @@ impl WideFibComponent { #[allow(clippy::needless_range_loop)] for i in 0..trace_eval_domain.size() { - first_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 3] + first_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 4] * (trace_evals[0][0][i] - lookup_values[LOOKUP_VALUE_0_ID]) - + accum.random_coeff_powers[self.n_columns() + 2] + + accum.random_coeff_powers[self.n_columns() + 3] * (trace_evals[0][1][i] - lookup_values[LOOKUP_VALUE_1_ID]); - last_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 1] + last_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 2] * (trace_evals[0][self.n_columns() - 2][i] - lookup_values[LOOKUP_VALUE_N_MINUS_2_ID]) - + accum.random_coeff_powers[self.n_columns()] + + accum.random_coeff_powers[self.n_columns() + 1] * (trace_evals[0][self.n_columns() - 1][i] - lookup_values[LOOKUP_VALUE_N_MINUS_1_ID]); } @@ -144,23 +144,30 @@ impl WideFibComponent { } } - fn evaluate_lookup_boundary_constraint( + fn evaluate_lookup_boundary_constraints( &self, trace_evals: &TreeVec>>, trace_eval_domain: CircleDomain, zero_domain: Coset, accum: &mut ColumnAccumulator<'_, CpuBackend>, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) { let max_constraint_degree = self.max_constraint_log_degree_bound(); - let mut denoms = vec![]; + let mut first_point_denoms = vec![]; + let mut last_point_denoms = vec![]; for point in trace_eval_domain.iter() { - denoms.push(point_vanishing(zero_domain.at(0), point)); + first_point_denoms.push(point_vanishing(zero_domain.at(0), point)); + last_point_denoms.push(point_vanishing(zero_domain.at(zero_domain.size()), point)); } - bit_reverse(&mut denoms); - let mut denom_inverses = vec![BaseField::zero(); 1 << (max_constraint_degree)]; - BaseField::batch_inverse(&denoms, &mut denom_inverses); - let mut numerators = vec![SecureField::zero(); 1 << (max_constraint_degree)]; + bit_reverse(&mut first_point_denoms); + bit_reverse(&mut last_point_denoms); + let mut first_point_denom_inverses = vec![BaseField::zero(); 1 << (max_constraint_degree)]; + let mut last_point_denom_inverses = vec![BaseField::zero(); 1 << (max_constraint_degree)]; + BaseField::batch_inverse(&first_point_denoms, &mut first_point_denom_inverses); + BaseField::batch_inverse(&last_point_denoms, &mut last_point_denom_inverses); + let mut first_point_numerators = vec![SecureField::zero(); 1 << (max_constraint_degree)]; + let mut last_point_numerators = vec![SecureField::zero(); 1 << (max_constraint_degree)]; let (alpha, z) = (interaction_elements[ALPHA_ID], interaction_elements[Z_ID]); #[allow(clippy::needless_range_loop)] @@ -169,7 +176,7 @@ impl WideFibComponent { SecureCirclePoly::::eval_from_partial_evals(std::array::from_fn(|j| { trace_evals[1][j][i].into() })); - numerators[i] = accum.random_coeff_powers[self.n_columns() - 2] + first_point_numerators[i] = accum.random_coeff_powers[self.n_columns() - 1] * ((value * shifted_secure_combination( &[ @@ -184,8 +191,37 @@ impl WideFibComponent { alpha, z, )); + last_point_numerators[i] = accum.random_coeff_powers[self.n_columns() - 2] + * ((value + * shifted_secure_combination( + &[ + lookup_values[LOOKUP_VALUE_N_MINUS_2_ID], + lookup_values[LOOKUP_VALUE_N_MINUS_1_ID], + ], + alpha, + z, + )) + - shifted_secure_combination( + &[ + lookup_values[LOOKUP_VALUE_0_ID], + lookup_values[LOOKUP_VALUE_1_ID], + ], + alpha, + z, + )); } - for (i, (num, denom_inverse)) in numerators.iter().zip(denom_inverses.iter()).enumerate() { + for (i, (num, denom_inverse)) in first_point_numerators + .iter() + .zip(first_point_denom_inverses.iter()) + .enumerate() + { + accum.accumulate(i, *num * *denom_inverse); + } + for (i, (num, denom_inverse)) in last_point_numerators + .iter() + .zip(last_point_denom_inverses.iter()) + .enumerate() + { accum.accumulate(i, *num * *denom_inverse); } } @@ -223,7 +259,7 @@ impl WideFibComponent { SecureCirclePoly::::eval_from_partial_evals(std::array::from_fn(|j| { trace_evals[1][j][prev_index].into() })); - numerators[i] = accum.random_coeff_powers[self.n_columns() - 1] + numerators[i] = accum.random_coeff_powers[self.n_columns()] * ((value * shifted_secure_combination( &[ @@ -268,26 +304,27 @@ impl ComponentProver for WideFibComponent { &mut accum, lookup_values, ); - self.evaluate_trace_step_constraints( + self.evaluate_lookup_step_constraints( trace_evals, trace_eval_domain, zero_domain, &mut accum, + interaction_elements, ); - self.evaluate_lookup_boundary_constraint( + self.evaluate_lookup_boundary_constraints( trace_evals, trace_eval_domain, zero_domain, &mut accum, interaction_elements, + lookup_values, ); - self.evaluate_lookup_step_constraints( + self.evaluate_trace_step_constraints( trace_evals, trace_eval_domain, zero_domain, &mut accum, - interaction_elements, - ) + ); } fn lookup_values(&self, trace: &ComponentTrace<'_, CpuBackend>) -> LookupValues {