Progress towards using generators

This commit is contained in:
wborgeaud 2022-02-15 16:59:17 +01:00
parent 0aefe92b8c
commit c74b0c91c8
7 changed files with 53 additions and 129 deletions

View File

@ -1,80 +0,0 @@
// use std::collections::HashMap;
// use std::fmt::{Debug, Error, Formatter};
// use std::hash::{Hash, Hasher};
// use std::sync::Arc;
//
// use plonky2_field::extension_field::Extendable;
//
// use crate::gates::gate::Gate;
// use crate::hash::hash_types::RichField;
// use crate::iop::target::Target;
// use crate::plonk::circuit_builder::CircuitBuilder;
//
// pub trait BatchableGate<F: RichField + Extendable<D>, const D: usize>: Gate<F, D> {
// fn num_ops(&self) -> usize;
//
// // TODO: It would be nice to have a `Parameters` associated type.
// fn fill_gate(
// &self,
// params: &[F],
// current_slot: &CurrentSlot<F, D>,
// builder: &mut CircuitBuilder<F, D>,
// );
// }
//
// #[derive(Clone, Debug)]
// pub struct CurrentSlot<F: RichField + Extendable<D>, const D: usize> {
// pub current_slot: HashMap<Vec<F>, (usize, usize)>,
// }
//
// #[derive(Clone)]
// pub struct GateRef<F: RichField + Extendable<D>, const D: usize>(
// pub(crate) Arc<dyn BatchableGate<F, D>>,
// );
//
// impl<F: RichField + Extendable<D>, const D: usize> GateRef<F, D> {
// pub fn new<G: BatchableGate<F, D>>(gate: G) -> GateRef<F, D> {
// GateRef(Arc::new(gate))
// }
// }
//
// impl<F: RichField + Extendable<D>, const D: usize> PartialEq for GateRef<F, D> {
// fn eq(&self, other: &Self) -> bool {
// self.0.id() == other.0.id()
// }
// }
//
// impl<F: RichField + Extendable<D>, const D: usize> Hash for GateRef<F, D> {
// fn hash<H: Hasher>(&self, state: &mut H) {
// self.0.id().hash(state)
// }
// }
//
// impl<F: RichField + Extendable<D>, const D: usize> Eq for GateRef<F, D> {}
//
// impl<F: RichField + Extendable<D>, const D: usize> Debug for GateRef<F, D> {
// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
// write!(f, "{}", self.0.id())
// }
// }
//
// // pub trait SingleOpGate<F: RichField + Extendable<D>, const D: usize>: Gate<F, D> {}
// // impl<F: RichField + Extendable<D>, G: SingleOpGate<F, D>, const D: usize> MultiOpsGate<F, D> for G {
// // fn num_ops(&self) -> usize {
// // 1
// // }
// //
// // fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec<Target> {
// // unreachable!()
// // }
// // }
//
// pub trait MultiOpsGate<F: RichField + Extendable<D>, const D: usize>: Gate<F, D> {}
//
// impl<F: RichField + Extendable<D>, G: MultiOpsGate<F, D>, const D: usize> BatchableGate<F, D>
// for G
// {
// fn num_ops(&self) -> usize {
// self.num_ops()
// }
// }

View File

@ -321,16 +321,6 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
} }
} }
// impl<F: Richfield + Extendable<d>, const D: usize> Singleopgate<f, d> for multiopsgate<f, d> {
// fn num_ops(&self) -> usize {
// 1
// }
//
// fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec<Target> {
// unreachable!()
// }
// }
impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D>
for ComparisonGate<F, D> for ComparisonGate<F, D>
{ {

View File

@ -1,5 +1,3 @@
use std::ops::Range;
use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field; use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField; use plonky2_field::packed_field::PackedField;
@ -26,12 +24,14 @@ pub struct ConstantGate {
} }
impl ConstantGate { impl ConstantGate {
pub fn consts_inputs(&self) -> Range<usize> { pub fn const_input(&self, i: usize) -> usize {
0..self.num_consts debug_assert!(i < self.num_consts);
i
} }
pub fn wires_outputs(&self) -> Range<usize> { pub fn wire_output(&self, i: usize) -> usize {
0..self.num_consts debug_assert!(i < self.num_consts);
i
} }
} }
@ -41,9 +41,10 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
} }
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> { fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
self.consts_inputs() (0..self.num_consts)
.zip(self.wires_outputs()) .map(|i| {
.map(|(con, out)| vars.local_constants[con] - vars.local_wires[out]) vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)]
})
.collect() .collect()
} }
@ -64,10 +65,12 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
builder: &mut CircuitBuilder<F, D>, builder: &mut CircuitBuilder<F, D>,
vars: EvaluationTargets<D>, vars: EvaluationTargets<D>,
) -> Vec<ExtensionTarget<D>> { ) -> Vec<ExtensionTarget<D>> {
self.consts_inputs() (0..self.num_consts)
.zip(self.wires_outputs()) .map(|i| {
.map(|(con, out)| { builder.sub_extension(
builder.sub_extension(vars.local_constants[con], vars.local_wires[out]) vars.local_constants[self.const_input(i)],
vars.local_wires[self.wire_output(i)],
)
}) })
.collect() .collect()
} }
@ -77,12 +80,20 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
gate_index: usize, gate_index: usize,
local_constants: &[F], local_constants: &[F],
) -> Vec<Box<dyn WitnessGenerator<F>>> { ) -> Vec<Box<dyn WitnessGenerator<F>>> {
let gen = ConstantGenerator { (0..self.num_consts)
gate_index, .map(|i| {
gate: *self, let g: Box<dyn WitnessGenerator<F>> = Box::new(
constants: local_constants[self.consts_inputs()].to_vec(), ConstantGenerator {
}; gate_index,
vec![Box::new(gen.adapter())] gate: *self,
i,
constant: local_constants[self.const_input(i)],
}
.adapter(),
);
g
})
.collect()
} }
fn num_wires(&self) -> usize { fn num_wires(&self) -> usize {
@ -116,11 +127,9 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
vars: EvaluationVarsBasePacked<P>, vars: EvaluationVarsBasePacked<P>,
mut yield_constr: StridedConstraintConsumer<P>, mut yield_constr: StridedConstraintConsumer<P>,
) { ) {
yield_constr.many( yield_constr.many((0..self.num_consts).map(|i| {
self.consts_inputs() vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)]
.zip(self.wires_outputs()) }));
.map(|(con, out)| vars.local_constants[con] - vars.local_wires[out]),
);
} }
} }
@ -128,7 +137,8 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
struct ConstantGenerator<F: Field> { struct ConstantGenerator<F: Field> {
gate_index: usize, gate_index: usize,
gate: ConstantGate, gate: ConstantGate,
constants: Vec<F>, i: usize,
constant: F,
} }
impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> { impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
@ -137,13 +147,11 @@ impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
} }
fn run_once(&self, _witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { fn run_once(&self, _witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
for (con, out) in self.gate.consts_inputs().zip(self.gate.wires_outputs()) { let wire = Wire {
let wire = Wire { gate: self.gate_index,
gate: self.gate_index, input: self.gate.wire_output(self.i),
input: out, };
}; out_buffer.set_wire(wire, self.constant);
out_buffer.set_wire(wire, self.constants[con]);
}
} }
} }

View File

@ -142,10 +142,13 @@ pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + S
fn num_constraints(&self) -> usize; fn num_constraints(&self) -> usize;
/// Number of operations performed by the gate.
fn num_ops(&self) -> usize; fn num_ops(&self) -> usize;
/// Dependencies (inputs) for the i-th operation.
fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec<Target>; fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec<Target>;
/// Fill the dependencies of the
fn fill_gate( fn fill_gate(
&self, &self,
params: &[F], params: &[F],

View File

@ -7,7 +7,6 @@ pub mod arithmetic_extension;
pub mod arithmetic_u32; pub mod arithmetic_u32;
pub mod assert_le; pub mod assert_le;
pub mod base_sum; pub mod base_sum;
pub mod batchable;
pub mod comparison; pub mod comparison;
pub mod constant; pub mod constant;
pub mod exponentiation; pub mod exponentiation;

View File

@ -57,7 +57,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
} }
fn num_ops(&self) -> usize { fn num_ops(&self) -> usize {
1 0
} }
fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec<Target> { fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec<Target> {

View File

@ -662,6 +662,15 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let start = Instant::now(); let start = Instant::now();
let rate_bits = self.config.fri_config.rate_bits; let rate_bits = self.config.fri_config.rate_bits;
for g in &self.gate_instances {
assert_eq!(
g.gate_ref.0.generators(0, &[F::ZERO; 100]).len(),
g.gate_ref.0.num_ops(),
"{}",
g.gate_ref.0.id()
);
}
self.fill_batched_gates(); self.fill_batched_gates();
// Hash the public inputs, and route them to a `PublicInputGate` which will enforce that // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that
@ -739,11 +748,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
constants_sigmas_cap: constants_sigmas_cap.clone(), constants_sigmas_cap: constants_sigmas_cap.clone(),
}; };
let mut gens = self.generators.len();
for (i, g) in self.gate_instances.iter().enumerate() {
gens += g.gate_ref.0.generators(i, &g.constants).len();
dbg!(g.gate_ref.0.id(), gens);
}
// Add gate generators. // Add gate generators.
self.add_generators( self.add_generators(
self.gate_instances self.gate_instances