1#[cfg(feature = "platform_wasm")]
3use instant::{Duration, Instant};
4#[cfg(not(feature = "platform_wasm"))]
5use std::time::{Duration, Instant};
6use {
7 crate::{
8 assign, cdb,
9 solver::{RestartManager, SolverEvent, StageManager},
10 types::*,
11 },
12 std::{
13 fmt,
14 io::{stdout, Write},
15 ops::{Index, IndexMut},
16 },
17};
18const PROGRESS_REPORT_ROWS: usize = 7;
19
20pub trait StateIF {
22 fn is_timeout(&self) -> bool;
24 fn elapsed(&self) -> Option<f64>;
27 fn progress_header(&mut self);
29 fn progress<A, C>(&mut self, asg: &A, cdb: &C)
31 where
32 A: PropertyDereference<assign::property::Tusize, usize>
33 + PropertyDereference<assign::property::Tf64, f64>
34 + PropertyReference<assign::property::TEma, EmaView>,
35 C: PropertyDereference<cdb::property::Tusize, usize>
36 + PropertyDereference<cdb::property::Tf64, f64>
37 + PropertyReference<cdb::property::TEma, EmaView>;
38 fn flush<S: AsRef<str>>(&self, mes: S);
40 fn log<S: AsRef<str>>(&mut self, tick: Option<(Option<usize>, Option<usize>, usize)>, mes: S);
42}
43
44#[derive(Clone, Eq, PartialEq)]
46pub enum Stat {
47 Restart,
48 Vivification,
50 VivifiedClause,
52 VivifiedVar,
54 Simplify,
56 SubsumedClause,
58 SLS,
60 EndOfStatIndex,
62}
63
64impl Index<Stat> for [usize] {
65 type Output = usize;
66 #[inline]
67 fn index(&self, i: Stat) -> &usize {
68 #[cfg(feature = "unsafe_access")]
69 unsafe {
70 self.get_unchecked(i as usize)
71 }
72 #[cfg(not(feature = "unsafe_access"))]
73 &self[i as usize]
74 }
75}
76
77impl IndexMut<Stat> for [usize] {
78 #[inline]
79 fn index_mut(&mut self, i: Stat) -> &mut usize {
80 #[cfg(feature = "unsafe_access")]
81 unsafe {
82 self.get_unchecked_mut(i as usize)
83 }
84 #[cfg(not(feature = "unsafe_access"))]
85 &mut self[i as usize]
86 }
87}
88
89#[derive(Clone, Debug)]
91pub struct State {
92 pub config: Config,
94 pub cnf: CNFDescription,
96 pub stats: [usize; Stat::EndOfStatIndex as usize],
98 pub restart: RestartManager,
100 pub stm: StageManager,
102 pub target: CNFDescription,
104 pub reflection_interval: usize,
106
107 pub b_lvl: Ema,
112 pub c_lvl: Ema,
114 pub e_mode: Ema2,
116 pub e_mode_threshold: f64,
117 pub exploration_rate_ema: Ema,
118
119 #[cfg(feature = "support_user_assumption")]
120 pub conflicts: Vec<Lit>,
122
123 #[cfg(feature = "chronoBT")]
124 pub chrono_bt_threshold: DecisionLevel,
126
127 pub last_asg: usize,
129 pub new_learnt: Vec<Lit>,
131 pub derive20: Vec<ClauseId>,
133 pub progress_cnt: usize,
135 pub record: ProgressRecord,
137 pub sls_index: usize,
139 pub start: Instant,
141 pub time_limit: f64,
143 log_messages: Vec<String>,
145}
146
147impl Default for State {
148 fn default() -> State {
149 State {
150 config: Config::default(),
151 cnf: CNFDescription::default(),
152 stats: [0; Stat::EndOfStatIndex as usize],
153 restart: RestartManager::default(),
154 stm: StageManager::default(),
155 target: CNFDescription::default(),
156 reflection_interval: 10_000,
157
158 b_lvl: Ema::new(5_000),
159 c_lvl: Ema::new(5_000),
160 e_mode: Ema2::new(40).with_slow(4_000).with_value(10.0),
161 e_mode_threshold: 1.20,
162 exploration_rate_ema: Ema::new(1000),
163
164 #[cfg(feature = "support_user_assumption")]
165 conflicts: Vec::new(),
166
167 #[cfg(feature = "chronoBT")]
168 chrono_bt_threshold: 100,
169
170 last_asg: 0,
171 new_learnt: Vec::new(),
172 derive20: Vec::new(),
173 progress_cnt: 0,
174 record: ProgressRecord::default(),
175 sls_index: 0,
176 start: Instant::now(),
177 time_limit: 0.0,
178 log_messages: Vec::new(),
179 }
180 }
181}
182
183impl Index<Stat> for State {
184 type Output = usize;
185 #[inline]
186 fn index(&self, i: Stat) -> &usize {
187 #[cfg(feature = "unsafe_access")]
188 unsafe {
189 self.stats.get_unchecked(i as usize)
190 }
191 #[cfg(not(feature = "unsafe_access"))]
192 &self.stats[i as usize]
193 }
194}
195
196impl IndexMut<Stat> for State {
197 #[inline]
198 fn index_mut(&mut self, i: Stat) -> &mut usize {
199 #[cfg(feature = "unsafe_access")]
200 unsafe {
201 self.stats.get_unchecked_mut(i as usize)
202 }
203 #[cfg(not(feature = "unsafe_access"))]
204 &mut self.stats[i as usize]
205 }
206}
207
208impl Instantiate for State {
209 fn instantiate(config: &Config, cnf: &CNFDescription) -> State {
210 State {
211 config: config.clone(),
212 cnf: cnf.clone(),
213 restart: RestartManager::instantiate(config, cnf),
214 stm: StageManager::instantiate(config, cnf),
215 target: cnf.clone(),
216 time_limit: config.c_timeout,
217 ..State::default()
218 }
219 }
220 fn handle(&mut self, e: SolverEvent) {
221 match e {
222 SolverEvent::NewVar => {
223 self.target.num_of_variables += 1;
224 }
225 SolverEvent::Assert(_) => (),
226 SolverEvent::Conflict => (),
227 SolverEvent::Eliminate(_) => (),
228 SolverEvent::Instantiate => (),
229 SolverEvent::Reinitialize => (),
230 SolverEvent::Restart => {
231 self[Stat::Restart] += 1;
232 self.restart.handle(SolverEvent::Restart);
233 }
234 SolverEvent::Stage(_) => (),
235
236 #[cfg(feature = "clause_vivification")]
237 SolverEvent::Vivify(_) => (),
238 }
239 }
240}
241
242macro_rules! im {
243 ($format: expr, $state: expr, $key: expr, $val: expr) => {
244 match ($val, $key) {
245 (v, LogUsizeId::End) => format!($format, v),
246 (v, k) => {
247 let ptr = &mut $state.record[k];
248 if $state.config.no_color {
249 *ptr = v;
250 format!($format, *ptr)
251 } else if (v as f64) * 1.6 < *ptr as f64 {
252 *ptr = v;
253 format!("\x1B[001m\x1B[031m{}\x1B[000m", format!($format, *ptr))
254 } else if v < *ptr {
255 *ptr = v;
256 format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
257 } else if (*ptr as f64) * 1.6 < v as f64 {
258 *ptr = v;
259 format!("\x1B[001m\x1B[036m{}\x1B[000m", format!($format, *ptr))
260 } else if *ptr < v {
261 *ptr = v;
262 format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
263 } else {
264 *ptr = v;
265 format!($format, *ptr)
266 }
267 }
268 }
269 };
270 ($format: expr, $state: expr, $key: expr, $val: expr, $threshold: expr) => {
271 match ($val, $key) {
272 (v, LogUsizeId::End) => format!($format, v),
273 (v, k) => {
274 let ptr = &mut $state.record[k];
275 if $state.config.no_color {
276 *ptr = v;
277 format!($format, *ptr)
278 } else if v < $threshold {
279 *ptr = v;
280 format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
281 } else if $threshold < v {
282 *ptr = v;
283 format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
284 } else {
285 *ptr = v;
286 format!($format, *ptr)
287 }
288 }
289 }
290 };
291}
292
293macro_rules! i {
294 ($format: expr, $state: expr, $key: expr, $val: expr) => {
295 match ($val, $key) {
296 (v, LogUsizeId::End) => format!($format, v),
297 (v, k) => {
298 let ptr = &mut $state.record[k];
299 *ptr = v;
300 format!($format, *ptr)
301 }
302 }
303 };
304}
305
306macro_rules! fm {
307 ($format: expr, $state: expr, $key: expr, $val: expr) => {
308 match ($val, $key) {
309 (v, LogF64Id::End) => format!($format, v),
310 (v, k) => {
311 let ptr = &mut $state.record[k];
312 if $state.config.no_color {
313 *ptr = v;
314 format!($format, *ptr)
315 } else if v * 1.6 < *ptr {
316 *ptr = v;
317 format!("\x1B[001m\x1B[031m{}\x1B[000m", format!($format, *ptr))
318 } else if v < *ptr {
319 *ptr = v;
320 format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
321 } else if *ptr * 1.6 < v {
322 *ptr = v;
323 format!("\x1B[001m\x1B[036m{}\x1B[000m", format!($format, *ptr))
324 } else if *ptr < v {
325 *ptr = v;
326 format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
327 } else {
328 *ptr = v;
329 format!($format, *ptr)
330 }
331 }
332 }
333 };
334 ($format: expr, $state: expr, $key: expr, $val: expr, $threshold: expr) => {
335 match ($val, $key) {
336 (v, LogF64Id::End) => format!($format, v),
337 (v, k) => {
338 let ptr = &mut $state.record[k];
339 if $state.config.no_color {
340 *ptr = v;
341 format!($format, *ptr)
342 } else if v < $threshold {
343 *ptr = v;
344 format!("\x1B[031m{}\x1B[000m", format!($format, *ptr))
345 } else if $threshold < v {
346 *ptr = v;
347 format!("\x1B[036m{}\x1B[000m", format!($format, *ptr))
348 } else {
349 *ptr = v;
350 format!($format, *ptr)
351 }
352 }
353 }
354 };
355}
356
357#[allow(unused_macros)]
358macro_rules! f {
359 ($format: expr, $state: expr, $key: expr, $val: expr) => {
360 match ($val, $key) {
361 (v, LogF64Id::End) => format!($format, v),
362 (v, k) => {
363 let ptr = &mut $state.record[k];
364 *ptr = v;
365 format!($format, *ptr)
366 }
367 }
368 };
369}
370
371impl StateIF for State {
372 fn is_timeout(&self) -> bool {
373 Duration::from_secs(self.config.c_timeout as u64) < self.start.elapsed()
374 }
375 fn elapsed(&self) -> Option<f64> {
376 Some(
377 self.start.elapsed().as_secs_f64()
378 / Duration::from_secs(self.config.c_timeout as u64).as_secs_f64(),
379 )
380 }
381 fn progress_header(&mut self) {
382 if !self.config.splr_interface || self.config.quiet_mode {
383 return;
384 }
385 if self.config.use_log {
386 self.dump_header();
387 return;
388 }
389 if 0 == self.progress_cnt {
390 self.progress_cnt = 1;
391 println!("{self}");
392
393 for _i in 0..PROGRESS_REPORT_ROWS - 1 {
395 println!(" ");
396 }
397 }
398 }
399 fn flush<S: AsRef<str>>(&self, mes: S) {
400 if self.config.splr_interface && !self.config.quiet_mode && !self.config.use_log {
401 if mes.as_ref().is_empty() {
402 print!("\x1B[1G\x1B[K")
403 } else {
404 print!("{}", mes.as_ref());
405 }
406 stdout().flush().unwrap();
407 }
408 }
409 fn log<S: AsRef<str>>(&mut self, tick: Option<(Option<usize>, Option<usize>, usize)>, mes: S) {
410 if self.config.splr_interface && !self.config.quiet_mode && !self.config.use_log {
411 self.log_messages.insert(
412 0,
413 match tick {
414 Some((Some(seg), Some(cyc), stg)) => {
415 format!("stage({:>2},{:>4},{:>5}): {}", seg, cyc, stg, mes.as_ref())
416 }
417 Some((None, Some(cyc), stg)) => {
418 format!("stage( ,{:>4},{:>5}): {}", cyc, stg, mes.as_ref())
419 }
420 Some((None, None, stg)) => {
421 format!("stage( , ,{:>5}): {}", stg, mes.as_ref())
422 }
423 Some(_) => unreachable!(),
424 None => format!("### {}", mes.as_ref()),
425 },
426 );
427 }
428 }
429 #[allow(clippy::cognitive_complexity)]
431 fn progress<A, C>(&mut self, asg: &A, cdb: &C)
432 where
433 A: PropertyDereference<assign::property::Tusize, usize>
434 + PropertyDereference<assign::property::Tf64, f64>
435 + PropertyReference<assign::property::TEma, EmaView>,
436 C: PropertyDereference<cdb::property::Tusize, usize>
437 + PropertyDereference<cdb::property::Tf64, f64>
438 + PropertyReference<cdb::property::TEma, EmaView>,
439 {
440 if !self.config.splr_interface || self.config.quiet_mode {
441 self.log_messages.clear();
442 self.record_stats(asg, cdb);
443 return;
444 }
445
446 let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
450 let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
451 let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
452 let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
453 let asg_num_unreachables = asg.derefer(assign::property::Tusize::NumUnreachableVar);
454 let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
455 let asg_num_conflict = asg.derefer(assign::property::Tusize::NumConflict);
456 let asg_num_decision = asg.derefer(assign::property::Tusize::NumDecision);
457 let asg_num_propagation = asg.derefer(assign::property::Tusize::NumPropagation);
458 let asg_dpc_ema = asg.refer(assign::property::TEma::DecisionPerConflict);
460 let asg_ppc_ema = asg.refer(assign::property::TEma::PropagationPerConflict);
461 let asg_cpr_ema = asg.refer(assign::property::TEma::ConflictPerRestart);
462
463 let cdb_num_clause = cdb.derefer(cdb::property::Tusize::NumClause);
464 let cdb_num_bi_clause = cdb.derefer(cdb::property::Tusize::NumBiClause);
465 let cdb_num_lbd2 = cdb.derefer(cdb::property::Tusize::NumLBD2);
466 let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
467 let cdb_lb_ent: f64 = cdb.derefer(cdb::property::Tf64::LiteralBlockEntanglement);
468 let rst_num_rst: usize = self[Stat::Restart];
469 let rst_asg: &EmaView = asg.refer(assign::property::TEma::AssignRate);
470 let rst_lbd: &EmaView = cdb.refer(cdb::property::TEma::LBD);
471 let rst_eng: f64 = self.restart.penetration_energy_charged;
472 let stg_segment: usize = self.stm.current_segment();
473
474 if self.config.use_log {
475 self.dump(asg, cdb);
476 return;
477 }
478 self.progress_cnt += 1;
479 print!("\x1B[");
481 print!("{PROGRESS_REPORT_ROWS}");
482 print!("A\x1B[1G");
483
484 if self.config.show_journal {
485 while let Some(m) = self.log_messages.pop() {
486 if self.config.no_color {
487 println!("{m}");
488 } else {
489 println!("\x1B[2K\x1B[000m\x1B[034m{m}\x1B[000m");
490 }
491 }
492 } else {
493 self.log_messages.clear();
494 }
495 println!("\x1B[2K{self}");
496 println!(
497 "\x1B[2K #conflict:{}, #decision:{}, #propagate:{}",
498 i!("{:>11}", self, LogUsizeId::NumConflict, asg_num_conflict),
499 i!("{:>13}", self, LogUsizeId::NumDecision, asg_num_decision),
500 i!(
501 "{:>15}",
502 self,
503 LogUsizeId::NumPropagate,
504 asg_num_propagation
505 ),
506 );
507 println!(
508 "\x1B[2K Assignment|#rem:{}, #fix:{}, #elm:{}, prg%:{}",
509 im!(
510 "{:>9}",
511 self,
512 LogUsizeId::RemainingVar,
513 asg_num_unasserted_vars
514 ),
515 im!(
516 "{:>9}",
517 self,
518 LogUsizeId::AssertedVar,
519 asg_num_asserted_vars
520 ),
521 im!(
522 "{:>9}",
523 self,
524 LogUsizeId::EliminatedVar,
525 asg_num_eliminated_vars
526 ),
527 fm!("{:>9.4}", self, LogF64Id::Progress, rate * 100.0),
528 );
529 println!(
530 "\x1B[2K Clause|Remv:{}, LBD2:{}, BinC:{}, Perm:{}",
531 im!("{:>9}", self, LogUsizeId::RemovableClause, cdb_num_learnt),
532 im!("{:>9}", self, LogUsizeId::LBD2Clause, cdb_num_lbd2),
533 im!(
534 "{:>9}",
535 self,
536 LogUsizeId::BiClause,
537 cdb_num_bi_clause ),
539 im!(
540 "{:>9}",
541 self,
542 LogUsizeId::PermanentClause,
543 cdb_num_clause - cdb_num_learnt
544 ),
545 );
546 self[LogUsizeId::StageSegment] = stg_segment;
547 self[LogF64Id::RestartEnergy] = rst_eng;
548 self[LogF64Id::TrendASG] = rst_asg.trend();
549 println!(
550 "\x1B[2K Conflict|entg:{}, cLvl:{}, bLvl:{}, /cpr:{}",
551 fm!(
552 "{:>9.4}",
553 self,
554 LogF64Id::LiteralBlockEntanglement,
555 cdb_lb_ent
556 ),
557 fm!("{:>9.4}", self, LogF64Id::CLevel, self.c_lvl.get()),
558 fm!("{:>9.4}", self, LogF64Id::BLevel, self.b_lvl.get()),
559 fm!(
560 "{:>9.2}",
561 self,
562 LogF64Id::ConflictPerRestart,
563 asg_cpr_ema.get()
564 )
565 );
566 println!(
567 "\x1B[2K Learning|avrg:{}, trnd:{}, #RST:{}, /dpc:{}",
568 fm!("{:>9.4}", self, LogF64Id::EmaLBD, rst_lbd.get_fast()),
569 fm!("{:>9.4}", self, LogF64Id::TrendLBD, rst_lbd.trend()),
570 im!("{:>9}", self, LogUsizeId::Restart, rst_num_rst),
571 fm!(
572 "{:>9.2}",
573 self,
574 LogF64Id::DecisionPerConflict,
575 asg_dpc_ema.get()
576 ),
577 );
578 println!(
579 "\x1B[2K misc|vivC:{}, xplr:{}, core:{}, /ppc:{}",
580 im!(
581 "{:>9}",
582 self,
583 LogUsizeId::VivifiedClause,
584 self[Stat::VivifiedClause]
585 ),
586 fm!(
587 "{:>9.4}",
588 self,
589 LogF64Id::ExExTrend,
590 self.exploration_rate_ema.get() ),
593 im!(
594 "{:>9}",
595 self,
596 LogUsizeId::UnreachableCore,
597 if asg_num_unreachables == 0 {
598 self[LogUsizeId::UnreachableCore]
599 } else {
600 asg_num_unreachables
601 }
602 ),
603 fm!(
604 "{:>9.2}",
605 self,
606 LogF64Id::PropagationPerConflict,
607 asg_ppc_ema.get()
608 ),
609 );
610 self[LogUsizeId::Stage] = self.stm.current_stage();
611 self[LogUsizeId::StageCycle] = self.stm.current_cycle();
612 self[LogUsizeId::Vivify] = self[Stat::Vivification];
613 self.flush("");
614 }
615}
616
617impl State {
618 #[allow(clippy::cognitive_complexity)]
619 fn record_stats<A, C>(&mut self, asg: &A, cdb: &C)
620 where
621 A: PropertyDereference<assign::property::Tusize, usize>
622 + PropertyReference<assign::property::TEma, EmaView>,
623 C: PropertyDereference<cdb::property::Tusize, usize>
624 + PropertyDereference<cdb::property::Tf64, f64>
625 + PropertyReference<cdb::property::TEma, EmaView>,
626 {
627 self[LogUsizeId::NumConflict] = asg.derefer(assign::property::Tusize::NumConflict);
628 self[LogUsizeId::NumDecision] = asg.derefer(assign::property::Tusize::NumDecision);
629 self[LogUsizeId::NumPropagate] = asg.derefer(assign::property::Tusize::NumPropagation);
630 self[LogUsizeId::RemainingVar] = asg.derefer(assign::property::Tusize::NumUnassertedVar);
631 self[LogUsizeId::AssertedVar] = asg.derefer(assign::property::Tusize::NumAssertedVar);
632 self[LogUsizeId::EliminatedVar] = asg.derefer(assign::property::Tusize::NumEliminatedVar);
633 self[LogF64Id::Progress] = 100.0
634 * (self[LogUsizeId::AssertedVar]
635 + asg.derefer(assign::property::Tusize::NumEliminatedVar)) as f64
636 / asg.derefer(assign::property::Tusize::NumVar) as f64;
637 self[LogUsizeId::RemovableClause] = cdb.derefer(cdb::property::Tusize::NumLearnt);
638 self[LogUsizeId::LBD2Clause] = cdb.derefer(cdb::property::Tusize::NumLBD2);
639 self[LogUsizeId::BiClause] = cdb.derefer(cdb::property::Tusize::NumBiClause);
640 self[LogUsizeId::PermanentClause] =
641 cdb.derefer(cdb::property::Tusize::NumClause) - self[LogUsizeId::RemovableClause];
642 self[LogUsizeId::Restart] = self[Stat::Restart];
643 self[LogUsizeId::Stage] = self.stm.current_stage();
644 self[LogUsizeId::StageCycle] = self.stm.current_cycle();
645 self[LogUsizeId::StageSegment] = self.stm.max_scale();
646 self[LogUsizeId::Simplify] = self[Stat::Simplify];
647 self[LogUsizeId::SubsumedClause] = self[Stat::SubsumedClause];
648 self[LogUsizeId::VivifiedClause] = self[Stat::VivifiedClause];
649 self[LogUsizeId::VivifiedVar] = self[Stat::VivifiedVar];
650 self[LogUsizeId::Vivify] = self[Stat::Vivification];
651 let rst_lbd: &EmaView = cdb.refer(cdb::property::TEma::LBD);
652 self[LogF64Id::EmaLBD] = rst_lbd.get_fast();
653 self[LogF64Id::TrendLBD] = rst_lbd.trend();
654
655 self[LogF64Id::LiteralBlockEntanglement] =
656 cdb.derefer(cdb::property::Tf64::LiteralBlockEntanglement);
657 self[LogF64Id::DecisionPerConflict] =
658 asg.refer(assign::property::TEma::DecisionPerConflict).get();
659
660 self[LogF64Id::TrendASG] = asg.refer(assign::property::TEma::AssignRate).trend();
661 self[LogF64Id::CLevel] = self.c_lvl.get();
662 self[LogF64Id::BLevel] = self.b_lvl.get();
663 self[LogF64Id::PropagationPerConflict] = asg
664 .refer(assign::property::TEma::PropagationPerConflict)
665 .get();
666 {
667 let core = asg.derefer(assign::property::Tusize::NumUnreachableVar);
668 if 0 < core {
669 self[LogUsizeId::UnreachableCore] = core;
670 }
671 }
672 self[LogF64Id::ConflictPerRestart] =
673 asg.refer(assign::property::TEma::ConflictPerRestart).get();
674 }
675}
676
677impl fmt::Display for State {
678 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
679 let tm: f64 = (self.start.elapsed().as_millis() as f64) / 1_000.0;
680 let vc = format!(
681 "{},{}",
682 self.target.num_of_variables, self.target.num_of_clauses,
683 );
684 let vclen = vc.len();
685 let width = 59;
686 let mut fname = match &self.target.pathname {
687 CNFIndicator::Void => "(no cnf)".to_string(),
688 CNFIndicator::File(f) => f.to_string(),
689 CNFIndicator::LitVec(n) => format!("(embedded {n} element vector)"),
690 };
691 if width <= fname.len() {
692 fname.truncate(58 - vclen);
693 }
694 let fnlen = fname.len();
695 if width < vclen + fnlen + 1 {
696 write!(f, "{fname:<width$} |time:{tm:>9.2}")
697 } else {
698 write!(f, "{fname}{:>w$} |time:{tm:>9.2}", &vc, w = width - fnlen,)
699 }
700 }
701}
702
703impl Index<LogUsizeId> for State {
704 type Output = usize;
705 #[inline]
706 fn index(&self, i: LogUsizeId) -> &Self::Output {
707 #[cfg(feature = "unsafe_access")]
708 unsafe {
709 self.record.vali.get_unchecked(i as usize)
710 }
711 #[cfg(not(feature = "unsafe_access"))]
712 &self.record.vali[i as usize]
713 }
714}
715
716impl IndexMut<LogUsizeId> for State {
717 #[inline]
718 fn index_mut(&mut self, i: LogUsizeId) -> &mut Self::Output {
719 #[cfg(feature = "unsafe_access")]
720 unsafe {
721 self.record.vali.get_unchecked_mut(i as usize)
722 }
723 #[cfg(not(feature = "unsafe_access"))]
724 &mut self.record.vali[i as usize]
725 }
726}
727
728impl Index<LogF64Id> for State {
729 type Output = f64;
730 #[inline]
731 fn index(&self, i: LogF64Id) -> &Self::Output {
732 #[cfg(feature = "unsafe_access")]
733 unsafe {
734 self.record.valf.get_unchecked(i as usize)
735 }
736 #[cfg(not(feature = "unsafe_access"))]
737 &self.record.valf[i as usize]
738 }
739}
740
741impl IndexMut<LogF64Id> for State {
742 #[inline]
743 fn index_mut(&mut self, i: LogF64Id) -> &mut Self::Output {
744 #[cfg(feature = "unsafe_access")]
745 unsafe {
746 self.record.valf.get_unchecked_mut(i as usize)
747 }
748 #[cfg(not(feature = "unsafe_access"))]
749 &mut self.record.valf[i as usize]
750 }
751}
752
753impl State {
754 #[allow(dead_code)]
755 fn dump_header_details(&self) {
756 println!(
757 " #mode, Variable Assignment ,, \
758 Clause Database ent ,, Restart Strategy ,, \
759 Misc Progress Parameters,, Eliminator"
760 );
761 println!(
762 " #init, #remain,#asserted,#elim,total%,,#learnt, \
763 #perm,#binary,,block,force, #asgn, lbd/,, lbd, \
764 back lv, conf lv,,clause, var"
765 );
766 }
767 fn dump_header(&self) {
768 println!(
769 "c | RESTARTS | ORIGINAL FORMULA | LEARNT CLAUSES | Progress |\n\
770 c | number av. cnfl | Remains Elim-ed Clauses | #rdct Learnts LBD2 | |\n\
771 c |-------------------|----------------------------|--------------------------|----------|"
772 );
773 }
774 fn dump<A, C>(&mut self, asg: &A, cdb: &C)
775 where
776 A: PropertyDereference<assign::property::Tusize, usize>,
777 C: PropertyDereference<cdb::property::Tusize, usize>,
778 {
779 self.progress_cnt += 1;
780 let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
781 let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
782 let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
783 let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
784 let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
785 let asg_num_conflict = asg.derefer(assign::property::Tusize::NumConflict);
786 let asg_num_restart = asg.derefer(assign::property::Tusize::NumRestart);
787 let cdb_num_clause = cdb.derefer(cdb::property::Tusize::NumClause);
788 let cdb_num_lbd2 = cdb.derefer(cdb::property::Tusize::NumLBD2);
789 let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
790 let cdb_num_reduction = cdb.derefer(cdb::property::Tusize::NumReduction);
791 println!(
792 "c | {:>8} {:>8} | {:>8} {:>8} {:>8} | {:>4} {:>8} {:>8} | {:>6.3} % |",
793 asg_num_restart, asg_num_conflict / asg_num_restart.max(1), asg_num_unasserted_vars, asg_num_eliminated_vars, cdb_num_clause - cdb_num_learnt, cdb_num_reduction, cdb_num_learnt, cdb_num_lbd2, rate * 100.0, );
803 }
804 #[allow(dead_code)]
805 fn dump_details<A, C>(&mut self, asg: &A, cdb: &C)
806 where
807 A: PropertyDereference<assign::property::Tusize, usize>
808 + PropertyReference<assign::property::TEma, EmaView>,
809 C: PropertyDereference<cdb::property::Tusize, usize>
810 + PropertyReference<cdb::property::TEma, EmaView>,
811 {
812 self.progress_cnt += 1;
813 let asg_num_vars = asg.derefer(assign::property::Tusize::NumVar);
814 let asg_num_asserted_vars = asg.derefer(assign::property::Tusize::NumAssertedVar);
815 let asg_num_eliminated_vars = asg.derefer(assign::property::Tusize::NumEliminatedVar);
816 let asg_num_unasserted_vars = asg.derefer(assign::property::Tusize::NumUnassertedVar);
817 let rate = (asg_num_asserted_vars + asg_num_eliminated_vars) as f64 / asg_num_vars as f64;
818 let asg_num_restart = asg.derefer(assign::property::Tusize::NumRestart);
819 let cdb_num_clause = cdb.derefer(cdb::property::Tusize::NumClause);
820 let cdb_num_learnt = cdb.derefer(cdb::property::Tusize::NumLearnt);
821 let rst_asg = asg.refer(assign::property::TEma::AssignRate);
822 let rst_lbd = cdb.refer(cdb::property::TEma::LBD);
823
824 println!(
825 "{:>3},{:>7},{:>7},{:>7},{:>6.3},,{:>7},{:>7},\
826 {:>7},,{:>5},{:>5},{:>6.2},{:>6.2},,{:>7.2},{:>8.2},{:>8.2},,\
827 {:>6},{:>6}",
828 self.progress_cnt,
829 asg_num_unasserted_vars,
830 asg_num_asserted_vars,
831 asg_num_eliminated_vars,
832 rate * 100.0,
833 cdb_num_learnt,
834 cdb_num_clause,
835 0,
836 0,
837 asg_num_restart,
838 rst_asg.trend(),
839 rst_lbd.get(),
840 rst_lbd.trend(),
841 self.b_lvl.get(),
842 self.c_lvl.get(),
843 0, 0, );
846 }
847}
848
849#[derive(Clone, Copy, Debug)]
851pub enum LogUsizeId {
852 NumConflict = 0,
856 NumPropagate,
857 NumDecision,
858
859 RemainingVar,
863 AssertedVar,
864 EliminatedVar,
865 UnreachableCore,
866
867 RemovableClause,
871 LBD2Clause,
872 BiClause,
873 PermanentClause,
874
875 Restart,
879
880 Stage,
884 StageCycle,
885 StageSegment,
886
887 Simplify,
891 SubsumedClause,
892 VivifiedClause,
893 VivifiedVar,
894 Vivify,
895
896 SLS,
900
901 End,
903}
904
905#[derive(Clone, Copy, Debug)]
907pub enum LogF64Id {
908 Progress = 0,
909 EmaASG,
910 EmaCCC,
911 EmaLBD,
912 EmaMLD,
913 TrendASG,
914 TrendLBD,
915 BLevel,
916 CLevel,
917 ExExTrend,
918 DecisionPerConflict,
919 ConflictPerRestart,
920 PropagationPerConflict,
921 LiteralBlockEntanglement,
922 RestartEnergy,
923
924 End,
925}
926
927#[derive(Clone, Debug)]
929pub struct ProgressRecord {
930 pub vali: [usize; LogUsizeId::End as usize],
931 pub valf: [f64; LogF64Id::End as usize],
932}
933
934impl Default for ProgressRecord {
935 fn default() -> ProgressRecord {
936 ProgressRecord {
937 vali: [0; LogUsizeId::End as usize],
938 valf: [0.0; LogF64Id::End as usize],
939 }
940 }
941}
942
943impl Index<LogUsizeId> for ProgressRecord {
944 type Output = usize;
945 #[inline]
946 fn index(&self, i: LogUsizeId) -> &usize {
947 #[cfg(feature = "unsafe_access")]
948 unsafe {
949 self.vali.get_unchecked(i as usize)
950 }
951 #[cfg(not(feature = "unsafe_access"))]
952 &self.vali[i as usize]
953 }
954}
955
956impl IndexMut<LogUsizeId> for ProgressRecord {
957 #[inline]
958 fn index_mut(&mut self, i: LogUsizeId) -> &mut usize {
959 #[cfg(feature = "unsafe_access")]
960 unsafe {
961 self.vali.get_unchecked_mut(i as usize)
962 }
963 #[cfg(not(feature = "unsafe_access"))]
964 &mut self.vali[i as usize]
965 }
966}
967
968impl Index<LogF64Id> for ProgressRecord {
969 type Output = f64;
970 #[inline]
971 fn index(&self, i: LogF64Id) -> &f64 {
972 #[cfg(feature = "unsafe_access")]
973 unsafe {
974 self.valf.get_unchecked(i as usize)
975 }
976 #[cfg(not(feature = "unsafe_access"))]
977 &self.valf[i as usize]
978 }
979}
980
981impl IndexMut<LogF64Id> for ProgressRecord {
982 #[inline]
983 fn index_mut(&mut self, i: LogF64Id) -> &mut f64 {
984 #[cfg(feature = "unsafe_access")]
985 unsafe {
986 self.valf.get_unchecked_mut(i as usize)
987 }
988 #[cfg(not(feature = "unsafe_access"))]
989 &mut self.valf[i as usize]
990 }
991}
992
993pub mod property {
994 use super::*;
995
996 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
997 pub enum Tusize {
998 Vivification,
1000 VivifiedClause,
1002 VivifiedVar,
1004
1005 NumCycle,
1009 NumStage,
1010 IntervalScale,
1011 IntervalScaleMax,
1012 }
1013
1014 pub const USIZES: [Tusize; 7] = [
1015 Tusize::Vivification,
1016 Tusize::VivifiedClause,
1017 Tusize::VivifiedVar,
1018 Tusize::NumCycle,
1019 Tusize::NumStage,
1020 Tusize::IntervalScale,
1021 Tusize::IntervalScaleMax,
1022 ];
1023
1024 impl PropertyDereference<Tusize, usize> for State {
1025 #[inline]
1026 fn derefer(&self, k: Tusize) -> usize {
1027 match k {
1028 Tusize::Vivification => self[Stat::Vivification],
1029 Tusize::VivifiedClause => self[Stat::VivifiedClause],
1030 Tusize::VivifiedVar => self[Stat::VivifiedVar],
1031 Tusize::NumCycle => self.stm.current_cycle(),
1032 Tusize::NumStage => self.stm.current_stage(),
1033 Tusize::IntervalScale => self.stm.current_scale(),
1034 Tusize::IntervalScaleMax => self.stm.max_scale(),
1035 }
1036 }
1037 }
1038
1039 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
1040 pub enum TEma {
1041 BackjumpLevel,
1042 ConflictLevel,
1043 }
1044
1045 pub const EMAS: [TEma; 2] = [TEma::BackjumpLevel, TEma::ConflictLevel];
1046
1047 impl PropertyReference<TEma, EmaView> for State {
1048 #[inline]
1049 fn refer(&self, k: TEma) -> &EmaView {
1050 match k {
1051 TEma::BackjumpLevel => self.b_lvl.as_view(),
1052 TEma::ConflictLevel => self.c_lvl.as_view(),
1053 }
1054 }
1055 }
1056}