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>
for ComparisonGate<F, D>
{

View File

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

View File

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

View File

@ -7,7 +7,6 @@ pub mod arithmetic_extension;
pub mod arithmetic_u32;
pub mod assert_le;
pub mod base_sum;
pub mod batchable;
pub mod comparison;
pub mod constant;
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 {
1
0
}
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 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();
// 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(),
};
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.
self.add_generators(
self.gate_instances