#[doc(hidden)]
pub mod activity;
#[doc(hidden)]
pub mod valuation;
pub mod watch_db;
use watch_db::WatchTag;
use crate::{
config::{dbs::AtomDBConfig, Activity, Config},
db::{atom::watch_db::WatchDB, LevelIndex},
generic::index_heap::IndexHeap,
misc::log::targets::{self},
structures::{
atom::{Atom, ATOM_MAX},
clause::ClauseKind,
valuation::{vValuation, Valuation},
},
types::err::{self, AtomDBError},
};
use super::ClauseKey;
#[allow(dead_code)]
pub struct AtomDB {
watch_dbs: Vec<WatchDB>,
valuation: vValuation,
previous_valuation: Vec<bool>,
activity_heap: IndexHeap<Activity>,
decision_indicies: Vec<Option<LevelIndex>>,
config: AtomDBConfig,
}
pub enum AtomValue {
NotSet,
Same,
Different,
}
impl AtomDB {
pub fn new(config: &Config) -> Self {
let mut db = AtomDB {
watch_dbs: Vec::default(),
activity_heap: IndexHeap::default(),
valuation: Vec::default(),
previous_valuation: Vec::default(),
decision_indicies: Vec::default(),
config: config.atom_db.clone(),
};
let the_true = unsafe { db.fresh_atom(true).unwrap_unchecked() };
unsafe { db.set_value(the_true, true, None) };
db
}
pub fn count(&self) -> usize {
self.valuation.len()
}
pub fn valuation(&self) -> &impl Valuation {
&self.valuation
}
pub fn valuation_canonical(&self) -> &vValuation {
&self.valuation
}
pub fn fresh_atom(&mut self, previous_value: bool) -> Result<Atom, AtomDBError> {
let atom = match self.valuation.len().try_into() {
Ok(atom) if atom <= ATOM_MAX => atom,
_ => {
return Err(AtomDBError::AtomsExhausted);
}
};
self.activity_heap.add(atom as usize, 1.0);
self.watch_dbs.push(WatchDB::default());
self.valuation.push(None);
self.previous_valuation.push(previous_value);
self.decision_indicies.push(None);
Ok(atom)
}
pub unsafe fn atom_decision_level_unchecked(&self, atom: Atom) -> Option<LevelIndex> {
*self.decision_indicies.get_unchecked(atom as usize)
}
pub unsafe fn set_value(
&mut self,
atom: Atom,
value: bool,
level: Option<LevelIndex>,
) -> Result<AtomValue, AtomValue> {
match self.value_of(atom) {
None => {
*self.valuation.get_unchecked_mut(atom as usize) = Some(value);
*self.decision_indicies.get_unchecked_mut(atom as usize) = level;
Ok(AtomValue::NotSet)
}
Some(v) if v == value => Ok(AtomValue::Same),
Some(_) => Err(AtomValue::Different),
}
}
pub unsafe fn drop_value(&mut self, atom: Atom) {
log::trace!(target: targets::VALUATION, "Cleared atom: {atom}");
self.clear_value(atom);
self.activity_heap.activate(atom as usize);
}
pub unsafe fn watch_unchecked(&mut self, atom: Atom, value: bool, watch_tag: WatchTag) {
let atom = self.watch_dbs.get_unchecked_mut(atom as usize);
match watch_tag {
WatchTag::Binary(_, _) => match value {
true => atom.positive_binary.push(watch_tag),
false => atom.negative_binary.push(watch_tag),
},
WatchTag::Long(_) => match value {
true => atom.positive_long.push(watch_tag),
false => atom.negative_long.push(watch_tag),
},
}
}
pub unsafe fn unwatch_unchecked(
&mut self,
atom: Atom,
value: bool,
key: &ClauseKey,
) -> Result<(), err::ClauseDBError> {
let atom = self.watch_dbs.get_unchecked_mut(atom as usize);
match key {
ClauseKey::Original(_) | ClauseKey::Addition(_, _) => {
let list = match value {
true => &mut atom.positive_long,
false => &mut atom.negative_long,
};
let mut index = 0;
let mut limit = list.len();
while index < limit {
let WatchTag::Long(list_key) = list.get_unchecked(index) else {
return Err(err::ClauseDBError::CorruptList);
};
if list_key == key {
list.swap_remove(index);
limit -= 1;
} else {
index += 1;
}
}
Ok(())
}
ClauseKey::OriginalUnit(_)
| ClauseKey::AdditionUnit(_)
| ClauseKey::OriginalBinary(_)
| ClauseKey::AdditionBinary(_) => Err(err::ClauseDBError::CorruptList),
}
}
pub unsafe fn watchers_unchecked(
&mut self,
atom: Atom,
kind: ClauseKind,
value: bool,
) -> *mut Vec<WatchTag> {
let atom = self.watch_dbs.get_unchecked_mut(atom as usize);
match kind {
ClauseKind::Empty => panic!("! Attempt to retrieve watch list for an empty clause"),
ClauseKind::Unit => panic!("! Attempt to retrieve watch list for a unit clause"),
ClauseKind::Binary => match value {
true => &mut atom.positive_binary,
false => &mut atom.negative_binary,
},
ClauseKind::Long => match value {
true => &mut atom.positive_long,
false => &mut atom.negative_long,
},
}
}
}