Program Listing for File solver.h¶
↰ Return to documentation for file (src/solver.h
)
#ifndef SOLVER_H_
#define SOLVER_H_
#include <sys/time.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <string>
#include "statistics.h"
#include "instance.h"
#include "component_management.h"
#include "solver_config.h"
#include "model_sampler.h"
#include "cached_assignment.h"
//#include "top_tree_sampler.h"
class StopWatch {
public:
StopWatch();
bool timeBoundBroken() {
timeval actual_time = (struct timeval) {0};
gettimeofday(&actual_time, nullptr);
return actual_time.tv_sec - start_time_.tv_sec > time_bound_;
}
bool start() {
auto ret = static_cast<bool>(gettimeofday(&last_interval_start_, nullptr));
start_time_ = stop_time_ = last_interval_start_;
return !ret;
}
bool stop() {
return gettimeofday(&stop_time_, nullptr) == 0;
}
double getElapsedSeconds() {
timeval r = getElapsedTime();
return r.tv_sec + static_cast<double>(r.tv_usec) / 1000000;
}
bool interval_tick() {
timeval actual_time = (struct timeval) {0};
gettimeofday(&actual_time, nullptr);
if (actual_time.tv_sec - last_interval_start_.tv_sec
> interval_length_.tv_sec) {
gettimeofday(&last_interval_start_, nullptr);
return true;
}
return false;
}
void setTimeBound(uint64_t seconds) {
time_bound_ = seconds;
}
// ZH Appears to neither be implemented or used.
//long int getTimeBound();
private:
timeval start_time_;
timeval stop_time_;
uint64_t time_bound_ = UINT64_MAX;
timeval interval_length_;
timeval last_interval_start_;
timeval getElapsedTime();
};
class Solver: public Instance {
public:
Solver(int argc, char *argv[]);
Solver(SolverConfiguration &config, DataAndStatistics &statistics,
SampleSize num_samples = 0, bool two_pass = true)
: config_(config), final_samples_(num_samples, config_) {
LinkConfigAndStatistics();
statistics_.input_file_ = statistics.input_file_;
// ToDo modify to support caching multiple samples
//config_.num_samples_to_cache_ = num_samples;
config_.num_samples_to_cache_ = 1;
sampler_stopwatch_.setTimeBound(config_.time_bound_seconds); // Initialize the time bound.
config_.samples_output_file = "";
config_.disable_samples_write_ = true;
config_.num_samples_ = num_samples;
time(&statistics_.start_time_);
config_.perform_two_pass_sampling_ = two_pass;
}
Solver(const Solver &other)
: config_(other.config_), final_samples_(other.final_samples_.num_samples(), config_) {
// Bring over the configuration and statistics
statistics_ = other.statistics_;
LinkConfigAndStatistics();
config_.num_samples_to_cache_ = 1;
config_.disable_samples_write_ = true;
// Data structures used in the createFromFile Function
literal_pool_ = other.literal_pool_;
variables_ = other.variables_;
literal_values_ = other.literal_values_;
unit_clauses_ = other.unit_clauses_;
unused_vars_ = other.unused_vars_;
independent_support = other.independent_support;
has_independent_support_ = other.has_independent_support_;
conflict_clauses_ = other.conflict_clauses_;
occurrence_lists_ = other.occurrence_lists_;
literals_ = other.literals_;
// Initialize other variables as needed
statistics_.start_time_ = other.statistics_.start_time_; // Needed to ensure timeout
sampler_stopwatch_.setTimeBound(config_.time_bound_seconds); // Initialize the time bound.
original_lit_pool_size_ = other.original_lit_pool_size_;
}
void solve(const PartialAssignment &partial_assn = PartialAssignment());
void sample_models();
const SolverConfiguration &config() {
return config_;
}
void DisableTopTreeSampling() {
assert(config_.perform_top_tree_sampling);
config_.perform_top_tree_sampling = false;
}
const DataAndStatistics &statistics() {
return statistics_;
}
void PushNewSamplesManagerOnStack() {
if (config_.store_sampled_models())
samples_stack_.emplace_back(SamplesManager(config_.num_samples_, config_));
}
// /**
// * Literal Stack Location Printer
// *
// * Debug only tool. Often, a CNF formula has hundreds of thousands
// * of variables on the literal stack. Finding where a specific variable
// * is on the stack (if at all) can be time consuming. This function
// * prints whether the specified variable is on the stack.
// *
// * @param var Variable number of interest.
// */
// void PrintLiteralStackLocation(VariableIndex var);
// End Sampler Objects
private:
SolverConfiguration config_;
DecisionStack stack_;
std::vector<LiteralID> literal_stack_;
ComponentManager comp_manager_ = ComponentManager(config_, statistics_, literal_values_);
StopWatch sampler_stopwatch_;
uint64_t last_ccl_deletion_time_ = 0;
uint64_t last_ccl_cleanup_time_ = 0;
std::vector<SamplesManager> samples_stack_;
SamplesManager final_samples_;
bool simplePreProcess();
bool prepFailedLiteralTest();
void reservoir_sample_models(const PartialAssignment &partial_assn, Solver &temp_solver);
// /**
// * MT - we assert that the formula is consistent and has not been
// * found UNSAT yet hard wires all assertions in the literal stack
// * into the formula removes all set variables and essentially
// * reinitializes all further data.
// */
// void HardWireAndCompact();
SolverExitState countSAT();
void decideLiteral();
bool bcp();
void decayActivitiesOf(Component & comp) {
for (auto it = comp.varsBegin(); *it != varsSENTINEL; it++) {
literal(LiteralID(*it, true)).activity_score_ *=0.5;
literal(LiteralID(*it, false)).activity_score_ *=0.5;
}
}
bool implicitBCP();
bool BCP(VariableIndex start_at_stack_ofs);
SolverNextAction backtrack();
void ProcessCacheStore();
void ProcessSampleComponentSplitBacktrack();
SolverNextAction resolveConflict();
void PrintFinalSamplerResults();
// BEGIN small helper functions
float scoreOf(VariableIndex v) {
float score = comp_manager_.scoreOf(v);
score += 10.0 * literal(LiteralID(v, true)).activity_score_;
score += 10.0 * literal(LiteralID(v, false)).activity_score_;
// score += (10*stack_.get_decision_level()) * literal(LiteralID(v, true)).activity_score_;
// score += (10*stack_.get_decision_level()) * literal(LiteralID(v, false)).activity_score_;
return score;
}
bool setLiteralIfFree(LiteralID lit, Antecedent ant = Antecedent(NOT_A_CLAUSE)) {
if (literal_values_[lit] != X_TRI)
return false;
var(lit).decision_level = stack_.get_decision_level();
var(lit).ante = ant;
literal_stack_.push_back(lit);
if (ant.isAClause() && ant.asCl() != NOT_A_CLAUSE)
getHeaderOf(ant.asCl()).increaseScore();
literal_values_[lit] = T_TRI;
literal_values_[lit.neg()] = F_TRI;
return true;
}
void printOnlineStats();
// /**
// * Literal Stack Contents Checker
// *
// * Checks whether the specified variable is in the literal stack.
// *
// * @param var Variable of interest
// * @return true if the specified variable @see var is in the literal stack.
// */
// bool IsVarInLiteralStack(VariableIndex var);
void setConflictState(LiteralID litA, LiteralID litB) {
violated_clause.clear();
violated_clause.push_back(litA);
violated_clause.push_back(litB);
}
void setConflictState(ClauseOfs cl_ofs) {
getHeaderOf(cl_ofs).increaseScore();
violated_clause.clear();
for (auto it = beginOf(cl_ofs); *it != SENTINEL_LIT; it++)
violated_clause.push_back(*it);
}
std::vector<LiteralID>::const_iterator TOSLiteralsBegin() {
return literal_stack_.begin() + stack_.top().literal_stack_ofs();
}
void initStack(unsigned long resSize = 0) {
stack_.clear();
if (resSize != 0)
stack_.reserve(resSize);
literal_stack_.clear();
if (resSize != 0)
literal_stack_.reserve(resSize);
// initialize the stack to contain at least level zero
stack_.push_back(StackLevel(1, 0, 2));
stack_.back().changeBranch();
// Reset the samples stack.
if (config_.store_sampled_models()) {
samples_stack_.clear();
samples_stack_.reserve(30);
}
set_variable_depth_ = 0;
statistics_.max_component_split_depth_ = 0;
}
const LiteralID &TOS_decLit() const {
assert(stack_.top_const().literal_stack_ofs() < literal_stack_.size());
return literal_stack_[stack_.top_const().literal_stack_ofs()];
}
void reactivateTOS() {
for (auto it = TOSLiteralsBegin(); it != literal_stack_.end(); it++)
unSet(*it);
comp_manager_.cleanRemainingComponentsOf(stack_.top());
literal_stack_.resize(stack_.top().literal_stack_ofs());
stack_.top().resetRemainingComps();
}
bool fail_test(LiteralID lit) {
VariableIndex sz = literal_stack_.size();
// we increase the decLev artificially
// s.t. after the tentative BCP call, we can learn a conflict clause
// relative to the assn_ of *jt
stack_.startFailedLitTest();
setLiteralIfFree(lit);
assert(!hasAntecedent(lit));
bool bSucceeded = BCP(sz);
if (!bSucceeded)
recordAllUIPCauses();
stack_.stopFailedLitTest();
while (literal_stack_.size() > sz) {
unSet(literal_stack_.back());
literal_stack_.pop_back();
}
return bSucceeded;
}
// BEGIN conflict analysis
// if the state name is CONFLICT,
// then violated_clause contains the clause determining the conflict;
std::vector<LiteralID> violated_clause;
// this is an array of all the clauses found
// during the most recent conflict analysis
// it might contain more than 2 clauses
// but always will have:
// uip_clauses_.front() the 1UIP clause found
// uip_clauses_.back() the lastUIP clause found
// possible clauses in between will be other UIP clauses
std::vector<std::vector<LiteralID>> uip_clauses_;
// the assertion level of uip_clauses_.back()
// or (if the decision variable did not have an antecedent
// before) then assertionLevel_ == DL;
int64_t assertion_level_ = 0;
// build conflict clauses from most recent conflict
// as stored in state_.violated_clause
// solver state must be CONFLICT to work;
// this first method record only the last UIP clause
// so as to create clause that asserts the current decision
// literal
void recordLastUIPCauses();
void recordAllUIPCauses();
void minimizeAndStoreUIPClause(LiteralID uipLit,
std::vector<LiteralID> & tmp_clause,
const bool seen[]);
// Commented out by ZH as not implemented
// void storeUIPClause(LiteralID uipLit, std::vector<LiteralID> & tmp_clause);
// int getAssertionLevel() const {
// return assertion_level_;
// }
// END conflict analysis
VariableIndex set_variable_depth_ = 0;
bool InitializeSolverAndPreprocess(const PartialAssignment &partial_assn);
void applyPartialAssignment(const PartialAssignment &partial_assn);
void ReportSharpSatResults();
void PerformInitialSampling();
inline void FillPartialAssignments(Solver &temp_solver);
inline bool IsEndSamplesStackSizeValid() const {
return samples_stack_.size() == 1
|| (samples_stack_.size() == 2 && samples_stack_[0].model_count() == 0);
}
// /**
// * Checks whether the current point in the solver execution is valid for storing a top
// * tree sample.
// *
// * @return true If there none of the current literal assignments led to a component split,
// * the current depth is below the maximum and top tree mode is enabled.
// */
// inline bool IsValidTopTreeNodeStorePoint() {
// return config_.perform_top_tree_sampling && set_variable_depth_ < config_.max_top_tree_depth_;
// }
inline void LinkConfigAndStatistics() {
// ToDo If the solver is multithreaded, static for config and statistics will need to change.
StackLevel::set_solver_config_and_statistics(config_, statistics_);
// SamplesManager::set_solver_config(config_);
}
};
#endif // SOLVER_H_