1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00
ZoKrates/zokrates_core/src/optimizer/duplicate.rs

132 lines
3.8 KiB
Rust

//! Module containing the `DuplicateOptimizer` to remove duplicate constraints
use crate::ir::folder::*;
use crate::ir::*;
use crate::optimizer::canonicalizer::Canonicalizer;
use std::collections::{hash_map::DefaultHasher, HashSet};
use zokrates_field::Field;
type Hash = u64;
fn hash<T: Field>(s: &Statement<T>) -> Hash {
use std::hash::Hash;
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
s.hash(&mut hasher);
hasher.finish()
}
#[derive(Debug, Default)]
pub struct DuplicateOptimizer {
seen: HashSet<Hash>,
}
impl<T: Field> Folder<T> for DuplicateOptimizer {
fn fold_module(&mut self, p: Prog<T>) -> Prog<T> {
// in order to correctly identify duplicates, we need to first canonicalize the statements
let mut canonicalizer = Canonicalizer;
let p = Prog {
statements: p
.statements
.into_iter()
.flat_map(|s| canonicalizer.fold_statement(s))
.collect(),
..p
};
fold_module(self, p)
}
fn fold_statement(&mut self, s: Statement<T>) -> Vec<Statement<T>> {
let hashed = hash(&s);
let result = match self.seen.get(&hashed) {
Some(_) => vec![],
None => vec![s],
};
self.seen.insert(hashed);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::flat_absy::FlatVariable;
use zokrates_field::Bn128Field;
#[test]
fn identity() {
let p: Prog<Bn128Field> = Prog {
statements: vec![
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(3, FlatVariable::new(3)),
LinComb::summand(3, FlatVariable::new(3)),
),
LinComb::one(),
),
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(3, FlatVariable::new(42)),
LinComb::summand(3, FlatVariable::new(3)),
),
LinComb::zero(),
),
],
returns: vec![],
arguments: vec![],
};
let expected = p.clone();
assert_eq!(DuplicateOptimizer::optimize(p), expected);
}
#[test]
fn remove_duplicates() {
let constraint = Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(3, FlatVariable::new(3)),
LinComb::summand(3, FlatVariable::new(3)),
),
LinComb::one(),
);
let p: Prog<Bn128Field> = Prog {
statements: vec![
constraint.clone(),
constraint.clone(),
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(3, FlatVariable::new(42)),
LinComb::summand(3, FlatVariable::new(3)),
),
LinComb::zero(),
),
constraint.clone(),
constraint.clone(),
],
returns: vec![],
arguments: vec![],
};
let expected = Prog {
statements: vec![
constraint,
Statement::constraint(
QuadComb::from_linear_combinations(
LinComb::summand(3, FlatVariable::new(42)),
LinComb::summand(3, FlatVariable::new(3)),
),
LinComb::zero(),
),
],
returns: vec![],
arguments: vec![],
};
assert_eq!(DuplicateOptimizer::optimize(p), expected);
}
}