use std::collections::BTreeSet;
use l_group_formulas::literal::Literal;
use l_group_formulas::free_group_term::{FreeGroupTerm, FREE_GROUP_IDENTITY};
use l_group_formulas::short_free_group_term::ShortFreeGroupTerm;
use l_group_formulas::l_group_term::LGroupTerm;
use super::normal_cnf::CNF;
#[derive(PartialEq, Eq, Debug)]
pub struct ThreeCNF {
pub meetands: BTreeSet<BTreeSet<ShortFreeGroupTerm>>
}
impl From<LGroupTerm> for ThreeCNF {
fn from(term: LGroupTerm) -> ThreeCNF {
let normal_cnf = CNF::from(term);
let mut new_meetands = BTreeSet::new();
let mut count = 1;
for meetand in normal_cnf.meetands {
match meetand.len() {
0 => panic!("empty meet!"),
1 => {
let element = meetand.iter().next().unwrap();
if *element == FREE_GROUP_IDENTITY {
let mut singleton_set = BTreeSet::new();
singleton_set.insert(ShortFreeGroupTerm::new(None, None, None));
new_meetands.insert(singleton_set);
} },
_ => {
let mut joinands = BTreeSet::new();
for term in meetand {
for new_term in split(term, &mut count) {
joinands.insert(new_term);
}
}
new_meetands.insert(joinands);
}
};
}
ThreeCNF { meetands: new_meetands }
}
}
impl ToString for ThreeCNF {
fn to_string(&self) -> String {
let mut string = String::new();
for meetand in &self.meetands {
string.push('(');
for joinand in meetand {
string.push_str(joinand.to_string().as_str());
string.push_str(" v ");
}
string = string[0 .. string.len() - 3].to_string();
string.push_str(") ^ ");
}
if string.len() == 0 {
return String::from("(())")
}
string[0..string.len() - 3].to_string()
}
}
fn split(term: FreeGroupTerm, counter: &mut usize) -> BTreeSet<ShortFreeGroupTerm> {
let mut output = BTreeSet::new();
if term.literals.len() <= 3 {
output.insert(ShortFreeGroupTerm::from(term.clone()));
return output;
}
output.insert(ShortFreeGroupTerm {
left: Some(term.literals[0]),
mid: Some(term.literals[1]),
right: Some(Literal::new('v', *counter, false))
});
let mut rest_literals = Vec::new();
rest_literals.push(Literal::new('v', *counter, true));
*counter += 1;
for x in &term.literals[2 .. term.literals.len()] {
rest_literals.push(*x);
}
let rest_term = FreeGroupTerm { literals: rest_literals };
for x in split(rest_term, counter) {
output.insert(x);
}
return output;
}