use crate::cnf::CnfFormula;
pub(super) fn compute_weight(formula: &CnfFormula, total_vertices: u32) -> Vec<u32> {
let q = quantize(&jw_degree_normalized(formula, total_vertices));
q.into_iter().map(|w| u32::MAX - w).collect()
}
fn jeroslow_wang(formula: &CnfFormula, total_vertices: u32) -> Vec<f64> {
let mut score = vec![0.0f64; total_vertices as usize];
for clause in &formula.clauses {
let w = 2f64.powi(-(clause.literals.len() as i32));
for lit in &clause.literals {
score[lit.var.0 as usize] += w;
}
}
score
}
fn jw_degree_normalized(formula: &CnfFormula, total_vertices: u32) -> Vec<f64> {
let jw = jeroslow_wang(formula, total_vertices);
let cnt = clause_count(formula, total_vertices);
jw.iter()
.zip(cnt.iter())
.map(|(&s, &c)| s / (1.0 + c))
.collect()
}
fn clause_count(formula: &CnfFormula, total_vertices: u32) -> Vec<f64> {
let mut score = vec![0.0f64; total_vertices as usize];
for clause in &formula.clauses {
for lit in &clause.literals {
score[lit.var.0 as usize] += 1.0;
}
}
score
}
fn quantize(scores: &[f64]) -> Vec<u32> {
let max = scores.iter().cloned().fold(0.0f64, f64::max);
if max <= 0.0 {
return vec![0u32; scores.len()];
}
let scale = 1_000_000.0 / max;
scores
.iter()
.map(|&w| {
let v = (w * scale) as i64;
v.clamp(0, 1_000_000) as u32
})
.collect()
}