@@ -4,8 +4,12 @@ use p3_field::Field;
4
4
use rustc_hash:: FxHashMap ;
5
5
use serde:: { Deserialize , Serialize } ;
6
6
7
- use crate :: air_builders:: symbolic:: {
8
- symbolic_expression:: SymbolicExpression , symbolic_variable:: SymbolicVariable ,
7
+ use super :: SymbolicConstraints ;
8
+ use crate :: {
9
+ air_builders:: symbolic:: {
10
+ symbolic_expression:: SymbolicExpression , symbolic_variable:: SymbolicVariable ,
11
+ } ,
12
+ interaction:: { Interaction , SymbolicInteraction } ,
9
13
} ;
10
14
11
15
/// A node in symbolic expression DAG.
@@ -50,18 +54,62 @@ pub struct SymbolicExpressionDag<F> {
50
54
pub ( crate ) constraint_idx : Vec < usize > ,
51
55
}
52
56
53
- pub ( crate ) fn build_symbolic_expr_dag < F : Field > (
54
- exprs : & [ SymbolicExpression < F > ] ,
55
- ) -> SymbolicExpressionDag < F > {
57
+ #[ derive( Clone , Debug , Serialize , Deserialize ) ]
58
+ #[ serde( bound = "F: Field" ) ]
59
+ pub struct SymbolicConstraintsDag < F > {
60
+ /// DAG with all symbolic expressions as nodes.
61
+ /// A subset of the nodes represents all constraints that will be
62
+ /// included in the quotient polynomial via DEEP-ALI.
63
+ pub constraints : SymbolicExpressionDag < F > ,
64
+ /// List of all interactions, where expressions in the interactions
65
+ /// are referenced by node idx as `usize`.
66
+ ///
67
+ /// This is used by the prover for after challenge trace generation,
68
+ /// and some partial information may be used by the verifier.
69
+ ///
70
+ /// **However**, any contributions to the quotient polynomial from
71
+ /// logup are already included in `constraints` and do not need to
72
+ /// be separately calculated from `interactions`.
73
+ pub interactions : Vec < Interaction < usize > > ,
74
+ }
75
+
76
+ pub ( crate ) fn build_symbolic_constraints_dag < F : Field > (
77
+ constraints : & [ SymbolicExpression < F > ] ,
78
+ interactions : & [ SymbolicInteraction < F > ] ,
79
+ ) -> SymbolicConstraintsDag < F > {
56
80
let mut expr_to_idx = FxHashMap :: default ( ) ;
57
81
let mut nodes = Vec :: new ( ) ;
58
- let constraint_idx = exprs
82
+ let constraint_idx = constraints
59
83
. iter ( )
60
84
. map ( |expr| topological_sort_symbolic_expr ( expr, & mut expr_to_idx, & mut nodes) )
61
85
. collect ( ) ;
62
- SymbolicExpressionDag {
86
+ let interactions: Vec < Interaction < usize > > = interactions
87
+ . iter ( )
88
+ . map ( |interaction| {
89
+ let fields: Vec < usize > = interaction
90
+ . fields
91
+ . iter ( )
92
+ . map ( |field_expr| {
93
+ topological_sort_symbolic_expr ( field_expr, & mut expr_to_idx, & mut nodes)
94
+ } )
95
+ . collect ( ) ;
96
+ let count =
97
+ topological_sort_symbolic_expr ( & interaction. count , & mut expr_to_idx, & mut nodes) ;
98
+ Interaction {
99
+ fields,
100
+ count,
101
+ bus_index : interaction. bus_index ,
102
+ interaction_type : interaction. interaction_type ,
103
+ }
104
+ } )
105
+ . collect ( ) ;
106
+ let constraints = SymbolicExpressionDag {
63
107
nodes,
64
108
constraint_idx,
109
+ } ;
110
+ SymbolicConstraintsDag {
111
+ constraints,
112
+ interactions,
65
113
}
66
114
}
67
115
@@ -139,8 +187,9 @@ fn topological_sort_symbolic_expr<'a, F: Field>(
139
187
}
140
188
141
189
impl < F : Field > SymbolicExpressionDag < F > {
142
- /// Returns symbolic expressions for each constraint
143
- pub fn to_symbolic_expressions ( & self ) -> Vec < SymbolicExpression < F > > {
190
+ /// Convert each node to a [`SymbolicExpression<F>`] reference and return
191
+ /// the full list.
192
+ fn to_symbolic_expressions ( & self ) -> Vec < Arc < SymbolicExpression < F > > > {
144
193
let mut exprs: Vec < Arc < SymbolicExpression < _ > > > = Vec :: with_capacity ( self . nodes . len ( ) ) ;
145
194
for node in & self . nodes {
146
195
let expr = match * node {
@@ -186,10 +235,48 @@ impl<F: Field> SymbolicExpressionDag<F> {
186
235
} ;
187
236
exprs. push ( Arc :: new ( expr) ) ;
188
237
}
189
- self . constraint_idx
190
- . iter ( )
191
- . map ( |& idx| exprs[ idx] . as_ref ( ) . clone ( ) )
192
- . collect ( )
238
+ exprs
239
+ }
240
+ }
241
+
242
+ // TEMPORARY conversions until we switch main interfaces to use SymbolicConstraintsDag
243
+ impl < F : Field > From < SymbolicConstraintsDag < F > > for SymbolicConstraints < F > {
244
+ fn from ( dag : SymbolicConstraintsDag < F > ) -> Self {
245
+ let exprs = dag. constraints . to_symbolic_expressions ( ) ;
246
+ let constraints = dag
247
+ . constraints
248
+ . constraint_idx
249
+ . into_iter ( )
250
+ . map ( |idx| exprs[ idx] . as_ref ( ) . clone ( ) )
251
+ . collect :: < Vec < _ > > ( ) ;
252
+ let interactions = dag
253
+ . interactions
254
+ . into_iter ( )
255
+ . map ( |interaction| {
256
+ let fields = interaction
257
+ . fields
258
+ . into_iter ( )
259
+ . map ( |idx| exprs[ idx] . as_ref ( ) . clone ( ) )
260
+ . collect ( ) ;
261
+ let count = exprs[ interaction. count ] . as_ref ( ) . clone ( ) ;
262
+ Interaction {
263
+ fields,
264
+ count,
265
+ bus_index : interaction. bus_index ,
266
+ interaction_type : interaction. interaction_type ,
267
+ }
268
+ } )
269
+ . collect :: < Vec < _ > > ( ) ;
270
+ SymbolicConstraints {
271
+ constraints,
272
+ interactions,
273
+ }
274
+ }
275
+ }
276
+
277
+ impl < F : Field > From < SymbolicConstraints < F > > for SymbolicConstraintsDag < F > {
278
+ fn from ( sc : SymbolicConstraints < F > ) -> Self {
279
+ build_symbolic_constraints_dag ( & sc. constraints , & sc. interactions )
193
280
}
194
281
}
195
282
@@ -198,17 +285,20 @@ mod tests {
198
285
use p3_baby_bear:: BabyBear ;
199
286
use p3_field:: AbstractField ;
200
287
201
- use crate :: air_builders:: symbolic:: {
202
- dag:: { build_symbolic_expr_dag, SymbolicExpressionDag , SymbolicExpressionNode } ,
203
- symbolic_expression:: SymbolicExpression ,
204
- symbolic_variable:: { Entry , SymbolicVariable } ,
205
- SymbolicConstraints ,
288
+ use crate :: {
289
+ air_builders:: symbolic:: {
290
+ dag:: { build_symbolic_constraints_dag, SymbolicExpressionDag , SymbolicExpressionNode } ,
291
+ symbolic_expression:: SymbolicExpression ,
292
+ symbolic_variable:: { Entry , SymbolicVariable } ,
293
+ SymbolicConstraints ,
294
+ } ,
295
+ interaction:: { Interaction , InteractionType } ,
206
296
} ;
207
297
208
298
type F = BabyBear ;
209
299
210
300
#[ test]
211
- fn test_symbolic_expressions_dag ( ) {
301
+ fn test_symbolic_constraints_dag ( ) {
212
302
let expr = SymbolicExpression :: Constant ( F :: ONE )
213
303
* SymbolicVariable :: new (
214
304
Entry :: Main {
@@ -217,16 +307,22 @@ mod tests {
217
307
} ,
218
308
3 ,
219
309
) ;
220
- let exprs = vec ! [
310
+ let constraints = vec ! [
221
311
SymbolicExpression :: IsFirstRow * SymbolicExpression :: IsLastRow
222
312
+ SymbolicExpression :: Constant ( F :: ONE )
223
313
+ SymbolicExpression :: IsFirstRow * SymbolicExpression :: IsLastRow
224
314
+ expr. clone( ) ,
225
315
expr. clone( ) * expr. clone( ) ,
226
316
] ;
227
- let expr_list = build_symbolic_expr_dag ( & exprs) ;
317
+ let interactions = vec ! [ Interaction {
318
+ bus_index: 0 ,
319
+ fields: vec![ expr. clone( ) , SymbolicExpression :: Constant ( F :: TWO ) ] ,
320
+ count: SymbolicExpression :: Constant ( F :: ONE ) ,
321
+ interaction_type: InteractionType :: Send ,
322
+ } ] ;
323
+ let dag = build_symbolic_constraints_dag ( & constraints, & interactions) ;
228
324
assert_eq ! (
229
- expr_list ,
325
+ dag . constraints ,
230
326
SymbolicExpressionDag :: <F > {
231
327
nodes: vec![
232
328
SymbolicExpressionNode :: IsFirstRow ,
@@ -274,17 +370,28 @@ mod tests {
274
370
left_idx: 8 ,
275
371
right_idx: 8 ,
276
372
degree_multiple: 2
277
- }
373
+ } ,
374
+ SymbolicExpressionNode :: Constant ( F :: TWO ) ,
278
375
] ,
279
376
constraint_idx: vec![ 9 , 10 ] ,
280
377
}
281
378
) ;
379
+ assert_eq ! (
380
+ dag. interactions,
381
+ vec![ Interaction {
382
+ bus_index: 0 ,
383
+ fields: vec![ 8 , 11 ] ,
384
+ count: 3 ,
385
+ interaction_type: InteractionType :: Send ,
386
+ } ]
387
+ ) ;
388
+
282
389
let sc = SymbolicConstraints {
283
- constraints : exprs ,
284
- interactions : vec ! [ ] ,
390
+ constraints,
391
+ interactions,
285
392
} ;
286
393
let ser_str = serde_json:: to_string ( & sc) . unwrap ( ) ;
287
394
let new_sc: SymbolicConstraints < _ > = serde_json:: from_str ( & ser_str) . unwrap ( ) ;
288
- assert_eq ! ( sc. constraints , new_sc. constraints ) ;
395
+ assert_eq ! ( sc, new_sc) ;
289
396
}
290
397
}
0 commit comments