Merge branch 'main' into efficient_insert

This commit is contained in:
Nicholas Ward 2021-07-01 10:36:22 -07:00
commit 8f33f8e2be
5 changed files with 24 additions and 21 deletions

View File

@ -36,7 +36,7 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
/// The next available index for a public input. /// The next available index for a public input.
public_input_index: usize, public_input_index: usize,
/// The next available index for a VirtualAdviceTarget. /// The next available index for a `VirtualTarget`.
virtual_target_index: usize, virtual_target_index: usize,
copy_constraints: Vec<(Target, Target)>, copy_constraints: Vec<(Target, Target)>,
@ -77,22 +77,18 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(0..n).map(|_i| self.add_public_input()).collect() (0..n).map(|_i| self.add_public_input()).collect()
} }
/// Adds a new "virtual" advice target. This is not an actual wire in the witness, but just a /// Adds a new "virtual" target. This is not an actual wire in the witness, but just a target
/// target that help facilitate witness generation. In particular, a generator can assign a /// that help facilitate witness generation. In particular, a generator can assign a values to a
/// values to a virtual target, which can then be copied to other (virtual or concrete) targets /// virtual target, which can then be copied to other (virtual or concrete) targets. When we
/// via `generate_copy`. When we generate the final witness (a grid of wire values), these /// generate the final witness (a grid of wire values), these virtual targets will go away.
/// virtual targets will go away. pub fn add_virtual_target(&mut self) -> Target {
///
/// Since virtual targets are not part of the actual permutation argument, they cannot be used
/// with `assert_equal`.
pub fn add_virtual_advice_target(&mut self) -> Target {
let index = self.virtual_target_index; let index = self.virtual_target_index;
self.virtual_target_index += 1; self.virtual_target_index += 1;
Target::VirtualAdviceTarget { index } Target::VirtualTarget { index }
} }
pub fn add_virtual_advice_targets(&mut self, n: usize) -> Vec<Target> { pub fn add_virtual_targets(&mut self, n: usize) -> Vec<Target> {
(0..n).map(|_i| self.add_virtual_advice_target()).collect() (0..n).map(|_i| self.add_virtual_target()).collect()
} }
pub fn add_gate_no_constants(&mut self, gate_type: GateRef<F, D>) -> usize { pub fn add_gate_no_constants(&mut self, gate_type: GateRef<F, D>) -> usize {
@ -368,7 +364,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
} }
for index in 0..self.public_input_index { for index in 0..self.public_input_index {
target_partitions.add_partition(Target::PublicInput { index }) target_partitions.add_partition(Target::PublicInput { index });
}
for index in 0..self.virtual_target_index {
target_partitions.add_partition(Target::VirtualTarget { index });
} }
for &(a, b) in &self.copy_constraints { for &(a, b) in &self.copy_constraints {

View File

@ -9,14 +9,14 @@ use crate::wire::Wire;
use crate::witness::PartialWitness; use crate::witness::PartialWitness;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Split the given integer into a list of virtual advice targets, where each one represents a /// Split the given integer into a list of virtual targets, where each one represents a bit of
/// bit of the integer, with little-endian ordering. /// the integer, with little-endian ordering.
/// ///
/// Note that this only handles witness generation; it does not enforce that the decomposition /// Note that this only handles witness generation; it does not enforce that the decomposition
/// is correct. The output should be treated as a "purported" decomposition which must be /// is correct. The output should be treated as a "purported" decomposition which must be
/// enforced elsewhere. /// enforced elsewhere.
pub(crate) fn split_le_virtual(&mut self, integer: Target, num_bits: usize) -> Vec<Target> { pub(crate) fn split_le_virtual(&mut self, integer: Target, num_bits: usize) -> Vec<Target> {
let bit_targets = self.add_virtual_advice_targets(num_bits); let bit_targets = self.add_virtual_targets(num_bits);
self.add_generator(SplitGenerator { self.add_generator(SplitGenerator {
integer, integer,
bits: bit_targets.clone(), bits: bit_targets.clone(),

View File

@ -57,7 +57,7 @@ impl TargetPartitions {
} }
pub fn to_wire_partitions(&self) -> WirePartitions { pub fn to_wire_partitions(&self) -> WirePartitions {
// Here we just drop all CircuitInputs, leaving all GateInputs. // Here we keep just the Wire targets, filtering out everything else.
let mut partitions = Vec::new(); let mut partitions = Vec::new();
let mut indices = HashMap::new(); let mut indices = HashMap::new();

View File

@ -8,7 +8,10 @@ use crate::wire::Wire;
pub enum Target { pub enum Target {
Wire(Wire), Wire(Wire),
PublicInput { index: usize }, PublicInput { index: usize },
VirtualAdviceTarget { index: usize }, /// A target that doesn't have any inherent location in the witness (but it can be copied to
/// another target that does). This is useful for representing intermediate values in witness
/// generation.
VirtualTarget { index: usize },
} }
impl Target { impl Target {
@ -20,7 +23,7 @@ impl Target {
match self { match self {
Target::Wire(wire) => wire.is_routable(config), Target::Wire(wire) => wire.is_routable(config),
Target::PublicInput { .. } => true, Target::PublicInput { .. } => true,
Target::VirtualAdviceTarget { .. } => false, Target::VirtualTarget { .. } => true,
} }
} }

View File

@ -30,7 +30,7 @@ impl<F: Field> Witness<F> {
F: Extendable<D>, F: Extendable<D>,
{ {
for &(a, b) in copy_constraints { for &(a, b) in copy_constraints {
// TODO: Take care of public inputs once they land. // TODO: Take care of public inputs once they land, and virtual targets.
if let ( if let (
Target::Wire(Wire { Target::Wire(Wire {
gate: a_gate, gate: a_gate,