mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-05-13 03:00:26 -04:00
Merge pull request #524 from powdr-labs/processor-tests
Add unit test to Processor
This commit is contained in:
@@ -164,9 +164,9 @@ impl<T: FieldElement> FixedLookup<T> {
|
||||
_fixed_data: &FixedData<T>,
|
||||
identities: &[&Identity<T>],
|
||||
witness_names: &HashSet<&str>,
|
||||
) -> Option<Box<Self>> {
|
||||
) -> Option<Self> {
|
||||
if identities.is_empty() && witness_names.is_empty() {
|
||||
Some(Box::default())
|
||||
Some(Default::default())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ pub fn split_out_machines<'a, T: FieldElement>(
|
||||
}
|
||||
}
|
||||
ExtractionOutput {
|
||||
fixed_lookup: *fixed_lookup,
|
||||
fixed_lookup,
|
||||
machines,
|
||||
base_identities,
|
||||
base_witnesses: remaining_witnesses,
|
||||
|
||||
@@ -46,27 +46,7 @@ where
|
||||
if degree.is_zero() {
|
||||
panic!("Resulting degree is zero. Please ensure that there is at least one non-constant fixed column to set the degree.");
|
||||
}
|
||||
let witness_cols = ColumnMap::from(
|
||||
analyzed
|
||||
.committed_polys_in_source_order()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (poly, value))| {
|
||||
if poly.length.is_some() {
|
||||
unimplemented!("Committed arrays not implemented.")
|
||||
}
|
||||
assert_eq!(i as u64, poly.id);
|
||||
let col = WitnessColumn::new(i, &poly.absolute_name, value);
|
||||
col
|
||||
}),
|
||||
PolynomialType::Committed,
|
||||
);
|
||||
|
||||
let fixed_cols = ColumnMap::from(
|
||||
fixed_col_values.iter().map(|(n, v)| FixedColumn::new(n, v)),
|
||||
PolynomialType::Constant,
|
||||
);
|
||||
let fixed = FixedData::new(degree, fixed_cols, witness_cols);
|
||||
let fixed = FixedData::new(analyzed, degree, fixed_col_values);
|
||||
let identities = substitute_constants(&analyzed.identities, &analyzed.constants);
|
||||
|
||||
let GlobalConstraints {
|
||||
@@ -204,10 +184,30 @@ pub struct FixedData<'a, T> {
|
||||
|
||||
impl<'a, T: FieldElement> FixedData<'a, T> {
|
||||
pub fn new(
|
||||
analyzed: &'a Analyzed<T>,
|
||||
degree: DegreeType,
|
||||
fixed_cols: ColumnMap<FixedColumn<'a, T>>,
|
||||
witness_cols: ColumnMap<WitnessColumn<'a, T>>,
|
||||
fixed_col_values: &'a [(&'a str, Vec<T>)],
|
||||
) -> Self {
|
||||
let witness_cols = ColumnMap::from(
|
||||
analyzed
|
||||
.committed_polys_in_source_order()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, (poly, value))| {
|
||||
if poly.length.is_some() {
|
||||
unimplemented!("Committed arrays not implemented.")
|
||||
}
|
||||
assert_eq!(i as u64, poly.id);
|
||||
let col = WitnessColumn::new(i, &poly.absolute_name, value);
|
||||
col
|
||||
}),
|
||||
PolynomialType::Committed,
|
||||
);
|
||||
|
||||
let fixed_cols = ColumnMap::from(
|
||||
fixed_col_values.iter().map(|(n, v)| FixedColumn::new(n, v)),
|
||||
PolynomialType::Constant,
|
||||
);
|
||||
FixedData {
|
||||
degree,
|
||||
fixed_cols,
|
||||
|
||||
@@ -126,3 +126,109 @@ impl<'a, T: FieldElement> Processor<'a, T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ast::analyzed::PolyID;
|
||||
use number::{FieldElement, GoldilocksField};
|
||||
use pil_analyzer::analyze_string;
|
||||
|
||||
use crate::{
|
||||
constant_evaluator::generate,
|
||||
witgen::{
|
||||
identity_processor::IdentityProcessor, machines::FixedLookup, rows::RowFactory,
|
||||
FixedData,
|
||||
},
|
||||
};
|
||||
|
||||
use super::Processor;
|
||||
|
||||
fn name_to_poly_id<T: FieldElement>(fixed_data: &FixedData<T>) -> BTreeMap<String, PolyID> {
|
||||
let mut name_to_poly_id = BTreeMap::new();
|
||||
for (poly_id, col) in fixed_data.witness_cols.iter() {
|
||||
name_to_poly_id.insert(col.name.clone(), poly_id);
|
||||
}
|
||||
for (poly_id, col) in fixed_data.fixed_cols.iter() {
|
||||
name_to_poly_id.insert(col.name.clone(), poly_id);
|
||||
}
|
||||
name_to_poly_id
|
||||
}
|
||||
|
||||
/// Constructs a processor for a given PIL, then calls a function on it.
|
||||
fn do_with_processor<T: FieldElement, R>(
|
||||
src: &str,
|
||||
f: impl Fn(&mut Processor<T>, BTreeMap<String, PolyID>) -> R,
|
||||
) -> R {
|
||||
let analyzed = analyze_string(src);
|
||||
let (constants, degree) = generate(&analyzed);
|
||||
let fixed_data = FixedData::new(&analyzed, degree, &constants);
|
||||
|
||||
// No submachines
|
||||
let mut fixed_lookup = FixedLookup::default();
|
||||
let machines = vec![];
|
||||
|
||||
// No global range constraints
|
||||
let global_range_constraints = fixed_data.witness_map_with(None);
|
||||
|
||||
let row_factory = RowFactory::new(&fixed_data, global_range_constraints);
|
||||
let data = vec![row_factory.fresh_row(); fixed_data.degree as usize];
|
||||
let identity_processor = IdentityProcessor::new(&fixed_data, &mut fixed_lookup, machines);
|
||||
let row_offset = 0;
|
||||
let identities = analyzed.identities.iter().collect();
|
||||
|
||||
let mut processor = Processor::new(
|
||||
row_offset,
|
||||
data,
|
||||
identity_processor,
|
||||
identities,
|
||||
&fixed_data,
|
||||
row_factory,
|
||||
);
|
||||
|
||||
f(&mut processor, name_to_poly_id(&fixed_data))
|
||||
}
|
||||
|
||||
fn solve_and_assert<T: FieldElement>(src: &str, asserted_values: &[(usize, &str, u64)]) {
|
||||
do_with_processor(src, |processor, poly_ids| {
|
||||
processor.solve().unwrap();
|
||||
|
||||
// Can't use processor.finish(), because we don't own it...
|
||||
let data = processor.data.clone();
|
||||
|
||||
// In case of any error, this will be useful
|
||||
for (i, row) in data.iter().enumerate() {
|
||||
println!("{}", row.render(&format!("Row {i}"), true));
|
||||
}
|
||||
|
||||
for &(i, name, expected) in asserted_values.iter() {
|
||||
let poly_id = poly_ids[name];
|
||||
let row = &data[i];
|
||||
let actual: T = row[&poly_id].value.unwrap_or_default();
|
||||
assert_eq!(actual, T::from(expected));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fibonacci() {
|
||||
let src = r#"
|
||||
constant %N = 8;
|
||||
|
||||
namespace Fibonacci(%N);
|
||||
col fixed ISFIRST = [1] + [0]*;
|
||||
col fixed ISLAST = [0]* + [1];
|
||||
col witness x, y;
|
||||
|
||||
// Start with 1, 1
|
||||
ISFIRST * (y - 1) = 0;
|
||||
ISFIRST * (x - 1) = 0;
|
||||
|
||||
(1-ISLAST) * (x' - y) = 0;
|
||||
(1-ISLAST) * (y' - (x + y)) = 0;
|
||||
"#;
|
||||
|
||||
solve_and_assert::<GoldilocksField>(src, &[(7, "Fibonacci.y", 34)]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user