use crate::formulas::{EncodedFormula, FormulaFactory};
use crate::handlers::{ClauseLimitFactorizationHandler, FactorizationHandler};
use crate::operations::transformations::cnf::CnfAlgorithm::Tseitin;
use crate::operations::transformations::cnf::{CancellableCnfAlgorithm, CnfAlgorithm};
use super::CnfEncoder;
pub fn advanced_cnf_encoding(
formula: EncodedFormula,
f: &FormulaFactory,
config: &AdvancedFactorizationConfig,
state: &mut CnfEncoder,
) -> EncodedFormula {
if formula.is_and() {
let new_ops = formula.operands(f).iter().map(|&op| single_advanced_encoding(op, f, config, state)).collect::<Box<[_]>>();
f.and(&new_ops)
} else {
single_advanced_encoding(formula, f, config, state)
}
}
fn single_advanced_encoding(
formula: EncodedFormula,
f: &FormulaFactory,
config: &AdvancedFactorizationConfig,
state: &mut CnfEncoder,
) -> EncodedFormula {
CancellableCnfAlgorithm::FactorizationWithHandler(config.handler())
.transform(formula, f)
.unwrap_or_else(|_| (*config.fallback_algorithm).transform(formula, f, state))
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AdvancedFactorizationConfig {
distribution_boundary: u64,
created_clause_boundary: u64,
atom_boundary: u64,
fallback_algorithm: Box<CnfAlgorithm>,
}
impl Default for AdvancedFactorizationConfig {
fn default() -> Self {
Self { distribution_boundary: u64::MAX, created_clause_boundary: 1000, atom_boundary: 12, fallback_algorithm: Box::new(Tseitin) }
}
}
impl AdvancedFactorizationConfig {
#[must_use]
pub const fn distribution_boundary(mut self, distribution_boundary: u64) -> Self {
self.distribution_boundary = distribution_boundary;
self
}
#[must_use]
pub const fn created_clause_boundary(mut self, created_clause_boundary: u64) -> Self {
self.created_clause_boundary = created_clause_boundary;
self
}
#[must_use]
pub const fn atom_boundary(mut self, atom_boundary: u64) -> Self {
self.atom_boundary = atom_boundary;
self
}
#[must_use]
pub fn fallback_algorithm(mut self, fallback_algorithm: CnfAlgorithm) -> Self {
self.fallback_algorithm = Box::new(fallback_algorithm);
self
}
pub fn handler(&self) -> Box<dyn FactorizationHandler> {
Box::new(ClauseLimitFactorizationHandler::new(self.distribution_boundary, self.created_clause_boundary))
}
}