#[cfg(feature = "sat-integration")]
use crate::drat::{Clause, DratProof, DratProofProducer, Lit};
#[cfg(feature = "sat-integration")]
pub struct ProofRecordingSolver {
solver: oxiz_sat::Solver,
proof: Option<DratProof>,
}
#[cfg(feature = "sat-integration")]
impl ProofRecordingSolver {
#[must_use]
pub fn new() -> Self {
Self {
solver: oxiz_sat::Solver::new(),
proof: None,
}
}
#[must_use]
pub fn with_config(config: oxiz_sat::SolverConfig) -> Self {
Self {
solver: oxiz_sat::Solver::with_config(config),
proof: None,
}
}
#[must_use]
pub fn solver(&self) -> &oxiz_sat::Solver {
&self.solver
}
pub fn solver_mut(&mut self) -> &mut oxiz_sat::Solver {
&mut self.solver
}
pub fn add_clause(&mut self, lits: &[oxiz_sat::Lit]) {
let proof_lits: Vec<Lit> = lits.iter().map(|l| l.to_dimacs()).collect();
if let Some(proof) = &mut self.proof {
proof.add_clause(proof_lits);
}
self.solver.add_clause(lits.iter().copied());
}
pub fn delete_clause(&mut self, lits: &[oxiz_sat::Lit]) {
let proof_lits: Vec<Lit> = lits.iter().map(|l| l.to_dimacs()).collect();
if let Some(proof) = &mut self.proof {
proof.delete_clause(proof_lits);
}
}
pub fn solve(&mut self) -> oxiz_sat::SolverResult {
self.solver.solve()
}
}
#[cfg(feature = "sat-integration")]
impl Default for ProofRecordingSolver {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "sat-integration")]
impl DratProofProducer for ProofRecordingSolver {
fn enable_proof(&mut self) {
self.proof = Some(DratProof::new());
}
fn disable_proof(&mut self) {
self.proof = None;
}
fn get_proof(&self) -> Option<&DratProof> {
self.proof.as_ref()
}
fn take_proof(&mut self) -> Option<DratProof> {
self.proof.take()
}
}
#[cfg(feature = "sat-integration")]
#[must_use]
pub fn sat_lit_to_drat(lit: oxiz_sat::Lit) -> Lit {
lit.to_dimacs()
}
#[cfg(feature = "sat-integration")]
#[must_use]
pub fn drat_lit_to_sat(lit: Lit) -> oxiz_sat::Lit {
oxiz_sat::Lit::from_dimacs(lit)
}
#[cfg(feature = "sat-integration")]
#[must_use]
pub fn sat_clause_to_drat(clause: &[oxiz_sat::Lit]) -> Clause {
clause.iter().map(|&lit| sat_lit_to_drat(lit)).collect()
}
#[cfg(feature = "sat-integration")]
#[must_use]
pub fn drat_clause_to_sat(clause: &Clause) -> Vec<oxiz_sat::Lit> {
clause.iter().map(|&lit| drat_lit_to_sat(lit)).collect()
}
#[cfg(all(test, feature = "sat-integration"))]
mod tests {
use super::*;
#[test]
fn test_proof_recording_solver_creation() {
let solver = ProofRecordingSolver::new();
assert!(solver.get_proof().is_none());
}
#[test]
fn test_enable_proof() {
let mut solver = ProofRecordingSolver::new();
solver.enable_proof();
assert!(solver.get_proof().is_some());
}
#[test]
fn test_disable_proof() {
let mut solver = ProofRecordingSolver::new();
solver.enable_proof();
solver.disable_proof();
assert!(solver.get_proof().is_none());
}
#[test]
fn test_take_proof() {
let mut solver = ProofRecordingSolver::new();
solver.enable_proof();
let proof = solver.take_proof();
assert!(proof.is_some());
assert!(solver.get_proof().is_none());
}
}
#[cfg(not(feature = "sat-integration"))]
mod placeholder {
}