use bridge::ffi;
use cxx::UniquePtr;
pub mod bridge;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Status {
SATISFIABLE = 10,
UNSATISFIABLE = 20,
UNKNOWN = 0,
}
impl From<i32> for Status {
fn from(val: i32) -> Self {
match val {
10 => Status::SATISFIABLE,
20 => Status::UNSATISFIABLE,
0 => Status::UNKNOWN,
_ => unreachable!(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum State {
INITIALIZING = 1,
CONFIGURING = 2,
STEADY = 4,
ADDING = 8,
SOLVING = 16,
SATISFIED = 32,
UNSATISFIED = 64,
DELETING = 128,
READY = 102,
VALID = 110,
INVALID = 129,
}
impl From<i32> for State {
fn from(val: i32) -> Self {
match val {
1 => State::INITIALIZING,
2 => State::CONFIGURING,
4 => State::STEADY,
8 => State::ADDING,
16 => State::SOLVING,
32 => State::SATISFIED,
64 => State::UNSATISFIED,
128 => State::DELETING,
102 => State::READY,
110 => State::VALID,
129 => State::INVALID,
_ => unreachable!(),
}
}
}
pub struct CaDiCal {
solver: UniquePtr<ffi::Solver>,
last_terminator: Option<UniquePtr<ffi::Terminator>>,
last_learner: Option<UniquePtr<ffi::Learner>>,
last_external_propagator: Option<UniquePtr<ffi::ExternalPropagator>>,
last_fixed_listener: Option<UniquePtr<ffi::FixedAssignmentListener>>,
last_tracer: Option<UniquePtr<ffi::Tracer>>,
}
impl Clone for CaDiCal {
fn clone(&self) -> Self {
let mut r = Self::new();
Self::copy(self, &mut r);
r
}
}
impl Default for CaDiCal {
fn default() -> Self {
Self::new()
}
}
impl CaDiCal {
#[must_use]
#[inline]
pub fn new() -> Self {
Self {
solver: ffi::constructor(),
last_terminator: None,
last_learner: None,
last_external_propagator: None,
last_fixed_listener: None,
last_tracer: None,
}
}
#[inline]
pub fn add(&mut self, lit: i32) {
ffi::add(&mut self.solver, lit);
}
#[inline]
pub fn clause1(&mut self, l1: i32) {
ffi::clause1(&mut self.solver, l1);
}
#[inline]
pub fn clause2(&mut self, l1: i32, l2: i32) {
ffi::clause2(&mut self.solver, l1, l2);
}
#[inline]
pub fn clause3(&mut self, l1: i32, l2: i32, l3: i32) {
ffi::clause3(&mut self.solver, l1, l2, l3);
}
#[inline]
pub fn clause4(&mut self, l1: i32, l2: i32, l3: i32, l4: i32) {
ffi::clause4(&mut self.solver, l1, l2, l3, l4);
}
#[inline]
pub fn clause5(&mut self, l1: i32, l2: i32, l3: i32, l4: i32, l5: i32) {
ffi::clause5(&mut self.solver, l1, l2, l3, l4, l5);
}
#[inline]
pub fn clause6(&mut self, v: &[i32]) {
ffi::clause6(&mut self.solver, v);
}
#[inline]
pub fn inconsistent(&mut self) -> bool {
ffi::inconsistent(&mut self.solver)
}
#[inline]
pub fn assume(&mut self, lit: i32) {
ffi::assume(&mut self.solver, lit);
}
#[inline]
pub fn solve(&mut self) -> Status {
ffi::solve(&mut self.solver).into()
}
#[inline]
pub fn val(&mut self, lit: i32) -> i32 {
ffi::val(&mut self.solver, lit)
}
#[inline]
pub fn flip(&mut self, lit: i32) -> bool {
ffi::flip(&mut self.solver, lit)
}
#[inline]
pub fn flippable(&mut self, lit: i32) -> bool {
ffi::flippable(&mut self.solver, lit)
}
#[inline]
pub fn failed(&mut self, lit: i32) -> bool {
ffi::failed(&mut self.solver, lit)
}
#[inline]
#[allow(clippy::missing_panics_doc)]
pub fn connect_terminator<'a, 'b: 'a, T: Terminator>(&'a mut self, terminator: &'b mut T) {
fn f<T: Terminator>(state: *mut u8) -> bool {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.terminated()
}
let terminator =
unsafe { ffi::new_terminator(std::ptr::from_mut(terminator).cast::<u8>(), f::<T>) };
self.last_terminator = Some(terminator);
ffi::connect_terminator(&mut self.solver, self.last_terminator.as_mut().unwrap());
}
#[inline]
pub fn disconnect_terminator(&mut self) {
ffi::disconnect_terminator(&mut self.solver);
self.last_terminator = None;
}
#[inline]
#[allow(clippy::missing_panics_doc)]
pub fn connect_learner<'a, 'b: 'a, T: Learner>(&'a mut self, learner: &'b mut T) {
fn learning<T: Learner>(state: *mut u8, size: i32) -> bool {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.learning(size)
}
fn learn<T: Learner>(state: *mut u8, lit: i32) {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.learn(lit);
}
let learner = unsafe {
ffi::new_learner(
std::ptr::from_mut(learner).cast::<u8>(),
learning::<T>,
learn::<T>,
)
};
self.last_learner = Some(learner);
ffi::connect_learner(&mut self.solver, self.last_learner.as_mut().unwrap());
}
#[inline]
pub fn disconnect_learner(&mut self) {
ffi::disconnect_learner(&mut self.solver);
self.last_learner = None;
}
#[allow(clippy::missing_panics_doc)]
pub fn connect_fixed_listener<'a, 'b: 'a, F: FixedAssignmentListener>(
&'a mut self,
fixed_listener: &'b mut F,
) {
fn notify_fixed_assignment<F: FixedAssignmentListener>(state: *mut u8, lit: i32) {
let ptr: *mut F = state.cast::<F>();
let i = unsafe { &mut *ptr };
i.notify_fixed_assignment(lit);
}
let s = std::ptr::from_mut(fixed_listener).cast::<u8>();
let listener =
unsafe { ffi::new_fixed_assignment_listener(s, notify_fixed_assignment::<F>) };
self.last_fixed_listener = Some(listener);
ffi::connect_fixed_listener(&mut self.solver, self.last_fixed_listener.as_mut().unwrap());
}
#[inline]
pub fn disconnect_fixed_listener(&mut self) {
ffi::disconnect_fixed_listener(&mut self.solver);
self.last_fixed_listener = None;
}
#[allow(clippy::missing_panics_doc)]
pub fn connect_external_propagator<'a, 'b: 'a, T: ExternalPropagator>(
&'a mut self,
propagator: &'b mut T,
) {
fn notify_assignment<T: ExternalPropagator>(state: *mut u8, x: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.notify_assignment(x);
}
fn notify_new_decision_level<T: ExternalPropagator>(state: *mut u8) {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.notify_new_decision_level();
}
fn notify_backtrack<T: ExternalPropagator>(state: *mut u8, x: usize) {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.notify_backtrack(x);
}
fn cb_check_found_model<T: ExternalPropagator>(state: *mut u8, x: &[i32]) -> bool {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_check_found_model(x)
}
fn cb_decide<T: ExternalPropagator>(state: *mut u8) -> i32 {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_decide()
}
fn cb_propagate<T: ExternalPropagator>(state: *mut u8) -> i32 {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_propagate()
}
fn cb_add_reason_clause_lit<T: ExternalPropagator>(state: *mut u8, x: i32) -> i32 {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_add_reason_clause_lit(x)
}
fn cb_has_external_clause<T: ExternalPropagator>(state: *mut u8, x: *mut bool) -> bool {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_has_external_clause(unsafe { &mut *x })
}
fn cb_add_external_clause_lit<T: ExternalPropagator>(state: *mut u8) -> i32 {
let ptr: *mut T = state.cast::<T>();
let i = unsafe { &mut *ptr };
i.cb_add_external_clause_lit()
}
let is_lazy = propagator.is_lazy();
let are_reasons_forgettable = propagator.are_reasons_forgettable();
let external_propagator = unsafe {
ffi::new_external_propagator(
std::ptr::from_mut(propagator).cast::<u8>(),
is_lazy,
are_reasons_forgettable,
notify_assignment::<T>,
notify_new_decision_level::<T>,
notify_backtrack::<T>,
cb_check_found_model::<T>,
cb_decide::<T>,
cb_propagate::<T>,
cb_add_reason_clause_lit::<T>,
cb_has_external_clause::<T>,
cb_add_external_clause_lit::<T>,
)
};
self.last_external_propagator = Some(external_propagator);
ffi::connect_external_propagator(
&mut self.solver,
self.last_external_propagator.as_mut().unwrap(),
);
}
pub fn disconnect_external_propagator(&mut self) {
ffi::disconnect_external_propagator(&mut self.solver);
self.last_external_propagator = None;
}
#[inline]
pub fn add_observed_var(&mut self, var: i32) {
ffi::add_observed_var(&mut self.solver, var);
}
#[inline]
pub fn remove_observed_var(&mut self, var: i32) {
ffi::remove_observed_var(&mut self.solver, var);
}
#[inline]
pub fn reset_observed_vars(&mut self) {
ffi::reset_observed_vars(&mut self.solver);
}
#[inline]
pub fn is_decision(&mut self, lit: i32) -> bool {
ffi::is_decision(&mut self.solver, lit)
}
#[inline]
pub fn force_backtrack(&mut self, new_level: usize) {
ffi::force_backtrack(&mut self.solver, new_level);
}
#[inline]
pub fn constrain(&mut self, lit: i32) {
ffi::constrain(&mut self.solver, lit);
}
#[inline]
pub fn constraint_failed(&mut self) -> bool {
ffi::constraint_failed(&mut self.solver)
}
#[inline]
pub fn lookahead(&mut self) -> i32 {
ffi::lookahead(&mut self.solver)
}
#[inline]
pub fn generate_cubes(&mut self, x: i32, min_depth: i32, result_cubes: &mut Vec<i32>) -> i32 {
ffi::generate_cubes(&mut self.solver, x, min_depth, result_cubes)
}
#[inline]
pub fn reset_assumptions(&mut self) {
ffi::reset_assumptions(&mut self.solver);
}
#[inline]
pub fn reset_constraint(&mut self) {
ffi::reset_constraint(&mut self.solver);
}
#[must_use]
#[inline]
pub fn state(&self) -> State {
ffi::state(&self.solver).into()
}
#[must_use]
#[inline]
pub fn status(&self) -> Status {
ffi::status(&self.solver).into()
}
#[must_use]
#[inline]
pub fn version() -> String {
ffi::version()
}
#[inline]
pub fn copy(source: &CaDiCal, destination: &mut CaDiCal) {
ffi::copy(&source.solver, &mut destination.solver);
}
#[inline]
pub fn vars(&mut self) -> i32 {
ffi::vars(&mut self.solver)
}
#[inline]
pub fn reserve(&mut self, min_max_var: i32) {
ffi::reserve(&mut self.solver, min_max_var);
}
#[must_use]
#[inline]
pub fn is_valid_option(name: String) -> bool {
ffi::is_valid_option(name)
}
#[must_use]
#[inline]
pub fn is_preprocessing_option(name: String) -> bool {
ffi::is_preprocessing_option(name)
}
#[must_use]
#[inline]
pub fn is_valid_long_option(arg: String) -> bool {
ffi::is_valid_long_option(arg)
}
#[inline]
pub fn get(&mut self, name: String) -> i32 {
ffi::get(&mut self.solver, name)
}
#[inline]
pub fn prefix(&mut self, verbose_message_prefix: String) {
ffi::prefix(&mut self.solver, verbose_message_prefix);
}
#[inline]
pub fn set(&mut self, name: String, val: i32) -> bool {
ffi::set(&mut self.solver, name, val)
}
#[inline]
pub fn set_long_option(&mut self, arg: String) -> bool {
ffi::set_long_option(&mut self.solver, arg)
}
#[must_use]
#[inline]
pub fn is_valid_configuration(name: String) -> bool {
ffi::is_valid_configuration(name)
}
#[inline]
pub fn configure(&mut self, name: String) -> bool {
ffi::configure(&mut self.solver, name)
}
#[inline]
pub fn optimize(&mut self, val: i32) {
ffi::optimize(&mut self.solver, val);
}
#[inline]
pub fn limit(&mut self, arg: String, val: i32) -> bool {
ffi::limit(&mut self.solver, arg, val)
}
#[inline]
pub fn is_valid_limit(&mut self, arg: String) -> bool {
ffi::is_valid_limit(&mut self.solver, arg)
}
#[must_use]
#[inline]
pub fn active(&self) -> i32 {
ffi::active(&self.solver)
}
#[must_use]
#[inline]
pub fn redundant(&self) -> i64 {
ffi::redundant(&self.solver)
}
#[must_use]
#[inline]
pub fn irredundant(&self) -> i64 {
ffi::irredundant(&self.solver)
}
#[inline]
pub fn simplify(&mut self, rounds: i32) -> Status {
ffi::simplify(&mut self.solver, rounds).into()
}
#[inline]
pub fn terminate(&mut self) {
ffi::terminate(&mut self.solver);
}
#[must_use]
#[inline]
pub fn frozen(&self, lit: i32) -> bool {
ffi::frozen(&self.solver, lit)
}
#[inline]
pub fn freeze(&mut self, lit: i32) {
ffi::freeze(&mut self.solver, lit);
}
#[inline]
pub fn melt(&mut self, lit: i32) {
ffi::melt(&mut self.solver, lit);
}
#[must_use]
#[inline]
pub fn fixed(&self, lit: i32) -> i32 {
ffi::fixed(&self.solver, lit)
}
#[inline]
pub fn phase(&mut self, lit: i32) {
ffi::phase(&mut self.solver, lit);
}
#[inline]
pub fn unphase(&mut self, lit: i32) {
ffi::unphase(&mut self.solver, lit);
}
#[inline]
pub fn trace_proof1(&mut self, file: String, name: String) -> bool {
ffi::trace_proof1(&mut self.solver, file, name)
}
#[inline]
pub fn trace_proof2(&mut self, path: String) -> bool {
ffi::trace_proof2(&mut self.solver, path)
}
#[inline]
pub fn flush_proof_trace(&mut self, print: bool) {
ffi::flush_proof_trace(&mut self.solver, print);
}
#[inline]
pub fn close_proof_trace(&mut self, print: bool) {
ffi::close_proof_trace(&mut self.solver, print);
}
#[allow(clippy::missing_panics_doc)]
#[allow(clippy::too_many_lines)]
pub fn connect_proof_tracer1<'a, 'b: 'a, T: ProofTracer>(
&'a mut self,
tracer: &'b mut T,
antecedents: bool,
) {
fn add_original_clause<T: ProofTracer>(
state: *mut u8,
id: u64,
redundant: bool,
clause: &[i32],
restored: bool,
) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.add_original_clause(id, redundant, clause, restored);
}
fn add_derived_clause<T: ProofTracer>(
state: *mut u8,
id: u64,
redundant: bool,
clause: &[i32],
antecedents: &[u64],
) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.add_derived_clause(id, redundant, clause, antecedents);
}
fn delete_clause<T: ProofTracer>(state: *mut u8, id: u64, redundant: bool, clause: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.delete_clause(id, redundant, clause);
}
fn weaken_minus<T: ProofTracer>(state: *mut u8, id: u64, clause: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.weaken_minus(id, clause);
}
fn strengthen<T: ProofTracer>(state: *mut u8, id: u64) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.strengthen(id);
}
fn finalize_clause<T: ProofTracer>(state: *mut u8, id: u64, clause: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.finalize_clause(id, clause);
}
fn add_assumption<T: ProofTracer>(state: *mut u8, lit: i32) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.add_assumption(lit);
}
fn add_constraint<T: ProofTracer>(state: *mut u8, clause: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.add_constraint(clause);
}
fn reset_assumptions<T: ProofTracer>(state: *mut u8) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.reset_assumptions();
}
fn add_assumption_clause<T: ProofTracer>(
state: *mut u8,
id: u64,
clause: &[i32],
antecedents: &[u64],
) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.add_assumption_clause(id, clause, antecedents);
}
fn conclude_sat<T: ProofTracer>(state: *mut u8, conclusion_type: i32, model: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.conclude_sat(conclusion_type, model);
}
fn conclude_unsat<T: ProofTracer>(
state: *mut u8,
conclusion_type: i32,
clause_ids: &[u64],
) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.conclude_unsat(conclusion_type, clause_ids);
}
fn conclude_unknown<T: ProofTracer>(state: *mut u8, trail: &[i32]) {
let ptr: *mut T = state.cast::<T>();
let t = unsafe { &mut *ptr };
t.conclude_unknown(trail);
}
let tracer_ptr = unsafe {
ffi::new_tracer(
std::ptr::from_mut(tracer).cast::<u8>(),
add_original_clause::<T>,
add_derived_clause::<T>,
delete_clause::<T>,
weaken_minus::<T>,
strengthen::<T>,
finalize_clause::<T>,
add_assumption::<T>,
add_constraint::<T>,
reset_assumptions::<T>,
add_assumption_clause::<T>,
conclude_sat::<T>,
conclude_unsat::<T>,
conclude_unknown::<T>,
)
};
self.last_tracer = Some(tracer_ptr);
ffi::connect_proof_tracer1(
&mut self.solver,
self.last_tracer.as_mut().unwrap(),
antecedents,
);
}
#[inline]
pub fn conclude(&mut self) {
ffi::conclude(&mut self.solver);
}
pub fn disconnect_proof_tracer1(&mut self) {
if let Some(tracer) = &mut self.last_tracer {
ffi::disconnect_proof_tracer1(&mut self.solver, tracer);
}
self.last_tracer = None;
}
#[inline]
pub fn usage() {
ffi::usage();
}
#[inline]
pub fn configurations() {
ffi::configurations();
}
#[inline]
pub fn statistics(&mut self) {
ffi::statistics(&mut self.solver);
}
#[inline]
pub fn resources(&mut self) {
ffi::resources(&mut self.solver);
}
#[inline]
pub fn options(&mut self) {
ffi::options(&mut self.solver);
}
#[inline]
pub fn traverse_clauses<I: ClauseIterator>(&self, i: &mut I) -> bool {
fn f<I: ClauseIterator>(state: *mut u8, clause: &[i32]) -> bool {
let ptr: *mut I = state.cast::<I>();
let i = unsafe { &mut *ptr };
i.clause(clause)
}
let mut iter =
unsafe { ffi::new_clause_iterator(std::ptr::from_mut(i).cast::<u8>(), f::<I>) };
ffi::traverse_clauses(&self.solver, &mut iter)
}
#[inline]
pub fn traverse_witnesses_backward<I: WitnessIterator>(&self, i: &mut I) -> bool {
fn f<I: WitnessIterator>(state: *mut u8, clause: &[i32], witness: &[i32], id: u64) -> bool {
let ptr: *mut I = state.cast::<I>();
let i = unsafe { &mut *ptr };
i.witness(clause, witness, id)
}
let mut iter =
unsafe { ffi::new_witness_iterator(std::ptr::from_mut(i).cast::<u8>(), f::<I>) };
ffi::traverse_witnesses_backward(&self.solver, &mut iter)
}
#[inline]
pub fn traverse_witnesses_forward<I: WitnessIterator>(&self, i: &mut I) -> bool {
fn f<I: WitnessIterator>(state: *mut u8, clause: &[i32], witness: &[i32], id: u64) -> bool {
let ptr: *mut I = state.cast::<I>();
let i = unsafe { &mut *ptr };
i.witness(clause, witness, id)
}
let mut iter =
unsafe { ffi::new_witness_iterator(std::ptr::from_mut(i).cast::<u8>(), f::<I>) };
ffi::traverse_witnesses_forward(&self.solver, &mut iter)
}
#[inline]
pub fn read_dimacs1(
&mut self,
file: String,
name: String,
vars: &mut i32,
strict: i32,
) -> String {
ffi::read_dimacs1(&mut self.solver, file, name, vars, strict)
}
#[inline]
pub fn read_dimacs2(&mut self, path: String, vars: &mut i32, strict: i32) -> String {
ffi::read_dimacs2(&mut self.solver, path, vars, strict)
}
#[inline]
pub fn read_dimacs3(
&mut self,
file: String,
name: String,
vars: &mut i32,
strict: i32,
incremental: &mut bool,
cubes: &mut Vec<i32>,
) -> String {
ffi::read_dimacs3(
&mut self.solver,
file,
name,
vars,
strict,
incremental,
cubes,
)
}
#[inline]
pub fn read_dimacs4(
&mut self,
path: String,
vars: &mut i32,
strict: i32,
incremental: &mut bool,
cubes: &mut Vec<i32>,
) -> String {
ffi::read_dimacs4(&mut self.solver, path, vars, strict, incremental, cubes)
}
#[inline]
pub fn write_dimacs(&mut self, path: String, min_max_var: i32) -> String {
ffi::write_dimacs(&mut self.solver, path, min_max_var)
}
#[inline]
pub fn write_extension(&mut self, path: String) -> String {
ffi::write_extension(&mut self.solver, path)
}
#[inline]
pub fn build(file: String, prefix: String) {
ffi::build(file, prefix);
}
}
pub trait Terminator {
fn terminated(&mut self) -> bool;
}
pub trait Learner {
fn learning(&mut self, size: i32) -> bool;
fn learn(&mut self, lit: i32);
}
pub trait FixedAssignmentListener {
fn notify_fixed_assignment(&mut self, lit: i32);
}
use std::vec::Vec;
pub trait ExternalPropagator {
fn is_lazy(&mut self) -> bool {
false
}
fn are_reasons_forgettable(&mut self) -> bool {
false
}
fn notify_assignment(&mut self, lits: &[i32]);
fn notify_new_decision_level(&mut self);
fn notify_backtrack(&mut self, new_level: usize);
fn cb_check_found_model(&mut self, model: &[i32]) -> bool;
fn cb_decide(&mut self) -> i32 {
0
}
fn cb_propagate(&mut self) -> i32 {
0
}
fn cb_add_reason_clause_lit(&mut self, _propagated_lit: i32) -> i32 {
0
}
fn cb_has_external_clause(&mut self, is_forgettable: &mut bool) -> bool;
fn cb_add_external_clause_lit(&mut self) -> i32;
}
pub trait ClauseIterator {
fn clause(&mut self, clause: &[i32]) -> bool;
}
pub trait WitnessIterator {
fn witness(&mut self, clause: &[i32], witness: &[i32], id: u64) -> bool;
}
pub trait ProofTracer {
fn add_original_clause(&mut self, id: u64, redundant: bool, clause: &[i32], restored: bool);
fn add_derived_clause(&mut self, id: u64, redundant: bool, clause: &[i32], antecedents: &[u64]);
fn delete_clause(&mut self, id: u64, redundant: bool, clause: &[i32]);
fn weaken_minus(&mut self, id: u64, clause: &[i32]);
fn strengthen(&mut self, id: u64);
fn finalize_clause(&mut self, id: u64, clause: &[i32]);
fn add_assumption(&mut self, lit: i32);
fn add_constraint(&mut self, clause: &[i32]);
fn reset_assumptions(&mut self);
fn add_assumption_clause(&mut self, id: u64, clause: &[i32], antecedents: &[u64]);
fn conclude_sat(&mut self, conclusion_type: i32, model: &[i32]);
fn conclude_unsat(&mut self, conclusion_type: i32, clause_ids: &[u64]);
fn conclude_unknown(&mut self, trail: &[i32]);
}