Skip to content

Commit 9b991e0

Browse files
PratyushCopilot
andauthored
Use closures in enforce_constraints (#405)
* Use closures in `enforce_constraints` * Parallelize finalize * Optimizations and fixes * Add itertools * Deduplicate some code * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> * Address review comment * Remove itertools --------- Co-authored-by: Copilot <[email protected]>
1 parent 4445b8f commit 9b991e0

File tree

14 files changed

+706
-220
lines changed

14 files changed

+706
-220
lines changed

relations/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ foldhash = { workspace = true }
2626
[dev-dependencies]
2727
ark-test-curves = { workspace = true, default-features = false, features = [ "bls12_381_scalar_field" ] }
2828
jemallocator = { version = "0.5" }
29+
mimalloc = { version = "0.1" }
2930

3031
[features]
3132
default = []
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#[global_allocator]
2+
static GLOBAL: MiMalloc = MiMalloc;
3+
4+
use ark_ff::{Field, UniformRand};
5+
use ark_relations::gr1cs::{
6+
ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, LinearCombination,
7+
OptimizationGoal, SynthesisMode,
8+
};
9+
use ark_std::rand::{Rng, SeedableRng};
10+
use ark_test_curves::bls12_381::Fr;
11+
// use jemallocator::Jemalloc;
12+
use mimalloc::MiMalloc;
13+
14+
pub const NUM_COEFFS_IN_LC: usize = 10;
15+
16+
struct BenchCircuit {
17+
a: Fr,
18+
b: Fr,
19+
c: Fr,
20+
num_constraints: usize,
21+
}
22+
23+
impl ConstraintSynthesizer<Fr> for BenchCircuit {
24+
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> ark_relations::gr1cs::Result<()> {
25+
let a = cs.new_witness_variable(|| Ok(self.a)).unwrap();
26+
let b = cs.new_witness_variable(|| Ok(self.b)).unwrap();
27+
let c = cs.new_witness_variable(|| Ok(self.c)).unwrap();
28+
let mut variables = vec![a, b, c];
29+
variables.reserve(3 * self.num_constraints);
30+
let mut lcs = Vec::with_capacity(self.num_constraints);
31+
32+
let mut rng_a = ark_std::rand::rngs::StdRng::seed_from_u64(0 as u64);
33+
let mut rng_b = ark_std::rand::rngs::StdRng::seed_from_u64(rng_a.gen::<u64>());
34+
let mut rng_c = ark_std::rand::rngs::StdRng::seed_from_u64(rng_a.gen::<u64>());
35+
36+
for i in 0..self.num_constraints {
37+
let cur_num_vars = ark_std::cmp::min(variables.len(), 10);
38+
let lower = variables.len().checked_sub(cur_num_vars).unwrap_or(0);
39+
let upper = variables.len();
40+
41+
let a_i_lc_size = rng_a.gen_range(1..=NUM_COEFFS_IN_LC);
42+
let mut a_i = || {
43+
LinearCombination(
44+
(0..a_i_lc_size)
45+
.map(|_| (Fr::ONE, variables[rng_a.gen_range(lower..upper)]))
46+
.collect::<Vec<_>>(),
47+
)
48+
};
49+
50+
let b_i_lc_size = rng_b.gen_range(1..=NUM_COEFFS_IN_LC);
51+
let b_i = || {
52+
LinearCombination(
53+
(0..b_i_lc_size)
54+
.map(|_| (Fr::ONE, variables[rng_b.gen_range(lower..upper)]))
55+
.collect::<Vec<_>>(),
56+
)
57+
};
58+
59+
let c_i = variables[rng_c.gen_range(lower..upper)];
60+
61+
if i % 2 == 0 {
62+
let extra_lc = || {
63+
LinearCombination(
64+
(0..a_i_lc_size)
65+
.map(|_| (Fr::ONE, variables[rng_c.gen_range(lower..upper)]))
66+
.collect::<Vec<_>>(),
67+
)
68+
};
69+
let extra_lc = cs.new_lc(extra_lc)?;
70+
lcs.push(extra_lc);
71+
cs.enforce_r1cs_constraint(|| a_i() + extra_lc, b_i, || c_i.into())?;
72+
} else {
73+
cs.enforce_r1cs_constraint(a_i, b_i, || c_i.into())?;
74+
};
75+
let v1 = cs.new_witness_variable(|| Ok(self.a))?;
76+
let v2 = cs.new_witness_variable(|| Ok(self.a))?;
77+
let v3 = cs.new_witness_variable(|| Ok(self.a))?;
78+
variables.push(v1);
79+
variables.push(v2);
80+
variables.push(v3);
81+
}
82+
83+
Ok(())
84+
}
85+
}
86+
87+
fn main() {
88+
for log_num_constraints in 23..24 {
89+
let circuit = BenchCircuit {
90+
a: Fr::rand(&mut ark_std::test_rng()),
91+
b: Fr::rand(&mut ark_std::test_rng()),
92+
c: Fr::rand(&mut ark_std::test_rng()),
93+
num_constraints: 2usize.pow(log_num_constraints),
94+
};
95+
let cs = ConstraintSystem::<Fr>::new_ref();
96+
cs.set_optimization_goal(OptimizationGoal::Constraints);
97+
cs.set_mode(SynthesisMode::Prove {
98+
construct_matrices: false,
99+
generate_lc_assignments: false,
100+
});
101+
let start = std::time::Instant::now();
102+
circuit.generate_constraints(cs.clone()).unwrap();
103+
// cs.finalize();
104+
let elapsed = start.elapsed();
105+
println!(
106+
"Synthesizing 2^{} constraints took {:?}",
107+
log_num_constraints,
108+
elapsed.as_secs_f32()
109+
);
110+
}
111+
}

relations/examples/bench.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,40 +28,48 @@ impl ConstraintSynthesizer<Fr> for BenchCircuit {
2828
variables.reserve(3 * self.num_constraints);
2929
let mut lcs = Vec::with_capacity(self.num_constraints);
3030

31-
let mut rng = ark_std::rand::rngs::StdRng::seed_from_u64(0u64);
31+
let mut rng_a = ark_std::rand::rngs::StdRng::seed_from_u64(0u64);
32+
let mut rng_b = ark_std::rand::rngs::StdRng::seed_from_u64(rng_a.gen::<u64>());
33+
let mut rng_c = ark_std::rand::rngs::StdRng::seed_from_u64(rng_a.gen::<u64>());
3234

3335
for i in 0..self.num_constraints {
3436
let cur_num_vars = ark_std::cmp::min(variables.len(), 10);
3537
let lower = variables.len().checked_sub(cur_num_vars).unwrap_or(0);
3638
let upper = variables.len();
3739

38-
let a_i_lc_size = rng.gen_range(1..=NUM_COEFFS_IN_LC);
39-
let a_i = LinearCombination(
40-
(0..a_i_lc_size)
41-
.map(|_| (Fr::ONE, variables[rng.gen_range(lower..upper)]))
42-
.collect::<Vec<_>>(),
43-
);
40+
let a_i_lc_size = rng_a.gen_range(1..=NUM_COEFFS_IN_LC);
41+
let mut a_i = || {
42+
LinearCombination(
43+
(0..a_i_lc_size)
44+
.map(|_| (Fr::ONE, variables[rng_a.gen_range(lower..upper)]))
45+
.collect::<Vec<_>>(),
46+
)
47+
};
4448

45-
let b_i_lc_size = rng.gen_range(1..=NUM_COEFFS_IN_LC);
46-
let b_i = LinearCombination(
47-
(0..b_i_lc_size)
48-
.map(|_| (Fr::ONE, variables[rng.gen_range(lower..upper)]))
49-
.collect::<Vec<_>>(),
50-
);
49+
let b_i_lc_size = rng_b.gen_range(1..=NUM_COEFFS_IN_LC);
50+
let b_i = || {
51+
LinearCombination(
52+
(0..b_i_lc_size)
53+
.map(|_| (Fr::ONE, variables[rng_b.gen_range(lower..upper)]))
54+
.collect::<Vec<_>>(),
55+
)
56+
};
5157

52-
let c_i = variables[rng.gen_range(lower..upper)];
58+
let c_i = variables[rng_c.gen_range(lower..upper)];
5359

5460
if i % 2 == 0 {
55-
let extra_lc = LinearCombination(
56-
(0..a_i_lc_size)
57-
.map(|_| (Fr::ONE, variables[rng.gen_range(lower..upper)]))
58-
.collect::<Vec<_>>(),
59-
);
61+
let extra_lc = || {
62+
LinearCombination(
63+
(0..a_i_lc_size)
64+
.map(|_| (Fr::ONE, variables[rng_c.gen_range(lower..upper)]))
65+
.collect::<Vec<_>>(),
66+
)
67+
};
6068
let extra_lc = cs.new_lc(extra_lc)?;
6169
lcs.push(extra_lc);
62-
cs.enforce_r1cs_constraint(a_i + extra_lc, b_i, c_i.into())?;
70+
cs.enforce_r1cs_constraint(|| a_i() + extra_lc, b_i, || c_i.into())?;
6371
} else {
64-
cs.enforce_r1cs_constraint(a_i, b_i, c_i.into())?;
72+
cs.enforce_r1cs_constraint(a_i, b_i, || c_i.into())?;
6573
};
6674
let v1 = cs.new_witness_variable(|| Ok(self.a))?;
6775
let v2 = cs.new_witness_variable(|| Ok(self.a))?;
@@ -70,7 +78,6 @@ impl ConstraintSynthesizer<Fr> for BenchCircuit {
7078
variables.push(v2);
7179
variables.push(v3);
7280
}
73-
7481
Ok(())
7582
}
7683
}

relations/examples/non_satisfiable.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ fn generate_constraints<F: Field>(
6666
let final_result = enforce_addition(cs.clone(), subcircuit1_result, subcircuit2_result)?;
6767
// Verify that the final result matches the expected result
6868
cs.enforce_r1cs_constraint(
69-
LinearCombination::from(final_result),
70-
LinearCombination::from(Variable::One),
71-
LinearCombination::from(expected_result),
69+
|| LinearCombination::from(final_result),
70+
|| LinearCombination::from(Variable::One),
71+
|| LinearCombination::from(expected_result),
7272
)?;
7373

7474
Ok(final_result)
@@ -134,9 +134,9 @@ fn enforce_multiplication<F: Field>(
134134
})?; // Placeholder for product
135135

136136
cs.enforce_r1cs_constraint(
137-
LinearCombination::from(left),
138-
LinearCombination::from(right),
139-
LinearCombination::from(product),
137+
|| LinearCombination::from(left),
138+
|| LinearCombination::from(right),
139+
|| LinearCombination::from(product),
140140
)?;
141141

142142
Ok(product)
@@ -157,9 +157,9 @@ fn enforce_addition<F: Field>(
157157
})?; // Placeholder for sum
158158

159159
cs.enforce_r1cs_constraint(
160-
LinearCombination::from(left) + LinearCombination::from(right),
161-
LinearCombination::from(Variable::One),
162-
LinearCombination::from(sum),
160+
|| LinearCombination::from(left) + LinearCombination::from(right),
161+
|| LinearCombination::from(Variable::One),
162+
|| LinearCombination::from(sum),
163163
)?;
164164

165165
Ok(sum)

relations/examples/satisfiable.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ fn generate_constraints<F: Field>(
5555
let final_result = enforce_addition(cs.clone(), subcircuit1_result, subcircuit2_result)?;
5656
// Verify that the final result matches the expected result
5757
cs.enforce_r1cs_constraint(
58-
LinearCombination::from(final_result),
59-
LinearCombination::from(Variable::One),
60-
LinearCombination::from(expected_result),
58+
|| LinearCombination::from(final_result),
59+
|| LinearCombination::from(Variable::One),
60+
|| LinearCombination::from(expected_result),
6161
)?;
6262

6363
Ok(final_result)
@@ -123,9 +123,9 @@ fn enforce_multiplication<F: Field>(
123123
})?; // Placeholder for product
124124

125125
cs.enforce_r1cs_constraint(
126-
LinearCombination::from(left),
127-
LinearCombination::from(right),
128-
LinearCombination::from(product),
126+
|| LinearCombination::from(left),
127+
|| LinearCombination::from(right),
128+
|| LinearCombination::from(product),
129129
)?;
130130

131131
Ok(product)
@@ -145,9 +145,9 @@ fn enforce_addition<F: Field>(
145145
})?; // Placeholder for sum
146146

147147
cs.enforce_r1cs_constraint(
148-
LinearCombination::from(left) + LinearCombination::from(right),
149-
LinearCombination::from(Variable::One),
150-
LinearCombination::from(sum),
148+
|| LinearCombination::from(left) + LinearCombination::from(right),
149+
|| LinearCombination::from(Variable::One),
150+
|| LinearCombination::from(sum),
151151
)?;
152152

153153
Ok(sum)

0 commit comments

Comments
 (0)