From 2148085725a6a2d861cb14d6a0b2b710bc31d9d7 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Tue, 5 Oct 2021 16:18:00 -0700 Subject: [PATCH] Give MinSize a max arity option (#284) * Give MinSize a max arity option * Add Fixed option * Fix --- src/fri/reduction_strategies.rs | 54 ++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/fri/reduction_strategies.rs b/src/fri/reduction_strategies.rs index 4ca50661..c0423c2c 100644 --- a/src/fri/reduction_strategies.rs +++ b/src/fri/reduction_strategies.rs @@ -5,14 +5,19 @@ use log::debug; /// A method for deciding what arity to use at each reduction layer. #[derive(Debug, Clone, Eq, PartialEq)] pub enum FriReductionStrategy { + /// Specifies the exact sequence of arities (expressed in bits) to use. + Fixed(Vec), + /// `ConstantArityBits(arity_bits, final_poly_bits)` applies reductions of arity `2^arity_bits` /// until the polynomial degree is `2^final_poly_bits` or less. This tends to work well in the /// recursive setting, as it avoids needing multiple configurations of gates used in FRI /// verification, such as `InterpolationGate`. ConstantArityBits(usize, usize), - /// Optimize for size. - MinSize, + /// `MinSize(opt_max_arity_bits)` searches for an optimal sequence of reduction arities, with an + /// optional max `arity_bits`. If this proof will have recursive proofs on top of it, a max + /// `arity_bits` of 3 is recommended. + MinSize(Option), } impl FriReductionStrategy { @@ -24,28 +29,39 @@ impl FriReductionStrategy { num_queries: usize, ) -> Vec { match self { - &FriReductionStrategy::ConstantArityBits(arity_bits, final_poly_bits) => { + FriReductionStrategy::Fixed(reduction_arity_bits) => reduction_arity_bits.to_vec(), + + FriReductionStrategy::ConstantArityBits(arity_bits, final_poly_bits) => { let mut result = Vec::new(); - while degree_bits > final_poly_bits { - result.push(arity_bits); - assert!(degree_bits >= arity_bits); - degree_bits -= arity_bits; + while degree_bits > *final_poly_bits { + result.push(*arity_bits); + assert!(degree_bits >= *arity_bits); + degree_bits -= *arity_bits; } result.shrink_to_fit(); result } - &FriReductionStrategy::MinSize => { - min_size_arity_bits(degree_bits, rate_bits, num_queries) + FriReductionStrategy::MinSize(opt_max_arity_bits) => { + min_size_arity_bits(degree_bits, rate_bits, num_queries, *opt_max_arity_bits) } } } } -fn min_size_arity_bits(degree_bits: usize, rate_bits: usize, num_queries: usize) -> Vec { +fn min_size_arity_bits( + degree_bits: usize, + rate_bits: usize, + num_queries: usize, + opt_max_arity_bits: Option, +) -> Vec { + // 2^4 is the largest arity we see in optimal reduction sequences in practice. For 2^5 to occur + // in an optimal sequence, we would need a really massive polynomial. + let max_arity_bits = opt_max_arity_bits.unwrap_or(4); + let start = Instant::now(); let (mut arity_bits, fri_proof_size) = - min_size_arity_bits_helper(degree_bits, rate_bits, num_queries, vec![]); + min_size_arity_bits_helper(degree_bits, rate_bits, num_queries, max_arity_bits, vec![]); arity_bits.shrink_to_fit(); debug!( @@ -65,12 +81,9 @@ fn min_size_arity_bits_helper( degree_bits: usize, rate_bits: usize, num_queries: usize, + global_max_arity_bits: usize, prefix: Vec, ) -> (Vec, usize) { - // 2^4 is the largest arity we see in optimal reduction sequences in practice. For 2^5 to occur - // in an optimal sequence, we would need a really massive polynomial. - const MAX_ARITY_BITS: usize = 4; - let sum_of_arities: usize = prefix.iter().sum(); let current_layer_bits = degree_bits + rate_bits - sum_of_arities; assert!(current_layer_bits >= rate_bits); @@ -84,15 +97,20 @@ fn min_size_arity_bits_helper( let max_arity_bits = prefix .last() .copied() - .unwrap_or(MAX_ARITY_BITS) + .unwrap_or(global_max_arity_bits) .min(current_layer_bits - rate_bits); for next_arity_bits in 1..=max_arity_bits { let mut extended_prefix = prefix.clone(); extended_prefix.push(next_arity_bits); - let (arity_bits, size) = - min_size_arity_bits_helper(degree_bits, rate_bits, num_queries, extended_prefix); + let (arity_bits, size) = min_size_arity_bits_helper( + degree_bits, + rate_bits, + num_queries, + max_arity_bits, + extended_prefix, + ); if size < best_size { best_arity_bits = arity_bits; best_size = size;