use std::{
collections::{HashMap, VecDeque},
sync::{Arc, Mutex},
};
use crate::{
db::ClauseKey,
dispatch::{
library::delta::{self, AtomDB, ClauseDB, Delta, LiteralDB, Resolution, BCP},
Dispatch,
},
structures::{
clause::{vClause, Clause},
literal::{abLiteral, Literal},
},
types::err::{self},
};
#[derive(Default)]
pub struct CoreDB {
conflict: Option<ClauseKey>,
clause_buffer: Vec<abLiteral>,
resolution_buffer: Vec<ClauseKey>,
resolution_q: VecDeque<Vec<ClauseKey>>,
bcp_buffer: Option<(ClauseKey, abLiteral)>,
original_map: HashMap<ClauseKey, vClause>,
clause_map: HashMap<ClauseKey, Vec<ClauseKey>>,
literal_map: HashMap<abLiteral, Vec<ClauseKey>>,
}
impl CoreDB {
pub fn core_clauses(&self) -> Result<Vec<vClause>, err::Core> {
let mut core_q = std::collections::VecDeque::<ClauseKey>::new();
let mut seen_keys = std::collections::BTreeSet::new();
let mut seen_literals = std::collections::BTreeSet::new();
let mut core_clauses = std::collections::BTreeSet::new();
match self.conflict {
Some(c) => core_q.push_back(c),
None => return Err(err::Core::NoConflict),
}
'the_loop: while let Some(key) = core_q.pop_front() {
if !seen_keys.insert(key) {
continue 'the_loop;
}
let maybe_clause = match key {
ClauseKey::Unit(_) => {
todo!()
}
ClauseKey::Original(_) => match self.original_map.get(&key) {
Some(the_clause) => Some(the_clause),
None => return Err(err::Core::MissedKey),
},
ClauseKey::Binary(_) => match self.clause_map.get(&key) {
None => match self.original_map.get(&key) {
Some(the_clause) => Some(the_clause),
None => return Err(err::Core::MissedKey),
},
Some(keys) => {
core_q.extend(keys);
None
}
},
ClauseKey::Addition(_, _) => match self.clause_map.get(&key) {
None => return Err(err::Core::MissedKey),
Some(keys) => {
core_q.extend(keys);
None
}
},
};
if let Some(clause) = maybe_clause {
'literal_loop: for literal in clause.literals() {
if !seen_literals.insert(*literal) {
continue 'literal_loop;
} else if let Some(past) = self.literal_map.get(&literal.negate()) {
core_q.extend(past)
}
}
core_clauses.insert(clause);
}
}
Ok(core_clauses.into_iter().cloned().collect())
}
}
impl CoreDB {
pub fn process_resolution_delta(&mut self, δ: &Resolution) -> Result<(), err::Core> {
use delta::Resolution::*;
match δ {
Begin => {
if !self.resolution_buffer.is_empty() {
return Err(err::Core::CorruptClauseBuffer);
}
}
End => {
let the_clause = std::mem::take(&mut self.resolution_buffer);
self.resolution_q.push_back(the_clause)
}
Used(k) => self.resolution_buffer.push(*k),
Subsumed(_, _) => {} }
Ok(())
}
pub fn process_clause_db_delta(&mut self, δ: &ClauseDB) -> Result<(), err::Core> {
use delta::ClauseDB::*;
match δ {
ClauseStart => {
if !self.resolution_buffer.is_empty() {
return Err(err::Core::CorruptClauseBuffer);
}
}
ClauseLiteral(literal) => {
self.clause_buffer.push(*literal);
}
Added(key) | Transfer(_, key) => {
let Some(the_sources) = self.resolution_q.pop_front() else {
return Err(err::Core::QueueMiss);
};
self.clause_map.insert(*key, the_sources);
self.clause_buffer.clear();
}
Original(key) => {
let the_clause = std::mem::take(&mut self.clause_buffer);
self.original_map.insert(*key, the_clause);
}
Deletion(_) => {
self.clause_buffer.clear();
}
BCP(_) => {}
}
Ok(())
}
pub fn process_literal_db_delta(&mut self, _δ: &LiteralDB) -> Result<(), err::Core> {
Ok(())
}
pub fn process_atom_db_delta(&mut self, δ: &AtomDB) -> Result<(), err::Core> {
use delta::AtomDB::*;
match δ {
Unsatisfiable(key) => self.conflict = Some(*key),
_ => {}
};
Ok(())
}
pub fn process_bcp_delta(&mut self, δ: &BCP) -> Result<(), err::Core> {
use delta::BCP::*;
match δ {
Instance {
clause: via,
literal: to,
} => self.bcp_buffer = Some((*via, *to)),
Conflict { .. } => {}
}
Ok(())
}
}
type CoreReceiver<'g> = Box<dyn FnMut(&Dispatch) -> Result<(), err::Core> + 'g>;
#[allow(clippy::single_match)]
#[allow(clippy::collapsible_match)]
pub fn core_db_builder(core_db_ptr: &Option<Arc<Mutex<CoreDB>>>) -> CoreReceiver {
let mut core_db = core_db_ptr.as_ref().unwrap().lock().unwrap();
let handler = move |dispatch: &Dispatch| {
match dispatch {
Dispatch::Delta(the_delta) => {
use Delta::*;
match the_delta {
Resolution(δ) => core_db.process_resolution_delta(δ)?,
ClauseDB(δ) => core_db.process_clause_db_delta(δ)?,
LiteralDB(δ) => core_db.process_literal_db_delta(δ)?,
AtomDB(δ) => core_db.process_atom_db_delta(δ)?,
BCP(δ) => core_db.process_bcp_delta(δ)?,
}
}
_ => {}
}
Ok(())
};
Box::new(handler)
}