Skip to content

Commit 1fae366

Browse files
committed
sca: wip
1 parent 084ebd5 commit 1fae366

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

patronus-sca/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ patronus = { path = "../patronus" }
1414
baa = {version = "0.17.1", features = ["bigint"]}
1515
rustc-hash.workspace = true
1616
polysub = "0.2.2"
17+
bit-set = "0.8.0"

patronus-sca/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn verify_word_level_equality(ctx: &mut Context, p: ScaEqualityProblem) -> S
4545
})
4646
.collect();
4747

48-
let gate_poly = build_gate_polynomial(ctx, &input_vars, word_poly.get_mod(), p.gate_level);
48+
//let gate_poly = build_gate_polynomial(ctx, &input_vars, word_poly.get_mod(), p.gate_level);
4949

5050
// the actual reference polynomial needs to contain the output bits as well
5151
let output_poly = poly_for_bv_expr(ctx, p.word_level);

patronus-sca/src/rewrite.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
use crate::{DefaultCoef, Poly, expr_to_var};
66
use baa::BitVecOps;
7+
use bit_set::BitSet;
78
use patronus::expr::{
8-
Context, DenseExprSet, Expr, ExprRef, ExprSet, ForEachChild, count_expr_uses, traversal,
9+
Context, DenseExprMetaData, DenseExprSet, Expr, ExprMap, ExprRef, ExprSet, ForEachChild,
10+
count_expr_uses, traversal,
911
};
1012
use polysub::{Coef, Mod, PhaseOptPolynom, VarIndex};
1113
use rustc_hash::FxHashSet;
@@ -20,6 +22,10 @@ pub fn backwards_sub(
2022
todo: Vec<(VarIndex, ExprRef)>,
2123
spec: Poly,
2224
) -> Poly {
25+
let root_vars: Vec<_> = todo.iter().map(|(v, _)| *v).collect();
26+
let root_exprs: Vec<_> = todo.iter().map(|(_, e)| *e).collect();
27+
let root_uses = analyze_uses(ctx, &root_exprs);
28+
2329
// empirically, it looks like we should not use a stack
2430
let mut todo: VecDeque<_> = todo.into();
2531
let mut spec: PolyOpt = spec.into();
@@ -33,15 +39,22 @@ pub fn backwards_sub(
3339
let mut seen = DenseExprSet::default();
3440

3541
while !todo.is_empty() {
36-
let min_idx = try_exhaustive(ctx, input_vars, &spec, todo.iter().cloned());
42+
let min_idx = try_exhaustive(ctx, input_vars, &spec, todo.iter().cloned(), &root_uses);
3743
let (output_var, gate) = todo.swap_remove_back(min_idx).unwrap();
3844

3945
// chose variable to replace
4046
//let (output_var, gate) = todo.pop_back().unwrap();
4147

4248
replaced.push(output_var);
49+
let gate_uses = &root_uses[gate];
50+
let num_output_uses = gate_uses.len();
51+
let output_use_str = gate_uses
52+
.iter()
53+
.map(|ii| format!("{}", root_vars[ii]))
54+
.collect::<Vec<_>>()
55+
.join(", ");
4356
println!(
44-
"{output_var} {:?}: {}, {}",
57+
"{output_var} ({output_use_str}) {:?}: {}, {}",
4558
&ctx[gate],
4659
todo.len() + 1,
4760
spec.size()
@@ -154,20 +167,30 @@ fn try_exhaustive(
154167
input_vars: &FxHashSet<VarIndex>,
155168
spec: &PolyOpt,
156169
todo: impl Iterator<Item = (VarIndex, ExprRef)>,
170+
root_uses: &impl ExprMap<BitSet>,
157171
) -> usize {
158172
let sizes: Vec<_> = todo
159173
.enumerate()
160174
.map(|(ii, (output_var, gate))| {
161175
let mut s = spec.clone();
162176
replace_gate(ctx, input_vars, &mut s, output_var, gate);
163-
s.size()
177+
(s.size(), root_uses[gate].len())
164178
})
165179
.collect();
166-
let min = sizes.iter().cloned().min().unwrap();
167-
let max = sizes.iter().cloned().max().unwrap();
168-
let first_min = sizes.iter().position(|s| *s == min).unwrap();
169-
println!("{} -> {min}/{max}", spec.size());
170-
first_min
180+
let min = sizes.iter().map(|(s, _)| *s).min().unwrap();
181+
let max = sizes.iter().map(|(s, _)| *s).max().unwrap();
182+
let all_mins: Vec<_> = sizes.iter().filter(|(s, _)| *s == min).collect();
183+
let lowest_min_use = all_mins.iter().map(|(_, u)| *u).min().unwrap();
184+
let min_with_lowest_use = sizes
185+
.iter()
186+
.position(|(s, u)| *s == min && *u == lowest_min_use)
187+
.unwrap();
188+
println!(
189+
"{} -> {min}/{max}, {} mins, lowest use: {lowest_min_use}",
190+
spec.size(),
191+
all_mins.len()
192+
);
193+
min_with_lowest_use
171194
}
172195

173196
/// tries to build the gate-level polynomial from the bottom up.
@@ -230,3 +253,18 @@ pub fn build_gate_polynomial(
230253
}
231254
})
232255
}
256+
257+
/// Calculates for each expression which root depends on it.
258+
fn analyze_uses(ctx: &Context, roots: &[ExprRef]) -> impl ExprMap<BitSet> {
259+
let mut out = DenseExprMetaData::<BitSet>::default();
260+
261+
for (ii, &root) in roots.iter().enumerate() {
262+
let mut id = BitSet::new();
263+
id.insert(ii);
264+
traversal::bottom_up(ctx, root, |_, e, _| {
265+
out[e].union_with(&id);
266+
})
267+
}
268+
269+
out
270+
}

0 commit comments

Comments
 (0)