55use crate :: { DefaultCoef , Poly , expr_to_var} ;
66use baa:: BitVecOps ;
77use patronus:: expr:: {
8- Context , DenseExprSet , Expr , ExprRef , ExprSet , ForEachChild , count_expr_uses,
8+ Context , DenseExprSet , Expr , ExprRef , ExprSet , ForEachChild , count_expr_uses, traversal ,
99} ;
10- use polysub:: { PhaseOptPolynom , VarIndex } ;
10+ use polysub:: { Coef , Mod , PhaseOptPolynom , VarIndex } ;
1111use rustc_hash:: FxHashSet ;
1212use std:: collections:: VecDeque ;
1313
1414/// Used for backwards substitution
15- type PolyOpt = polysub :: PhaseOptPolynom < DefaultCoef > ;
15+ type PolyOpt = PhaseOptPolynom < DefaultCoef > ;
1616
1717pub fn backwards_sub (
1818 ctx : & Context ,
@@ -33,10 +33,11 @@ pub fn backwards_sub(
3333 let mut seen = DenseExprSet :: default ( ) ;
3434
3535 while !todo. is_empty ( ) {
36- //try_exhaustive(ctx, input_vars, &spec, todo.iter().cloned());
36+ let min_idx = try_exhaustive ( ctx, input_vars, & spec, todo. iter ( ) . cloned ( ) ) ;
37+ let ( output_var, gate) = todo. swap_remove_back ( min_idx) . unwrap ( ) ;
3738
3839 // chose variable to replace
39- let ( output_var, gate) = todo. pop_back ( ) . unwrap ( ) ;
40+ // let (output_var, gate) = todo.pop_back().unwrap();
4041
4142 replaced. push ( output_var) ;
4243 println ! (
@@ -153,15 +154,79 @@ fn try_exhaustive(
153154 input_vars : & FxHashSet < VarIndex > ,
154155 spec : & PolyOpt ,
155156 todo : impl Iterator < Item = ( VarIndex , ExprRef ) > ,
156- ) {
157- for ( ii, ( output_var, gate) ) in todo. enumerate ( ) {
158- let mut s = spec. clone ( ) ;
159- replace_gate ( ctx, input_vars, & mut s, output_var, gate) ;
160- println ! (
161- " {ii:>3}: {output_var} {:?}: {} -> {}" ,
162- & ctx[ gate] ,
163- spec. size( ) ,
157+ ) -> usize {
158+ let sizes: Vec < _ > = todo
159+ . enumerate ( )
160+ . map ( |( ii, ( output_var, gate) ) | {
161+ let mut s = spec. clone ( ) ;
162+ replace_gate ( ctx, input_vars, & mut s, output_var, gate) ;
164163 s. size ( )
165- ) ;
166- }
164+ } )
165+ . collect ( ) ;
166+ let min = sizes. iter ( ) . cloned ( ) . min ( ) . unwrap ( ) ;
167+ let max = sizes. iter ( ) . cloned ( ) . max ( ) . unwrap ( ) ;
168+ let first_min = sizes. iter ( ) . position ( |s| * s == min) . unwrap ( ) ;
169+ println ! ( "{} -> {min}/{max}" , spec. size( ) ) ;
170+ first_min
171+ }
172+
173+ /// tries to build the gate-level polynomial from the bottom up.
174+ pub fn build_gate_polynomial (
175+ ctx : & Context ,
176+ input_vars : & FxHashSet < VarIndex > ,
177+ m : Mod ,
178+ e : ExprRef ,
179+ ) -> Poly {
180+ traversal:: bottom_up ( ctx, e, |ctx, gate, children : & [ Poly ] | {
181+ let var = expr_to_var ( gate) ;
182+
183+ // if this is an input, we just want to return the variable
184+ if input_vars. contains ( & var) {
185+ return Poly :: from_monoms ( m, [ ( Coef :: from_i64 ( 1 , m) , vec ! [ var] . into ( ) ) ] . into_iter ( ) ) ;
186+ }
187+
188+ match ( ctx[ gate] . clone ( ) , children) {
189+ ( Expr :: BVOr ( _, _, 1 ) , [ a, b] ) => {
190+ // a + b - ab
191+ let mut r = a. mul ( b) ;
192+ r. scale ( & Coef :: from_i64 ( -1 , m) ) ;
193+ r. add_assign ( a) ;
194+ r. add_assign ( b) ;
195+ r
196+ }
197+ ( Expr :: BVXor ( _, _, 1 ) , [ a, b] ) => {
198+ // a + b - 2ab
199+ let mut r = a. mul ( b) ;
200+ r. scale ( & Coef :: from_i64 ( -2 , m) ) ;
201+ r. add_assign ( a) ;
202+ r. add_assign ( b) ;
203+ r
204+ }
205+ ( Expr :: BVAnd ( _, _, 1 ) , [ a, b] ) => {
206+ // ab
207+ a. mul ( b)
208+ }
209+ ( Expr :: BVNot ( _, 1 ) , [ a] ) => {
210+ // 1 - a
211+ let one = Poly :: from_monoms ( m, [ ( Coef :: from_i64 ( 1 , m) , vec ! [ ] . into ( ) ) ] . into_iter ( ) ) ;
212+ let mut r = a. clone ( ) ;
213+ r. scale ( & Coef :: from_i64 ( -1 , m) ) ;
214+ r. add_assign ( & one) ;
215+ r
216+ }
217+ ( Expr :: BVSlice { .. } , [ _] ) => {
218+ todo ! ( "should not get here!" )
219+ }
220+ ( Expr :: BVLiteral ( value) , _) => {
221+ let value = value. get ( ctx) ;
222+ debug_assert_eq ! ( value. width( ) , 1 ) ;
223+ if value. is_true ( ) {
224+ Poly :: from_monoms ( m, [ ( Coef :: from_i64 ( 1 , m) , vec ! [ ] . into ( ) ) ] . into_iter ( ) )
225+ } else {
226+ Poly :: from_monoms ( m, [ ( Coef :: from_i64 ( 0 , m) , vec ! [ ] . into ( ) ) ] . into_iter ( ) )
227+ }
228+ }
229+ other => todo ! ( "add support for {other:?}" ) ,
230+ }
231+ } )
167232}
0 commit comments