11use crate :: adapter:: { Adapter , AdapterApc , AdapterVmConfig } ;
22use crate :: blocks:: BasicBlock ;
33use crate :: bus_map:: { BusMap , BusType } ;
4+ use crate :: empirical_constraints:: { add_empirical_constraints, EmpiricalConstraints } ;
45use crate :: evaluation:: AirStats ;
56use crate :: expression_conversion:: algebraic_to_grouped_expression;
67use crate :: symbolic_machine_generator:: convert_machine_field_type;
@@ -394,9 +395,10 @@ impl<T, I> Apc<T, I> {
394395}
395396
396397/// Allocates global poly_ids and keeps track of substitutions
398+ #[ derive( Debug ) ]
397399pub struct ColumnAllocator {
398400 /// For each original air, for each original column index, the associated poly_id in the APC air
399- subs : Vec < Vec < u64 > > ,
401+ pub subs : Vec < Vec < u64 > > ,
400402 /// The next poly_id to issue
401403 next_poly_id : u64 ,
402404}
@@ -421,6 +423,7 @@ pub fn build<A: Adapter>(
421423 vm_config : AdapterVmConfig < A > ,
422424 degree_bound : DegreeBound ,
423425 apc_candidates_dir_path : Option < & Path > ,
426+ empirical_constraints : & EmpiricalConstraints ,
424427) -> Result < AdapterApc < A > , crate :: constraint_optimizer:: Error > {
425428 let start = std:: time:: Instant :: now ( ) ;
426429
@@ -430,6 +433,14 @@ pub fn build<A: Adapter>(
430433 & vm_config. bus_map ,
431434 ) ;
432435
436+ let ( range_analyzer_constraints, _equivalence_analyzer_constraints) =
437+ add_empirical_constraints :: < A > (
438+ empirical_constraints,
439+ & column_allocator. subs ,
440+ & block,
441+ machine. main_columns ( ) ,
442+ ) ;
443+
433444 let labels = [ ( "apc_start_pc" , block. start_pc . to_string ( ) ) ] ;
434445 metrics:: counter!( "before_opt_cols" , & labels)
435446 . absolute ( machine. unique_references ( ) . count ( ) as u64 ) ;
@@ -438,13 +449,33 @@ pub fn build<A: Adapter>(
438449 metrics:: counter!( "before_opt_interactions" , & labels)
439450 . absolute ( machine. unique_references ( ) . count ( ) as u64 ) ;
440451
452+ let mut baseline = machine;
453+
454+ let ( machine, column_allocator) = optimizer:: optimize :: < A > (
455+ baseline. clone ( ) ,
456+ vm_config. bus_interaction_handler . clone ( ) ,
457+ degree_bound,
458+ & vm_config. bus_map ,
459+ column_allocator,
460+ )
461+ . unwrap ( ) ;
462+ let dumb_precompile = machine. render ( & vm_config. bus_map ) ;
463+
464+ baseline. constraints . extend ( range_analyzer_constraints) ;
465+ // TODO: Appears to be buggy
466+ // baseline
467+ // .constraints
468+ // .extend(equivalence_analyzer_constraints);
469+
441470 let ( machine, column_allocator) = optimizer:: optimize :: < A > (
442- machine ,
471+ baseline ,
443472 vm_config. bus_interaction_handler ,
444473 degree_bound,
445474 & vm_config. bus_map ,
446475 column_allocator,
447- ) ?;
476+ )
477+ . unwrap ( ) ;
478+ let ai_precompile = machine. render ( & vm_config. bus_map ) ;
448479
449480 // add guards to constraints that are not satisfied by zeroes
450481 let ( machine, column_allocator) = add_guards ( machine, column_allocator) ;
@@ -469,6 +500,16 @@ pub fn build<A: Adapter>(
469500 std:: fs:: File :: create ( & ser_path) . expect ( "Failed to create file for APC candidate" ) ;
470501 let writer = BufWriter :: new ( file) ;
471502 serde_cbor:: to_writer ( writer, & apc) . expect ( "Failed to write APC candidate to file" ) ;
503+
504+ let dumb_path = path
505+ . join ( format ! ( "apc_candidate_{}_dumb.txt" , apc. start_pc( ) ) )
506+ . with_extension ( "txt" ) ;
507+ std:: fs:: write ( dumb_path, dumb_precompile) . unwrap ( ) ;
508+
509+ let ai_path = path
510+ . join ( format ! ( "apc_candidate_{}_ai.txt" , apc. start_pc( ) ) )
511+ . with_extension ( "txt" ) ;
512+ std:: fs:: write ( ai_path, ai_precompile) . unwrap ( ) ;
472513 }
473514
474515 metrics:: gauge!( "apc_gen_time_ms" , & labels) . set ( start. elapsed ( ) . as_millis ( ) as f64 ) ;
@@ -556,11 +597,16 @@ fn add_guards<T: FieldElement>(
556597
557598 machine. constraints . extend ( is_valid_mults) ;
558599
559- assert_eq ! (
560- pre_degree,
561- machine. degree( ) ,
562- "Degree should not change after adding guards"
563- ) ;
600+ // TODO: Why do we need this?
601+ if pre_degree != 0 {
602+ assert_eq ! (
603+ pre_degree,
604+ machine. degree( ) ,
605+ "Degree should not change after adding guards, but changed from {} to {}" ,
606+ pre_degree,
607+ machine. degree( ) ,
608+ ) ;
609+ }
564610
565611 // This needs to be added after the assertion above because it's a quadratic constraint
566612 // so it may increase the degree of the machine.
0 commit comments