use partial_ref::{partial, PartialRef};
use varisat_formula::{lit::LitIdx, Lit, Var};
use crate::{
clause::ClauseRef,
context::{parts::*, Context},
};
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Reason {
Unit,
Binary([Lit; 1]),
Long(ClauseRef),
}
impl Reason {
pub fn lits<'out, 'a, 'b>(&'a self, ctx: &'b partial!('b Context, ClauseAllocP)) -> &'out [Lit]
where
'a: 'out,
'b: 'out,
{
match self {
Reason::Unit => &[],
Reason::Binary(lit) => lit,
Reason::Long(cref) => &ctx.part(ClauseAllocP).clause(*cref).lits()[1..],
}
}
pub fn is_unit(&self) -> bool {
match self {
Reason::Unit => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Conflict {
Binary([Lit; 2]),
Long(ClauseRef),
}
impl Conflict {
pub fn lits<'out, 'a, 'b>(&'a self, ctx: &'b partial!('b Context, ClauseAllocP)) -> &'out [Lit]
where
'a: 'out,
'b: 'out,
{
match self {
Conflict::Binary(lits) => lits,
Conflict::Long(cref) => ctx.part(ClauseAllocP).clause(*cref).lits(),
}
}
}
#[derive(Copy, Clone)]
pub struct ImplNode {
pub reason: Reason,
pub level: LitIdx,
pub depth: LitIdx,
}
#[derive(Default)]
pub struct ImplGraph {
pub nodes: Vec<ImplNode>,
}
impl ImplGraph {
pub fn set_var_count(&mut self, count: usize) {
self.nodes.resize(
count,
ImplNode {
reason: Reason::Unit,
level: 0,
depth: 0,
},
);
}
pub fn reason(&self, var: Var) -> &Reason {
&self.nodes[var.index()].reason
}
pub fn level(&self, var: Var) -> usize {
self.nodes[var.index()].level as usize
}
pub fn depth(&self, var: Var) -> usize {
self.nodes[var.index()].depth as usize
}
pub fn update_reason(&mut self, var: Var, reason: Reason) {
self.nodes[var.index()].reason = reason
}
pub fn update_removed_unit(&mut self, var: Var) {
let node = &mut self.nodes[var.index()];
node.reason = Reason::Unit;
node.depth = LitIdx::max_value();
}
pub fn is_removed_unit(&self, var: Var) -> bool {
self.nodes[var.index()].depth == LitIdx::max_value()
}
}