#[cfg(feature = "strategy_adaptation")]
use {crate::cdb::ClauseDBIF, std::cmp::Ordering};
use {
crate::{
assign, cdb, processor,
solver::{self, SolverEvent},
types::*,
},
std::{
fmt,
io::{stdout, Write},
ops::{Index, IndexMut},
time::{Duration, Instant},
},
};
#[cfg(not(feature = "strategy_adaptation"))]
const PROGRESS_REPORT_ROWS: usize = 8;
#[cfg(feature = "strategy_adaptation")]
const PROGRESS_REPORT_ROWS: usize = 9;
pub trait StateIF {
fn is_timeout(&self) -> bool;
fn elapsed(&self) -> Option<f64>;
#[cfg(feature = "strategy_adaptation")]
fn select_strategy<A, C>(&mut self, asg: &A, cdb: &C)
where
A: AssignIF,
C: PropertyDereference<cdb::property::Tusize, usize>;
fn progress_header(&mut self);
fn progress<A, C, E, R>(&mut self, asg: &A, cdb: &C, elim: &E, rst: &R)
where
A: PropertyDereference<assign::property::Tusize, usize>
+ PropertyReference<assign::property::TEma, Ema>,
C: PropertyDereference<cdb::property::Tusize, usize>
+ PropertyDereference<cdb::property::Tf64, f64>,
E: PropertyDereference<processor::property::Tusize, usize>,
R: PropertyDereference<solver::restart::property::Tusize, usize>
+ PropertyReference<solver::restart::property::TEma2, Ema2>;
fn flush<S: AsRef<str>>(&self, mes: S);
fn log<S: AsRef<str>>(&mut self, tick: usize, mes: S);
}
#[derive(Debug, Eq, PartialEq)]
pub enum StagingTarget {
Backbone,
BestPhases,
Clear,
}
impl fmt::Display for StagingTarget {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"{}",
match self {
StagingTarget::Backbone => "Staging_backbone",
StagingTarget::BestPhases => "Staging_bestphase",
StagingTarget::Clear => "Staging_none",
}
)
}
}
#[cfg(feature = "strategy_adaptation")]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SearchStrategy {
Initial,
Generic,
LowDecisions,
HighSuccessive,
LowSuccessive,
ManyGlues,
}
#[cfg(feature = "strategy_adaptation")]
impl fmt::Display for SearchStrategy {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if formatter.alternate() {
write!(formatter, "{}", self.to_str())
} else {
let name = match self {
SearchStrategy::Initial => "Initial",
SearchStrategy::Generic => "Generic",
SearchStrategy::LowDecisions => "LowDecs",
SearchStrategy::HighSuccessive => "HighSucc",
SearchStrategy::LowSuccessive => "LowSucc",
SearchStrategy::ManyGlues => "ManyGlue",
};
if let Some(w) = formatter.width() {
match name.len().cmp(&w) {
Ordering::Equal => write!(formatter, "{}", name),
Ordering::Less => write!(formatter, "{}{}", " ".repeat(w - name.len()), name),
Ordering::Greater => write!(formatter, "{}", &name[..w]),
}
} else {
write!(formatter, "{}", name)
}
}
}
}
#[cfg(feature = "strategy_adaptation")]
impl SearchStrategy {
pub fn to_str(self) -> &'static str {
match self {
SearchStrategy::Initial => "Initial search phase before a main strategy",
SearchStrategy::Generic => "Generic (using a generic parameter set)",
SearchStrategy::LowDecisions => "LowDecisions (many conflicts at low levels)",
SearchStrategy::HighSuccessive => "HighSuccessiveConflict (long decision chains)",
SearchStrategy::LowSuccessive => "LowSuccessive (successive conflicts)",
SearchStrategy::ManyGlues => "ManyGlueClauses",
}
}
}
#[derive(Clone, Eq, PartialEq)]
pub enum Stat {
NoDecisionConflict,
Vivification,
VivifiedVar,
EndOfStatIndex,
}
impl Index<Stat> for [usize] {
type Output = usize;
#[inline]
fn index(&self, i: Stat) -> &usize {
unsafe { self.get_unchecked(i as usize) }
}
}
impl IndexMut<Stat> for [usize] {
#[inline]
fn index_mut(&mut self, i: Stat) -> &mut usize {
unsafe { self.get_unchecked_mut(i as usize) }
}
}
#[derive(Clone, Debug)]
pub struct State {
pub config: Config,
pub stats: [usize; Stat::EndOfStatIndex as usize],
#[cfg(feature = "strategy_adaptation")]
pub strategy: (SearchStrategy, usize),
pub target: CNFDescription,
pub reflection_interval: usize,
pub b_lvl: Ema,
pub c_lvl: Ema,
pub conflicts: Vec<Lit>,
pub chrono_bt_threshold: DecisionLevel,
pub last_asg: usize,
pub new_learnt: Vec<Lit>,
pub derive20: Vec<ClauseId>,
pub progress_cnt: usize,
pub record: ProgressRecord,
pub start: Instant,
pub time_limit: f64,
log_messages: Vec<String>,
}
impl Default for State {
fn default() -> State {
State {
config: Config::default(),
stats: [0; Stat::EndOfStatIndex as usize],
#[cfg(feature = "strategy_adaptation")]
strategy: (SearchStrategy::Initial, 0),
target: CNFDescription::default(),
reflection_interval: 10_000,
b_lvl: Ema::new(5_000),
c_lvl: Ema::new(5_000),
conflicts: Vec::new(),
chrono_bt_threshold: 100,
last_asg: 0,
new_learnt: Vec::new(),
derive20: Vec::new(),
progress_cnt: 0,
record: ProgressRecord::default(),
start: Instant::now(),
time_limit: 0.0,
log_messages: Vec::new(),
}
}
}
impl Index<Stat> for State {
type Output = usize;
#[inline]
fn index(&self, i: Stat) -> &usize {
unsafe { self.stats.get_unchecked(i as usize) }
}
}
impl IndexMut<Stat> for State {
#[inline]
fn index_mut(&mut self, i: Stat) -> &mut usize {
unsafe { self.stats.get_unchecked_mut(i as usize) }
}
}
impl Instantiate for State {
fn instantiate(config: &Config, cnf: &CNFDescription) -> State {
State {
config: config.clone(),
#[cfg(feature = "strategy_adaptation")]
strategy: (SearchStrategy::Initial, 0),
target: cnf.clone(),
time_limit: config.c_timeout,
..State::default()
}
}
fn handle(&mut self, e: SolverEvent) {
match e {
SolverEvent::NewVar => {
self.target.num_of_variables += 1;
}
SolverEvent::Assert(_) => (),
SolverEvent::Conflict => (),
SolverEvent::Eliminate(_) => (),
SolverEvent::Instantiate => (),
SolverEvent::Reinitialize => (),
SolverEvent::Restart => (),
SolverEvent::ShrinkCore => (),
SolverEvent::Stabilize((_, _)) => (),
#[cfg(feature = "clause_vivification")]
SolverEvent::Vivify(_) => (),
#[cfg(feature = "strategy_adaptation")]
SolverEvent::Adapt(_, _) => (),
}
}
}
macro_rules! im {
($format: expr, $state: expr, $key: expr, $val: expr) => {
match ($val, $key) {
(v, LogUsizeId::End) => format!($format, v),
(v, k) => {
let ptr = &mut $state.record[k];
if $state.config.no_color {
*ptr = v;
format!($format, *ptr)
} else if (v as f64) * 1.6 < *ptr as f64 {
*ptr = v;
format!("\x1B[001m\x1B[031m{}\x1B[000m", format!($format, *ptr))
} else if v < *ptr {
*ptr = v;
format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
} else if (*ptr as f64) * 1.6 < v as f64 {
*ptr = v;
format!("\x1B[001m\x1B[036m{}\x1B[000m", format!($format, *ptr))
} else if *ptr < v {
*ptr = v;
format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
} else {
*ptr = v;
format!($format, *ptr)
}
}
}
};
}
macro_rules! i {
($format: expr, $state: expr, $key: expr, $val: expr) => {
match ($val, $key) {
(v, LogUsizeId::End) => format!($format, v),
(v, k) => {
let ptr = &mut $state.record[k];
*ptr = v;
format!($format, *ptr)
}
}
};
}
macro_rules! fm {
($format: expr, $state: expr, $key: expr, $val: expr) => {
match ($val, $key) {
(v, LogF64Id::End) => format!($format, v),
(v, k) => {
let ptr = &mut $state.record[k];
if $state.config.no_color {
*ptr = v;
format!($format, *ptr)
} else if v * 1.6 < *ptr {
*ptr = v;
format!("\x1B[001m\x1B[031m{}\x1B[000m", format!($format, *ptr))
} else if v < *ptr {
*ptr = v;
format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
} else if *ptr * 1.6 < v {
*ptr = v;
format!("\x1B[001m\x1B[036m{}\x1B[000m", format!($format, *ptr))
} else if *ptr < v {
*ptr = v;
format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
} else {
*ptr = v;
format!($format, *ptr)
}
}
}
};
}
#[allow(unused_macros)]
macro_rules! f {
($format: expr, $state: expr, $key: expr, $val: expr) => {
match ($val, $key) {
(v, LogF64Id::End) => format!($format, v),
(v, k) => {
let ptr = &mut $state.record[k];
*ptr = v;
format!($format, *ptr)
}
}
};
}
impl StateIF for State {
fn is_timeout(&self) -> bool {
Duration::from_secs(self.config.c_timeout as u64) < self.start.elapsed()
}
fn elapsed(&self) -> Option<f64> {
Some(
self.start.elapsed().as_secs_f64()
/ Duration::from_secs(self.config.c_timeout as u64).as_secs_f64(),
)
}
#[cfg(feature = "strategy_adaptation")]
fn select_strategy<A, C>(&mut self, asg: &A, cdb: &C)
where
A: AssignIF,
C: PropertyDereference<cdb::property::Tusize, usize>,
{
let asg_num_conflict = asg.refer(assign::property::A2usize::NumConflict);
let asg_num_decision = asg.refer(assign::property::A2usize::NumDecision);
let asg_num_propagation = asg.refer(assign::property::A2usize::NumPropergation);
let asg_num_restart = asg.refer(assign::property::A2usize::NumRestart);
let cdb_num_bi_learnt = cdb.refer(cdb::property::Tusize::NumBiLearnt);
let cdb_num_lbd2 = cdb.refer(cdb::property::Tusize::NumLBD2);
debug_assert_eq!(self.strategy.0, SearchStrategy::Initial);
self.strategy.0 = match () {
_ if cdb_num_bi_learnt + 20_000 < cdb_num_lbd2 => SearchStrategy::ManyGlues,
_ if self[Stat::Decision] as f64 <= 1.2 * asg_num_conflict as f64 => {
SearchStrategy::LowDecisions
}
_ if self[Stat::NoDecisionConflict] < 15_000 => SearchStrategy::LowSuccessive,
_ if 54_400 < self[Stat::NoDecisionConflict] => SearchStrategy::HighSuccessive,
_ => SearchStrategy::Generic,
};
self.strategy.1 = asg_num_conflict;
}
fn progress_header(&mut self) {
if !self.config.splr_interface || self.config.quiet_mode {
return;
}
if self.config.use_log {
self.dump_header();
return;
}
if 0 == self.progress_cnt {
self.progress_cnt = 1;
println!("{}", self);
for _i in 0..PROGRESS_REPORT_ROWS - 1 {
println!(" ");
}
}
}
fn flush<S: AsRef<str>>(&self, mes: S) {
if self.config.splr_interface && !self.config.quiet_mode && !self.config.use_log {
if mes.as_ref().is_empty() {
print!("\x1B[1G\x1B[K")
} else {
print!("{}", mes.as_ref());
}
stdout().flush().unwrap();
}
}
fn log<S: AsRef<str>>(&mut self, tick: usize, mes: S) {
if self.config.splr_interface && !self.config.quiet_mode && !self.config.use_log {
self.log_messages
.insert(0, format!("[{:>10}] {}", tick, mes.as_ref()));
}
}
#[allow(clippy::cognitive_complexity)]
fn progress<A, C, E, R>(&mut self, asg: &A, cdb: &C, elim: &E, rst: &R)
where
A: PropertyDereference<assign::property::Tusize, usize>
+ PropertyReference<assign::property::TEma, Ema>,
C: PropertyDereference<cdb::property::Tusize, usize>
+ PropertyDereference<cdb::property::Tf64, f64>,
E: PropertyDereference<processor::property::Tusize, usize>,
R: PropertyDereference<solver::restart::property::Tusize, usize>
+ PropertyReference<solver::restart::property::TEma2, Ema2>,
{
if !self.config.splr_interface || self.config.quiet_mode {
return;
}
let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
let asg_num_unreachables = asg.derefer(assign::property::Tusize::NumUnreachableVar);
let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
let asg_num_conflict = asg.derefer(assign::property::Tusize::NumConflict);
let asg_num_decision = asg.derefer(assign::property::Tusize::NumDecision);
let asg_num_propagation = asg.derefer(assign::property::Tusize::NumPropagation);
let asg_dpc_ema = asg.refer(assign::property::TEma::DPC);
let asg_ppc_ema = asg.refer(assign::property::TEma::PPC);
let asg_cpr_ema = asg.refer(assign::property::TEma::CPR);
let cdb_num_active = cdb.derefer(cdb::property::Tusize::NumActive);
let cdb_num_biclause = cdb.derefer(cdb::property::Tusize::NumBiClause);
let cdb_num_lbd2 = cdb.derefer(cdb::property::Tusize::NumLBD2);
let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
let cdb_lbd_of_dp: f64 = cdb.derefer(cdb::property::Tf64::DpAverageLBD);
let elim_num_full = elim.derefer(processor::property::Tusize::NumFullElimination);
let elim_num_sub = elim.derefer(processor::property::Tusize::NumClauseSubsumption);
let rst_num_blk: usize = rst.derefer(solver::restart::property::Tusize::NumBlock);
let rst_num_rst: usize = rst.derefer(solver::restart::property::Tusize::NumRestart);
let rst_trg_lvl: usize = rst.derefer(solver::restart::property::Tusize::TriggerLevel);
let rst_trg_lvl_max: usize =
rst.derefer(solver::restart::property::Tusize::TriggerLevelMax);
let rst_asg: &Ema2 = rst.refer(solver::restart::property::TEma2::ASG);
let rst_lbd: &Ema2 = rst.refer(solver::restart::property::TEma2::LBD);
if self.config.use_log {
self.dump(asg, cdb, rst);
return;
}
self.progress_cnt += 1;
print!("\x1B[");
print!("{}", PROGRESS_REPORT_ROWS);
print!("A\x1B[1G");
if self.config.show_journal {
while let Some(m) = self.log_messages.pop() {
if self.config.no_color {
println!("{}", m);
} else {
println!("\x1B[2K\x1B[000m\x1B[034m{}\x1B[000m", m);
}
}
} else {
self.log_messages.clear();
}
println!("\x1B[2K{}", self);
println!(
"\x1B[2K #conflict:{}, #decision:{}, #propagate:{}",
i!("{:>11}", self, LogUsizeId::NumConflict, asg_num_conflict),
i!("{:>13}", self, LogUsizeId::NumDecision, asg_num_decision),
i!(
"{:>15}",
self,
LogUsizeId::NumPropagate,
asg_num_propagation
),
);
println!(
"\x1B[2K Assignment|#rem:{}, #ass:{}, #elm:{}, prg%:{}",
im!(
"{:>9}",
self,
LogUsizeId::RemainingVar,
asg_num_unasserted_vars
),
im!(
"{:>9}",
self,
LogUsizeId::AssertedVar,
asg_num_asserted_vars
),
im!(
"{:>9}",
self,
LogUsizeId::EliminatedVar,
asg_num_eliminated_vars
),
fm!("{:>9.4}", self, LogF64Id::Progress, rate * 100.0),
);
println!(
"\x1B[2K Clause|Remv:{}, LBD2:{}, Binc:{}, Perm:{}",
im!("{:>9}", self, LogUsizeId::RemovableClause, cdb_num_learnt),
im!("{:>9}", self, LogUsizeId::LBD2Clause, cdb_num_lbd2),
im!(
"{:>9}",
self,
LogUsizeId::Binclause,
cdb_num_biclause
),
im!(
"{:>9}",
self,
LogUsizeId::PermanentClause,
cdb_num_active - cdb_num_learnt
),
);
println!(
"\x1B[2K Restart|#BLK:{}, #RST:{}, trgr:{}, peak:{}",
im!("{:>9}", self, LogUsizeId::RestartBlock, rst_num_blk),
im!("{:>9}", self, LogUsizeId::Restart, rst_num_rst),
im!("{:>9}", self, LogUsizeId::RestartTriggerLevel, rst_trg_lvl),
im!(
"{:>9}",
self,
LogUsizeId::RestartTriggerLevelMax,
rst_trg_lvl_max
),
);
println!(
"\x1B[2K LBD|avrg:{}, trnd:{}, depG:{}, /dpc:{}",
fm!("{:>9.4}", self, LogF64Id::EmaLBD, rst_lbd.get()),
fm!("{:>9.4}", self, LogF64Id::TrendLBD, rst_lbd.trend()),
fm!("{:>9.4}", self, LogF64Id::DpAverageLBD, cdb_lbd_of_dp),
fm!(
"{:>9.2}",
self,
LogF64Id::DecisionPerConflict,
asg_dpc_ema.get()
),
);
println!(
"\x1B[2K Conflict|tASG:{}, cLvl:{}, bLvl:{}, /ppc:{}",
fm!("{:>9.4}", self, LogF64Id::TrendASG, rst_asg.trend()),
fm!("{:>9.2}", self, LogF64Id::CLevel, self.c_lvl.get()),
fm!("{:>9.2}", self, LogF64Id::BLevel, self.b_lvl.get()),
fm!(
"{:>9.2}",
self,
LogF64Id::PropagationPerConflict,
asg_ppc_ema.get()
),
);
println!(
"\x1B[2K misc|elim:{}, #sub:{}, core:{}, /cpr:{}",
im!("{:>9}", self, LogUsizeId::Simplify, elim_num_full),
im!("{:>9}", self, LogUsizeId::ClauseSubsumption, elim_num_sub),
im!(
"{:>9}",
self,
LogUsizeId::UnreachableCore,
asg_num_unreachables
),
fm!(
"{:>9.2}",
self,
LogF64Id::ConflictPerRestart,
asg_cpr_ema.get()
)
);
#[cfg(feature = "strategy_adaptation")]
{
println!("\x1B[2K Strategy|mode: {:#}", self.strategy.0);
}
self.flush("");
}
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let tm: f64 = (self.start.elapsed().as_millis() as f64) / 1_000.0;
let vc = format!(
"{},{}",
self.target.num_of_variables, self.target.num_of_clauses,
);
let vclen = vc.len();
let width = 59;
let mut fname = match &self.target.pathname {
CNFIndicator::Void => "(no cnf)".to_string(),
CNFIndicator::File(f) => f.to_string(),
CNFIndicator::LitVec(n) => format!("(embedded {} element vector)", n),
};
if width <= fname.len() {
fname.truncate(58 - vclen);
}
let fnlen = fname.len();
if width < vclen + fnlen + 1 {
write!(f, "{:<w$} |time:{:>9.2}", fname, tm, w = width)
} else {
write!(
f,
"{}{:>w$} |time:{:>9.2}",
fname,
&vc,
tm,
w = width - fnlen,
)
}
}
}
impl Index<LogUsizeId> for State {
type Output = usize;
#[inline]
fn index(&self, i: LogUsizeId) -> &Self::Output {
&self.record[i]
}
}
impl IndexMut<LogUsizeId> for State {
#[inline]
fn index_mut(&mut self, i: LogUsizeId) -> &mut Self::Output {
&mut self.record[i]
}
}
impl Index<LogF64Id> for State {
type Output = f64;
#[inline]
fn index(&self, i: LogF64Id) -> &Self::Output {
&self.record[i]
}
}
impl IndexMut<LogF64Id> for State {
#[inline]
fn index_mut(&mut self, i: LogF64Id) -> &mut Self::Output {
&mut self.record[i]
}
}
impl State {
#[allow(dead_code)]
fn dump_header_details(&self) {
println!(
" #mode, Variable Assignment ,, \
Clause Database ent ,, Restart Strategy ,, \
Misc Progress Parameters,, Eliminator"
);
println!(
" #init, #remain,#asserted,#elim,total%,,#learnt, \
#perm,#binary,,block,force, #asgn, lbd/,, lbd, \
back lv, conf lv,,clause, var"
);
}
fn dump_header(&self) {
println!(
"c | RESTARTS | ORIGINAL | LEARNT | Progress |\n\
c | NB Blocked Avg Cfc | Vars Clauses Literals | Red Learnts LBD2 Removed | |\n\
c ========================================================================================================="
);
}
fn dump<A, C, R>(&mut self, asg: &A, cdb: &C, rst: &R)
where
A: PropertyDereference<assign::property::Tusize, usize>,
C: PropertyDereference<cdb::property::Tusize, usize>,
R: PropertyDereference<solver::restart::property::Tusize, usize>,
{
self.progress_cnt += 1;
let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
let asg_num_conflict = asg.derefer(assign::property::Tusize::NumConflict);
let asg_num_restart = asg.derefer(assign::property::Tusize::NumRestart);
let cdb_num_active = cdb.derefer(cdb::property::Tusize::NumActive);
let cdb_num_lbd2 = cdb.derefer(cdb::property::Tusize::NumLBD2);
let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
let cdb_num_reduction = cdb.derefer(cdb::property::Tusize::NumReduction);
let rst_num_block = rst.derefer(solver::restart::property::Tusize::NumBlock);
println!(
"c | {:>8} {:>8} {:>8} | {:>7} {:>8} {:>8} | {:>4} {:>8} {:>7} {:>8} | {:>6.3} % |",
asg_num_restart,
rst_num_block,
asg_num_conflict / asg_num_restart.max(1),
asg_num_unasserted_vars,
cdb_num_active - cdb_num_learnt,
0,
cdb_num_reduction,
cdb_num_learnt,
cdb_num_lbd2,
asg_num_conflict - cdb_num_learnt,
rate * 100.0,
);
}
#[allow(dead_code)]
fn dump_details<'r, A, C, E, R, V>(&mut self, asg: &A, cdb: &C, rst: &'r R)
where
A: PropertyDereference<assign::property::Tusize, usize>,
C: PropertyDereference<cdb::property::Tusize, usize>,
R: PropertyDereference<solver::restart::property::Tusize, usize>
+ PropertyReference<solver::restart::property::TEma2, Ema2>,
{
self.progress_cnt += 1;
let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
let asg_num_restart = asg.derefer(assign::property::Tusize::NumRestart);
let cdb_num_active = cdb.derefer(cdb::property::Tusize::NumActive);
let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
let rst_num_block = rst.derefer(solver::restart::property::Tusize::NumBlock);
let rst_asg = rst.refer(solver::restart::property::TEma2::ASG);
let rst_lbd = rst.refer(solver::restart::property::TEma2::LBD);
println!(
"{:>3},{:>7},{:>7},{:>7},{:>6.3},,{:>7},{:>7},\
{:>7},,{:>5},{:>5},{:>6.2},{:>6.2},,{:>7.2},{:>8.2},{:>8.2},,\
{:>6},{:>6}",
self.progress_cnt,
asg_num_unasserted_vars,
asg_num_asserted_vars,
asg_num_eliminated_vars,
rate * 100.0,
cdb_num_learnt,
cdb_num_active,
0,
rst_num_block,
asg_num_restart,
rst_asg.trend(),
rst_lbd.get(),
rst_lbd.trend(),
self.b_lvl.get(),
self.c_lvl.get(),
0,
0,
);
}
}
#[derive(Clone, Copy, Debug)]
pub enum LogUsizeId {
NumConflict = 0,
NumPropagate,
NumDecision,
RemainingVar,
AssertedVar,
EliminatedVar,
UnreachableCore,
RemovableClause,
LBD2Clause,
Binclause,
PermanentClause,
Restart,
RestartBlock,
RestartCancel,
RestartStabilize,
RestartTriggerLevel,
RestartTriggerLevelMax,
Simplify,
Stabilize,
ClauseSubsumption,
Vivify,
VivifiedVar,
End,
}
#[derive(Clone, Copy, Debug)]
pub enum LogF64Id {
Progress = 0,
EmaASG,
EmaCCC,
EmaLBD,
EmaMLD,
TrendASG,
TrendLBD,
BLevel,
CLevel,
DecisionPerConflict,
ConflictPerRestart,
PropagationPerConflict,
DpAverageLBD,
End,
}
#[derive(Clone, Debug)]
pub struct ProgressRecord {
pub vali: [usize; LogUsizeId::End as usize],
pub valf: [f64; LogF64Id::End as usize],
}
impl Default for ProgressRecord {
fn default() -> ProgressRecord {
ProgressRecord {
vali: [0; LogUsizeId::End as usize],
valf: [0.0; LogF64Id::End as usize],
}
}
}
impl Index<LogUsizeId> for ProgressRecord {
type Output = usize;
#[inline]
fn index(&self, i: LogUsizeId) -> &usize {
&self.vali[i as usize]
}
}
impl IndexMut<LogUsizeId> for ProgressRecord {
#[inline]
fn index_mut(&mut self, i: LogUsizeId) -> &mut usize {
&mut self.vali[i as usize]
}
}
impl Index<LogF64Id> for ProgressRecord {
type Output = f64;
#[inline]
fn index(&self, i: LogF64Id) -> &f64 {
&self.valf[i as usize]
}
}
impl IndexMut<LogF64Id> for ProgressRecord {
#[inline]
fn index_mut(&mut self, i: LogF64Id) -> &mut f64 {
&mut self.valf[i as usize]
}
}