Main.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*****************************************************************************************[Main.cc]
  2. Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
  3. Copyright (c) 2007, Niklas Sorensson
  4. Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
  5. Maple_LCM, Based on MapleCOMSPS_DRUP -- Copyright (c) 2017, Mao Luo, Chu-Min LI, Fan Xiao: implementing a learnt clause minimisation approach
  6. Reference: M. Luo, C.-M. Li, F. Xiao, F. Manya, and Z. L. , “An effective learnt clause minimization approach for cdcl sat solvers,” in IJCAI-2017, 2017, pp. to–appear.
  7. Maple_LCM_Dist, Based on Maple_LCM -- Copyright (c) 2017, Fan Xiao, Chu-Min LI, Mao Luo: using a new branching heuristic called Distance at the beginning of search
  8. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
  9. associated documentation files (the "Software"), to deal in the Software without restriction,
  10. including without limitation the rights to use, copy, modify, merge, publish, distribute,
  11. sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in all copies or
  14. substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
  16. NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
  19. OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. **************************************************************************************************/
  21. #include <errno.h>
  22. #include <signal.h>
  23. #include <zlib.h>
  24. #include <sys/resource.h>
  25. #include "utils/System.h"
  26. #include "utils/ParseUtils.h"
  27. #include "utils/Options.h"
  28. #include "core/Dimacs.h"
  29. #include "simp/SimpSolver.h"
  30. using namespace Minisat;
  31. //=================================================================================================
  32. void printStats(Solver& solver)
  33. {
  34. double cpu_time = cpuTime();
  35. double mem_used = memUsedPeak();
  36. printf("c restarts : %"PRIu64"\n", solver.starts);
  37. printf("c conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time);
  38. printf("c decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time);
  39. printf("c propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
  40. printf("c conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
  41. if (mem_used != 0) printf("c Memory used : %.2f MB\n", mem_used);
  42. printf("c CPU time : %g s\n", cpu_time);
  43. }
  44. static Solver* solver;
  45. // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
  46. // for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
  47. static void SIGINT_interrupt(int signum) { solver->interrupt(); }
  48. // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
  49. // destructors and may cause deadlocks if a malloc/free function happens to be running (these
  50. // functions are guarded by locks for multithreaded use).
  51. static void SIGINT_exit(int signum) {
  52. printf("\n"); printf("c *** INTERRUPTED ***\n");
  53. if (solver->verbosity > 0){
  54. printStats(*solver);
  55. printf("\n"); printf("c *** INTERRUPTED ***\n"); }
  56. _exit(1); }
  57. //=================================================================================================
  58. // Main:
  59. int main(int argc, char** argv)
  60. {
  61. try {
  62. setUsageHelp("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n");
  63. printf("c This is COMiniSatPS.\n");
  64. #if defined(__linux__)
  65. fpu_control_t oldcw, newcw;
  66. _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
  67. printf("c WARNING: for repeatability, setting FPU to use double precision\n");
  68. #endif
  69. // Extra options:
  70. //
  71. IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
  72. BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true);
  73. StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file.");
  74. IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
  75. IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
  76. BoolOption drup ("MAIN", "drup", "Generate DRUP UNSAT proof.", false);
  77. StringOption drup_file("MAIN", "drup-file", "DRUP UNSAT proof ouput file.", "/dev/null");
  78. parseOptions(argc, argv, true);
  79. SimpSolver S;
  80. double initial_time = cpuTime();
  81. if (!pre) S.eliminate(true);
  82. S.parsing = true;
  83. S.verbosity = verb;
  84. if (drup || strlen(drup_file)){
  85. S.drup_file = strlen(drup_file) ? fopen(drup_file, "wb") : stdout;
  86. if (S.drup_file == NULL){
  87. S.drup_file = stdout;
  88. printf("c Error opening %s for write.\n", (const char*) drup_file); }
  89. printf("c DRUP proof generation: %s\n", S.drup_file == stdout ? "stdout" : drup_file);
  90. }
  91. solver = &S;
  92. // Use signal handlers that forcibly quit until the solver will be able to respond to
  93. // interrupts:
  94. signal(SIGINT, SIGINT_exit);
  95. signal(SIGXCPU,SIGINT_exit);
  96. // Set limit on CPU-time:
  97. if (cpu_lim != INT32_MAX){
  98. rlimit rl;
  99. getrlimit(RLIMIT_CPU, &rl);
  100. if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
  101. rl.rlim_cur = cpu_lim;
  102. if (setrlimit(RLIMIT_CPU, &rl) == -1)
  103. printf("c WARNING! Could not set resource limit: CPU-time.\n");
  104. } }
  105. // Set limit on virtual memory:
  106. if (mem_lim != INT32_MAX){
  107. rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
  108. rlimit rl;
  109. getrlimit(RLIMIT_AS, &rl);
  110. if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
  111. rl.rlim_cur = new_mem_lim;
  112. if (setrlimit(RLIMIT_AS, &rl) == -1)
  113. printf("c WARNING! Could not set resource limit: Virtual memory.\n");
  114. } }
  115. if (argc == 1)
  116. printf("c Reading from standard input... Use '--help' for help.\n");
  117. gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
  118. if (in == NULL)
  119. printf("c ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
  120. if (S.verbosity > 0){
  121. printf("c ============================[ Problem Statistics ]=============================\n");
  122. printf("c | |\n"); }
  123. parse_DIMACS(in, S);
  124. gzclose(in);
  125. FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL;
  126. if (S.verbosity > 0){
  127. printf("c | Number of variables: %12d |\n", S.nVars());
  128. printf("c | Number of clauses: %12d |\n", S.nClauses()); }
  129. double parsed_time = cpuTime();
  130. if (S.verbosity > 0)
  131. printf("c | Parse time: %12.2f s |\n", parsed_time - initial_time);
  132. // Change to signal-handlers that will only notify the solver and allow it to terminate
  133. // voluntarily:
  134. signal(SIGINT, SIGINT_interrupt);
  135. signal(SIGXCPU,SIGINT_interrupt);
  136. S.parsing = false;
  137. S.eliminate(true);
  138. double simplified_time = cpuTime();
  139. if (S.verbosity > 0){
  140. printf("c | Simplification time: %12.2f s |\n", simplified_time - parsed_time);
  141. printf("c | |\n"); }
  142. if (!S.okay()){
  143. if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
  144. if (S.verbosity > 0){
  145. printf("c ===============================================================================\n");
  146. printf("c Solved by simplification\n");
  147. printStats(S);
  148. printf("\n"); }
  149. printf("s UNSATISFIABLE\n");
  150. if (S.drup_file){
  151. #ifdef BIN_DRUP
  152. fputc('a', S.drup_file); fputc(0, S.drup_file);
  153. #else
  154. fprintf(S.drup_file, "0\n");
  155. #endif
  156. }
  157. if (S.drup_file && S.drup_file != stdout) fclose(S.drup_file);
  158. exit(20);
  159. }
  160. if (dimacs){
  161. if (S.verbosity > 0)
  162. printf("c ==============================[ Writing DIMACS ]===============================\n");
  163. S.toDimacs((const char*)dimacs);
  164. if (S.verbosity > 0)
  165. printStats(S);
  166. exit(0);
  167. }
  168. vec<Lit> dummy;
  169. lbool ret = S.solveLimited(dummy);
  170. if (S.verbosity > 0){
  171. printStats(S);
  172. printf("\n"); }
  173. printf(ret == l_True ? "s SATISFIABLE\n" : ret == l_False ? "s UNSATISFIABLE\n" : "s UNKNOWN\n");
  174. if (ret == l_True){
  175. printf("v ");
  176. for (int i = 0; i < S.nVars(); i++)
  177. if (S.model[i] != l_Undef)
  178. printf("%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
  179. printf(" 0\n");
  180. //----------------------
  181. //printf("c solvedBy : ");if(S.solvedByUncom) printf("UnCom\n"); else printf("Com\n");
  182. //=====================
  183. }
  184. //------------------------------------------
  185. //printf("c UncomTime : %lf\n",S.UnComTime);
  186. //printf("c UncomNum : %d\n",S.callNum);
  187. //=========================================
  188. if (S.drup_file && ret == l_False){
  189. #ifdef BIN_DRUP
  190. fputc('a', S.drup_file); fputc(0, S.drup_file);
  191. #else
  192. fprintf(S.drup_file, "0\n");
  193. #endif
  194. }
  195. if (S.drup_file && S.drup_file != stdout) fclose(S.drup_file);
  196. if (res != NULL){
  197. if (ret == l_True){
  198. fprintf(res, "SAT\n");
  199. for (int i = 0; i < S.nVars(); i++)
  200. if (S.model[i] != l_Undef)
  201. fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
  202. fprintf(res, " 0\n");
  203. }else if (ret == l_False)
  204. fprintf(res, "UNSAT\n");
  205. else
  206. fprintf(res, "INDET\n");
  207. //--------------------------
  208. //fprintf(res,"c solvedBy : ");if(S.solvedByUncom) fprintf(res,"UnCom\n"); else fprintf(res,"Com\n");
  209. //fprintf(res,"c UncomTime : %lf\n",S.UnComTime);
  210. //fprintf(res,"c TotalTime : %lf\n",cpuTime());
  211. //fprintf(res,"c UncomNum : %d\n",S.callNum);
  212. //==========================
  213. fclose(res);
  214. }
  215. #ifdef NDEBUG
  216. exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver')
  217. #else
  218. return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
  219. #endif
  220. } catch (OutOfMemoryException&){
  221. printf("c ===============================================================================\n");
  222. printf("c Out of memory\n");
  223. printf("s UNKNOWN\n");
  224. exit(0);
  225. }
  226. }