//! Binary clauses. use partial_ref::{partial, PartialRef}; use varisat_formula::Lit; use varisat_internal_proof::{DeleteClauseProof, ProofStep}; use crate::{ context::{parts::*, Context}, proof, }; /// Binary clauses. #[derive(Default)] pub struct BinaryClauses { by_lit: Vec>, count: usize, } impl BinaryClauses { /// Update structures for a new variable count. pub fn set_var_count(&mut self, count: usize) { self.by_lit.resize(count * 2, vec![]); } /// Add a binary clause. pub fn add_binary_clause(&mut self, lits: [Lit; 2]) { for i in 0..2 { self.by_lit[(!lits[i]).code()].push(lits[i ^ 1]); } self.count += 1; } /// Implications of a given literal pub fn implied(&self, lit: Lit) -> &[Lit] { &self.by_lit[lit.code()] } /// Number of binary clauses. pub fn count(&self) -> usize { self.count } } /// Remove binary clauses that have an assigned literal. pub fn simplify_binary<'a>( mut ctx: partial!(Context<'a>, mut BinaryClausesP, mut ProofP<'a>, mut SolverStateP, AssignmentP, VariablesP), ) { let (binary_clauses, mut ctx) = ctx.split_part_mut(BinaryClausesP); let (assignment, mut ctx) = ctx.split_part(AssignmentP); let mut double_count = 0; for (code, implied) in binary_clauses.by_lit.iter_mut().enumerate() { let lit = Lit::from_code(code); if !assignment.lit_is_unk(lit) { if ctx.part(ProofP).is_active() { for &other_lit in implied.iter() { // This check avoids deleting binary clauses twice if both literals are assigned. if (!lit) < other_lit { let lits = [!lit, other_lit]; proof::add_step( ctx.borrow(), true, &ProofStep::DeleteClause { clause: &lits[..], proof: DeleteClauseProof::Satisfied, }, ); } } } implied.clear(); } else { implied.retain(|&other_lit| { let retain = assignment.lit_is_unk(other_lit); // This check avoids deleting binary clauses twice if both literals are assigned. if ctx.part(ProofP).is_active() && !retain && (!lit) < other_lit { let lits = [!lit, other_lit]; proof::add_step( ctx.borrow(), true, &ProofStep::DeleteClause { clause: &lits[..], proof: DeleteClauseProof::Satisfied, }, ); } retain }); double_count += implied.len(); } } binary_clauses.count = double_count / 2; }