use partial_ref::{partial, PartialRef};
use varisat_formula::Lit;
use crate::{
clause::{db, ClauseRef},
context::{parts::*, Context},
};
#[derive(Copy, Clone)]
pub struct Watch {
pub cref: ClauseRef,
pub blocking: Lit,
}
pub struct Watchlists {
watches: Vec<Vec<Watch>>,
enabled: bool,
}
impl Default for Watchlists {
fn default() -> Watchlists {
Watchlists {
watches: vec![],
enabled: true,
}
}
}
impl Watchlists {
pub fn set_var_count(&mut self, count: usize) {
self.watches.resize(count * 2, vec![]);
}
pub fn watch_clause(&mut self, cref: ClauseRef, lits: [Lit; 2]) {
if !self.enabled {
return;
}
for i in 0..2 {
let watch = Watch {
cref,
blocking: lits[i ^ 1],
};
self.add_watch(!lits[i], watch);
}
}
pub fn watched_by_mut(&mut self, lit: Lit) -> &mut Vec<Watch> {
&mut self.watches[lit.code()]
}
pub fn add_watch(&mut self, lit: Lit, watch: Watch) {
self.watches[lit.code()].push(watch)
}
pub fn enabled(&self) -> bool {
self.enabled
}
pub fn disable(&mut self) {
self.enabled = false;
}
}
pub fn enable_watchlists(mut ctx: partial!(Context, mut WatchlistsP, ClauseAllocP, ClauseDbP)) {
let (watchlists, mut ctx) = ctx.split_part_mut(WatchlistsP);
if watchlists.enabled {
return;
}
for watchlist in watchlists.watches.iter_mut() {
watchlist.clear();
}
watchlists.enabled = true;
let (alloc, mut ctx) = ctx.split_part(ClauseAllocP);
for cref in db::clauses_iter(&ctx.borrow()) {
let lits = alloc.clause(cref).lits();
watchlists.watch_clause(cref, [lits[0], lits[1]]);
}
}