Program Listing for File component_management.h¶
↰ Return to documentation for file (src/component_management.h
)
#ifndef COMPONENT_MANAGEMENT_H_
#define COMPONENT_MANAGEMENT_H_
#include <gmpxx.h>
#include <utility>
#include <algorithm>
#include <string>
#include <vector>
#include "component_types/component.h"
#include "component_cache.h"
#include "alt_component_analyzer.h"
#include "containers.h"
#include "stack.h"
#include "solver_config.h"
#include "model_sampler.h"
//#include "top_tree_sampler.h"
typedef AltComponentAnalyzer ComponentAnalyzer;
class ComponentManager {
public:
ComponentManager(SolverConfiguration &config, DataAndStatistics &statistics,
LiteralIndexedVector<TriValue> & lit_values) :
config_(config), /*statistics_(statistics),*/ cache_(statistics, config),
ana_(statistics, lit_values) {
}
void initialize(LiteralIndexedVector<Literal> & literals,
std::vector<LiteralID> &lit_pool, bool quiet = false);
unsigned scoreOf(VariableIndex v) {
return ana_.scoreOf(v);
}
void cacheModelCountOf(VariableIndex stack_comp_id, const mpz_class &value) {
if (config_.perform_component_caching)
cache_.storeValueOf(component_stack_[stack_comp_id]->id(), value);
}
void cacheModelCountAndAssignment(const VariableIndex stack_comp_id, const mpz_class &value,
const SampleAssignment &assn, const Component &component) {
mpz_class combined_value = 0;
mpz_class temp_value = 0;
// If the component is UNSAT do not push any assignment
if (value > 0) {
VariableIndex last_shift_len = 0, offset_amount = 0;
uint64_t cached_word = 0;
const VariableIndex MAX_OFFSET_AMOUNT = 28;
std::vector<ComponentVarAndCls> comp_data = component.getData();
for (VariableIndex i = 0; i < component.num_variables(); i++) {
AssignmentEncoding var_assn = assn.var_assignment(comp_data[i]);
// Make sure the assignment is valid
assert((var_assn != ASSN_U && !assn.IsVarEmancipated(comp_data[i]))
|| (var_assn == ASSN_U && assn.IsVarEmancipated(comp_data[i])));
cached_word += var_assn << (offset_amount);
if (offset_amount == MAX_OFFSET_AMOUNT) {
mpz_import(temp_value.get_mpz_t(), 1, 1, sizeof(cached_word), 0, 0, &cached_word);
combined_value += temp_value << last_shift_len;
last_shift_len = CACHED_VARIABLE_LEN * (i + 1);
offset_amount = 0;
cached_word = 0;
} else {
offset_amount += CACHED_VARIABLE_LEN;
}
}
if (offset_amount > 0) {
mpz_import(temp_value.get_mpz_t(), 1, 1, sizeof(cached_word), 0, 0, &cached_word);
combined_value += temp_value << last_shift_len;
}
combined_value += value << (CACHED_VARIABLE_LEN * component.num_variables());
}
cacheModelCountOf(stack_comp_id, combined_value);
}
Component & superComponentOf(StackLevel &lev) {
assert(component_stack_.size() > lev.super_component());
return *component_stack_[lev.super_component()];
}
const Component & super_component(StackLevel &lev) const {
assert(component_stack_.size() > lev.super_component());
return *component_stack_[lev.super_component()];
}
VariableIndex component_stack_size() const {
return static_cast<VariableIndex>(component_stack_.size());
}
void cleanRemainingComponentsOf(StackLevel &top) {
while (component_stack_.size() > top.remaining_components_ofs()) {
if (cache_.hasEntry(component_stack_.back()->id()))
cache_.entry(component_stack_.back()->id()).set_deletable();
delete component_stack_.back();
component_stack_.pop_back();
}
assert(top.remaining_components_ofs() <= component_stack_.size());
}
inline const Component &component(unsigned long comp_idx) const {
return *component_stack_[comp_idx];
}
// Component & currentRemainingComponentOf(StackLevel &top) {
// assert(component_stack_.size() > top.currentRemainingComponent());
// return *component_stack_[top.currentRemainingComponent()];
// }
inline bool findNextRemainingComponentOf(StackLevel &top,
const std::vector<LiteralID> &literal_stack,
SamplesManager &samples);
inline void recordRemainingCompsFor(StackLevel &top,
const std::vector<LiteralID> &literal_stack);
inline void buildResidualComponent(StackLevel &top);
inline Component* top_stack() {
return component_stack_.back();
}
inline void sortComponentStackRange(unsigned long start, unsigned long end);
void gatherStatistics() {
// statistics_.cache_bytes_memory_usage_ =
// cache_.recompute_bytes_memory_usage();
cache_.compute_byte_size_infrastructure();
}
void removeAllCachePollutionsOf(StackLevel &top);
std::vector<VariableIndex> buildFreedVariableList(const StackLevel & top,
const std::vector<LiteralID> &literal_stack);
private:
std::vector<VariableIndex> cached_vars_;
std::vector<CacheEntryID> cached_comp_ids_;
SolverConfiguration &config_;
// DataAndStatistics &statistics_;
std::vector<Component *> component_stack_;
ComponentCache cache_;
ComponentAnalyzer ana_;
};
void ComponentManager::sortComponentStackRange(unsigned long start, unsigned long end) {
assert(start <= end);
// sort the remaining components for processing
for (unsigned long i = start; i < end; i++)
for (unsigned long j = i + 1; j < end; j++) {
if (component_stack_[i]->num_variables()
< component_stack_[j]->num_variables())
std::swap(component_stack_[i], component_stack_[j]);
}
}
bool ComponentManager::findNextRemainingComponentOf(StackLevel &top,
const std::vector<LiteralID> &literal_stack,
SamplesManager &samples) {
// record Remaining Components if there are none!
if (component_stack_.size() <= top.remaining_components_ofs())
recordRemainingCompsFor(top, literal_stack);
assert(!top.branch_found_unsat());
if (top.hasUnprocessedComponents()) {
// Perform reservoir sampling if the model count is greater than zero
if (config_.perform_random_sampling_ && top.getActiveModelCount() > 0) {
if (!top.isComponentSplit() || top.isFirstComponent()) {
top.includeSolutionSampleMultiplier(top.getActiveModelCount());
std::vector<VariableIndex> freed_vars = buildFreedVariableList(top, literal_stack);
top.addFreeVariables(freed_vars);
top.addCachedCompIds(cached_comp_ids_);
}
}
return true;
}
// if no component remains
// make sure, at least that the current branch is considered SAT
top.includeSolution(1);
// Perform reservoir sampling if the model count is greater than zero
if (config_.store_sampled_models()) {
if (config_.verbose) {
std::cout << "\t# Solutions Found: " << top.getActiveModelCount()
<< ". Total multiplied weight is "
<< top.getActiveModelCount() * top.getSamplerSolutionMultiplier()
<< std::endl;
}
SampleAssignment cached_sample(config_.num_samples_to_cache_);
if (!top.cached_comp_ids().empty())
cached_comp_ids_.insert(cached_comp_ids_.end(), top.cached_comp_ids().begin(),
top.cached_comp_ids().end());
samples.reservoirSample(component_stack_[top.super_component()], literal_stack,
top.getActiveModelCount(), top.getSamplerSolutionMultiplier(),
ana_, top.literal_stack_ofs(), top.emancipated_vars(),
cached_comp_ids_, top.cached_assn(), cached_sample);
if (config_.perform_sample_caching()) {
top.ClearCachedAssn();
top.set_cache_sample(cached_sample);
}
// DebugZH
// assert(samples.VerifySolutions(statistics_.input_file_, true));
}
return false;
}
void ComponentManager::recordRemainingCompsFor(StackLevel &top,
const std::vector<LiteralID> &literal_stack) {
Component & super_comp = superComponentOf(top);
VariableIndex new_comps_start_ofs = component_stack_.size(); // Location to store new comp if any
// Clear the variables considered cached.
cached_vars_.clear();
cached_comp_ids_.clear();
CachedAssignment cached_assn;
// Initialize data structures for the component analyzer
ana_.setupAnalysisContext(top, super_comp);
// Go through each variable and checks its component to see if cached or new
for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) {
if (ana_.isUnseenAndActive(*vt) && ana_.exploreRemainingCompOf(*vt)) {
Component *p_new_comp = ana_.makeComponentFromArcheType();
auto *packed_comp = new CacheableComponent(ana_.getArchetype().current_comp_for_caching_);
CacheEntryID cache_entry_id;
if (!cache_.manageNewComponent(top, *packed_comp, p_new_comp, cached_assn, cache_entry_id)) {
component_stack_.push_back(p_new_comp);
p_new_comp->set_id(cache_.storeAsEntry(*packed_comp, super_comp.id()));
} else {
if (config_.perform_random_sampling_) {
// Store any cached vars in case of a split.
std::vector<ComponentVarAndCls> cached_comp_data = p_new_comp->getData();
VariableIndex comp_i = 0;
// Store the variables in the component for proper processing of emancipated variables
while (cached_comp_data[comp_i] != varsSENTINEL) {
cached_vars_.push_back(cached_comp_data[comp_i]);
comp_i++;
}
cached_comp_ids_.push_back(cache_entry_id);
}
// Delete component as it was found in the cache
delete packed_comp;
delete p_new_comp;
}
}
}
top.set_unprocessed_components_end(component_stack_.size());
sortComponentStackRange(new_comps_start_ofs, component_stack_.size());
if (config_.perform_random_sampling_) {
long split_width = component_stack_.size() - new_comps_start_ofs;
if (split_width > 1 || (split_width == 1 && !cached_assn.empty())) {
top.setAsComponentSplit();
if (config_.verbose) {
std::stringstream ss;
ss << "Component #" << (new_comps_start_ofs - 1) << " split into " << (split_width)
<< " pieces at depth " << StackLevel::componentSplitDepth() << ".";
PrintInColor(ss, COLOR_CYAN);
}
}
if (!cached_assn.empty())
top.set_cached_assn(cached_assn);
}
// For simplicity, sort the cached variable list
if (cached_vars_.size() > 1) {
sort(cached_vars_.begin(), cached_vars_.end());
sort(cached_comp_ids_.begin(), cached_comp_ids_.end());
}
}
void ComponentManager::buildResidualComponent(StackLevel &top) {
Component & super_comp = superComponentOf(top);
std::vector<VariableIndex> comp_vars;
std::vector<ClauseIndex> comp_cls;
// Initialize data structures for the component analyzer
ana_.setupAnalysisContext(top, super_comp);
// Go through all components to be spawned and build a list of vars and comp
for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) {
if (ana_.isUnseenAndActive(*vt) && ana_.exploreRemainingCompOf(*vt)) {
Component *p_new_comp = ana_.makeComponentFromArcheType();
auto comp_data = p_new_comp->getData();
for (VariableIndex i = 0; i < p_new_comp->num_variables(); i++)
comp_vars.push_back(comp_data[i]);
for (ClauseIndex i = 0; i < p_new_comp->numLongClauses(); i++) {
ClauseIndex cls = comp_data[p_new_comp->clauses_ofs() + i];
comp_cls.push_back(cls);
}
delete p_new_comp;
}
}
delete component_stack_.back();
component_stack_.pop_back();
// Sort the lists as components are build from only sorted lists
std::sort(comp_vars.begin(), comp_vars.end());
std::sort(comp_cls.begin(), comp_cls.end());
auto * initial_component = new Component();
for (auto var : comp_vars)
initial_component->addVar(var);
initial_component->closeVariableData();
for (auto cls : comp_cls)
initial_component->addCl(cls);
initial_component->closeClauseData();
component_stack_.push_back(initial_component);
}
VariableIndex UpdateVarDescedantsList(const std::vector<ComponentVarAndCls> &ref_vars,
VariableIndex ref_num_vars,
std::vector<bool> &varInDescendants,
std::vector<ComponentVarAndCls> descendant_vars,
VariableIndex desc_num_vars);
//bool varInVector(long var_num, std::vector<unsigned int> vec);
#endif /* COMPONENT_MANAGEMENT_H_ */