fn get_boundary_constraints()

in air/src/air/tests.rs [69:217]


fn get_boundary_constraints() {
    // define assertions
    let values = vec![
        BaseElement::new(1),
        BaseElement::new(2),
        BaseElement::new(3),
        BaseElement::new(4),
    ];
    let assertions = vec![
        Assertion::single(0, 0, BaseElement::new(3)), // register 0, step 0 -> group 0
        Assertion::single(0, 9, BaseElement::new(5)), // register 0, step 9 -> group 1
        Assertion::single(1, 9, BaseElement::new(9)), // register 0, step 9 -> group 1
        Assertion::sequence(0, 2, 4, values.clone()), // register 0, steps 2, 6, 10, 14 -> group 4
        Assertion::sequence(1, 2, 4, values.clone()), // register 1, steps 2, 6, 10, 14 -> group 4
        Assertion::sequence(1, 0, 8, values[..2].to_vec()), // register 1, steps 0, 8 -> group 2
        Assertion::sequence(0, 3, 8, values[..2].to_vec()), // register 0, steps 3, 11 -> group 3
        Assertion::periodic(1, 3, 8, BaseElement::new(7)), // register 1, steps 3, 11 -> group 3
    ];

    // instantiate mock AIR
    let trace_length = 16;
    let air = MockAir::with_assertions(assertions, trace_length);
    let no_poly_offset = (0, BaseElement::ONE);
    let g = BaseElement::get_root_of_unity(log2(trace_length)); // trace domain generator

    // build coefficients for random liner combination; these will be derived for assertions
    // sorted first by stride, then by first step, and finally by register (similar to the order)
    // of assertions above
    let mut prng = build_prng();
    let mut expected_cc = BTreeMap::<usize, (BaseElement, BaseElement)>::new();
    expected_cc.insert(0, prng.draw_pair().unwrap());
    expected_cc.insert(1, prng.draw_pair().unwrap());
    expected_cc.insert(2, prng.draw_pair().unwrap());
    expected_cc.insert(6, prng.draw_pair().unwrap());
    expected_cc.insert(7, prng.draw_pair().unwrap());
    expected_cc.insert(3, prng.draw_pair().unwrap());
    expected_cc.insert(4, prng.draw_pair().unwrap());
    expected_cc.insert(5, prng.draw_pair().unwrap());

    // get boundary constraints from AIR, and sort constraint groups so that the order
    // is stable; the original order is just by degree_adjustment
    let mut prng = build_prng();
    let coefficients = (0..8)
        .map(|_| prng.draw_pair().unwrap())
        .collect::<Vec<(BaseElement, BaseElement)>>();
    let mut groups = air.get_boundary_constraints(&coefficients);
    groups.sort_by(|g1, g2| {
        if g1.degree_adjustment() == g2.degree_adjustment() {
            let n1 = &g1.divisor().numerator()[0].1;
            let n2 = &g2.divisor().numerator()[0].1;
            n1.as_int().partial_cmp(&n2.as_int()).unwrap()
        } else {
            g1.degree_adjustment()
                .partial_cmp(&g2.degree_adjustment())
                .unwrap()
        }
    });
    assert_eq!(5, groups.len());

    // group 0
    let group = &groups[0];
    assert_eq!(1, group.divisor().degree());
    assert_eq!(vec![(1, g.exp(0))], group.divisor().numerator());
    assert_eq!(1, group.constraints().len());

    let constraint = &group.constraints()[0];
    assert_eq!(0, constraint.register());
    assert_eq!(vec![BaseElement::new(3)], constraint.poly());
    assert_eq!(no_poly_offset, constraint.poly_offset());
    assert_eq!(expected_cc[&0], constraint.cc().clone());

    // group 1
    let group = &groups[1];
    assert_eq!(1, group.divisor().degree());
    assert_eq!(vec![(1, g.exp(9))], group.divisor().numerator());
    assert_eq!(2, group.constraints().len());

    let constraint = &group.constraints()[0];
    assert_eq!(0, constraint.register());
    assert_eq!(vec![BaseElement::new(5)], constraint.poly());
    assert_eq!(no_poly_offset, constraint.poly_offset());
    assert_eq!(expected_cc[&1], constraint.cc().clone());

    let constraint = &group.constraints()[1];
    assert_eq!(1, constraint.register());
    assert_eq!(vec![BaseElement::new(9)], constraint.poly());
    assert_eq!(no_poly_offset, constraint.poly_offset());
    assert_eq!(expected_cc[&2], constraint.cc().clone());

    // group 2
    let group = &groups[2];
    assert_eq!(2, group.divisor().degree());
    assert_eq!(vec![(2, g.exp(0))], group.divisor().numerator());
    assert_eq!(1, group.constraints().len());

    let constraint = &group.constraints()[0];
    assert_eq!(1, constraint.register());
    assert_eq!(
        build_sequence_poly(&values[..2], trace_length),
        constraint.poly()
    );
    assert_eq!(no_poly_offset, constraint.poly_offset());
    assert_eq!(expected_cc[&3], constraint.cc().clone());

    // group 3
    let group = &groups[3];
    assert_eq!(2, group.divisor().degree());
    assert_eq!(vec![(2, g.exp(2 * 3))], group.divisor().numerator());
    assert_eq!(2, group.constraints().len());

    let constraint = &group.constraints()[0];
    assert_eq!(0, constraint.register());
    assert_eq!(
        build_sequence_poly(&values[..2], trace_length),
        constraint.poly()
    );
    assert_eq!((3, g.inv().exp(3)), constraint.poly_offset());
    assert_eq!(expected_cc[&4], constraint.cc().clone());

    let constraint = &group.constraints()[1];
    assert_eq!(1, constraint.register());
    assert_eq!(vec![BaseElement::new(7)], constraint.poly());
    assert_eq!(no_poly_offset, constraint.poly_offset());
    assert_eq!(expected_cc[&5], constraint.cc().clone());

    // group 4
    let group = &groups[4];
    assert_eq!(4, group.divisor().degree());
    assert_eq!(vec![(4, g.exp(4 * 2))], group.divisor().numerator());
    assert_eq!(2, group.constraints().len());

    let constraint = &group.constraints()[0];
    assert_eq!(0, constraint.register());
    assert_eq!(
        build_sequence_poly(&values, trace_length),
        constraint.poly()
    );
    assert_eq!((2, g.inv().exp(2)), constraint.poly_offset());
    assert_eq!(expected_cc[&6], constraint.cc().clone());

    let constraint = &group.constraints()[1];
    assert_eq!(1, constraint.register());
    assert_eq!(
        build_sequence_poly(&values, trace_length),
        constraint.poly()
    );
    assert_eq!((2, g.inv().exp(2)), constraint.poly_offset());
    assert_eq!(expected_cc[&7], constraint.cc().clone());
}