Advertisement
JosepRivaille

LI - SATSolver

Jun 23rd, 2017
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.76 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <chrono>
  5. using namespace std;
  6.  
  7. /****************************
  8. * CONSTANTS AND DEFINITIONS *
  9. ****************************/
  10. #define UNDEF 0
  11. #define TRUE 1
  12. #define FALSE -1
  13.  
  14. const int ALL_DEFINED = 0;
  15. const int DECISION_MARK = 0;
  16.  
  17. typedef vector<int> Clause;
  18. typedef vector<Clause*> Clause_Appear;
  19.  
  20. /******************************
  21. * DATA STRUCTURES AND GLOBALS *
  22. ******************************/
  23. uint num_vars;
  24. vector<int> model;
  25.  
  26. uint num_clauses;
  27. vector<Clause> clauses;
  28.  
  29. uint index_of_next_lit_to_propagate;
  30. uint decision_level;
  31.  
  32. vector<int> model_stack;
  33.  
  34. // Literal lit appears in clauses x1 .. xn -> v[lit] = vector<int>
  35. vector<Clause_Appear> clauses_where_appear_positive;
  36. vector<Clause_Appear> clauses_where_appear_negative;
  37.  
  38. vector<int> heuristic_order;
  39.  
  40. // Statistics
  41. chrono::time_point<chrono::system_clock> t_start, t_end;
  42. unsigned long propagations_count, decisions_count;
  43.  
  44. /**********
  45. * HELPERS *
  46. **********/
  47. inline int current_value_in_model(int lit) {
  48.   uint mask = -(lit < 0);
  49.   uint abs_lit = (lit ^ mask) - mask;
  50.   int value_in_model = model[abs_lit];
  51.   return (value_in_model ^ mask) - mask;
  52. }
  53.  
  54. inline void set_literal_to_true(int lit) {
  55.   uint mask = -(lit < 0);
  56.   uint abs_lit = (lit ^ mask) - mask;
  57.   model[abs_lit] = mask + (mask == 0);
  58.   model_stack.push_back(lit);
  59. }
  60.  
  61. inline void check_model(){
  62.   for (uint i = 0; i < num_clauses; ++i){
  63.     bool some_true = false;
  64.     for (int j = 0; not some_true and j < clauses[i].size(); ++j) {
  65.       some_true = (current_value_in_model(clauses[i][j]) == TRUE);
  66.     }
  67.     if (not some_true) {
  68.       cout << "Error in model, clause is not satisfied: ";
  69.       for (int j = 0; j < clauses[i].size(); ++j) {
  70.         cout << clauses[i][j] << " ";
  71.       } cout << endl;
  72.       exit(1);
  73.     }
  74.   }
  75. }
  76.  
  77. inline void print_and_finish(bool sat) {
  78.   t_end = chrono::system_clock::now();
  79.   chrono::duration<double> elapsed_seconds = t_end - t_start;
  80.   string sat_insat = sat ? "SATISFIABLE" : "UNSATISFIABLE";
  81.   cout << "Problem Statistics ]==============" << endl;
  82.   cout << "|  Number of variables: " << num_vars << endl;
  83.   cout << "|  Number of clauses: " << num_clauses << endl;
  84.   cout << "|  SAT/INSAT: " << sat_insat << endl;
  85.   cout << "|  Time: " << elapsed_seconds.count() << endl;
  86.   cout << "|  Decisions: " << decisions_count << endl;
  87.   cout << "|  Propagations: " << propagations_count << endl << endl;
  88.   exit(sat ? 20 : 10);
  89. }
  90.  
  91. inline void initial_clauses() {
  92.   for (uint i = 0; i < num_clauses; ++i) {
  93.     if (clauses[i].size() == 1) {
  94.       int lit = clauses[i][0];
  95.       int val = current_value_in_model(lit);
  96.       if (val == FALSE) print_and_finish(false);
  97.       else if (val == UNDEF) set_literal_to_true(lit);
  98.     }
  99.   }
  100. }
  101.  
  102. /******************
  103. * INITIALIZATIONS *
  104. ******************/
  105. inline void read_clauses() {
  106.   // Skip comments
  107.   char c = cin.get();
  108.   while (c == 'c') {
  109.     while (c != '\n') c = cin.get();
  110.     c = cin.get();
  111.   }
  112.   string aux;
  113.   // Read "cnf numVars numClauses"
  114.   cin >> aux >> num_vars >> num_clauses;
  115. }
  116.  
  117. inline void init_data_structures() {
  118.   clauses.resize(num_clauses);
  119.   model.resize(num_vars + 1, UNDEF);
  120.   heuristic_order.resize(num_vars + 1, UNDEF);
  121.   clauses_where_appear_positive.resize(num_vars + 1);
  122.   clauses_where_appear_negative.resize(num_vars + 1);
  123. }
  124.  
  125. inline void fill_data_structures() {
  126.   for (uint i = 0; i < num_clauses; ++i) {
  127.     int lit;
  128.     while (cin >> lit and lit != 0) {
  129.       lit > 0
  130.         ? clauses_where_appear_positive[lit].push_back(&clauses[i])
  131.         : clauses_where_appear_negative[-lit].push_back(&clauses[i]);
  132.       clauses[i].push_back(lit);
  133.       ++heuristic_order[abs(lit)];
  134.     }
  135.   }
  136.   index_of_next_lit_to_propagate = decision_level = decisions_count = propagations_count = 0;
  137. }
  138.  
  139. inline void init_sat() {
  140.   t_start = chrono::system_clock::now();
  141.   read_clauses();
  142.   init_data_structures();
  143.   fill_data_structures();
  144. }
  145.  
  146. /*****************
  147. * SOLVER METHODS *
  148. *****************/
  149. inline int get_next_decision_literal_heuristic() {
  150.   uint lit;
  151.   int max_priority = -1;
  152.   for (uint i = 0; i < num_vars; ++i) {
  153.     if (model[i] == UNDEF and heuristic_order[i] > max_priority) {
  154.       max_priority = heuristic_order[i];
  155.       lit = i;
  156.     }
  157.   }
  158.   return max_priority == -1 ? ALL_DEFINED : lit;
  159. }
  160.  
  161. inline bool propagate() {
  162.   int propagated_literal = model_stack[index_of_next_lit_to_propagate];
  163.   uint propagated_variable = abs(propagated_literal);
  164.   vector<Clause*>& clauses_affected = propagated_literal > 0
  165.     ? clauses_where_appear_negative[propagated_variable]
  166.     : clauses_where_appear_positive[propagated_variable];
  167.  
  168.   for (uint i = 0; i < clauses_affected.size(); ++i) {
  169.     Clause& clause = *clauses_affected[i];
  170.  
  171.     uint num_undefs = 0;
  172.     int last_lit_undef = 0;
  173.     bool some_lit_true = false;
  174.  
  175.     for (uint j = 0; not some_lit_true and j < clause.size(); ++j) {
  176.       int lit = clause[j];
  177.       int val = current_value_in_model(lit);
  178.       num_undefs += (val == UNDEF);
  179.       last_lit_undef = lit - ((lit - last_lit_undef) & val);
  180.       some_lit_true = (val == TRUE);
  181.     }
  182.  
  183.     if (not some_lit_true and num_undefs <= 1) {
  184.       if (num_undefs == 1) {
  185.         set_literal_to_true(last_lit_undef);
  186.       } else {
  187.         heuristic_order[propagated_variable]++;
  188.         return true;
  189.       }
  190.     }
  191.   }
  192.   return false;
  193. }
  194.  
  195. inline bool propagate_gives_conflict() {
  196.   while (index_of_next_lit_to_propagate < model_stack.size()) {
  197.     if (propagate()) return true;
  198.     ++propagations_count;
  199.     ++index_of_next_lit_to_propagate;
  200.   }
  201.   return false;
  202. }
  203.  
  204. inline void decide_positive_literal(int lit) {
  205.   model_stack.push_back(DECISION_MARK);
  206.   ++decisions_count;
  207.   ++index_of_next_lit_to_propagate;
  208.   ++decision_level;
  209.   set_literal_to_true(lit);
  210. }
  211.  
  212. inline void decide_negative_literal(int lit) {
  213.   model_stack.pop_back();
  214.   index_of_next_lit_to_propagate = model_stack.size();
  215.   --decision_level;
  216.   set_literal_to_true(-lit);
  217. }
  218.  
  219. void backtrack() {
  220.   uint i = model_stack.size() - 1;
  221.   int lit = 0;
  222.   while (model_stack[i] != DECISION_MARK) {
  223.     lit = model_stack[i--];
  224.     model[abs(lit)] = UNDEF;
  225.     model_stack.pop_back();
  226.   }
  227.   decide_negative_literal(lit);
  228. }
  229.  
  230. /*******
  231. * MAIN *
  232. ********/
  233. int main() {
  234.   init_sat();
  235.   initial_clauses();
  236.  
  237.   // DPLL algorithm (Davis–Putnam–Logemann–Loveland)
  238.   while (true) {
  239.     while (propagate_gives_conflict()) {
  240.       if (decision_level == 0) print_and_finish(false);
  241.       backtrack();
  242.     }
  243.  
  244.     int decision_lit = get_next_decision_literal_heuristic();
  245.     if (decision_lit == ALL_DEFINED) {
  246.       check_model();
  247.       print_and_finish(true);
  248.     }
  249.  
  250.     decide_positive_literal(decision_lit);
  251.   }
  252. }
  253.  
  254. // JosepRivaille
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement