use std::{borrow::Borrow, collections::HashSet};
use crate::{
db::{atom::AtomDB, ClauseKey},
misc::log::targets,
structures::literal::{CLiteral, Literal},
types::err::{self},
};
use super::dbClause;
impl dbClause {
pub fn subsume(
&mut self,
literal: impl Borrow<CLiteral>,
atom_db: &mut AtomDB,
fix_watch: bool,
premises: HashSet<ClauseKey>,
increment_proof_count: bool,
) -> Result<usize, err::SubsumptionError> {
if self.clause.len() < 3 {
log::error!(target: targets::SUBSUMPTION, "Subsumption attempted on non-long clause");
return Err(err::SubsumptionError::ShortClause);
}
let mut position = {
let search = self
.clause
.iter()
.position(|clause_literal| clause_literal == literal.borrow());
match search {
None => {
log::error!(target: targets::SUBSUMPTION, "Pivot not found for subsumption");
return Err(err::SubsumptionError::NoPivot);
}
Some(p) => p,
}
};
let mut zero_swap = false;
if position == 0 {
self.clause.swap(0, self.watch_ptr);
zero_swap = true;
position = self.watch_ptr;
}
let removed = self.clause.swap_remove(position);
match unsafe { atom_db.unwatch_unchecked(removed.atom(), removed.polarity(), &self.key) } {
Ok(()) => {}
Err(_) => return Err(err::SubsumptionError::WatchError),
};
if fix_watch && position == self.watch_ptr {
let clause_length = self.clause.len();
self.watch_ptr = 1;
for index in 1..clause_length {
let index_literal = unsafe { self.clause.get_unchecked(index) };
let index_value = atom_db.value_of(index_literal.atom());
match index_value {
Some(value) if value != index_literal.polarity() => {}
_ => {
self.watch_ptr = index;
break;
}
}
}
let watched_literal = unsafe { self.clause.get_unchecked(self.watch_ptr) };
self.note_watch(watched_literal.atom(), watched_literal.polarity(), atom_db);
if zero_swap && atom_db.value_of(watched_literal.atom()).is_none() {
self.clause.swap(0, self.watch_ptr);
}
}
self.premises.extend(premises);
if increment_proof_count {
self.increment_proof_count();
}
Ok(self.clause.len())
}
}