@@ -26,7 +26,12 @@ pub struct CanonicalLinearRelation<G: PrimeGroup> {
2626 pub num_scalars : usize ,
2727}
2828
29- type GroupExpr < G > = Vec < ( <G as group:: Group >:: Scalar , GroupVar < G > ) > ;
29+ /// Private type alias used to simplify function signatures below.
30+ ///
31+ /// The cache is essentially a mapping (GroupVar, Scalar) => GroupVar, which maps the original
32+ /// weighted group vars to a new assignment, such that if a pair appears more than once, it will
33+ /// map to the same group variable in the canonical linear relation.
34+ type WeightedGroupCache < G > = HashMap < GroupVar < G > , Vec < ( <G as group:: Group >:: Scalar , GroupVar < G > ) > > ;
3035
3136impl < G : PrimeGroup > CanonicalLinearRelation < G > {
3237 /// Create a new empty canonical linear relation
@@ -45,7 +50,7 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
4550 group_var : GroupVar < G > ,
4651 weight : & G :: Scalar ,
4752 original_group_elements : & GroupMap < G > ,
48- weighted_group_cache : & mut HashMap < GroupVar < G > , GroupExpr < G > > ,
53+ weighted_group_cache : & mut WeightedGroupCache < G > ,
4954 ) -> Result < GroupVar < G > , InvalidInstance > {
5055 // Check if we already have this (weight, group_var) combination
5156 let entry = weighted_group_cache. entry ( group_var) . or_default ( ) ;
@@ -74,7 +79,7 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
7479 & image_var: & GroupVar < G > ,
7580 equation : & LinearCombination < G > ,
7681 original_relation : & LinearRelation < G > ,
77- weighted_group_cache : & mut HashMap < GroupVar < G > , GroupExpr < G > > ,
82+ weighted_group_cache : & mut WeightedGroupCache < G > ,
7883 ) -> Result < ( ) , InvalidInstance > {
7984 let mut rhs_terms = Vec :: new ( ) ;
8085
@@ -130,7 +135,12 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
130135 pub fn label ( & self ) -> Vec < u8 > {
131136 let mut out = Vec :: new ( ) ;
132137
133- // Replicate the original LinearRelationReprBuilder ordering behavior
138+ // Create an ordered list of unique group element representations. Elements are ordered
139+ // based on the order they appear in the canonical linear relation, as seen by the loop
140+ // below. Note that this is dependent on the building order in TryFrom<LinearRelation>.
141+ // QUESTION: Does anything depend on this order being stable? This seems difficult to
142+ // maintain across versions of this library, and changes to the relation definition may
143+ // have difficult to predict effects on the order.
134144 let mut group_repr_mapping: HashMap < Box < [ u8 ] > , u32 > = HashMap :: new ( ) ;
135145 let mut group_elements_ordered = Vec :: new ( ) ;
136146
@@ -146,8 +156,9 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
146156 new_index
147157 } ;
148158
149- // Build constraint data in the same order as original
150- let mut constraint_data = Vec :: new ( ) ;
159+ // Build constraint data in the same order as original, as a nested list of group and
160+ // scalar indices. Note that the group indices are into group_elements_ordered.
161+ let mut constraint_data = Vec :: < ( u32 , Vec < ( u32 , u32 ) > ) > :: new ( ) ;
151162
152163 for ( image_elem, constraint_terms) in iter:: zip ( & self . image , & self . linear_combinations ) {
153164 // First, add the left-hand side (image) element
0 commit comments