use rand::{seq::IteratorRandom, Rng};
use crate::{
context::GenericContext,
db::dbStatus,
structures::{
atom::Atom,
literal::{abLiteral, Literal},
valuation::Valuation,
},
types::err,
};
pub enum Ok {
Literal(abLiteral),
Exhausted,
}
impl<R: rand::Rng + std::default::Default> GenericContext<R> {
pub fn make_decision(&mut self) -> Result<Ok, err::Queue> {
let mut rng = std::mem::take(&mut self.rng);
let chosen_atom = self.atom_without_value(&mut rng);
self.rng = rng;
match chosen_atom {
Some(chosen_atom) => {
self.counters.total_decisions += 1;
let decision_literal = match self.config.switch.phase_saving {
true => {
let previous_value = self.atom_db.previous_value_of(chosen_atom);
abLiteral::fresh(chosen_atom, previous_value)
}
false => {
let random_value = self.rng.gen_bool(self.config.polarity_lean);
abLiteral::fresh(chosen_atom, random_value)
}
};
log::trace!("Decision {decision_literal}");
Ok(Ok::Literal(decision_literal))
}
None => {
self.status = dbStatus::Consistent;
Ok(Ok::Exhausted)
}
}
}
pub fn atom_without_value(&mut self, rng: &mut impl Rng) -> Option<Atom> {
match rng.gen_bool(self.config.random_decision_bias) {
true => self.atom_db.valuation().unvalued_atoms().choose(rng),
false => {
while let Some(atom) = self.atom_db.heap_pop_most_active() {
if self.atom_db.value_of(atom as Atom).is_none() {
return Some(atom);
}
}
self.atom_db.valuation().unvalued_atoms().next()
}
}
}
pub fn clear_decisions(&mut self) {
self.backjump(0);
}
}