Program Listing for File stack.h

Return to documentation for file (src/stack.h)

#ifndef STACK_H_
#define STACK_H_


#include <gmpxx.h>

#include <cassert>
#include <vector>
#include <string>

#include "model_sampler.h"
#include "cached_assignment.h"
#include "solver_config.h"


class StackLevel {
  const VariableIndex super_component_ = 0;
  bool active_branch_ = false;
  const VariableIndex literal_stack_ofs_ = 0;
  bool is_component_split_ = false;
  bool first_component_ = false;
  SampleAssignment cache_sample_[2];
  mpz_class branch_model_count_[2] = {0, 0};
  bool branch_found_unsat_[2] = {false, false};
  void includeSolutionVar(const mpz_class &solutions, mpz_class solution_var[],
                          const std::string &name_var);
  const VariableIndex remaining_components_ofs_ = 0;
  VariableIndex unprocessed_components_end_ = 0;
  static VariableIndex component_split_depth_;

  /*---------------------------------------*
   *       Begin Sampler Variables         *
   *---------------------------------------*/

  mpz_class stack_solution_count_multiplier_[2] = {1, 1};
  std::vector<std::vector<VariableIndex>> stack_emancipated_vars_;
  std::vector<CacheEntryID> cache_comp_ids_[2];
  static SolverConfiguration* config_;
  static DataAndStatistics* statistics_;
  CachedAssignment cached_assn_;

 public:
  bool hasUnprocessedComponents() const {
    assert(unprocessed_components_end_ >= remaining_components_ofs_);
    return unprocessed_components_end_ > remaining_components_ofs_;
  }
  void nextUnprocessedComponent() {
    assert(unprocessed_components_end_ > remaining_components_ofs_);
    unprocessed_components_end_--;
  }
  void resetRemainingComps() {
    unprocessed_components_end_ = remaining_components_ofs_;
  }
  const VariableIndex super_component() const {
    return super_component_;
  }
  const VariableIndex remaining_components_ofs() const {
    return remaining_components_ofs_;
  }
  const VariableIndex unprocessed_components_end() const {
    return unprocessed_components_end_;
  }
  void set_unprocessed_components_end(VariableIndex end) {
    unprocessed_components_end_ = end;
    assert(remaining_components_ofs_ <= unprocessed_components_end_);
  }

  StackLevel() {
    stack_emancipated_vars_.resize(2);
  }

  StackLevel(VariableIndex super_comp, VariableIndex lit_stack_ofs,
             ClauseOfs comp_stack_ofs) :
      super_component_(super_comp),
      literal_stack_ofs_(lit_stack_ofs),
      remaining_components_ofs_(comp_stack_ofs),
      unprocessed_components_end_(comp_stack_ofs) {
    assert(super_comp < comp_stack_ofs);
    stack_emancipated_vars_.resize(2);
  }
  VariableIndex currentRemainingComponent() {
    assert(remaining_components_ofs_ <= unprocessed_components_end_ - 1);
    return unprocessed_components_end_ - 1;
  }
  bool isSecondBranch() {
    return active_branch_;
  }
  void changeBranch() {
    active_branch_ = true;
  }
  bool anotherCompProcessible() {
    return (!branch_found_unsat()) && hasUnprocessedComponents();
  }

  VariableIndex literal_stack_ofs() const {
    return literal_stack_ofs_;
  }
  void includeSolution(const mpz_class &solutions) {
    includeSolutionVar(solutions, branch_model_count_, "branch_model_count");
  }
  void includeSolutionSampleMultiplier(const mpz_class &solutions) {
    includeSolutionVar(solutions, stack_solution_count_multiplier_,
                       "sampler_solution_multiplier");
  }
  void includeSolution(unsigned solutions);
  void configureNewLevel(const StackLevel &top, const DecisionLevel decision_level) {
    // Do not push down any counts at the top of the decision stack when doing reservoir sampling
    // This is required in some cases in top tree sampling since the solution count at each leaf
    // is required while traversing the tree.
    if (decision_level == 0 && !(config_->perform_top_tree_sampling && !top.isComponentSplit()))
      return;
    // Push down the solution multiplier and freed variable list
    // Make sure to only use the active branch.
    for (auto &multiplier : stack_solution_count_multiplier_)
      multiplier = top.getSamplerSolutionMultiplier();

    for (auto &freed_variables : stack_emancipated_vars_)
      freed_variables = top.emancipated_vars();

    for (auto &cache_comp_ids : cache_comp_ids_)
      cache_comp_ids = top.cached_comp_ids();
  }
  void addFreeVariables(const std::vector<VariableIndex> &freed_vars) {
    int idx = (active_branch_) ? 1 : 0;
    stack_emancipated_vars_[idx].insert(stack_emancipated_vars_[idx].end(),
                                       freed_vars.begin(), freed_vars.end());
  }
  void addCachedCompIds(const std::vector<CacheEntryID> &ids) {
    int idx = (active_branch_) ? 1 : 0;
//    assert(cached_comp_ids_.empty());
    if (ids.empty())
      return;
    cache_comp_ids_[idx].insert(cache_comp_ids_[idx].end(), ids.begin(), ids.end());
  }
  inline bool branch_found_unsat() const {
    return branch_found_unsat_[active_branch_];
  }
  inline void mark_branch_unsat() {
    branch_found_unsat_[active_branch_] = true;
  }
  const mpz_class getTotalModelCount() const {
    return branch_model_count_[0] + branch_model_count_[1];
  }
  const mpz_class& getActiveModelCount() const {
    if (!active_branch_)
      return branch_model_count_[0];
    else
      return branch_model_count_[1];
  }
  const mpz_class& getSamplerSolutionMultiplier() const {
    if (!active_branch_)
      return stack_solution_count_multiplier_[0];
    else
      return stack_solution_count_multiplier_[1];
  }
//  /**
//   * Calculates the total descendent model count for this stack level.  It is equal to:
//   *
//   * FalseModelCount * FalseCountMultiplier + TrueModelCount * TrueCountMultiplier
//   *
//   * @return Total descendent model count.
//   */
//  const mpz_class GetDescendentModelCount() const {
//    mpz_class total_model_count = 0;
//    for (int i = 0; i < 2; i++) {
//      if (stack_solution_count_multiplier_[i] == 1)
//        total_model_count += branch_model_count_[i];
//      else
//        total_model_count += branch_model_count_[i] * stack_solution_count_multiplier_[i];
//    }
//    return total_model_count;
//  }
  const bool HasNoDescendentModels() {
    return branch_found_unsat_[0] && branch_found_unsat_[1];
  }
  inline const std::vector<VariableIndex> &emancipated_vars() const {
    if (!active_branch_)
      return stack_emancipated_vars_[0];
    else
      return stack_emancipated_vars_[1];
  }
  inline const std::vector<CacheEntryID> &cached_comp_ids() const {
    if (!active_branch_)
      return cache_comp_ids_[0];
    else
      return cache_comp_ids_[1];
  }
  inline const bool isComponentSplit() const {
    return is_component_split_ && config_->perform_random_sampling_;
  }
  inline void setAsComponentSplit() {
    if (!config_->perform_random_sampling_)
      return;

    if (!is_component_split_) {
      component_split_depth_++;
      if (component_split_depth_ > statistics_->max_component_split_depth_)
        statistics_->max_component_split_depth_ = component_split_depth_;
    }
    is_component_split_ = true;
    first_component_ = true;
  }
  inline void unsetAsComponentSplit() {
    if (!config_->perform_random_sampling_)
      return;

    if (is_component_split_)
      component_split_depth_--;
    assert(component_split_depth_>= 0);
    is_component_split_ = false;
    first_component_ = false;
  }
  inline static VariableIndex componentSplitDepth() {
    return component_split_depth_;
  }
  inline const bool isFirstComponent() const {
    assert(is_component_split_);
    return first_component_ && config_->perform_random_sampling_;
  }
  inline void markFirstComponentComplete() {
    assert(is_component_split_);
    first_component_ = false;
  }
  inline static void set_solver_config_and_statistics(SolverConfiguration &config,
                                                      DataAndStatistics &statistics) {
    config_ = &config;
    statistics_ = &statistics;
  }
  inline void set_cached_assn(CachedAssignment &cached_assn) {
    assert(config_->perform_random_sampling_);
    cached_assn_ = cached_assn;
  }
  inline const CachedAssignment& cached_assn() const { return cached_assn_; }
  inline void ClearCachedAssn() { cached_assn_.clear(); }
  inline void set_cache_sample(const SampleAssignment & cache_sample) {
    if (!active_branch_)
      cache_sample_[0] = cache_sample;
    else
      cache_sample_[1] = cache_sample;
  }
  SampleAssignment random_cache_sample() const;
};

class DecisionStack: public std::vector<StackLevel> {
  VariableIndex failed_literal_test_active = 0;

 public:
  DecisionStack() : std::vector<StackLevel>() {}
  void startFailedLitTest() {
//    failed_literal_test_active = true;  // Thurley's old code. Relies on casting
    failed_literal_test_active = 1;
  }
  void stopFailedLitTest() {
//    failed_literal_test_active = false;  // Thurley's old code. Relies on casting
    failed_literal_test_active = 0;
  }
  // end for implicit BCP
  StackLevel &top() {
    return const_cast<StackLevel&>(top_const());  // Strip off the const
  }
  const StackLevel &top_const() const {
    assert(!empty());
    return back();
  }
  StackLevel &on_deck() {
    assert(size() >= 2);
    return (*this)[size() - 2];
  }
  DecisionLevel get_decision_level() const {
    assert(!empty());
    return size() - 1 + failed_literal_test_active;
  }  // 0 means pre-1st-decision
};

#endif  // STACK_H_