From 194c4864d27c194f3991b08b2a1750dbf49434f5 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Mon, 1 Mar 2021 11:17:44 -0800 Subject: [PATCH] Remove bad attempt at automatic degree shrinking --- src/gates/output_graph.rs | 152 -------------------------------------- 1 file changed, 152 deletions(-) diff --git a/src/gates/output_graph.rs b/src/gates/output_graph.rs index 48f77dce..9e6c6651 100644 --- a/src/gates/output_graph.rs +++ b/src/gates/output_graph.rs @@ -20,93 +20,12 @@ impl OutputGraph { Self { outputs: vec![(loc, out)] } } - /// Compiles an output graph with potentially high-degree polynomials to one with low-degree - /// polynomials by introducing extra wires for some intermediate values. - /// - /// Note that this uses a simple greedy algorithm, so the result may not be optimal in terms of wire - /// count. - // TODO: This doesn't yet work with large exponentiations, i.e. x^n where n > max_degree. Not an - // immediate problem since our gates don't use those. - pub fn shrink_degree(&self, max_degree: usize) -> Self { - let max_degree_biguint = BigUint::from_usize(max_degree).unwrap(); - - let mut current_graph = self.clone(); - - 'shrinker: while current_graph.count_high_degree_polys(max_degree) > 0 { - // Find polynomials with a degree between 2 and the max, inclusive. - // These are candidates for becoming new wires. - let degrees = current_graph.degree_map(); - let current_high_deg_count = current_graph.count_high_degree_polys(max_degree); - let mut candidate_degrees: Vec<(ConstraintPolynomial, usize)> = degrees - .iter() - .filter(|(poly, deg)| *deg > &BigUint::one() && *deg <= &max_degree_biguint) - .map(|(poly, deg)| (poly.clone(), deg.to_usize().unwrap())) - .collect(); - candidate_degrees.sort_unstable_by_key(|(poly, deg)| *deg); - candidate_degrees.reverse(); - - for (poly, _deg) in &candidate_degrees { - let candidate_graph = current_graph.allocate_wire(poly.clone()); - let candidate_high_deg_count = candidate_graph.count_high_degree_polys(max_degree); - if candidate_high_deg_count < current_high_deg_count { - // println!("before {}", ¤t_graph); - // println!("after {}", &candidate_graph); - current_graph = candidate_graph; - println!("Reduced high degree polys to {}", candidate_high_deg_count); - continue 'shrinker; - } - } - - println!("No good candidates; cannot reduce high degree polys"); - for (poly, _deg) in candidate_degrees { - let candidate_graph = current_graph.allocate_wire(poly); - current_graph = candidate_graph; - continue 'shrinker; - } - - panic!("No candidate; cannot make progress"); - } - - current_graph - } - - /// The number of polynomials in this graph which exceed the given maximum degree. - fn count_high_degree_polys(&self, max_degree: usize) -> usize { - let max_degree = BigUint::from_usize(max_degree).unwrap(); - self.degree_map().into_iter() - .filter(|(_poly, deg)| deg > &max_degree) - .count() - } - - fn degree_map(&self) -> HashMap, BigUint> { - let mut degrees = HashMap::new(); - for (_loc, out) in &self.outputs { - out.populate_degree_map(&mut degrees); - } - degrees - } - /// The largest local wire index in this entire graph. pub(crate) fn max_wire_input_index(&self) -> Option { self.outputs.iter() .flat_map(|(loc, out)| out.max_wire_input_index()) .max() } - - /// Allocate a new wire for the given target polynomial, and return a new output graph with - /// references to the target polynomial replaced with references to that wire. - fn allocate_wire(&self, target: ConstraintPolynomial) -> Self { - let new_wire_index = self.max_wire_input_index() - .map_or(0, |i| i + 1); - - let new_wire = ConstraintPolynomial::local_wire_value(new_wire_index); - - let outputs = self.outputs.iter() - .map(|(loc, out)| (*loc, out.replace_all(target.clone(), new_wire.clone()))) - .chain(iter::once((GateOutputLocation::LocalWire(new_wire_index), target.clone()))) - .collect(); - Self { outputs } - } } impl Display for OutputGraph { @@ -135,74 +54,3 @@ impl Display for GateOutputLocation { } } } - -#[cfg(test)] -mod tests { - use crate::constraint_polynomial::ConstraintPolynomial; - use crate::field::crandall_field::CrandallField; - use crate::gates::output_graph::{GateOutputLocation, OutputGraph}; - - #[test] - fn shrink_mimc() { - // This is like a simplified version of GMiMC, for easy debugging. - type F = CrandallField; - let switch = ConstraintPolynomial::::local_wire_value(0); - let x = ConstraintPolynomial::::local_wire_value(1); - let y = ConstraintPolynomial::::local_wire_value(2); - - // deg 2 - let delta = &switch * (&y - &x); - let l0 = &x + δ - let r0 = &y - δ - let s0 = &l0 + &r0; - - // 2*3 - let l1 = s0.cube(); let r1 = r0.cube(); let s1 = &l1 + &r1; - // 2*3*3 - let l2 = s1.cube(); let r2 = r1.cube(); let s2 = &l2 + &r2; - // 2*3*3*3 - let l3 = s2.cube(); let r3 = r2.cube(); let s3 = &l3 + &r3; - - let og = OutputGraph { outputs: vec![ - (GateOutputLocation::NextWire(0), l3), - (GateOutputLocation::NextWire(1), r3), - ] }; - - let shrunk = og.shrink_degree(9); - assert_eq!(shrunk.max_wire_input_index(), Some(4)); - } - - #[test] - fn shrink_squaring_graph() { - type F = CrandallField; - let deg1 = ConstraintPolynomial::::local_wire_value(0); - let deg2 = deg1.square(); - let deg4 = deg2.square(); - let deg8 = deg4.square(); - let deg16 = deg8.square(); - - let original = OutputGraph::single_output( - GateOutputLocation::NextWire(0), - deg16); - - let degree_map = original.degree_map(); - assert_eq!(degree_map.len(), 5); - - assert_eq!(original.count_high_degree_polys(2), 3); - assert_eq!(original.count_high_degree_polys(3), 3); - assert_eq!(original.count_high_degree_polys(4), 2); - - let shrunk_deg_2 = original.shrink_degree(2); - let shrunk_deg_3 = original.shrink_degree(3); - let shrunk_deg_4 = original.shrink_degree(4); - - // `shrunk_deg_2` should have an intermediate wire for deg2, deg4, and deg8. - assert_eq!(shrunk_deg_2.max_wire_input_index(), Some(3)); - - // `shrunk_deg_3` should also have an intermediate wire for deg2, deg4, and deg8. - assert_eq!(shrunk_deg_3.max_wire_input_index(), Some(3)); - - // `shrunk_deg_4` should have an intermediate wire for deg4 only. - assert_eq!(shrunk_deg_4.max_wire_input_index(), Some(1)); - } -}