Skip to content

Commit 02d64e0

Browse files
authored
Give access to column allocator. (#3456)
If we need to create new variables / column in the optimization procedure, we have to make sure that their IDs do not clash and this is what the ColumnAllocator is for.
1 parent 1e69078 commit 02d64e0

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

autoprecompiles/src/lib.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,15 +393,22 @@ impl<T, I> Apc<T, I> {
393393
}
394394

395395
/// Allocates global poly_ids and keeps track of substitutions
396-
struct ColumnAllocator {
396+
pub struct ColumnAllocator {
397397
/// For each original air, for each original column index, the associated poly_id in the APC air
398398
subs: Vec<Vec<u64>>,
399399
/// The next poly_id to issue
400400
next_poly_id: u64,
401401
}
402402

403403
impl ColumnAllocator {
404-
fn issue_next_poly_id(&mut self) -> u64 {
404+
pub fn from_max_poly_id_of_machine(machine: &SymbolicMachine<impl FieldElement>) -> Self {
405+
Self {
406+
subs: Vec::new(),
407+
next_poly_id: machine.main_columns().map(|c| c.id).max().unwrap_or(0) + 1,
408+
}
409+
}
410+
411+
pub fn issue_next_poly_id(&mut self) -> u64 {
405412
let id = self.next_poly_id;
406413
self.next_poly_id += 1;
407414
id
@@ -430,11 +437,12 @@ pub fn build<A: Adapter>(
430437
metrics::counter!("before_opt_interactions", &labels)
431438
.absolute(machine.unique_references().count() as u64);
432439

433-
let machine = optimizer::optimize::<A>(
440+
let (machine, column_allocator) = optimizer::optimize::<A>(
434441
machine,
435442
vm_config.bus_interaction_handler,
436443
degree_bound,
437444
&vm_config.bus_map,
445+
column_allocator,
438446
)?;
439447

440448
// add guards to constraints that are not satisfied by zeroes

autoprecompiles/src/optimizer.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use powdr_number::FieldElement;
1616

1717
use crate::constraint_optimizer::trivial_simplifications;
1818
use crate::range_constraint_optimizer::optimize_range_constraints;
19+
use crate::ColumnAllocator;
1920
use crate::{
2021
adapter::Adapter,
2122
constraint_optimizer::optimize_constraints,
@@ -26,12 +27,16 @@ use crate::{
2627
BusMap, BusType, DegreeBound, SymbolicBusInteraction, SymbolicMachine,
2728
};
2829

30+
/// Optimizes a given symbolic machine and returns an equivalent, but "simpler" one.
31+
/// All constraints in the returned machine will respect the given degree bound.
32+
/// New variables may be introduced in the process.
2933
pub fn optimize<A: Adapter>(
3034
mut machine: SymbolicMachine<A::PowdrField>,
3135
bus_interaction_handler: A::BusInteractionHandler,
3236
degree_bound: DegreeBound,
3337
bus_map: &BusMap<A::CustomBusTypes>,
34-
) -> Result<SymbolicMachine<A::PowdrField>, crate::constraint_optimizer::Error> {
38+
column_allocator: ColumnAllocator,
39+
) -> Result<(SymbolicMachine<A::PowdrField>, ColumnAllocator), crate::constraint_optimizer::Error> {
3540
let mut stats_logger = StatsLogger::start(&machine);
3641

3742
if let Some(exec_bus_id) = bus_map.get_bus_id(&BusType::ExecutionBridge) {
@@ -112,7 +117,10 @@ pub fn optimize<A: Adapter>(
112117
== GroupedExpression::from_number(A::PowdrField::from(pc_lookup_bus_id))),
113118
"Expected all PC lookups to be removed."
114119
);
115-
Ok(constraint_system_to_symbolic_machine(constraint_system))
120+
Ok((
121+
constraint_system_to_symbolic_machine(constraint_system),
122+
column_allocator,
123+
))
116124
}
117125

118126
pub fn optimize_exec_bus<T: FieldElement>(

openvm/benches/optimizer_benchmark.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2-
use powdr_autoprecompiles::{optimizer::optimize, SymbolicMachine};
2+
use powdr_autoprecompiles::{optimizer::optimize, ColumnAllocator, SymbolicMachine};
33
use powdr_number::BabyBearField;
44
use powdr_openvm::{
55
bus_interaction_handler::OpenVmBusInteractionHandler, bus_map::default_openvm_bus_map,
@@ -14,16 +14,21 @@ fn optimize_keccak_benchmark(c: &mut Criterion) {
1414
let file = std::fs::File::open("tests/keccak_apc_pre_opt.cbor").unwrap();
1515
let reader = std::io::BufReader::new(file);
1616
let machine: SymbolicMachine<BabyBearField> = serde_cbor::from_reader(reader).unwrap();
17-
1817
group.bench_function("optimize", |b| {
1918
b.iter_batched(
20-
|| machine.clone(),
21-
|machine| {
19+
|| {
20+
(
21+
machine.clone(),
22+
ColumnAllocator::from_max_poly_id_of_machine(&machine),
23+
)
24+
},
25+
|(machine, column_allocator)| {
2226
optimize::<BabyBearOpenVmApcAdapter>(
2327
black_box(machine),
2428
OpenVmBusInteractionHandler::default(),
2529
DEFAULT_DEGREE_BOUND,
2630
&default_openvm_bus_map(),
31+
column_allocator,
2732
)
2833
.unwrap()
2934
},

openvm/tests/optimizer.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use expect_test::expect;
22
use powdr_autoprecompiles::optimizer::optimize;
3-
use powdr_autoprecompiles::SymbolicMachine;
3+
use powdr_autoprecompiles::{ColumnAllocator, SymbolicMachine};
44
use powdr_number::BabyBearField;
55
use powdr_openvm::{
66
bus_interaction_handler::OpenVmBusInteractionHandler, bus_map::default_openvm_bus_map,
@@ -39,13 +39,16 @@ fn test_optimize() {
3939
let machine: SymbolicMachine<BabyBearField> = serde_cbor::from_reader(reader).unwrap();
4040
assert!(machine.derived_columns.is_empty());
4141

42+
let column_allocator = ColumnAllocator::from_max_poly_id_of_machine(&machine);
4243
let machine = optimize::<BabyBearOpenVmApcAdapter>(
4344
machine,
4445
OpenVmBusInteractionHandler::default(),
4546
DEFAULT_DEGREE_BOUND,
4647
&default_openvm_bus_map(),
48+
column_allocator,
4749
)
48-
.unwrap();
50+
.unwrap()
51+
.0;
4952

5053
// This cbor file above has the `is_valid` column removed, this is why the number below
5154
// might be one less than in other tests.
@@ -69,14 +72,17 @@ fn test_sha256() {
6972
let reader = flate2::read::GzDecoder::new(file);
7073
let machine: SymbolicMachine<BabyBearField> = serde_cbor::from_reader(reader).unwrap();
7174
assert!(machine.derived_columns.is_empty());
75+
let column_allocator = ColumnAllocator::from_max_poly_id_of_machine(&machine);
7276

7377
let machine = optimize::<BabyBearOpenVmApcAdapter>(
7478
machine,
7579
OpenVmBusInteractionHandler::default(),
7680
DEFAULT_DEGREE_BOUND,
7781
&default_openvm_bus_map(),
82+
column_allocator,
7883
)
79-
.unwrap();
84+
.unwrap()
85+
.0;
8086

8187
// This cbor file above has the `is_valid` column removed, this is why the number below
8288
// might be one less than in other tests.

0 commit comments

Comments
 (0)