use std::fmt;
use bool_vec::BoolVec;
use crate::literal::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Clause(Vec<Literal>);
impl Clause {
pub fn new<T>(elems: T) -> Self
where
T: ToOwned<Owned = Vec<Literal>>,
{
Self(elems.to_owned())
}
pub fn from_indices<I, V>(var_indices: I, negates: V) -> Self
where
I: IntoIterator<Item = usize>,
V: IntoIterator<Item = bool>,
{
std::iter::zip(var_indices.into_iter(), negates.into_iter())
.map(|(i, n)| Literal::new(i, n))
.collect()
}
pub fn from_cnf<I>(cnfs: I) -> Self
where
I: IntoIterator<Item = isize>,
{
cnfs.into_iter().map(Literal::from_cnf).collect()
}
pub fn negated(&self) -> Self {
self.0.iter().map(|elem| elem.negated()).collect()
}
pub fn negate(&mut self) -> &Self {
for elem in &mut self.0 {
elem.negate();
}
self
}
pub fn iter_eval<'a>(&'a self, vars: &'a BoolVec) -> impl Iterator<Item = bool> + 'a {
self.0.iter().map(|elem| elem.eval_with(vars))
}
pub fn iter_eval_negated<'a>(&'a self, vars: &'a BoolVec) -> impl Iterator<Item = bool> + 'a {
self.0.iter().map(|elem| elem.negated().eval_with(vars))
}
pub fn test_sat(&self, vars: &BoolVec) -> bool {
self.iter_eval(vars).any(|x| x)
}
pub fn get_literals(&self) -> &[Literal] {
&self.0
}
}
impl FromIterator<Literal> for Clause {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Literal>,
{
Self(iter.into_iter().collect())
}
}
impl fmt::Display for Clause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(")?;
for (i, elem) in self.0.iter().enumerate() {
if i != 0 {
write!(f, " ∨ ")?;
}
if elem.is_negated() {
write!(f, "¬")?;
}
write!(f, "x{}", elem.index())?;
}
write!(f, ")")?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use bool_vec::BoolVec;
#[test]
fn construction() {
let vref1 = Literal::new(0, false);
let vref2 = Literal::new(1, true);
let clause = Clause::new(vec![vref1, vref2]);
let same_clause = Clause::from_indices(
vec![vref1.index(), vref2.index()],
vec![vref1.is_negated(), vref2.is_negated()],
);
let again_same_clause = Clause::from_cnf(vec![vref1.as_cnf(), vref2.as_cnf()]);
assert_eq!(clause, same_clause);
assert_eq!(clause, again_same_clause);
assert_eq!(again_same_clause, clause); }
#[test]
fn operations() {
let clause = Clause::from_cnf(vec![1, -2, 3]);
let negated_clause = clause.negated();
assert_eq!(negated_clause, Clause::from_cnf(vec![-1, 2, -3]));
let mut bv = BoolVec::from([false, false, false]);
assert!(clause.test_sat(&bv));
bv.set(1, true).unwrap();
assert!(!clause.test_sat(&bv));
bv.set(2, true).unwrap();
assert!(clause.test_sat(&bv));
assert!(
std::iter::zip(clause.iter_eval(&bv), clause.iter_eval_negated(&bv))
.map(|(x, nx)| x != nx)
.all(|x| x)
);
}
}