use std::collections::BTreeMap;
use crate::cnf::Cnf;
use crate::formula::Formula;
use crate::solver::Model;
pub const MAX_VARIABLES: usize = 22;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TooManyVariables(pub usize);
#[allow(clippy::missing_panics_doc)] pub fn satisfying_assignment(
formula: &Formula,
) -> Result<Option<Model>, TooManyVariables> {
let vars = formula.variables();
if vars.len() > MAX_VARIABLES {
return Err(TooManyVariables(vars.len()));
}
for bits in 0u32..1 << vars.len() {
let value = |name: &str| {
let i = vars.iter().position(|v| *v == name).unwrap();
bits >> i & 1 == 1
};
if formula.evaluate(&value) {
let map: BTreeMap<String, bool> =
vars.iter().map(|v| (v.to_string(), value(v))).collect();
return Ok(Some(Model::from_map(map)));
}
}
Ok(None)
}
pub fn satisfying_assignment_cnf(
cnf: &Cnf,
) -> Result<Option<Model>, TooManyVariables> {
let n = cnf.variables as usize;
if n > MAX_VARIABLES {
return Err(TooManyVariables(n));
}
let mut assignment = vec![false; n];
for bits in 0u32..1 << n {
for (i, a) in assignment.iter_mut().enumerate() {
*a = bits >> i & 1 == 1;
}
if cnf.evaluate(&assignment) {
let map = (0..n)
.map(|i| (format!("x{}", i + 1), assignment[i]))
.collect();
return Ok(Some(Model::from_map(map)));
}
}
Ok(None)
}