use crate::cnf::{CnfFormula, Literal, Reduced, ShowSet, Space, Weights};
use crate::diagnostics::diag;
use crate::error::VitriError;
use crate::preprocess::VarMap;
use crate::score::StructureProfile;
use std::time::Duration;
use std::time::Instant;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArjunSbva {
On,
Off,
Auto,
}
impl ArjunSbva {
pub fn from_env() -> Result<Self, VitriError> {
arjun_sbva_policy(crate::env::env_raw("VITRI_ARJUN_SBVA", SBVA_FORMS)?.as_deref())
}
}
const SBVA_FORMS: &str = "on (always run bounded variable addition), off (never), or \
auto (skip it when the input is coloring-like)";
pub(crate) fn arjun_sbva_policy(v: Option<&str>) -> Result<ArjunSbva, VitriError> {
crate::env::from_forms(
"VITRI_ARJUN_SBVA",
v,
ArjunSbva::On,
&[
("on", ArjunSbva::On),
("off", ArjunSbva::Off),
("auto", ArjunSbva::Auto),
],
SBVA_FORMS,
)
}
pub(crate) fn arjun_sbva_skip(formula: &CnfFormula, policy: ArjunSbva) -> bool {
match policy {
ArjunSbva::On => false,
ArjunSbva::Off => true,
ArjunSbva::Auto => {
let profile = StructureProfile::measure(formula);
if profile.coloring_like {
diag!(
"[arjun] VITRI_ARJUN_SBVA=auto — input is coloring-like, skipping SBVA \
(occ_cv={:.4} width_cv={:.4})",
profile.var_occurrence_cv,
profile.clause_width_cv,
);
}
profile.coloring_like
}
}
}
#[derive(Debug, PartialEq)]
pub(crate) struct ArjunResult {
pub formula: CnfFormula,
pub multiplier_exp: u32,
pub backbone: Vec<Literal>,
pub equiv: Vec<(Literal, Literal)>,
pub learnt_clauses: Vec<Vec<i32>>,
pub independent_support: ShowSet<Reduced>,
pub input_to_reduced_lit: VarMap<Reduced, Reduced>,
}
pub(crate) enum ArjunKeep {
ClauseCount {
raw_clauses: usize,
reduced_clauses: usize,
},
Projection {
show_shrank: bool,
multiplier_nontrivial: bool,
},
WeightedProjection {
show_shrank: bool,
multiplier_nontrivial: bool,
vars_shrank_10pct: bool,
},
Weighted {
solved_outright: bool,
inert: bool,
},
}
impl ArjunKeep {
pub(crate) fn projection_for(orig_show_len: usize, r: &ArjunProjResult) -> Self {
ArjunKeep::Projection {
show_shrank: r.show.len() != orig_show_len,
multiplier_nontrivial: r.multiplier_exp != 0,
}
}
pub(crate) fn weighted_projection_for(
orig_show_len: usize,
orig_num_vars: u32,
r: &ArjunWeightedProjResult,
) -> Self {
use num_traits::One;
ArjunKeep::WeightedProjection {
show_shrank: r.show.len() != orig_show_len,
multiplier_nontrivial: !r.multiplier.is_one(),
vars_shrank_10pct: (r.formula.num_vars as u64) * 10 < (orig_num_vars as u64) * 9,
}
}
pub(crate) fn weighted_for(input_num_vars: u32, r: &ArjunWeightedResult) -> Self {
use num_traits::One;
ArjunKeep::Weighted {
solved_outright: r.formula.num_vars == 0 || r.formula.clauses.is_empty(),
inert: r.formula.num_vars >= input_num_vars && r.multiplier.is_one(),
}
}
}
pub(crate) fn arjun_keep_reduction(criteria: ArjunKeep) -> bool {
match criteria {
ArjunKeep::ClauseCount {
raw_clauses,
reduced_clauses,
} => reduced_clauses <= raw_clauses,
ArjunKeep::Projection {
show_shrank,
multiplier_nontrivial,
} => show_shrank || multiplier_nontrivial,
ArjunKeep::WeightedProjection {
show_shrank,
multiplier_nontrivial,
vars_shrank_10pct,
} => show_shrank || multiplier_nontrivial || vars_shrank_10pct,
ArjunKeep::Weighted {
solved_outright,
inert,
} => !solved_outright && !inert,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct ArjunOptions {
pub effort: ArjunEffort,
pub sbva: ArjunSbva,
pub oracle_max_vars: OracleCaps,
pub keep_overrun: bool,
pub seed: u32,
pub export_learned_clauses: bool,
}
impl Default for ArjunOptions {
fn default() -> Self {
ArjunOptions {
effort: ArjunEffort::Full,
sbva: ArjunSbva::On,
oracle_max_vars: OracleCaps::default(),
keep_overrun: false,
seed: 42,
export_learned_clauses: false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum ArjunEffort {
#[default]
Full,
Lite,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct OracleCaps {
pub plain: Option<u32>,
pub projected: Option<u32>,
pub weighted_projected: Option<u32>,
}
impl Default for OracleCaps {
fn default() -> Self {
OracleCaps {
plain: None,
projected: Some(super::arjun_lib::PROJECTED_ORACLE_MAX_VARS_DEFAULT),
weighted_projected: Some(super::arjun_lib::PROJECTED_ORACLE_MAX_VARS_DEFAULT),
}
}
}
pub(crate) fn run_arjun_anytime(
formula: &CnfFormula,
budget: Duration,
arjun: ArjunOptions,
force_no_sbva: bool,
) -> Result<Option<ArjunResult>, VitriError> {
super::arjun_lib::reduce_anytime(formula, Instant::now() + budget, arjun, force_no_sbva)
}
pub(crate) fn run_arjun_projected_anytime<S: Space>(
formula: &CnfFormula,
show: &ShowSet<S>,
budget: Duration,
arjun: ArjunOptions,
force_no_sbva: bool,
) -> Result<Option<ArjunProjResult>, VitriError> {
super::arjun_lib::reduce_anytime_projected(
formula,
show,
Instant::now() + budget,
arjun,
force_no_sbva,
)
}
pub(crate) fn run_arjun_weighted_projected_anytime<S: Space>(
formula: &CnfFormula,
show: &ShowSet<S>,
weights: &[(i32, num_rational::BigRational)],
budget: Duration,
arjun: ArjunOptions,
force_no_sbva: bool,
) -> Result<Option<ArjunWeightedProjResult>, VitriError> {
super::arjun_lib::reduce_anytime_weighted_projected(
formula,
show,
weights,
Instant::now() + budget,
arjun,
force_no_sbva,
)
}
pub(crate) fn run_arjun_weighted_anytime(
formula: &CnfFormula,
weights: &[(i32, num_rational::BigRational)],
budget: Duration,
arjun: ArjunOptions,
force_no_sbva: bool,
) -> Result<Option<ArjunWeightedResult>, VitriError> {
super::arjun_lib::reduce_anytime_weighted(
formula,
weights,
Instant::now() + budget,
arjun,
force_no_sbva,
)
}
pub(crate) struct ArjunProjResult {
pub formula: CnfFormula,
pub show: ShowSet<Reduced>,
pub multiplier_exp: u32,
pub input_to_reduced_lit: VarMap<Reduced, Reduced>,
}
pub(crate) struct ArjunWeightedProjResult {
pub formula: CnfFormula,
pub show: ShowSet<Reduced>,
pub weights: Weights<Reduced>,
pub multiplier: num_rational::BigRational,
pub input_to_reduced_lit: VarMap<Reduced, Reduced>,
}
#[derive(Debug, PartialEq)]
pub(crate) struct ArjunWeightedResult {
pub formula: CnfFormula,
pub weights: Weights<Reduced>,
pub multiplier: num_rational::BigRational,
pub input_to_reduced_lit: VarMap<Reduced, Reduced>,
}