├── .gitignore ├── minisatConfig.cmake.in ├── cmake_uninstall.cmake.in ├── LICENSE ├── minisat ├── mtl │ ├── IntTypes.h │ ├── XAlloc.h │ ├── Rnd.h │ ├── Alg.h │ ├── Queue.h │ ├── Sort.h │ ├── IntMap.h │ ├── Alloc.h │ ├── Heap.h │ ├── Vec.h │ └── Map.h ├── utils │ ├── System.h │ ├── Options.cc │ ├── ParseUtils.h │ ├── System.cc │ └── Options.h ├── core │ ├── Dimacs.h │ ├── Main.cc │ ├── SolverTypes.h │ └── Solver.h └── simp │ ├── Main.cc │ ├── SimpSolver.h │ └── SimpSolver.cc ├── README ├── appveyor.yml ├── doc └── ReleaseNotes-2.2.0.txt ├── Makefile └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | config.mk 2 | build 3 | -------------------------------------------------------------------------------- /minisatConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Config file for the @EXPORT_TYPE@ cryptominisat Package 2 | # It defines the following variables 3 | # MINISAT_INCLUDE_DIRS - include directories for minisat 4 | # MINISAT_LIBRARIES - libraries to link against 5 | # MINISAT_EXECUTABLE - the cryptominisat executable 6 | 7 | # Compute paths 8 | get_filename_component(MINISAT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 9 | set(MINISAT_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") 10 | 11 | # Our library dependencies (contains definitions for IMPORTED targets) 12 | include("${MINISAT_CMAKE_DIR}/@MINISAT_TARGETS_FILENAME@") 13 | 14 | # These are IMPORTED targets created by @MINISAT_TARGETS_FILENAME@ 15 | set(MINISAT_LIBRARIES minisat) 16 | set(MINISAT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@) 17 | set(MINISAT_VERSION_MINOR @PROJECT_VERSION_MINOR@) 18 | set(MINISAT_EXECUTABLE minisat) 19 | -------------------------------------------------------------------------------- /cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | cmake_policy(SET CMP0007 NEW) # Suppress warnings see `cmake --help-policy CMP0007` 2 | 3 | if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 5 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 6 | 7 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 8 | string(REGEX REPLACE "\n" ";" files "${files}") 9 | list(REVERSE files) 10 | foreach (file ${files}) 11 | message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 12 | if (EXISTS "$ENV{DESTDIR}${file}") 13 | execute_process( 14 | COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" 15 | OUTPUT_VARIABLE rm_out 16 | RESULT_VARIABLE rm_retval 17 | ) 18 | if(NOT ${rm_retval} EQUAL 0) 19 | message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 20 | endif (NOT ${rm_retval} EQUAL 0) 21 | else (EXISTS "$ENV{DESTDIR}${file}") 22 | message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 23 | endif (EXISTS "$ENV{DESTDIR}${file}") 24 | endforeach(file) 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 2 | Copyright (c) 2007-2010 Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /minisat/mtl/IntTypes.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************[IntTypes.h] 2 | Copyright (c) 2009-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_IntTypes_h 21 | #define Minisat_IntTypes_h 22 | 23 | #ifdef __sun 24 | // Not sure if there are newer versions that support C99 headers. The 25 | // needed features are implemented in the headers below though: 26 | 27 | # include 28 | # include 29 | # include 30 | 31 | #else 32 | 33 | # include 34 | # include 35 | 36 | #endif 37 | 38 | #include 39 | 40 | //================================================================================================= 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /minisat/mtl/XAlloc.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[XAlloc.h] 2 | Copyright (c) 2009-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | 21 | #ifndef Minisat_XAlloc_h 22 | #define Minisat_XAlloc_h 23 | 24 | #include 25 | #include 26 | 27 | namespace Minisat { 28 | 29 | //================================================================================================= 30 | // Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: 31 | 32 | class OutOfMemoryException{}; 33 | static inline void* xrealloc(void *ptr, size_t size) 34 | { 35 | void* mem = realloc(ptr, size); 36 | if (mem == NULL && errno == ENOMEM){ 37 | throw OutOfMemoryException(); 38 | }else 39 | return mem; 40 | } 41 | 42 | //================================================================================================= 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Quick Install 3 | 4 | - Decide where to install the files . The simplest approach is to use 5 | GNU standard locations and just set a "prefix" for the root install 6 | directory (reffered to as $PREFIX below). More control can be 7 | achieved by overriding other of the GNU standard install locations 8 | (includedir, bindir, etc). Configuring with just a prefix: 9 | 10 | > make config prefix=$PREFIX 11 | 12 | - Compiling and installing: 13 | 14 | > make install 15 | 16 | ================================================================================ 17 | Configuration 18 | 19 | - Multiple configuration steps can be joined into one call to "make 20 | config" by appending multiple variable assignments on the same line. 21 | 22 | - The configuration is stored in the file "config.mk". Look here if 23 | you want to know what the current configuration looks like. 24 | 25 | - To reset from defaults simply remove the "config.mk" file or call 26 | "make distclean". 27 | 28 | - Recompilation can be done without the configuration step. 29 | 30 | [ TODO: describe configartion possibilities for compile flags / modes ] 31 | 32 | ================================================================================ 33 | Building 34 | 35 | [ TODO: describe seperate build modes ] 36 | 37 | ================================================================================ 38 | Install 39 | 40 | [ TODO: ? ] 41 | 42 | ================================================================================ 43 | Directory Overview: 44 | 45 | minisat/mtl/ Mini Template Library 46 | minisat/utils/ Generic helper code (I/O, Parsing, CPU-time, etc) 47 | minisat/core/ A core version of the solver 48 | minisat/simp/ An extended solver with simplification capabilities 49 | doc/ Documentation 50 | README 51 | LICENSE 52 | 53 | ================================================================================ 54 | Examples: 55 | 56 | Run minisat with same heuristics as version 2.0: 57 | 58 | > minisat -no-luby -rinc=1.5 -phase-saving=0 -rnd-freq=0.02 59 | -------------------------------------------------------------------------------- /minisat/mtl/Rnd.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Rnd.h] 2 | Copyright (c) 2012, Niklas Sorensson 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 4 | associated documentation files (the "Software"), to deal in the Software without restriction, 5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or 10 | substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 16 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | **************************************************************************************************/ 18 | 19 | #ifndef Minisat_Rnd_h 20 | #define Minisat_Rnd_h 21 | 22 | #include "minisat/mtl/Vec.h" 23 | 24 | namespace Minisat { 25 | 26 | // Generate a random double: 27 | static inline double drand(double& seed) 28 | { 29 | seed *= 1389796; 30 | int q = (int)(seed / 2147483647); 31 | seed -= (double)q * 2147483647; 32 | return seed / 2147483647; 33 | } 34 | 35 | 36 | // Generate a random integer: 37 | static inline int irand(double& seed, int size) { return (int)(drand(seed) * size); } 38 | 39 | 40 | // Randomly shuffle the contents of a vector: 41 | template 42 | static void randomShuffle(double& seed, vec& xs) 43 | { 44 | for (int i = 0; i < xs.size(); i++){ 45 | int pick = i + irand(seed, xs.size() - i); 46 | T tmp = xs[i]; 47 | xs[i] = xs[pick]; 48 | xs[pick] = tmp; 49 | } 50 | } 51 | 52 | // Randomly shuffle a vector of a vector (ugly) 53 | template 54 | static void randomShuffle(double& seed, vec >& xs) 55 | { 56 | for (int i = 0; i < xs.size(); i++){ 57 | int pick = i + irand(seed, xs.size() - i); 58 | vec tmp; xs[i].moveTo(tmp); 59 | xs[pick].moveTo(xs[i]); 60 | tmp.moveTo(xs[pick]); 61 | } 62 | } 63 | 64 | 65 | //================================================================================================= 66 | } // namespace Minisat 67 | #endif 68 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # branches to build 2 | branches: 3 | # whitelist 4 | only: 5 | - master 6 | - appveyor_debug 7 | 8 | # Operating system (build VM template) 9 | os: Visual Studio 2015 10 | 11 | # scripts that are called at very beginning, before repo cloning 12 | init: 13 | - git config --global core.autocrlf input 14 | 15 | 16 | # clone directory 17 | clone_folder: c:\projects\minisat 18 | 19 | platform: 20 | - x64 21 | # - x86 22 | 23 | environment: 24 | global: 25 | BOOST_ROOT: C:\projects\minisat\boost_1_59_0_install 26 | ZLIB_ROOT: C:\projects\minisat\zlib\myinstall 27 | BUILD_TYPE: Release 28 | MSBUILD_FLAGS: /maxcpucount /nologo 29 | 30 | configuration: 31 | - Release 32 | 33 | build_script: 34 | #- IF "%PLATFORM%" == "x86" ( SET BOOST_LIBRARYDIR=C:/Libraries/boost_1_59_0/lib32-msvc-14.0) 35 | - IF "%PLATFORM%" == "x86" ( SET CMAKE_GENERATOR="Visual Studio 14 2015") 36 | 37 | #- IF "%PLATFORM%" == "x64" ( SET BOOST_LIBRARYDIR=C:/Libraries/boost_1_59_0/lib64-msvc-14.0) 38 | - IF "%PLATFORM%" == "x64" ( SET CMAKE_GENERATOR="Visual Studio 14 2015 Win64") 39 | 40 | - echo %PLATFORM% 41 | - echo %BOOST_LIBRARYDIR% 42 | - echo %CMAKE_GENERATOR% 43 | - echo %configuration% 44 | - echo %APPVEYOR_BUILD_FOLDER% 45 | - echo %cd% 46 | 47 | # zlib 48 | # TODO check out http://stackoverflow.com/questions/10507893/libzip-with-visual-studio-2010 49 | - cd C:\projects\minisat 50 | - git clone https://github.com/madler/zlib 51 | - cd zlib 52 | - git checkout v1.2.8 53 | - echo %cd% 54 | - mkdir build 55 | - mkdir myinstall 56 | - cd build 57 | - cmake -G %CMAKE_GENERATOR% -DCMAKE_INSTALL_PREFIX=%ZLIB_ROOT% .. 58 | - if %PLATFORM%==x86 call msbuild %MSBUILD_FLAGS% /t:Build /p:Configuration=%CONFIGURATION% /p:Platform="x86" zlib.sln 59 | - if %PLATFORM%==x64 call msbuild %MSBUILD_FLAGS% /t:Build /p:Configuration=%CONFIGURATION% /p:Platform="x64" zlib.sln 60 | - msbuild %MSBUILD_FLAGS% INSTALL.vcxproj 61 | - dir ..\myinstall\ 62 | 63 | # minisat 64 | - cd C:\projects\minisat 65 | - mkdir build 66 | - mkdir myinstall 67 | - cd build 68 | - cmake -G %CMAKE_GENERATOR% -DCMAKE_INSTALL_PREFIX=%MINISAT_ROOT% -DZLIB_ROOT=%ZLIB_ROOT% .. 69 | - cmake --build . --config %CONFIGURATION% 70 | - dir ..\myinstall\ 71 | 72 | 73 | build: 74 | # project: INSTALL.vcxproj # path to Visual Studio solution or project 75 | parallel: true 76 | verbosity: minimal 77 | 78 | 79 | # scripts to run after build 80 | after_build: 81 | - 7z a c:\projects\minisat\minisat.zip %APPVEYOR_BUILD_FOLDER%\build -tzip 82 | - cd c:\projects\minisat 83 | 84 | artifacts: 85 | - path: minisat.zip 86 | name: minisat.zip 87 | 88 | deploy_script: 89 | #- cd c:\projects\minisat 90 | #- curl -T minisat.zip --user %ACCOUNT% https://someplace/ 91 | 92 | test: off 93 | -------------------------------------------------------------------------------- /minisat/mtl/Alg.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Alg.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Alg_h 22 | #define Minisat_Alg_h 23 | 24 | #include "minisat/mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | // Useful functions on vector-like types: 30 | 31 | //================================================================================================= 32 | // Removing and searching for elements: 33 | // 34 | 35 | template 36 | static inline void remove(V& ts, const T& t) 37 | { 38 | int j = 0; 39 | for (; j < (int)ts.size() && ts[j] != t; j++); 40 | assert(j < (int)ts.size()); 41 | for (; j < (int)ts.size()-1; j++) ts[j] = ts[j+1]; 42 | ts.pop(); 43 | } 44 | 45 | 46 | template 47 | static inline bool find(V& ts, const T& t) 48 | { 49 | int j = 0; 50 | for (; j < (int)ts.size() && ts[j] != t; j++); 51 | return j < (int)ts.size(); 52 | } 53 | 54 | 55 | //================================================================================================= 56 | // Copying vectors with support for nested vector types: 57 | // 58 | 59 | // Base case: 60 | template 61 | static inline void copy(const T& from, T& to) 62 | { 63 | to = from; 64 | } 65 | 66 | // Recursive case: 67 | template 68 | static inline void copy(const vec& from, vec& to, bool append = false) 69 | { 70 | if (!append) 71 | to.clear(); 72 | for (int i = 0; i < from.size(); i++){ 73 | to.push(); 74 | copy(from[i], to.last()); 75 | } 76 | } 77 | 78 | template 79 | static inline void append(const vec& from, vec& to){ copy(from, to, true); } 80 | 81 | //================================================================================================= 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /minisat/mtl/Queue.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Queue.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Queue_h 22 | #define Minisat_Queue_h 23 | 24 | #include "minisat/mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | 30 | template 31 | class Queue { 32 | vec buf; 33 | int first; 34 | int end; 35 | 36 | public: 37 | typedef T Key; 38 | 39 | Queue() : buf(1), first(0), end(0) {} 40 | 41 | void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; } 42 | int size () const { return (end >= first) ? end - first : end - first + buf.size(); } 43 | 44 | const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 45 | T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 46 | 47 | T peek () const { assert(first != end); return buf[first]; } 48 | void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; } 49 | void insert(T elem) { // INVARIANT: buf[end] is always unused 50 | buf[end++] = elem; 51 | if (end == buf.size()) end = 0; 52 | if (first == end){ // Resize: 53 | vec tmp((buf.size()*3 + 1) >> 1); 54 | //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0); 55 | int i = 0; 56 | for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j]; 57 | for (int j = 0 ; j < end ; j++) tmp[i++] = buf[j]; 58 | first = 0; 59 | end = buf.size(); 60 | tmp.moveTo(buf); 61 | } 62 | } 63 | }; 64 | 65 | 66 | //================================================================================================= 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /minisat/utils/System.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[System.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_System_h 22 | #define Minisat_System_h 23 | 24 | #if defined(__GLIBC__) 25 | #include 26 | #endif 27 | 28 | #include "minisat/mtl/IntTypes.h" 29 | 30 | //------------------------------------------------------------------------------------------------- 31 | 32 | namespace Minisat { 33 | 34 | static inline double cpuTime(void); // CPU-time in seconds. 35 | 36 | extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures). 37 | extern double memUsedPeak(bool strictlyPeak = false); // Peak-memory in mega bytes (returns 0 for unsupported architectures). 38 | 39 | extern void setX86FPUPrecision(); // Make sure double's are represented with the same precision 40 | // in memory and registers. 41 | 42 | extern void limitMemory(uint64_t max_mem_mb); // Set a limit on total memory usage. The exact 43 | // semantics varies depending on architecture. 44 | 45 | extern void limitTime(uint32_t max_cpu_time); // Set a limit on maximum CPU time. The exact 46 | // semantics varies depending on architecture. 47 | 48 | extern void sigTerm(void handler(int)); // Set up handling of available termination signals. 49 | 50 | } 51 | 52 | //------------------------------------------------------------------------------------------------- 53 | // Implementation of inline functions: 54 | 55 | #if defined(_MSC_VER) || defined(__MINGW32__) 56 | #include 57 | 58 | static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } 59 | 60 | #else 61 | #include 62 | #include 63 | #include 64 | 65 | static inline double Minisat::cpuTime(void) { 66 | struct rusage ru; 67 | getrusage(RUSAGE_SELF, &ru); 68 | return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } 69 | 70 | #endif 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /minisat/core/Dimacs.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[Dimacs.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Dimacs_h 22 | #define Minisat_Dimacs_h 23 | 24 | #include 25 | 26 | #include "minisat/utils/ParseUtils.h" 27 | #include "minisat/core/SolverTypes.h" 28 | 29 | namespace Minisat { 30 | 31 | //================================================================================================= 32 | // DIMACS Parser: 33 | 34 | template 35 | static void readClause(B& in, Solver& S, vec& lits) { 36 | int parsed_lit, var; 37 | lits.clear(); 38 | for (;;){ 39 | parsed_lit = parseInt(in); 40 | if (parsed_lit == 0) break; 41 | var = abs(parsed_lit)-1; 42 | while (var >= S.nVars()) S.newVar(); 43 | lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) ); 44 | } 45 | } 46 | 47 | template 48 | static void parse_DIMACS_main(B& in, Solver& S, bool strictp = false) { 49 | vec lits; 50 | int vars = 0; 51 | int clauses = 0; 52 | int cnt = 0; 53 | for (;;){ 54 | skipWhitespace(in); 55 | if (*in == EOF) break; 56 | else if (*in == 'p'){ 57 | if (eagerMatch(in, "p cnf")){ 58 | vars = parseInt(in); 59 | clauses = parseInt(in); 60 | // SATRACE'06 hack 61 | // if (clauses > 4000000) 62 | // S.eliminate(true); 63 | }else{ 64 | printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 65 | } 66 | } else if (*in == 'c' || *in == 'p') 67 | skipLine(in); 68 | else{ 69 | cnt++; 70 | readClause(in, S, lits); 71 | S.addClause_(lits); } 72 | } 73 | if (strictp && cnt != clauses) 74 | printf("PARSE ERROR! DIMACS header mismatch: wrong number of clauses\n"); 75 | } 76 | 77 | // Inserts problem into solver. 78 | // 79 | template 80 | static void parse_DIMACS(gzFile input_stream, Solver& S, bool strictp = false) { 81 | StreamBuffer in(input_stream); 82 | parse_DIMACS_main(in, S, strictp); } 83 | 84 | //================================================================================================= 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /minisat/mtl/Sort.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************[Sort.h] 2 | Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Sort_h 22 | #define Minisat_Sort_h 23 | 24 | #include "minisat/mtl/Vec.h" 25 | 26 | //================================================================================================= 27 | // Some sorting algorithms for vec's 28 | 29 | 30 | namespace Minisat { 31 | 32 | template 33 | struct LessThan_default { 34 | bool operator () (T x, T y) { return x < y; } 35 | }; 36 | 37 | 38 | template 39 | void selectionSort(T* array, int size, LessThan lt) 40 | { 41 | int i, j, best_i; 42 | T tmp; 43 | 44 | for (i = 0; i < size-1; i++){ 45 | best_i = i; 46 | for (j = i+1; j < size; j++){ 47 | if (lt(array[j], array[best_i])) 48 | best_i = j; 49 | } 50 | tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; 51 | } 52 | } 53 | template static inline void selectionSort(T* array, int size) { 54 | selectionSort(array, size, LessThan_default()); } 55 | 56 | template 57 | void sort(T* array, int size, LessThan lt) 58 | { 59 | if (size <= 15) 60 | selectionSort(array, size, lt); 61 | 62 | else{ 63 | T pivot = array[size / 2]; 64 | T tmp; 65 | int i = -1; 66 | int j = size; 67 | 68 | for(;;){ 69 | do i++; while(lt(array[i], pivot)); 70 | do j--; while(lt(pivot, array[j])); 71 | 72 | if (i >= j) break; 73 | 74 | tmp = array[i]; array[i] = array[j]; array[j] = tmp; 75 | } 76 | 77 | sort(array , i , lt); 78 | sort(&array[i], size-i, lt); 79 | } 80 | } 81 | template static inline void sort(T* array, int size) { 82 | sort(array, size, LessThan_default()); } 83 | 84 | 85 | //================================================================================================= 86 | // For 'vec's: 87 | 88 | 89 | template void sort(vec& v, LessThan lt) { 90 | sort((T*)v, v.size(), lt); } 91 | template void sort(vec& v) { 92 | sort(v, LessThan_default()); } 93 | 94 | 95 | //================================================================================================= 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /doc/ReleaseNotes-2.2.0.txt: -------------------------------------------------------------------------------- 1 | Release Notes for MiniSat 2.2.0 2 | =============================== 3 | 4 | Changes since version 2.0: 5 | 6 | * Started using a more standard release numbering. 7 | 8 | * Includes some now well-known heuristics: phase-saving and luby 9 | restarts. The old heuristics are still present and can be activated 10 | if needed. 11 | 12 | * Detection/Handling of out-of-memory and vector capacity 13 | overflow. This is fairly new and relatively untested. 14 | 15 | * Simple resource controls: CPU-time, memory, number of 16 | conflicts/decisions. 17 | 18 | * CPU-time limiting is implemented by a more general, but simple, 19 | asynchronous interruption feature. This means that the solving 20 | procedure can be interrupted from another thread or in a signal 21 | handler. 22 | 23 | * Improved portability with respect to building on Solaris and with 24 | Visual Studio. This is not regularly tested and chances are that 25 | this have been broken since, but should be fairly easy to fix if 26 | so. 27 | 28 | * Changed C++ file-extention to the less problematic ".cc". 29 | 30 | * Source code is now namespace-protected 31 | 32 | * Introducing a new Clause Memory Allocator that brings reduced 33 | memory consumption on 64-bit architechtures and improved 34 | performance (to some extent). The allocator uses a region-based 35 | approach were all references to clauses are represented as a 32-bit 36 | index into a global memory region that contains all clauses. To 37 | free up and compact memory it uses a simple copying garbage 38 | collector. 39 | 40 | * Improved unit-propagation by Blocking Literals. For each entry in 41 | the watcher lists, pair the pointer to a clause with some 42 | (arbitrary) literal from the clause. The idea is that if the 43 | literal is currently true (i.e. the clause is satisfied) the 44 | watchers of the clause does not need to be altered. This can thus 45 | be detected without touching the clause's memory at all. As often 46 | as can be done cheaply, the blocking literal for entries to the 47 | watcher list of a literal 'p' is set to the other literal watched 48 | in the corresponding clause. 49 | 50 | * Basic command-line/option handling system. Makes it easy to specify 51 | options in the class that they affect, and whenever that class is 52 | used in an executable, parsing of options and help messages are 53 | brought in automatically. 54 | 55 | * General clean-up and various minor bug-fixes. 56 | 57 | * Changed implementation of variable-elimination/model-extension: 58 | 59 | - The interface is changed so that arbitrary remembering is no longer 60 | possible. If you need to mention some variable again in the future, 61 | this variable has to be frozen. 62 | 63 | - When eliminating a variable, only clauses that contain the variable 64 | with one sign is necessary to store. Thereby making the other sign 65 | a "default" value when extending models. 66 | 67 | - The memory consumption for eliminated clauses is further improved 68 | by storing all eliminated clauses in a single contiguous vector. 69 | 70 | * Some common utility code (I/O, Parsing, CPU-time, etc) is ripped 71 | out and placed in a separate "utils" directory. 72 | 73 | * The DIMACS parse is refactored so that it can be reused in other 74 | applications (not very elegant, but at least possible). 75 | 76 | * Some simple improvements to scalability of preprocessing, using 77 | more lazy clause removal from data-structures and a couple of 78 | ad-hoc limits (the longest clause that can be produced in variable 79 | elimination, and the longest clause used in backward subsumption). 80 | -------------------------------------------------------------------------------- /minisat/utils/Options.cc: -------------------------------------------------------------------------------- 1 | /**************************************************************************************[Options.cc] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #include "minisat/mtl/Sort.h" 21 | #include "minisat/utils/Options.h" 22 | #include "minisat/utils/ParseUtils.h" 23 | 24 | using namespace Minisat; 25 | 26 | void Minisat::parseOptions(int& argc, char** argv, bool strict) 27 | { 28 | int i, j; 29 | for (i = j = 1; i < argc; i++){ 30 | const char* str = argv[i]; 31 | if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){ 32 | if (*str == '\0') 33 | printUsageAndExit(argc, argv); 34 | else if (match(str, "-verb")) 35 | printUsageAndExit(argc, argv, true); 36 | } else { 37 | bool parsed_ok = false; 38 | 39 | for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){ 40 | parsed_ok = Option::getOptionList()[k]->parse(argv[i]); 41 | 42 | // fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip"); 43 | } 44 | 45 | if (!parsed_ok){ 46 | if (strict && match(argv[i], "-")) 47 | fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1); 48 | else 49 | argv[j++] = argv[i]; 50 | } 51 | } 52 | } 53 | 54 | argc -= (i - j); 55 | } 56 | 57 | 58 | void Minisat::setUsageHelp (const char* str){ Option::getUsageString() = str; } 59 | void Minisat::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; } 60 | void Minisat::printUsageAndExit (int /*argc*/, char** argv, bool verbose) 61 | { 62 | const char* usage = Option::getUsageString(); 63 | if (usage != NULL) 64 | fprintf(stderr, usage, argv[0]); 65 | 66 | sort(Option::getOptionList(), Option::OptionLt()); 67 | 68 | const char* prev_cat = NULL; 69 | const char* prev_type = NULL; 70 | 71 | for (int i = 0; i < Option::getOptionList().size(); i++){ 72 | const char* cat = Option::getOptionList()[i]->category; 73 | const char* type = Option::getOptionList()[i]->type_name; 74 | 75 | if (cat != prev_cat) 76 | fprintf(stderr, "\n%s OPTIONS:\n\n", cat); 77 | else if (type != prev_type) 78 | fprintf(stderr, "\n"); 79 | 80 | Option::getOptionList()[i]->help(verbose); 81 | 82 | prev_cat = Option::getOptionList()[i]->category; 83 | prev_type = Option::getOptionList()[i]->type_name; 84 | } 85 | 86 | fprintf(stderr, "\nHELP OPTIONS:\n\n"); 87 | fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString()); 88 | fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString()); 89 | fprintf(stderr, "\n"); 90 | exit(0); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /minisat/mtl/IntMap.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[IntMap.h] 2 | Copyright (c) 2011, Niklas Sorensson 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 4 | associated documentation files (the "Software"), to deal in the Software without restriction, 5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or 10 | substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 16 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | **************************************************************************************************/ 18 | 19 | #ifndef Minisat_IntMap_h 20 | #define Minisat_IntMap_h 21 | 22 | #include "minisat/mtl/Vec.h" 23 | 24 | namespace Minisat { 25 | 26 | template struct MkIndexDefault { 27 | typename vec::Size operator()(T t) const { return (typename vec::Size)t; } 28 | }; 29 | 30 | template > 31 | class IntMap { 32 | vec map; 33 | MkIndex index; 34 | public: 35 | explicit IntMap(MkIndex _index = MkIndex()) : index(_index){} 36 | 37 | bool has (K k) const { return index(k) < map.size(); } 38 | 39 | const V& operator[](K k) const { assert(has(k)); return map[index(k)]; } 40 | V& operator[](K k) { assert(has(k)); return map[index(k)]; } 41 | 42 | const V* begin () const { return &map[0]; } 43 | const V* end () const { return &map[map.size()]; } 44 | V* begin () { return &map[0]; } 45 | V* end () { return &map[map.size()]; } 46 | 47 | void reserve(K key, V pad) { map.growTo(index(key)+1, pad); } 48 | void reserve(K key) { map.growTo(index(key)+1); } 49 | void insert (K key, V val, V pad){ reserve(key, pad); operator[](key) = val; } 50 | void insert (K key, V val) { reserve(key); operator[](key) = val; } 51 | 52 | void clear (bool dispose = false) { map.clear(dispose); } 53 | void moveTo (IntMap& to) { map.moveTo(to.map); to.index = index; } 54 | void copyTo (IntMap& to) const { map.copyTo(to.map); to.index = index; } 55 | }; 56 | 57 | 58 | template > 59 | class IntSet 60 | { 61 | IntMap in_set; 62 | vec xs; 63 | 64 | public: 65 | // Size operations: 66 | int size (void) const { return xs.size(); } 67 | void clear (bool free = false){ 68 | if (free) 69 | in_set.clear(true); 70 | else 71 | for (int i = 0; i < xs.size(); i++) 72 | in_set[xs[i]] = 0; 73 | xs.clear(free); 74 | } 75 | 76 | // Allow inspecting the internal vector: 77 | const vec& 78 | toVec () const { return xs; } 79 | 80 | // Vector interface: 81 | K operator [] (int index) const { return xs[index]; } 82 | 83 | 84 | void insert (K k) { in_set.reserve(k, 0); if (!in_set[k]) { in_set[k] = 1; xs.push(k); } } 85 | bool has (K k) { in_set.reserve(k, 0); return in_set[k]; } 86 | }; 87 | 88 | #if 0 89 | template > 90 | class IntMapNil { 91 | vec map; 92 | V nil; 93 | 94 | public: 95 | IntMap(){} 96 | 97 | void reserve(K); 98 | V& find (K); 99 | const V& operator[](K k) const; 100 | 101 | }; 102 | #endif 103 | 104 | //================================================================================================= 105 | } // namespace Minisat 106 | #endif 107 | -------------------------------------------------------------------------------- /minisat/utils/ParseUtils.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************[ParseUtils.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_ParseUtils_h 22 | #define Minisat_ParseUtils_h 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include "minisat/mtl/XAlloc.h" 30 | 31 | namespace Minisat { 32 | 33 | //------------------------------------------------------------------------------------------------- 34 | // A simple buffered character stream class: 35 | 36 | 37 | 38 | class StreamBuffer { 39 | gzFile in; 40 | unsigned char* buf; 41 | int pos; 42 | int size; 43 | 44 | enum { buffer_size = 64*1024 }; 45 | 46 | void assureLookahead() { 47 | if (pos >= size) { 48 | pos = 0; 49 | size = gzread(in, buf, buffer_size); } } 50 | 51 | public: 52 | explicit StreamBuffer(gzFile i) : in(i), pos(0), size(0){ 53 | buf = (unsigned char*)xrealloc(NULL, buffer_size); 54 | assureLookahead(); 55 | } 56 | ~StreamBuffer() { free(buf); } 57 | 58 | int operator * () const { return (pos >= size) ? EOF : buf[pos]; } 59 | void operator ++ () { pos++; assureLookahead(); } 60 | int position () const { return pos; } 61 | }; 62 | 63 | 64 | //------------------------------------------------------------------------------------------------- 65 | // End-of-file detection functions for StreamBuffer and char*: 66 | 67 | 68 | static inline bool isEof(StreamBuffer& in) { return *in == EOF; } 69 | static inline bool isEof(const char* in) { return *in == '\0'; } 70 | 71 | //------------------------------------------------------------------------------------------------- 72 | // Generic parse functions parametrized over the input-stream type. 73 | 74 | 75 | template 76 | static void skipWhitespace(B& in) { 77 | while ((*in >= 9 && *in <= 13) || *in == 32) 78 | ++in; } 79 | 80 | 81 | template 82 | static void skipLine(B& in) { 83 | for (;;){ 84 | if (isEof(in)) return; 85 | if (*in == '\n') { ++in; return; } 86 | ++in; } } 87 | 88 | 89 | template 90 | static int parseInt(B& in) { 91 | int val = 0; 92 | bool neg = false; 93 | skipWhitespace(in); 94 | if (*in == '-') neg = true, ++in; 95 | else if (*in == '+') ++in; 96 | if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 97 | while (*in >= '0' && *in <= '9') 98 | val = val*10 + (*in - '0'), 99 | ++in; 100 | return neg ? -val : val; } 101 | 102 | 103 | // String matching: in case of a match the input iterator will be advanced the corresponding 104 | // number of characters. 105 | template 106 | static bool match(B& in, const char* str) { 107 | int i; 108 | for (i = 0; str[i] != '\0'; i++) 109 | if (in[i] != str[i]) 110 | return false; 111 | 112 | in += i; 113 | 114 | return true; 115 | } 116 | 117 | // String matching: consumes characters eagerly, but does not require random access iterator. 118 | template 119 | static bool eagerMatch(B& in, const char* str) { 120 | for (; *str != '\0'; ++str, ++in) 121 | if (*str != *in) 122 | return false; 123 | return true; } 124 | 125 | 126 | //================================================================================================= 127 | } 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /minisat/mtl/Alloc.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Alloc.h] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | 21 | #ifndef Minisat_Alloc_h 22 | #define Minisat_Alloc_h 23 | 24 | #include "minisat/mtl/XAlloc.h" 25 | #include "minisat/mtl/Vec.h" 26 | 27 | namespace Minisat { 28 | 29 | //================================================================================================= 30 | // Simple Region-based memory allocator: 31 | 32 | template 33 | class RegionAllocator 34 | { 35 | T* memory; 36 | uint32_t sz; 37 | uint32_t cap; 38 | uint32_t wasted_; 39 | 40 | void capacity(uint32_t min_cap); 41 | 42 | public: 43 | // TODO: make this a class for better type-checking? 44 | typedef uint32_t Ref; 45 | enum { Ref_Undef = UINT32_MAX }; 46 | enum { Unit_Size = sizeof(T) }; 47 | 48 | explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); } 49 | ~RegionAllocator() 50 | { 51 | if (memory != NULL) 52 | ::free(memory); 53 | } 54 | 55 | 56 | uint32_t size () const { return sz; } 57 | uint32_t wasted () const { return wasted_; } 58 | 59 | Ref alloc (int size); 60 | void free (int size) { wasted_ += size; } 61 | 62 | // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): 63 | T& operator[](Ref r) { assert(r < sz); return memory[r]; } 64 | const T& operator[](Ref r) const { assert(r < sz); return memory[r]; } 65 | 66 | T* lea (Ref r) { assert(r < sz); return &memory[r]; } 67 | const T* lea (Ref r) const { assert(r < sz); return &memory[r]; } 68 | Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]); 69 | return (Ref)(t - &memory[0]); } 70 | 71 | void moveTo(RegionAllocator& to) { 72 | if (to.memory != NULL) ::free(to.memory); 73 | to.memory = memory; 74 | to.sz = sz; 75 | to.cap = cap; 76 | to.wasted_ = wasted_; 77 | 78 | memory = NULL; 79 | sz = cap = wasted_ = 0; 80 | } 81 | 82 | 83 | }; 84 | 85 | template 86 | void RegionAllocator::capacity(uint32_t min_cap) 87 | { 88 | if (cap >= min_cap) return; 89 | 90 | uint32_t prev_cap = cap; 91 | while (cap < min_cap){ 92 | // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the 93 | // result even by clearing the least significant bit. The resulting sequence of capacities 94 | // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when 95 | // using 'uint32_t' as indices so that as much as possible of this space can be used. 96 | uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1; 97 | cap += delta; 98 | 99 | if (cap <= prev_cap) 100 | throw OutOfMemoryException(); 101 | } 102 | // printf(" .. (%p) cap = %u\n", this, cap); 103 | 104 | assert(cap > 0); 105 | memory = (T*)xrealloc(memory, sizeof(T)*cap); 106 | } 107 | 108 | 109 | template 110 | typename RegionAllocator::Ref 111 | RegionAllocator::alloc(int size) 112 | { 113 | // printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout); 114 | assert(size > 0); 115 | capacity(sz + size); 116 | 117 | uint32_t prev_sz = sz; 118 | sz += size; 119 | 120 | // Handle overflow: 121 | if (sz < prev_sz) 122 | throw OutOfMemoryException(); 123 | 124 | return prev_sz; 125 | } 126 | 127 | 128 | //================================================================================================= 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /minisat/utils/System.cc: -------------------------------------------------------------------------------- 1 | /***************************************************************************************[System.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | #include "minisat/utils/System.h" 25 | 26 | #if defined(__linux__) 27 | 28 | #include 29 | 30 | using namespace Minisat; 31 | 32 | static inline int memReadStat(int field) 33 | { 34 | char name[256]; 35 | pid_t pid = getpid(); 36 | int value; 37 | 38 | sprintf(name, "/proc/%d/statm", pid); 39 | FILE* in = fopen(name, "rb"); 40 | if (in == NULL) return 0; 41 | 42 | for (; field >= 0; field--) 43 | if (fscanf(in, "%d", &value) != 1) 44 | printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1); 45 | fclose(in); 46 | return value; 47 | } 48 | 49 | 50 | static inline int memReadPeak(void) 51 | { 52 | char name[256]; 53 | pid_t pid = getpid(); 54 | 55 | sprintf(name, "/proc/%d/status", pid); 56 | FILE* in = fopen(name, "rb"); 57 | if (in == NULL) return 0; 58 | 59 | // Find the correct line, beginning with "VmPeak:": 60 | int peak_kb = 0; 61 | while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) 62 | while (!feof(in) && fgetc(in) != '\n') 63 | ; 64 | fclose(in); 65 | 66 | return peak_kb; 67 | } 68 | 69 | double Minisat::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); } 70 | double Minisat::memUsedPeak(bool strictlyPeak) { 71 | double peak = memReadPeak() / (double)1024; 72 | return peak == 0 && !strictlyPeak ? memUsed() : peak; } 73 | 74 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__gnu_hurd__) 75 | 76 | double Minisat::memUsed() { 77 | struct rusage ru; 78 | getrusage(RUSAGE_SELF, &ru); 79 | return (double)ru.ru_maxrss / 1024; } 80 | double Minisat::memUsedPeak(bool /*strictlyPeak*/) { return memUsed(); } 81 | 82 | 83 | #elif defined(__APPLE__) 84 | #include 85 | 86 | double Minisat::memUsed() { 87 | malloc_statistics_t t; 88 | malloc_zone_statistics(NULL, &t); 89 | return (double)t.max_size_in_use / (1024*1024); } 90 | double Minisat::memUsedPeak(bool /*strictlyPeak*/) { return memUsed(); } 91 | 92 | #else 93 | double Minisat::memUsed() { return 0; } 94 | double Minisat::memUsedPeak(bool /*strictlyPeak*/) { return 0; } 95 | #endif 96 | 97 | 98 | void Minisat::setX86FPUPrecision() 99 | { 100 | #if defined(__GLIBC__) && defined(_FPU_EXTENDED) && defined(_FPU_DOUBLE) && defined(_FPU_GETCW) 101 | // Only correct FPU precision on Linux architectures that needs and supports it: 102 | fpu_control_t oldcw, newcw; 103 | _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); 104 | printf("WARNING: for repeatability, setting FPU to use double precision\n"); 105 | #endif 106 | } 107 | 108 | 109 | #if !defined(_MSC_VER) && !defined(__MINGW32__) 110 | void Minisat::limitMemory(uint64_t max_mem_mb) 111 | { 112 | // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead. 113 | #if defined(__OpenBSD__) 114 | #define RLIMIT_AS RLIMIT_DATA 115 | #endif 116 | 117 | // Set limit on virtual memory: 118 | if (max_mem_mb != 0){ 119 | rlim_t new_mem_lim = (rlim_t)max_mem_mb * 1024*1024; 120 | rlimit rl; 121 | getrlimit(RLIMIT_AS, &rl); 122 | if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ 123 | rl.rlim_cur = new_mem_lim; 124 | if (setrlimit(RLIMIT_AS, &rl) == -1) 125 | printf("WARNING! Could not set resource limit: Virtual memory.\n"); 126 | } 127 | } 128 | 129 | #if defined(__OpenBSD__) 130 | #undef RLIMIT_AS 131 | #endif 132 | } 133 | #else 134 | void Minisat::limitMemory(uint64_t /*max_mem_mb*/) 135 | { 136 | printf("WARNING! Memory limit not supported on this architecture.\n"); 137 | } 138 | #endif 139 | 140 | 141 | #if !defined(_MSC_VER) && !defined(__MINGW32__) 142 | void Minisat::limitTime(uint32_t max_cpu_time) 143 | { 144 | if (max_cpu_time != 0){ 145 | rlimit rl; 146 | getrlimit(RLIMIT_CPU, &rl); 147 | if (rl.rlim_max == RLIM_INFINITY || (rlim_t)max_cpu_time < rl.rlim_max){ 148 | rl.rlim_cur = max_cpu_time; 149 | if (setrlimit(RLIMIT_CPU, &rl) == -1) 150 | printf("WARNING! Could not set resource limit: CPU-time.\n"); 151 | } 152 | } 153 | } 154 | #else 155 | void Minisat::limitTime(uint32_t /*max_cpu_time*/) 156 | { 157 | printf("WARNING! CPU-time limit not supported on this architecture.\n"); 158 | } 159 | #endif 160 | 161 | 162 | void Minisat::sigTerm(void handler(int)) 163 | { 164 | signal(SIGINT, handler); 165 | signal(SIGTERM,handler); 166 | #ifdef SIGXCPU 167 | signal(SIGXCPU,handler); 168 | #endif 169 | } 170 | -------------------------------------------------------------------------------- /minisat/mtl/Heap.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************[Heap.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Heap_h 22 | #define Minisat_Heap_h 23 | 24 | #include "minisat/mtl/Vec.h" 25 | #include "minisat/mtl/IntMap.h" 26 | 27 | namespace Minisat { 28 | 29 | //================================================================================================= 30 | // A heap implementation with support for decrease/increase key. 31 | 32 | 33 | template > 34 | class Heap { 35 | vec heap; // Heap of Keys 36 | IntMap indices; // Each Key's position (index) in the Heap 37 | Comp lt; // The heap is a minimum-heap with respect to this comparator 38 | 39 | // Index "traversal" functions 40 | static inline int left (int i) { return i*2+1; } 41 | static inline int right (int i) { return (i+1)*2; } 42 | static inline int parent(int i) { return (i-1) >> 1; } 43 | 44 | 45 | void percolateUp(int i) 46 | { 47 | K x = heap[i]; 48 | int p = parent(i); 49 | 50 | while (i != 0 && lt(x, heap[p])){ 51 | heap[i] = heap[p]; 52 | indices[heap[p]] = i; 53 | i = p; 54 | p = parent(p); 55 | } 56 | heap [i] = x; 57 | indices[x] = i; 58 | } 59 | 60 | 61 | void percolateDown(int i) 62 | { 63 | K x = heap[i]; 64 | while (left(i) < heap.size()){ 65 | int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); 66 | if (!lt(heap[child], x)) break; 67 | heap[i] = heap[child]; 68 | indices[heap[i]] = i; 69 | i = child; 70 | } 71 | heap [i] = x; 72 | indices[x] = i; 73 | } 74 | 75 | 76 | public: 77 | Heap(const Comp& c, MkIndex _index = MkIndex()) : indices(_index), lt(c) {} 78 | 79 | int size () const { return heap.size(); } 80 | bool empty () const { return heap.size() == 0; } 81 | bool inHeap (K k) const { return indices.has(k) && indices[k] >= 0; } 82 | int operator[](int index) const { assert(index < heap.size()); return heap[index]; } 83 | 84 | void decrease (K k) { assert(inHeap(k)); percolateUp (indices[k]); } 85 | void increase (K k) { assert(inHeap(k)); percolateDown(indices[k]); } 86 | 87 | 88 | // Safe variant of insert/decrease/increase: 89 | void update(K k) 90 | { 91 | if (!inHeap(k)) 92 | insert(k); 93 | else { 94 | percolateUp(indices[k]); 95 | percolateDown(indices[k]); } 96 | } 97 | 98 | 99 | void insert(K k) 100 | { 101 | indices.reserve(k, -1); 102 | assert(!inHeap(k)); 103 | 104 | indices[k] = heap.size(); 105 | heap.push(k); 106 | percolateUp(indices[k]); 107 | } 108 | 109 | 110 | void remove(K k) 111 | { 112 | assert(inHeap(k)); 113 | 114 | int k_pos = indices[k]; 115 | indices[k] = -1; 116 | 117 | if (k_pos < heap.size()-1){ 118 | heap[k_pos] = heap.last(); 119 | indices[heap[k_pos]] = k_pos; 120 | heap.pop(); 121 | percolateDown(k_pos); 122 | }else 123 | heap.pop(); 124 | } 125 | 126 | 127 | K removeMin() 128 | { 129 | K x = heap[0]; 130 | heap[0] = heap.last(); 131 | indices[heap[0]] = 0; 132 | indices[x] = -1; 133 | heap.pop(); 134 | if (heap.size() > 1) percolateDown(0); 135 | return x; 136 | } 137 | 138 | 139 | // Rebuild the heap from scratch, using the elements in 'ns': 140 | void build(const vec& ns) { 141 | for (int i = 0; i < heap.size(); i++) 142 | indices[heap[i]] = -1; 143 | heap.clear(); 144 | 145 | for (int i = 0; i < ns.size(); i++){ 146 | // TODO: this should probably call reserve instead of relying on it being reserved already. 147 | assert(indices.has(ns[i])); 148 | indices[ns[i]] = i; 149 | heap.push(ns[i]); } 150 | 151 | for (int i = heap.size() / 2 - 1; i >= 0; i--) 152 | percolateDown(i); 153 | } 154 | 155 | void clear(bool dispose = false) 156 | { 157 | // TODO: shouldn't the 'indices' map also be dispose-cleared? 158 | for (int i = 0; i < heap.size(); i++) 159 | indices[heap[i]] = -1; 160 | heap.clear(dispose); 161 | } 162 | }; 163 | 164 | 165 | //================================================================================================= 166 | } 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /minisat/mtl/Vec.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Vec.h] 2 | Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Vec_h 22 | #define Minisat_Vec_h 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "minisat/mtl/IntTypes.h" 29 | #include "minisat/mtl/XAlloc.h" 30 | 31 | namespace Minisat { 32 | 33 | //================================================================================================= 34 | // Automatically resizable arrays 35 | // 36 | // NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) 37 | 38 | template 39 | class vec { 40 | public: 41 | typedef _Size Size; 42 | private: 43 | T* data; 44 | Size sz; 45 | Size cap; 46 | 47 | // Don't allow copying (error prone): 48 | vec& operator=(vec& other); 49 | vec (vec& other); 50 | 51 | static inline Size max(Size x, Size y){ return (x > y) ? x : y; } 52 | 53 | public: 54 | // Constructors: 55 | vec() : data(NULL), sz(0), cap(0) { } 56 | explicit vec(Size size) : data(NULL), sz(0), cap(0) { growTo(size); } 57 | vec(Size size, const T& pad) : data(NULL), sz(0), cap(0) { growTo(size, pad); } 58 | ~vec() { clear(true); } 59 | 60 | // Pointer to first element: 61 | operator T* (void) { return data; } 62 | 63 | // Size operations: 64 | Size size (void) const { return sz; } 65 | void shrink (Size nelems) { assert(nelems <= sz); for (Size i = 0; i < nelems; i++) sz--, data[sz].~T(); } 66 | void shrink_ (Size nelems) { assert(nelems <= sz); sz -= nelems; } 67 | int capacity (void) const { return cap; } 68 | void capacity (Size min_cap); 69 | void growTo (Size size); 70 | void growTo (Size size, const T& pad); 71 | void clear (bool dealloc = false); 72 | 73 | // Stack interface: 74 | void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; } 75 | //void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; } 76 | void push (const T& elem) { if (sz == cap) capacity(sz+1); new (&data[sz++]) T(elem); } 77 | void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; } 78 | void pop (void) { assert(sz > 0); sz--, data[sz].~T(); } 79 | // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but 80 | // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not 81 | // happen given the way capacities are calculated (below). Essentially, all capacities are 82 | // even, but INT_MAX is odd. 83 | 84 | const T& last (void) const { return data[sz-1]; } 85 | T& last (void) { return data[sz-1]; } 86 | 87 | // Vector interface: 88 | const T& operator [] (Size index) const { return data[index]; } 89 | T& operator [] (Size index) { return data[index]; } 90 | 91 | // Duplicatation (preferred instead): 92 | void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (Size i = 0; i < sz; i++) copy[i] = data[i]; } 93 | void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } 94 | }; 95 | 96 | 97 | template 98 | void vec::capacity(Size min_cap) { 99 | if (cap >= min_cap) return; 100 | Size add = max((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 101 | const Size size_max = std::numeric_limits::max(); 102 | if ( ((size_max <= std::numeric_limits::max()) && (add > size_max - cap)) 103 | || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) ) 104 | throw OutOfMemoryException(); 105 | } 106 | 107 | 108 | template 109 | void vec::growTo(Size size, const T& pad) { 110 | if (sz >= size) return; 111 | capacity(size); 112 | for (Size i = sz; i < size; i++) data[i] = pad; 113 | sz = size; } 114 | 115 | 116 | template 117 | void vec::growTo(Size size) { 118 | if (sz >= size) return; 119 | capacity(size); 120 | for (Size i = sz; i < size; i++) new (&data[i]) T(); 121 | sz = size; } 122 | 123 | 124 | template 125 | void vec::clear(bool dealloc) { 126 | if (data != NULL){ 127 | for (Size i = 0; i < sz; i++) data[i].~T(); 128 | sz = 0; 129 | if (dealloc) free(data), data = NULL, cap = 0; } } 130 | 131 | //================================================================================================= 132 | } 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /minisat/core/Main.cc: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Main.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | #include "minisat/utils/System.h" 25 | #include "minisat/utils/ParseUtils.h" 26 | #include "minisat/utils/Options.h" 27 | #include "minisat/core/Dimacs.h" 28 | #include "minisat/core/Solver.h" 29 | 30 | using namespace Minisat; 31 | 32 | //================================================================================================= 33 | 34 | 35 | static Solver* solver; 36 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 37 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 38 | static void SIGINT_interrupt(int) { solver->interrupt(); } 39 | 40 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 41 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 42 | // functions are guarded by locks for multithreaded use). 43 | static void SIGINT_exit(int) { 44 | printf("\n"); printf("*** INTERRUPTED ***\n"); 45 | if (solver->verbosity > 0){ 46 | solver->printStats(); 47 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 48 | _exit(1); } 49 | 50 | 51 | //================================================================================================= 52 | // Main: 53 | 54 | 55 | int main(int argc, char** argv) 56 | { 57 | try { 58 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 59 | setX86FPUPrecision(); 60 | 61 | // Extra options: 62 | // 63 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 64 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", 0, IntRange(0, INT32_MAX)); 65 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", 0, IntRange(0, INT32_MAX)); 66 | BoolOption strictp("MAIN", "strict", "Validate DIMACS header during parsing.", false); 67 | 68 | parseOptions(argc, argv, true); 69 | 70 | Solver S; 71 | double initial_time = cpuTime(); 72 | 73 | S.verbosity = verb; 74 | 75 | solver = &S; 76 | // Use signal handlers that forcibly quit until the solver will be able to respond to 77 | // interrupts: 78 | sigTerm(SIGINT_exit); 79 | 80 | // Try to set resource limits: 81 | if (cpu_lim != 0) limitTime(cpu_lim); 82 | if (mem_lim != 0) limitMemory(mem_lim); 83 | 84 | if (argc == 1) 85 | printf("Reading from standard input... Use '--help' for help.\n"); 86 | 87 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 88 | if (in == NULL) 89 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 90 | 91 | if (S.verbosity > 0){ 92 | printf("============================[ Problem Statistics ]=============================\n"); 93 | printf("| |\n"); } 94 | 95 | parse_DIMACS(in, S, (bool)strictp); 96 | gzclose(in); 97 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 98 | 99 | if (S.verbosity > 0){ 100 | printf("| Number of variables: %12d |\n", S.nVars()); 101 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 102 | 103 | double parsed_time = cpuTime(); 104 | if (S.verbosity > 0){ 105 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 106 | printf("| |\n"); } 107 | 108 | // Change to signal-handlers that will only notify the solver and allow it to terminate 109 | // voluntarily: 110 | sigTerm(SIGINT_interrupt); 111 | 112 | if (!S.simplify()){ 113 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 114 | if (S.verbosity > 0){ 115 | printf("===============================================================================\n"); 116 | printf("Solved by unit propagation\n"); 117 | S.printStats(); 118 | printf("\n"); } 119 | printf("UNSATISFIABLE\n"); 120 | exit(20); 121 | } 122 | 123 | vec dummy; 124 | lbool ret = S.solveLimited(dummy); 125 | if (S.verbosity > 0){ 126 | S.printStats(); 127 | printf("\n"); } 128 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 129 | if (res != NULL){ 130 | if (ret == l_True){ 131 | fprintf(res, "SAT\n"); 132 | for (int i = 0; i < S.nVars(); i++) 133 | if (S.model[i] != l_Undef) 134 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); 135 | fprintf(res, " 0\n"); 136 | }else if (ret == l_False) 137 | fprintf(res, "UNSAT\n"); 138 | else 139 | fprintf(res, "INDET\n"); 140 | fclose(res); 141 | } 142 | 143 | #ifdef NDEBUG 144 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 145 | #else 146 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 147 | #endif 148 | } catch (OutOfMemoryException&){ 149 | printf("===============================================================================\n"); 150 | printf("INDETERMINATE\n"); 151 | exit(0); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /minisat/mtl/Map.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Map.h] 2 | Copyright (c) 2006-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_Map_h 21 | #define Minisat_Map_h 22 | 23 | #include "minisat/mtl/IntTypes.h" 24 | #include "minisat/mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | // Default hash/equals functions 30 | // 31 | 32 | template struct Hash { uint32_t operator()(const K& k) const { return hash(k); } }; 33 | template struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } }; 34 | 35 | template struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } }; 36 | template struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } }; 37 | 38 | static inline uint32_t hash(uint32_t x){ return x; } 39 | static inline uint32_t hash(uint64_t x){ return (uint32_t)x; } 40 | static inline uint32_t hash(int32_t x) { return (uint32_t)x; } 41 | static inline uint32_t hash(int64_t x) { return (uint32_t)x; } 42 | 43 | 44 | //================================================================================================= 45 | // Some primes 46 | // 47 | 48 | static const int nprimes = 25; 49 | static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 }; 50 | 51 | //================================================================================================= 52 | // Hash table implementation of Maps 53 | // 54 | 55 | template, class E = Equal > 56 | class Map { 57 | public: 58 | struct Pair { K key; D data; }; 59 | 60 | private: 61 | H hash; 62 | E equals; 63 | 64 | vec* table; 65 | int cap; 66 | int size; 67 | 68 | // Don't allow copying (error prone): 69 | Map& operator = (Map& other); 70 | Map (Map& other); 71 | 72 | bool checkCap(int new_size) const { return new_size > cap; } 73 | 74 | int32_t index (const K& k) const { return hash(k) % cap; } 75 | void _insert (const K& k, const D& d) { 76 | vec& ps = table[index(k)]; 77 | ps.push(); ps.last().key = k; ps.last().data = d; } 78 | 79 | void rehash () { 80 | const vec* old = table; 81 | 82 | int old_cap = cap; 83 | int newsize = primes[0]; 84 | for (int i = 1; newsize <= cap && i < nprimes; i++) 85 | newsize = primes[i]; 86 | 87 | table = new vec[newsize]; 88 | cap = newsize; 89 | 90 | for (int i = 0; i < old_cap; i++){ 91 | for (int j = 0; j < old[i].size(); j++){ 92 | _insert(old[i][j].key, old[i][j].data); }} 93 | 94 | delete [] old; 95 | 96 | // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize); 97 | } 98 | 99 | 100 | public: 101 | 102 | Map () : table(NULL), cap(0), size(0) {} 103 | Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){} 104 | ~Map () { delete [] table; } 105 | 106 | // PRECONDITION: the key must already exist in the map. 107 | const D& operator [] (const K& k) const 108 | { 109 | assert(size != 0); 110 | const D* res = NULL; 111 | const vec& ps = table[index(k)]; 112 | for (int i = 0; i < ps.size(); i++) 113 | if (equals(ps[i].key, k)) 114 | res = &ps[i].data; 115 | assert(res != NULL); 116 | return *res; 117 | } 118 | 119 | // PRECONDITION: the key must already exist in the map. 120 | D& operator [] (const K& k) 121 | { 122 | assert(size != 0); 123 | D* res = NULL; 124 | vec& ps = table[index(k)]; 125 | for (int i = 0; i < ps.size(); i++) 126 | if (equals(ps[i].key, k)) 127 | res = &ps[i].data; 128 | assert(res != NULL); 129 | return *res; 130 | } 131 | 132 | // PRECONDITION: the key must *NOT* exist in the map. 133 | void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; } 134 | bool peek (const K& k, D& d) const { 135 | if (size == 0) return false; 136 | const vec& ps = table[index(k)]; 137 | for (int i = 0; i < ps.size(); i++) 138 | if (equals(ps[i].key, k)){ 139 | d = ps[i].data; 140 | return true; } 141 | return false; 142 | } 143 | 144 | bool has (const K& k) const { 145 | if (size == 0) return false; 146 | const vec& ps = table[index(k)]; 147 | for (int i = 0; i < ps.size(); i++) 148 | if (equals(ps[i].key, k)) 149 | return true; 150 | return false; 151 | } 152 | 153 | // PRECONDITION: the key must exist in the map. 154 | void remove(const K& k) { 155 | assert(table != NULL); 156 | vec& ps = table[index(k)]; 157 | int j = 0; 158 | for (; j < ps.size() && !equals(ps[j].key, k); j++); 159 | assert(j < ps.size()); 160 | ps[j] = ps.last(); 161 | ps.pop(); 162 | size--; 163 | } 164 | 165 | void clear () { 166 | cap = size = 0; 167 | delete [] table; 168 | table = NULL; 169 | } 170 | 171 | int elems() const { return size; } 172 | int bucket_count() const { return cap; } 173 | 174 | // NOTE: the hash and equality objects are not moved by this method: 175 | void moveTo(Map& other){ 176 | delete [] other.table; 177 | 178 | other.table = table; 179 | other.cap = cap; 180 | other.size = size; 181 | 182 | table = NULL; 183 | size = cap = 0; 184 | } 185 | 186 | // NOTE: given a bit more time, I could make a more C++-style iterator out of this: 187 | const vec& bucket(int i) const { return table[i]; } 188 | }; 189 | 190 | //================================================================================================= 191 | } 192 | 193 | #endif 194 | -------------------------------------------------------------------------------- /minisat/simp/Main.cc: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Main.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | #include "minisat/utils/System.h" 25 | #include "minisat/utils/ParseUtils.h" 26 | #include "minisat/utils/Options.h" 27 | #include "minisat/core/Dimacs.h" 28 | #include "minisat/simp/SimpSolver.h" 29 | 30 | using namespace Minisat; 31 | 32 | //================================================================================================= 33 | 34 | 35 | static Solver* solver; 36 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 37 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 38 | static void SIGINT_interrupt(int) { solver->interrupt(); } 39 | 40 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 41 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 42 | // functions are guarded by locks for multithreaded use). 43 | static void SIGINT_exit(int) { 44 | printf("\n"); printf("*** INTERRUPTED ***\n"); 45 | if (solver->verbosity > 0){ 46 | solver->printStats(); 47 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 48 | _exit(1); } 49 | 50 | 51 | //================================================================================================= 52 | // Main: 53 | 54 | int main(int argc, char** argv) 55 | { 56 | try { 57 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 58 | setX86FPUPrecision(); 59 | 60 | // Extra options: 61 | // 62 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 63 | BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true); 64 | BoolOption solve ("MAIN", "solve", "Completely turn on/off solving after preprocessing.", true); 65 | StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file."); 66 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", 0, IntRange(0, INT32_MAX)); 67 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", 0, IntRange(0, INT32_MAX)); 68 | BoolOption strictp("MAIN", "strict", "Validate DIMACS header during parsing.", false); 69 | 70 | parseOptions(argc, argv, true); 71 | 72 | SimpSolver S; 73 | double initial_time = cpuTime(); 74 | 75 | if (!pre) S.eliminate(true); 76 | 77 | S.verbosity = verb; 78 | 79 | solver = &S; 80 | // Use signal handlers that forcibly quit until the solver will be able to respond to 81 | // interrupts: 82 | sigTerm(SIGINT_exit); 83 | 84 | // Try to set resource limits: 85 | if (cpu_lim != 0) limitTime(cpu_lim); 86 | if (mem_lim != 0) limitMemory(mem_lim); 87 | 88 | if (argc == 1) 89 | printf("Reading from standard input... Use '--help' for help.\n"); 90 | 91 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 92 | if (in == NULL) 93 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 94 | 95 | if (S.verbosity > 0){ 96 | printf("============================[ Problem Statistics ]=============================\n"); 97 | printf("| |\n"); } 98 | 99 | parse_DIMACS(in, S, (bool)strictp); 100 | gzclose(in); 101 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 102 | 103 | if (S.verbosity > 0){ 104 | printf("| Number of variables: %12d |\n", S.nVars()); 105 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 106 | 107 | double parsed_time = cpuTime(); 108 | if (S.verbosity > 0) 109 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 110 | 111 | // Change to signal-handlers that will only notify the solver and allow it to terminate 112 | // voluntarily: 113 | sigTerm(SIGINT_interrupt); 114 | 115 | S.eliminate(true); 116 | double simplified_time = cpuTime(); 117 | if (S.verbosity > 0){ 118 | printf("| Simplification time: %12.2f s |\n", simplified_time - parsed_time); 119 | printf("| |\n"); } 120 | 121 | if (!S.okay()){ 122 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 123 | if (S.verbosity > 0){ 124 | printf("===============================================================================\n"); 125 | printf("Solved by simplification\n"); 126 | S.printStats(); 127 | printf("\n"); } 128 | printf("UNSATISFIABLE\n"); 129 | exit(20); 130 | } 131 | 132 | lbool ret = l_Undef; 133 | 134 | if (solve){ 135 | vec dummy; 136 | ret = S.solveLimited(dummy); 137 | }else if (S.verbosity > 0) 138 | printf("===============================================================================\n"); 139 | 140 | if (dimacs && ret == l_Undef) 141 | S.toDimacs((const char*)dimacs); 142 | 143 | if (S.verbosity > 0){ 144 | S.printStats(); 145 | printf("\n"); } 146 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 147 | if (res != NULL){ 148 | if (ret == l_True){ 149 | fprintf(res, "SAT\n"); 150 | for (int i = 0; i < S.nVars(); i++) 151 | if (S.model[i] != l_Undef) 152 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); 153 | fprintf(res, " 0\n"); 154 | }else if (ret == l_False) 155 | fprintf(res, "UNSAT\n"); 156 | else 157 | fprintf(res, "INDET\n"); 158 | fclose(res); 159 | } 160 | 161 | #ifdef NDEBUG 162 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 163 | #else 164 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 165 | #endif 166 | } catch (OutOfMemoryException&){ 167 | printf("===============================================================================\n"); 168 | printf("INDETERMINATE\n"); 169 | exit(0); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ################################################################################################### 2 | 3 | .PHONY: r d p sh cr cd cp csh lr ld lp lsh config all install install-headers install-lib\ 4 | install-bin clean distclean 5 | all: r lr lsh 6 | 7 | ## Load Previous Configuration #################################################################### 8 | 9 | -include config.mk 10 | 11 | ## Configurable options ########################################################################### 12 | 13 | # Directory to store object files, libraries, executables, and dependencies: 14 | BUILD_DIR ?= build 15 | 16 | # Include debug-symbols in release builds 17 | MINISAT_RELSYM ?= -g 18 | 19 | # Sets of compile flags for different build types 20 | MINISAT_REL ?= -O3 -D NDEBUG 21 | MINISAT_DEB ?= -O0 -D DEBUG 22 | MINISAT_PRF ?= -O3 -D NDEBUG 23 | MINISAT_FPIC ?= -fpic 24 | 25 | # GNU Standard Install Prefix 26 | prefix ?= /usr/local 27 | 28 | ## Write Configuration ########################################################################### 29 | 30 | config: 31 | @( echo 'BUILD_DIR?=$(BUILD_DIR)' ; \ 32 | echo 'MINISAT_RELSYM?=$(MINISAT_RELSYM)' ; \ 33 | echo 'MINISAT_REL?=$(MINISAT_REL)' ; \ 34 | echo 'MINISAT_DEB?=$(MINISAT_DEB)' ; \ 35 | echo 'MINISAT_PRF?=$(MINISAT_PRF)' ; \ 36 | echo 'MINISAT_FPIC?=$(MINISAT_FPIC)' ; \ 37 | echo 'prefix?=$(prefix)' ) > config.mk 38 | 39 | ## Configurable options end ####################################################################### 40 | 41 | INSTALL ?= install 42 | 43 | # GNU Standard Install Variables 44 | exec_prefix ?= $(prefix) 45 | includedir ?= $(prefix)/include 46 | bindir ?= $(exec_prefix)/bin 47 | libdir ?= $(exec_prefix)/lib 48 | datarootdir ?= $(prefix)/share 49 | mandir ?= $(datarootdir)/man 50 | 51 | # Target file names 52 | MINISAT = minisat# Name of MiniSat main executable. 53 | MINISAT_CORE = minisat_core# Name of simplified MiniSat executable (only core solver support). 54 | MINISAT_SLIB = lib$(MINISAT).a# Name of MiniSat static library. 55 | MINISAT_DLIB = lib$(MINISAT).so# Name of MiniSat shared library. 56 | 57 | # Shared Library Version 58 | SOMAJOR=2 59 | SOMINOR=1 60 | SORELEASE?=.0# Declare empty to leave out from library file name. 61 | 62 | MINISAT_CXXFLAGS = -I. -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -Wall -Wno-parentheses -Wextra 63 | MINISAT_LDFLAGS = -Wall -lz 64 | 65 | ECHO=@echo 66 | ifeq ($(VERB),) 67 | VERB=@ 68 | else 69 | VERB= 70 | endif 71 | 72 | SRCS = $(wildcard minisat/core/*.cc) $(wildcard minisat/simp/*.cc) $(wildcard minisat/utils/*.cc) 73 | HDRS = $(wildcard minisat/mtl/*.h) $(wildcard minisat/core/*.h) $(wildcard minisat/simp/*.h) $(wildcard minisat/utils/*.h) 74 | OBJS = $(filter-out %Main.o, $(SRCS:.cc=.o)) 75 | 76 | r: $(BUILD_DIR)/release/bin/$(MINISAT) 77 | d: $(BUILD_DIR)/debug/bin/$(MINISAT) 78 | p: $(BUILD_DIR)/profile/bin/$(MINISAT) 79 | sh: $(BUILD_DIR)/dynamic/bin/$(MINISAT) 80 | 81 | cr: $(BUILD_DIR)/release/bin/$(MINISAT_CORE) 82 | cd: $(BUILD_DIR)/debug/bin/$(MINISAT_CORE) 83 | cp: $(BUILD_DIR)/profile/bin/$(MINISAT_CORE) 84 | csh: $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE) 85 | 86 | lr: $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 87 | ld: $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 88 | lp: $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 89 | lsh: $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) 90 | 91 | ## Build-type Compile-flags: 92 | $(BUILD_DIR)/release/%.o: MINISAT_CXXFLAGS +=$(MINISAT_REL) $(MINISAT_RELSYM) 93 | $(BUILD_DIR)/debug/%.o: MINISAT_CXXFLAGS +=$(MINISAT_DEB) -g 94 | $(BUILD_DIR)/profile/%.o: MINISAT_CXXFLAGS +=$(MINISAT_PRF) -pg 95 | $(BUILD_DIR)/dynamic/%.o: MINISAT_CXXFLAGS +=$(MINISAT_REL) $(MINISAT_FPIC) 96 | 97 | ## Build-type Link-flags: 98 | $(BUILD_DIR)/profile/bin/$(MINISAT): MINISAT_LDFLAGS += -pg 99 | $(BUILD_DIR)/release/bin/$(MINISAT): MINISAT_LDFLAGS += --static $(MINISAT_RELSYM) 100 | $(BUILD_DIR)/profile/bin/$(MINISAT_CORE): MINISAT_LDFLAGS += -pg 101 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE): MINISAT_LDFLAGS += --static $(MINISAT_RELSYM) 102 | 103 | ## Executable dependencies 104 | $(BUILD_DIR)/release/bin/$(MINISAT): $(BUILD_DIR)/release/minisat/simp/Main.o $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 105 | $(BUILD_DIR)/debug/bin/$(MINISAT): $(BUILD_DIR)/debug/minisat/simp/Main.o $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 106 | $(BUILD_DIR)/profile/bin/$(MINISAT): $(BUILD_DIR)/profile/minisat/simp/Main.o $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 107 | # need the main-file be compiled with fpic? 108 | $(BUILD_DIR)/dynamic/bin/$(MINISAT): $(BUILD_DIR)/dynamic/minisat/simp/Main.o $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 109 | 110 | ## Executable dependencies (core-version) 111 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE): $(BUILD_DIR)/release/minisat/core/Main.o $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 112 | $(BUILD_DIR)/debug/bin/$(MINISAT_CORE): $(BUILD_DIR)/debug/minisat/core/Main.o $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 113 | $(BUILD_DIR)/profile/bin/$(MINISAT_CORE): $(BUILD_DIR)/profile/minisat/core/Main.o $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 114 | # need the main-file be compiled with fpic? 115 | $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE): $(BUILD_DIR)/dynamic/minisat/core/Main.o $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 116 | 117 | ## Library dependencies 118 | $(BUILD_DIR)/release/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/release/$(o)) 119 | $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/debug/$(o)) 120 | $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/profile/$(o)) 121 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 122 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 123 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/dynamic/$(o)) 124 | 125 | ## Compile rules (these should be unified, buit I have not yet found a way which works in GNU Make) 126 | $(BUILD_DIR)/release/%.o: %.cc 127 | $(ECHO) Compiling: $@ 128 | $(VERB) mkdir -p $(dir $@) 129 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/release/$*.d 130 | 131 | $(BUILD_DIR)/profile/%.o: %.cc 132 | $(ECHO) Compiling: $@ 133 | $(VERB) mkdir -p $(dir $@) 134 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/profile/$*.d 135 | 136 | $(BUILD_DIR)/debug/%.o: %.cc 137 | $(ECHO) Compiling: $@ 138 | $(VERB) mkdir -p $(dir $@) 139 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/debug/$*.d 140 | 141 | $(BUILD_DIR)/dynamic/%.o: %.cc 142 | $(ECHO) Compiling: $@ 143 | $(VERB) mkdir -p $(dir $@) 144 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/dynamic/$*.d 145 | 146 | ## Linking rule 147 | $(BUILD_DIR)/release/bin/$(MINISAT) $(BUILD_DIR)/debug/bin/$(MINISAT) $(BUILD_DIR)/profile/bin/$(MINISAT) $(BUILD_DIR)/dynamic/bin/$(MINISAT)\ 148 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE) $(BUILD_DIR)/debug/bin/$(MINISAT_CORE) $(BUILD_DIR)/profile/bin/$(MINISAT_CORE) $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE): 149 | $(ECHO) Linking Binary: $@ 150 | $(VERB) mkdir -p $(dir $@) 151 | $(VERB) $(CXX) $^ $(MINISAT_LDFLAGS) $(LDFLAGS) -o $@ 152 | 153 | ## Static Library rule 154 | %/lib/$(MINISAT_SLIB): 155 | $(ECHO) Linking Static Library: $@ 156 | $(VERB) mkdir -p $(dir $@) 157 | $(VERB) $(AR) -rcs $@ $^ 158 | 159 | ## Shared Library rule 160 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 161 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 162 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB): 163 | $(ECHO) Linking Shared Library: $@ 164 | $(VERB) mkdir -p $(dir $@) 165 | $(VERB) $(CXX) $(MINISAT_LDFLAGS) $(LDFLAGS) -o $@ -shared -Wl,-soname,$(MINISAT_DLIB).$(SOMAJOR) $^ 166 | $(VERB) ln -sf $(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR) 167 | $(VERB) ln -sf $(MINISAT_DLIB).$(SOMAJOR) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 168 | 169 | install: install-headers install-lib install-bin 170 | install-debug: install-headers install-lib-debug 171 | 172 | install-headers: 173 | # Create directories 174 | $(INSTALL) -d $(DESTDIR)$(includedir)/minisat 175 | for dir in mtl utils core simp; do \ 176 | $(INSTALL) -d $(DESTDIR)$(includedir)/minisat/$$dir ; \ 177 | done 178 | # Install headers 179 | for h in $(HDRS) ; do \ 180 | $(INSTALL) -m 644 $$h $(DESTDIR)$(includedir)/$$h ; \ 181 | done 182 | 183 | install-lib-debug: $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 184 | $(INSTALL) -d $(DESTDIR)$(libdir) 185 | $(INSTALL) -m 644 $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) $(DESTDIR)$(libdir) 186 | 187 | install-lib: $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) 188 | $(INSTALL) -d $(DESTDIR)$(libdir) 189 | $(INSTALL) -m 644 $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(DESTDIR)$(libdir) 190 | ln -sf $(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(DESTDIR)$(libdir)/$(MINISAT_DLIB).$(SOMAJOR) 191 | ln -sf $(MINISAT_DLIB).$(SOMAJOR) $(DESTDIR)$(libdir)/$(MINISAT_DLIB) 192 | $(INSTALL) -m 644 $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) $(DESTDIR)$(libdir) 193 | 194 | install-bin: $(BUILD_DIR)/dynamic/bin/$(MINISAT) 195 | $(INSTALL) -d $(DESTDIR)$(bindir) 196 | $(INSTALL) -m 755 $(BUILD_DIR)/dynamic/bin/$(MINISAT) $(DESTDIR)$(bindir) 197 | 198 | clean: 199 | rm -f $(foreach t, release debug profile dynamic, $(foreach o, $(SRCS:.cc=.o), $(BUILD_DIR)/$t/$o)) \ 200 | $(foreach t, release debug profile dynamic, $(foreach d, $(SRCS:.cc=.d), $(BUILD_DIR)/$t/$d)) \ 201 | $(foreach t, release debug profile dynamic, $(BUILD_DIR)/$t/bin/$(MINISAT_CORE) $(BUILD_DIR)/$t/bin/$(MINISAT)) \ 202 | $(foreach t, release debug profile, $(BUILD_DIR)/$t/lib/$(MINISAT_SLIB)) \ 203 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 204 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 205 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 206 | 207 | distclean: clean 208 | rm -f config.mk 209 | 210 | ## Include generated dependencies 211 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/release/$s) 212 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/debug/$s) 213 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/profile/$s) 214 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/dynamic/$s) 215 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6 FATAL_ERROR) 2 | 3 | project(minisat) 4 | 5 | #-------------------------------------------------------------------------------------------------- 6 | # Configurable options: 7 | 8 | option(STATIC_BINARIES "Link binaries statically." ON) 9 | option(USE_SORELEASE "Use SORELEASE in shared library filename." ON) 10 | 11 | #-------------------------------------------------------------------------------------------------- 12 | # Library version: 13 | 14 | set(MINISAT_SOMAJOR 2) 15 | set(MINISAT_SOMINOR 1) 16 | set(MINISAT_SORELEASE 0) 17 | 18 | # Compute VERSION and SOVERSION: 19 | if (USE_SORELEASE) 20 | set(MINISAT_VERSION ${MINISAT_SOMAJOR}.${MINISAT_SOMINOR}.${MINISAT_SORELEASE}) 21 | else() 22 | set(MINISAT_VERSION ${MINISAT_SOMAJOR}.${MINISAT_SOMINOR}) 23 | endif() 24 | set(MINISAT_SOVERSION ${MINISAT_SOMAJOR}) 25 | 26 | # Reference specific library paths used during linking for install 27 | if (POLICY CMP0042) 28 | # Enable `MACOSX_RPATH` by default. 29 | cmake_policy(SET CMP0042 NEW) 30 | endif() 31 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 32 | 33 | #-------------------------------------------------------------------------------------------------- 34 | # Dependencies: 35 | 36 | find_package(ZLIB) 37 | include_directories(${ZLIB_INCLUDE_DIR}) 38 | include_directories(${minisat_SOURCE_DIR}) 39 | include (GenerateExportHeader) 40 | 41 | #-------------------------------------------------------------------------------------------------- 42 | # Compile flags: 43 | 44 | add_definitions(-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS) 45 | 46 | 47 | #-------------------------------------------------------------------------------------------------- 48 | option(STATICCOMPILE "Compile static library and executable" OFF) 49 | 50 | option(BUILD_SHARED_LIBS "Build the shared library" ON) 51 | if (STATICCOMPILE) 52 | set(BUILD_SHARED_LIBS OFF) 53 | endif() 54 | 55 | if (NOT BUILD_SHARED_LIBS) 56 | if (NOT MSVC) 57 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -static ") 58 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 59 | 60 | # removing -rdynamic that's automatically added 61 | foreach (language CXX C) 62 | set(VAR_TO_MODIFY "CMAKE_SHARED_LIBRARY_LINK_${language}_FLAGS") 63 | string(REGEX REPLACE "(^| )-rdynamic($| )" 64 | " " 65 | replacement 66 | "${${VAR_TO_MODIFY}}") 67 | #message("Original (${VAR_TO_MODIFY}) is ${${VAR_TO_MODIFY}} replacement is ${replacement}") 68 | set(${VAR_TO_MODIFY} "${replacement}" CACHE STRING "Default flags for ${build_config} configuration" FORCE) 69 | endforeach() 70 | endif() 71 | else () 72 | # use, i.e. don't skip the full RPATH for the build tree 73 | SET(CMAKE_SKIP_BUILD_RPATH FALSE) 74 | 75 | # when building, don't use the install RPATH already 76 | # (but later on when installing) 77 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 78 | 79 | SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}") 80 | 81 | # add the automatically determined parts of the RPATH 82 | # which point to directories outside the build tree to the install RPATH 83 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 84 | 85 | # the RPATH to be used when installing, but only if it's not a system directory 86 | LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_LIBDIR}" isSystemDir) 87 | IF("${isSystemDir}" STREQUAL "-1") 88 | SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}") 89 | ENDIF("${isSystemDir}" STREQUAL "-1") 90 | 91 | if (APPLE) 92 | set(CMAKE_MACOSX_RPATH ON) 93 | set(CMAKE_INSTALL_RPATH "@loader_path/../lib") 94 | message(STATUS "Using RPATH for dynamic linking") 95 | endif() 96 | endif() 97 | 98 | if (NOT MSVC) 99 | add_compile_options( -g) 100 | add_compile_options( -pthread ) 101 | 102 | add_compile_options("$<$:-O2>") 103 | 104 | add_compile_options("$<$:-O2>") 105 | add_compile_options("$<$:-g0>") 106 | 107 | add_compile_options("$<$:-O0>") 108 | 109 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 110 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2") 111 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O2") 112 | endif() 113 | else() 114 | # see https://msdn.microsoft.com/en-us/library/fwkeyyhe.aspx for details 115 | # /ZI = include debug info 116 | # /Wall = all warnings 117 | 118 | add_compile_options("$<$:/O2>") 119 | add_compile_options("$<$:/ZI>") 120 | 121 | add_compile_options("$<$:/O2>") 122 | add_compile_options("$<$:/D>") 123 | add_compile_options("$<$:/NDEBUG>") 124 | 125 | add_compile_options("$<$:/Od>") 126 | 127 | if (NOT BUILD_SHARED_LIBS) 128 | # We statically link to reduce dependencies 129 | foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 130 | # /MD -- Causes the application to use the multithread-specific 131 | # and DLL-specific version of the run-time library. 132 | # Defines _MT and _DLL and causes the compiler to place 133 | # the library name MSVCRT.lib into the .obj file. 134 | if(${flag_var} MATCHES "/MD") 135 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 136 | endif(${flag_var} MATCHES "/MD") 137 | 138 | # /MDd -- Defines _DEBUG, _MT, and _DLL and causes the application to use the debug multithread-specific and DLL-specific version of the run-time library. 139 | # It also causes the compiler to place the library name MSVCRTD.lib into the .obj file. 140 | if(${flag_var} MATCHES "/MDd") 141 | string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") 142 | endif(${flag_var} MATCHES "/MDd") 143 | endforeach(flag_var) 144 | 145 | # Creates a multithreaded executable (static) file using LIBCMT.lib. 146 | add_compile_options(/MT) 147 | endif() 148 | 149 | # buffers security check 150 | add_compile_options(/GS) 151 | 152 | # Proper warning level 153 | add_compile_options(/W1) 154 | 155 | # Disable STL used in DLL-boundary warning 156 | add_compile_options(/wd4251) 157 | add_compile_options(/D_CRT_SECURE_NO_WARNINGS) 158 | 159 | # Wall is MSVC's Weverything, so annoying unless used from the start 160 | # and with judiciously used warning disables 161 | # add_compile_options(/Wall) 162 | 163 | # /Za = only ansi C98 & C++11 164 | # /Za is not recommended for use, not tested, etc. 165 | # see: http://stackoverflow.com/questions/5489326/za-compiler-directive-does-not-compile-system-headers-in-vs2010 166 | # add_compile_options(/Za) 167 | 168 | add_compile_options(/fp:precise) 169 | 170 | # exception handling. s = The exception-handling model that catches C++ exceptions only and tells the compiler to assume that functions declared as extern "C" may throw an exception. 171 | # exception handling. c = If used with s (/EHsc), catches C++ exceptions only and tells the compiler to assume that functions declared as extern "C" never throw a C++ exception. 172 | add_compile_options(/EHsc) 173 | 174 | #what does this do? 175 | set(DEF_INSTALL_CMAKE_DIR CMake) 176 | endif() 177 | set(MINISAT_EXPORT_NAME "minisatTargets") 178 | 179 | # ----------------------------------------------------------------------------- 180 | # Add uninstall target for makefiles 181 | # ----------------------------------------------------------------------------- 182 | configure_file( 183 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" 184 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" 185 | IMMEDIATE @ONLY 186 | ) 187 | 188 | add_custom_target(uninstall 189 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 190 | ) 191 | 192 | 193 | #-------------------------------------------------------------------------------------------------- 194 | # Build Targets: 195 | 196 | set(MINISAT_LIB_SOURCES 197 | minisat/utils/Options.cc 198 | minisat/utils/System.cc 199 | minisat/core/Solver.cc 200 | minisat/simp/SimpSolver.cc) 201 | 202 | add_library(minisat ${MINISAT_LIB_SOURCES}) 203 | target_link_libraries(minisat ${ZLIB_LIBRARY}) 204 | 205 | add_executable(minisat_core minisat/core/Main.cc) 206 | add_executable(minisat_simp minisat/simp/Main.cc) 207 | 208 | 209 | target_link_libraries(minisat_core minisat) 210 | target_link_libraries(minisat_simp minisat) 211 | 212 | set_target_properties(minisat 213 | PROPERTIES 214 | OUTPUT_NAME "minisat" 215 | VERSION ${MINISAT_VERSION} 216 | SOVERSION ${MINISAT_SOVERSION}) 217 | 218 | set_target_properties(minisat_simp PROPERTIES OUTPUT_NAME "minisat") 219 | 220 | #-------------------------------------------------------------------------------------------------- 221 | # Installation targets: 222 | 223 | install(TARGETS minisat minisat_core minisat_simp 224 | EXPORT ${MINISAT_EXPORT_NAME} 225 | RUNTIME DESTINATION bin 226 | LIBRARY DESTINATION lib 227 | ARCHIVE DESTINATION lib) 228 | 229 | install(DIRECTORY minisat/mtl minisat/utils minisat/core minisat/simp 230 | DESTINATION include/minisat 231 | FILES_MATCHING PATTERN "*.h") 232 | 233 | # Setup for export 234 | set(MINISAT_TARGETS_FILENAME "minisatTargets.cmake") 235 | set(MINISAT_CONFIG_FILENAME "minisatConfig.cmake") 236 | 237 | # Export targets 238 | export( 239 | TARGETS minisat 240 | FILE "${CMAKE_CURRENT_BINARY_DIR}/${MINISAT_TARGETS_FILENAME}" 241 | ) 242 | 243 | # Create minisatConfig file 244 | set(EXPORT_TYPE "Build-tree") 245 | set(CONF_INCLUDE_DIRS "${minisat_SOURCE_DIR}/") 246 | configure_file(minisatConfig.cmake.in 247 | "${CMAKE_CURRENT_BINARY_DIR}/${MINISAT_CONFIG_FILENAME}" @ONLY 248 | ) 249 | 250 | # Export this package to the CMake user package registry 251 | # Now the user can just use find_package(minisat) on their system 252 | export(PACKAGE minisat) 253 | 254 | set(DEF_INSTALL_CMAKE_DIR lib/cmake/minisat) 255 | set(MINISAT_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH 256 | "Installation directory for minisat CMake files") 257 | 258 | # Create minisatConfig file 259 | set(EXPORT_TYPE "installed") 260 | configure_file(minisatConfig.cmake.in 261 | "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/${MINISAT_CONFIG_FILENAME}" @ONLY 262 | ) 263 | 264 | install(FILES 265 | "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/${MINISAT_CONFIG_FILENAME}" 266 | DESTINATION "${MINISAT_INSTALL_CMAKE_DIR}" 267 | ) 268 | 269 | # Install the export set for use with the install-tree 270 | install( 271 | EXPORT ${MINISAT_EXPORT_NAME} 272 | DESTINATION "${MINISAT_INSTALL_CMAKE_DIR}" 273 | ) 274 | -------------------------------------------------------------------------------- /minisat/simp/SimpSolver.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************[SimpSolver.h] 2 | Copyright (c) 2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_SimpSolver_h 22 | #define Minisat_SimpSolver_h 23 | 24 | #include "minisat/mtl/Queue.h" 25 | #include "minisat/core/Solver.h" 26 | 27 | 28 | namespace Minisat { 29 | 30 | //================================================================================================= 31 | 32 | 33 | class SimpSolver : public Solver { 34 | public: 35 | // Constructor/Destructor: 36 | // 37 | SimpSolver(); 38 | ~SimpSolver(); 39 | 40 | // Problem specification: 41 | // 42 | Var newVar (lbool upol = l_Undef, bool dvar = true); 43 | void releaseVar(Lit l); 44 | bool addClause (const vec& ps); 45 | bool addEmptyClause(); // Add the empty clause to the solver. 46 | bool addClause (Lit p); // Add a unit clause to the solver. 47 | bool addClause (Lit p, Lit q); // Add a binary clause to the solver. 48 | bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. 49 | bool addClause (Lit p, Lit q, Lit r, Lit s); // Add a quaternary clause to the solver. 50 | bool addClause_( vec& ps); 51 | bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction). 52 | 53 | // Variable mode: 54 | // 55 | void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated. 56 | bool isEliminated(Var v) const; 57 | 58 | // Alternative freeze interface (may replace 'setFrozen()'): 59 | void freezeVar (Var v); // Freeze one variable so it will not be eliminated. 60 | void thaw (); // Thaw all frozen variables. 61 | 62 | 63 | // Solving: 64 | // 65 | bool solve (const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 66 | lbool solveLimited(const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 67 | bool solve ( bool do_simp = true, bool turn_off_simp = false); 68 | bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false); 69 | bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false); 70 | bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false); 71 | bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification. 72 | 73 | // Memory managment: 74 | // 75 | virtual void garbageCollect(); 76 | 77 | 78 | // Generate a (possibly simplified) DIMACS file: 79 | // 80 | #if 0 81 | void toDimacs (const char* file, const vec& assumps); 82 | void toDimacs (const char* file); 83 | void toDimacs (const char* file, Lit p); 84 | void toDimacs (const char* file, Lit p, Lit q); 85 | void toDimacs (const char* file, Lit p, Lit q, Lit r); 86 | #endif 87 | 88 | // Mode of operation: 89 | // 90 | int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero). 91 | int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit. 92 | // -1 means no limit. 93 | int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit. 94 | double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac'). 95 | 96 | bool use_asymm; // Shrink clauses by asymmetric branching. 97 | bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :) 98 | bool use_elim; // Perform variable elimination. 99 | bool extend_model; // Flag to indicate whether the user needs to look at the full model. 100 | 101 | // Statistics: 102 | // 103 | int merges; 104 | int asymm_lits; 105 | int eliminated_vars; 106 | 107 | protected: 108 | 109 | // Helper structures: 110 | // 111 | struct ElimLt { 112 | const LMap& n_occ; 113 | explicit ElimLt(const LMap& no) : n_occ(no) {} 114 | 115 | // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating 116 | // 32-bit implementation instead then, but this will have to do for now. 117 | uint64_t cost (Var x) const { return (uint64_t)n_occ[mkLit(x)] * (uint64_t)n_occ[~mkLit(x)]; } 118 | bool operator()(Var x, Var y) const { return cost(x) < cost(y); } 119 | 120 | // TODO: investigate this order alternative more. 121 | // bool operator()(Var x, Var y) const { 122 | // int c_x = cost(x); 123 | // int c_y = cost(y); 124 | // return c_x < c_y || c_x == c_y && x < y; } 125 | }; 126 | 127 | struct ClauseDeleted { 128 | const ClauseAllocator& ca; 129 | explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {} 130 | bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } }; 131 | 132 | // Solver state: 133 | // 134 | int elimorder; 135 | bool use_simplification; 136 | Var max_simp_var; // Max variable at the point simplification was turned off. 137 | vec elimclauses; 138 | VMap touched; 139 | OccLists, ClauseDeleted> 140 | occurs; 141 | LMap n_occ; 142 | Heap elim_heap; 143 | Queue subsumption_queue; 144 | VMap frozen; 145 | vec frozen_vars; 146 | VMap eliminated; 147 | int bwdsub_assigns; 148 | int n_touched; 149 | 150 | // Temporaries: 151 | // 152 | CRef bwdsub_tmpunit; 153 | 154 | // Main internal methods: 155 | // 156 | lbool solve_ (bool do_simp = true, bool turn_off_simp = false); 157 | bool asymm (Var v, CRef cr); 158 | bool asymmVar (Var v); 159 | void updateElimHeap (Var v); 160 | void gatherTouchedClauses (); 161 | bool merge (const Clause& _ps, const Clause& _qs, Var v, vec& out_clause); 162 | bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size); 163 | bool backwardSubsumptionCheck (bool verbose = false); 164 | bool eliminateVar (Var v); 165 | void extendModel (); 166 | 167 | void removeClause (CRef cr); 168 | bool strengthenClause (CRef cr, Lit l); 169 | bool implied (const vec& c); 170 | void relocAll (ClauseAllocator& to); 171 | }; 172 | 173 | 174 | //================================================================================================= 175 | // Implementation of inline methods: 176 | 177 | 178 | inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; } 179 | inline void SimpSolver::updateElimHeap(Var v) { 180 | assert(use_simplification); 181 | // if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef) 182 | if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)) 183 | elim_heap.update(v); } 184 | 185 | 186 | inline bool SimpSolver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } 187 | inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); } 188 | inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } 189 | inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } 190 | inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } 191 | inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, Lit s){ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); add_tmp.push(s); return addClause_(add_tmp); } 192 | inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } } 193 | 194 | inline void SimpSolver::freezeVar(Var v){ 195 | if (!frozen[v]){ 196 | frozen[v] = 1; 197 | frozen_vars.push(v); 198 | } } 199 | 200 | inline void SimpSolver::thaw(){ 201 | for (int i = 0; i < frozen_vars.size(); i++){ 202 | Var v = frozen_vars[i]; 203 | frozen[v] = 0; 204 | if (use_simplification) 205 | updateElimHeap(v); 206 | } 207 | frozen_vars.clear(); } 208 | 209 | inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; } 210 | inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; } 211 | inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; } 212 | inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; } 213 | inline bool SimpSolver::solve (const vec& assumps, bool do_simp, bool turn_off_simp){ 214 | budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; } 215 | 216 | inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bool turn_off_simp){ 217 | assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); } 218 | 219 | //================================================================================================= 220 | } 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /minisat/utils/Options.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************[Options.h] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_Options_h 21 | #define Minisat_Options_h 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "minisat/mtl/IntTypes.h" 29 | #include "minisat/mtl/Vec.h" 30 | #include "minisat/utils/ParseUtils.h" 31 | 32 | namespace Minisat { 33 | 34 | //================================================================================================== 35 | // Top-level option parse/help functions: 36 | 37 | 38 | extern void parseOptions (int& argc, char** argv, bool strict = false); 39 | extern void printUsageAndExit(int argc, char** argv, bool verbose = false); 40 | extern void setUsageHelp (const char* str); 41 | extern void setHelpPrefixStr (const char* str); 42 | 43 | 44 | //================================================================================================== 45 | // Options is an abstract class that gives the interface for all types options: 46 | 47 | 48 | class Option 49 | { 50 | protected: 51 | const char* name; 52 | const char* description; 53 | const char* category; 54 | const char* type_name; 55 | 56 | static vec& getOptionList () { static vec options; return options; } 57 | static const char*& getUsageString() { static const char* usage_str; return usage_str; } 58 | static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } 59 | 60 | struct OptionLt { 61 | bool operator()(const Option* x, const Option* y) { 62 | int test1 = strcmp(x->category, y->category); 63 | return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); 64 | } 65 | }; 66 | 67 | Option(const char* name_, 68 | const char* desc_, 69 | const char* cate_, 70 | const char* type_) : 71 | name (name_) 72 | , description(desc_) 73 | , category (cate_) 74 | , type_name (type_) 75 | { 76 | getOptionList().push(this); 77 | } 78 | 79 | public: 80 | virtual ~Option() {} 81 | 82 | virtual bool parse (const char* str) = 0; 83 | virtual void help (bool verbose = false) = 0; 84 | 85 | friend void parseOptions (int& argc, char** argv, bool strict); 86 | friend void printUsageAndExit (int argc, char** argv, bool verbose); 87 | friend void setUsageHelp (const char* str); 88 | friend void setHelpPrefixStr (const char* str); 89 | }; 90 | 91 | 92 | //================================================================================================== 93 | // Range classes with specialization for floating types: 94 | 95 | 96 | struct IntRange { 97 | int begin; 98 | int end; 99 | IntRange(int b, int e) : begin(b), end(e) {} 100 | }; 101 | 102 | struct Int64Range { 103 | int64_t begin; 104 | int64_t end; 105 | Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} 106 | }; 107 | 108 | struct DoubleRange { 109 | double begin; 110 | double end; 111 | bool begin_inclusive; 112 | bool end_inclusive; 113 | DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} 114 | }; 115 | 116 | 117 | //================================================================================================== 118 | // Double options: 119 | 120 | 121 | class DoubleOption : public Option 122 | { 123 | protected: 124 | DoubleRange range; 125 | double value; 126 | 127 | public: 128 | DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) 129 | : Option(n, d, c, ""), range(r), value(def) { 130 | // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. 131 | } 132 | 133 | operator double (void) const { return value; } 134 | operator double& (void) { return value; } 135 | DoubleOption& operator=(double x) { value = x; return *this; } 136 | 137 | virtual bool parse(const char* str){ 138 | const char* span = str; 139 | 140 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 141 | return false; 142 | 143 | char* end; 144 | double tmp = strtod(span, &end); 145 | 146 | if (end == NULL) 147 | return false; 148 | else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ 149 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 150 | exit(1); 151 | }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ 152 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 153 | exit(1); } 154 | 155 | value = tmp; 156 | // fprintf(stderr, "READ VALUE: %g\n", value); 157 | 158 | return true; 159 | } 160 | 161 | virtual void help (bool verbose = false){ 162 | fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", 163 | name, type_name, 164 | range.begin_inclusive ? '[' : '(', 165 | range.begin, 166 | range.end, 167 | range.end_inclusive ? ']' : ')', 168 | value); 169 | if (verbose){ 170 | fprintf(stderr, "\n %s\n", description); 171 | fprintf(stderr, "\n"); 172 | } 173 | } 174 | }; 175 | 176 | 177 | //================================================================================================== 178 | // Int options: 179 | 180 | 181 | class IntOption : public Option 182 | { 183 | protected: 184 | IntRange range; 185 | int32_t value; 186 | 187 | public: 188 | IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) 189 | : Option(n, d, c, ""), range(r), value(def) {} 190 | 191 | operator int32_t (void) const { return value; } 192 | operator int32_t& (void) { return value; } 193 | IntOption& operator= (int32_t x) { value = x; return *this; } 194 | 195 | virtual bool parse(const char* str){ 196 | const char* span = str; 197 | 198 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 199 | return false; 200 | 201 | char* end; 202 | int32_t tmp = strtol(span, &end, 10); 203 | 204 | if (end == NULL) 205 | return false; 206 | else if (tmp > range.end){ 207 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 208 | exit(1); 209 | }else if (tmp < range.begin){ 210 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 211 | exit(1); } 212 | 213 | value = tmp; 214 | 215 | return true; 216 | } 217 | 218 | virtual void help (bool verbose = false){ 219 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 220 | if (range.begin == INT32_MIN) 221 | fprintf(stderr, "imin"); 222 | else 223 | fprintf(stderr, "%4d", range.begin); 224 | 225 | fprintf(stderr, " .. "); 226 | if (range.end == INT32_MAX) 227 | fprintf(stderr, "imax"); 228 | else 229 | fprintf(stderr, "%4d", range.end); 230 | 231 | fprintf(stderr, "] (default: %d)\n", value); 232 | if (verbose){ 233 | fprintf(stderr, "\n %s\n", description); 234 | fprintf(stderr, "\n"); 235 | } 236 | } 237 | }; 238 | 239 | 240 | // Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. 241 | #ifndef _MSC_VER 242 | 243 | class Int64Option : public Option 244 | { 245 | protected: 246 | Int64Range range; 247 | int64_t value; 248 | 249 | public: 250 | Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) 251 | : Option(n, d, c, ""), range(r), value(def) {} 252 | 253 | operator int64_t (void) const { return value; } 254 | operator int64_t& (void) { return value; } 255 | Int64Option& operator= (int64_t x) { value = x; return *this; } 256 | 257 | virtual bool parse(const char* str){ 258 | const char* span = str; 259 | 260 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 261 | return false; 262 | 263 | char* end; 264 | int64_t tmp = strtoll(span, &end, 10); 265 | 266 | if (end == NULL) 267 | return false; 268 | else if (tmp > range.end){ 269 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 270 | exit(1); 271 | }else if (tmp < range.begin){ 272 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 273 | exit(1); } 274 | 275 | value = tmp; 276 | 277 | return true; 278 | } 279 | 280 | virtual void help (bool verbose = false){ 281 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 282 | if (range.begin == INT64_MIN) 283 | fprintf(stderr, "imin"); 284 | else 285 | fprintf(stderr, "%4" PRIi64, range.begin); 286 | 287 | fprintf(stderr, " .. "); 288 | if (range.end == INT64_MAX) 289 | fprintf(stderr, "imax"); 290 | else 291 | fprintf(stderr, "%4" PRIi64, range.end); 292 | 293 | fprintf(stderr, "] (default: %" PRIi64 ")\n", value); 294 | if (verbose){ 295 | fprintf(stderr, "\n %s\n", description); 296 | fprintf(stderr, "\n"); 297 | } 298 | } 299 | }; 300 | #endif 301 | 302 | //================================================================================================== 303 | // String option: 304 | 305 | 306 | class StringOption : public Option 307 | { 308 | const char* value; 309 | public: 310 | StringOption(const char* c, const char* n, const char* d, const char* def = NULL) 311 | : Option(n, d, c, ""), value(def) {} 312 | 313 | operator const char* (void) const { return value; } 314 | operator const char*& (void) { return value; } 315 | StringOption& operator= (const char* x) { value = x; return *this; } 316 | 317 | virtual bool parse(const char* str){ 318 | const char* span = str; 319 | 320 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 321 | return false; 322 | 323 | value = span; 324 | return true; 325 | } 326 | 327 | virtual void help (bool verbose = false){ 328 | fprintf(stderr, " -%-10s = %8s\n", name, type_name); 329 | if (verbose){ 330 | fprintf(stderr, "\n %s\n", description); 331 | fprintf(stderr, "\n"); 332 | } 333 | } 334 | }; 335 | 336 | 337 | //================================================================================================== 338 | // Bool option: 339 | 340 | 341 | class BoolOption : public Option 342 | { 343 | bool value; 344 | 345 | public: 346 | BoolOption(const char* c, const char* n, const char* d, bool v) 347 | : Option(n, d, c, ""), value(v) {} 348 | 349 | operator bool (void) const { return value; } 350 | operator bool& (void) { return value; } 351 | BoolOption& operator=(bool b) { value = b; return *this; } 352 | 353 | virtual bool parse(const char* str){ 354 | const char* span = str; 355 | 356 | if (match(span, "-")){ 357 | bool b = !match(span, "no-"); 358 | 359 | if (strcmp(span, name) == 0){ 360 | value = b; 361 | return true; } 362 | } 363 | 364 | return false; 365 | } 366 | 367 | virtual void help (bool verbose = false){ 368 | 369 | fprintf(stderr, " -%s, -no-%s", name, name); 370 | 371 | for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) 372 | fprintf(stderr, " "); 373 | 374 | fprintf(stderr, " "); 375 | fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); 376 | if (verbose){ 377 | fprintf(stderr, "\n %s\n", description); 378 | fprintf(stderr, "\n"); 379 | } 380 | } 381 | }; 382 | 383 | //================================================================================================= 384 | } 385 | 386 | #endif 387 | -------------------------------------------------------------------------------- /minisat/core/SolverTypes.h: -------------------------------------------------------------------------------- 1 | /***********************************************************************************[SolverTypes.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | 22 | #ifndef Minisat_SolverTypes_h 23 | #define Minisat_SolverTypes_h 24 | 25 | #include 26 | 27 | #include "minisat/mtl/IntTypes.h" 28 | #include "minisat/mtl/Alg.h" 29 | #include "minisat/mtl/Vec.h" 30 | #include "minisat/mtl/IntMap.h" 31 | #include "minisat/mtl/Map.h" 32 | #include "minisat/mtl/Alloc.h" 33 | 34 | namespace Minisat { 35 | 36 | //================================================================================================= 37 | // Variables, literals, lifted booleans, clauses: 38 | 39 | 40 | // NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, 41 | // so that they can be used as array indices. 42 | 43 | typedef int Var; 44 | #if defined(MINISAT_CONSTANTS_AS_MACROS) 45 | #define var_Undef (-1) 46 | #else 47 | const Var var_Undef = -1; 48 | #endif 49 | 50 | 51 | struct Lit { 52 | int x; 53 | 54 | // Use this as a constructor: 55 | friend Lit mkLit(Var var, bool sign); 56 | 57 | bool operator == (Lit p) const { return x == p.x; } 58 | bool operator != (Lit p) const { return x != p.x; } 59 | bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering. 60 | }; 61 | 62 | 63 | inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; } 64 | inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } 65 | inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; } 66 | inline bool sign (Lit p) { return p.x & 1; } 67 | inline int var (Lit p) { return p.x >> 1; } 68 | 69 | // Mapping Literals to and from compact integers suitable for array indexing: 70 | inline int toInt (Var v) { return v; } 71 | inline int toInt (Lit p) { return p.x; } 72 | inline Lit toLit (int i) { Lit p; p.x = i; return p; } 73 | 74 | //const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants. 75 | //const Lit lit_Error = mkLit(var_Undef, true ); // } 76 | 77 | const Lit lit_Undef = { -2 }; // }- Useful special constants. 78 | const Lit lit_Error = { -1 }; // } 79 | 80 | struct MkIndexLit { vec::Size operator()(Lit l) const { return vec::Size(l.x); } }; 81 | 82 | template class VMap : public IntMap{}; 83 | template class LMap : public IntMap{}; 84 | class LSet : public IntSet{}; 85 | 86 | //================================================================================================= 87 | // Lifted booleans: 88 | // 89 | // NOTE: this implementation is optimized for the case when comparisons between values are mostly 90 | // between one variable and one constant. Some care had to be taken to make sure that gcc 91 | // does enough constant propagation to produce sensible code, and this appears to be somewhat 92 | // fragile unfortunately. 93 | 94 | class lbool { 95 | uint8_t value; 96 | 97 | public: 98 | explicit lbool(uint8_t v) : value(v) { } 99 | 100 | lbool() : value(0) { } 101 | explicit lbool(bool x) : value(!x) { } 102 | 103 | bool operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); } 104 | bool operator != (lbool b) const { return !(*this == b); } 105 | lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); } 106 | 107 | lbool operator && (lbool b) const { 108 | uint8_t sel = (this->value << 1) | (b.value << 3); 109 | uint8_t v = (0xF7F755F4 >> sel) & 3; 110 | return lbool(v); } 111 | 112 | lbool operator || (lbool b) const { 113 | uint8_t sel = (this->value << 1) | (b.value << 3); 114 | uint8_t v = (0xFCFCF400 >> sel) & 3; 115 | return lbool(v); } 116 | 117 | friend int toInt (lbool l); 118 | friend lbool toLbool(int v); 119 | }; 120 | inline int toInt (lbool l) { return l.value; } 121 | inline lbool toLbool(int v) { return lbool((uint8_t)v); } 122 | 123 | #if defined(MINISAT_CONSTANTS_AS_MACROS) 124 | #define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants. 125 | #define l_False (lbool((uint8_t)1)) 126 | #define l_Undef (lbool((uint8_t)2)) 127 | #else 128 | const lbool l_True ((uint8_t)0); 129 | const lbool l_False((uint8_t)1); 130 | const lbool l_Undef((uint8_t)2); 131 | #endif 132 | 133 | 134 | //================================================================================================= 135 | // Clause -- a simple class for representing a clause: 136 | 137 | class Clause; 138 | typedef RegionAllocator::Ref CRef; 139 | 140 | class Clause { 141 | struct { 142 | unsigned mark : 2; 143 | unsigned learnt : 1; 144 | unsigned has_extra : 1; 145 | unsigned reloced : 1; 146 | unsigned size : 27; } header; 147 | union { Lit lit; float act; uint32_t abs; CRef rel; } data[0]; 148 | 149 | friend class ClauseAllocator; 150 | 151 | // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). 152 | Clause(const vec& ps, bool use_extra, bool learnt) { 153 | header.mark = 0; 154 | header.learnt = learnt; 155 | header.has_extra = use_extra; 156 | header.reloced = 0; 157 | header.size = ps.size(); 158 | 159 | for (int i = 0; i < ps.size(); i++) 160 | data[i].lit = ps[i]; 161 | 162 | if (header.has_extra){ 163 | if (header.learnt) 164 | data[header.size].act = 0; 165 | else 166 | calcAbstraction(); 167 | } 168 | } 169 | 170 | // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). 171 | Clause(const Clause& from, bool use_extra){ 172 | header = from.header; 173 | header.has_extra = use_extra; // NOTE: the copied clause may lose the extra field. 174 | 175 | for (int i = 0; i < from.size(); i++) 176 | data[i].lit = from[i]; 177 | 178 | if (header.has_extra){ 179 | if (header.learnt) 180 | data[header.size].act = from.data[header.size].act; 181 | else 182 | data[header.size].abs = from.data[header.size].abs; 183 | } 184 | } 185 | 186 | public: 187 | void calcAbstraction() { 188 | assert(header.has_extra); 189 | uint32_t abstraction = 0; 190 | for (int i = 0; i < size(); i++) 191 | abstraction |= 1 << (var(data[i].lit) & 31); 192 | data[header.size].abs = abstraction; } 193 | 194 | 195 | int size () const { return header.size; } 196 | void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; } 197 | void pop () { shrink(1); } 198 | bool learnt () const { return header.learnt; } 199 | bool has_extra () const { return header.has_extra; } 200 | uint32_t mark () const { return header.mark; } 201 | void mark (uint32_t m) { header.mark = m; } 202 | const Lit& last () const { return data[header.size-1].lit; } 203 | 204 | bool reloced () const { return header.reloced; } 205 | CRef relocation () const { return data[0].rel; } 206 | void relocate (CRef c) { header.reloced = 1; data[0].rel = c; } 207 | 208 | // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for 209 | // subsumption operations to behave correctly. 210 | Lit& operator [] (int i) { return data[i].lit; } 211 | Lit operator [] (int i) const { return data[i].lit; } 212 | operator const Lit* (void) const { return (Lit*)data; } 213 | 214 | float& activity () { assert(header.has_extra); return data[header.size].act; } 215 | uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; } 216 | 217 | Lit subsumes (const Clause& other) const; 218 | void strengthen (Lit p); 219 | }; 220 | 221 | 222 | //================================================================================================= 223 | // ClauseAllocator -- a simple class for allocating memory for clauses: 224 | 225 | const CRef CRef_Undef = RegionAllocator::Ref_Undef; 226 | class ClauseAllocator 227 | { 228 | RegionAllocator ra; 229 | 230 | static uint32_t clauseWord32Size(int size, bool has_extra){ 231 | return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); } 232 | 233 | public: 234 | enum { Unit_Size = RegionAllocator::Unit_Size }; 235 | 236 | bool extra_clause_field; 237 | 238 | ClauseAllocator(uint32_t start_cap) : ra(start_cap), extra_clause_field(false){} 239 | ClauseAllocator() : extra_clause_field(false){} 240 | 241 | void moveTo(ClauseAllocator& to){ 242 | to.extra_clause_field = extra_clause_field; 243 | ra.moveTo(to.ra); } 244 | 245 | CRef alloc(const vec& ps, bool learnt = false) 246 | { 247 | assert(sizeof(Lit) == sizeof(uint32_t)); 248 | assert(sizeof(float) == sizeof(uint32_t)); 249 | bool use_extra = learnt | extra_clause_field; 250 | CRef cid = ra.alloc(clauseWord32Size(ps.size(), use_extra)); 251 | new (lea(cid)) Clause(ps, use_extra, learnt); 252 | 253 | return cid; 254 | } 255 | 256 | CRef alloc(const Clause& from) 257 | { 258 | bool use_extra = from.learnt() | extra_clause_field; 259 | CRef cid = ra.alloc(clauseWord32Size(from.size(), use_extra)); 260 | new (lea(cid)) Clause(from, use_extra); 261 | return cid; } 262 | 263 | uint32_t size () const { return ra.size(); } 264 | uint32_t wasted () const { return ra.wasted(); } 265 | 266 | // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): 267 | Clause& operator[](CRef r) { return (Clause&)ra[r]; } 268 | const Clause& operator[](CRef r) const { return (Clause&)ra[r]; } 269 | Clause* lea (CRef r) { return (Clause*)ra.lea(r); } 270 | const Clause* lea (CRef r) const { return (Clause*)ra.lea(r);; } 271 | CRef ael (const Clause* t){ return ra.ael((uint32_t*)t); } 272 | 273 | void free(CRef cid) 274 | { 275 | Clause& c = operator[](cid); 276 | ra.free(clauseWord32Size(c.size(), c.has_extra())); 277 | } 278 | 279 | void reloc(CRef& cr, ClauseAllocator& to) 280 | { 281 | Clause& c = operator[](cr); 282 | 283 | if (c.reloced()) { cr = c.relocation(); return; } 284 | 285 | cr = to.alloc(c); 286 | c.relocate(cr); 287 | } 288 | }; 289 | 290 | //================================================================================================= 291 | // Simple iterator classes (for iterating over clauses and top-level assignments): 292 | 293 | class ClauseIterator { 294 | const ClauseAllocator& ca; 295 | const CRef* crefs; 296 | public: 297 | ClauseIterator(const ClauseAllocator& _ca, const CRef* _crefs) : ca(_ca), crefs(_crefs){} 298 | 299 | void operator++(){ crefs++; } 300 | const Clause& operator*() const { return ca[*crefs]; } 301 | 302 | // NOTE: does not compare that references use the same clause-allocator: 303 | bool operator==(const ClauseIterator& ci) const { return crefs == ci.crefs; } 304 | bool operator!=(const ClauseIterator& ci) const { return crefs != ci.crefs; } 305 | }; 306 | 307 | 308 | class TrailIterator { 309 | const Lit* lits; 310 | public: 311 | TrailIterator(const Lit* _lits) : lits(_lits){} 312 | 313 | void operator++() { lits++; } 314 | Lit operator*() const { return *lits; } 315 | 316 | bool operator==(const TrailIterator& ti) const { return lits == ti.lits; } 317 | bool operator!=(const TrailIterator& ti) const { return lits != ti.lits; } 318 | }; 319 | 320 | 321 | //================================================================================================= 322 | // OccLists -- a class for maintaining occurence lists with lazy deletion: 323 | 324 | template > 325 | class OccLists 326 | { 327 | IntMap occs; 328 | IntMap dirty; 329 | vec dirties; 330 | Deleted deleted; 331 | 332 | public: 333 | OccLists(const Deleted& d, MkIndex _index = MkIndex()) : 334 | occs(_index), 335 | dirty(_index), 336 | deleted(d){} 337 | 338 | void init (const K& idx){ occs.reserve(idx); occs[idx].clear(); dirty.reserve(idx, 0); } 339 | Vec& operator[](const K& idx){ return occs[idx]; } 340 | Vec& lookup (const K& idx){ if (dirty[idx]) clean(idx); return occs[idx]; } 341 | 342 | void cleanAll (); 343 | void clean (const K& idx); 344 | void smudge (const K& idx){ 345 | if (dirty[idx] == 0){ 346 | dirty[idx] = 1; 347 | dirties.push(idx); 348 | } 349 | } 350 | 351 | void clear(bool free = true){ 352 | occs .clear(free); 353 | dirty .clear(free); 354 | dirties.clear(free); 355 | } 356 | }; 357 | 358 | 359 | template 360 | void OccLists::cleanAll() 361 | { 362 | for (int i = 0; i < dirties.size(); i++) 363 | // Dirties may contain duplicates so check here if a variable is already cleaned: 364 | if (dirty[dirties[i]]) 365 | clean(dirties[i]); 366 | dirties.clear(); 367 | } 368 | 369 | 370 | template 371 | void OccLists::clean(const K& idx) 372 | { 373 | Vec& vec = occs[idx]; 374 | int i, j; 375 | for (i = j = 0; i < vec.size(); i++) 376 | if (!deleted(vec[i])) 377 | vec[j++] = vec[i]; 378 | vec.shrink(i - j); 379 | dirty[idx] = 0; 380 | } 381 | 382 | 383 | //================================================================================================= 384 | // CMap -- a class for mapping clauses to values: 385 | 386 | 387 | template 388 | class CMap 389 | { 390 | struct CRefHash { 391 | uint32_t operator()(CRef cr) const { return (uint32_t)cr; } }; 392 | 393 | typedef Map HashTable; 394 | HashTable map; 395 | 396 | public: 397 | // Size-operations: 398 | void clear () { map.clear(); } 399 | int size () const { return map.elems(); } 400 | 401 | 402 | // Insert/Remove/Test mapping: 403 | void insert (CRef cr, const T& t){ map.insert(cr, t); } 404 | void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility 405 | void remove (CRef cr) { map.remove(cr); } 406 | bool has (CRef cr, T& t) { return map.peek(cr, t); } 407 | 408 | // Vector interface (the clause 'c' must already exist): 409 | const T& operator [] (CRef cr) const { return map[cr]; } 410 | T& operator [] (CRef cr) { return map[cr]; } 411 | 412 | // Iteration (not transparent at all at the moment): 413 | int bucket_count() const { return map.bucket_count(); } 414 | const vec& bucket(int i) const { return map.bucket(i); } 415 | 416 | // Move contents to other map: 417 | void moveTo(CMap& other){ map.moveTo(other.map); } 418 | 419 | // TMP debug: 420 | void debug(){ 421 | printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); } 422 | }; 423 | 424 | 425 | /*_________________________________________________________________________________________________ 426 | | 427 | | subsumes : (other : const Clause&) -> Lit 428 | | 429 | | Description: 430 | | Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other' 431 | | by subsumption resolution. 432 | | 433 | | Result: 434 | | lit_Error - No subsumption or simplification 435 | | lit_Undef - Clause subsumes 'other' 436 | | p - The literal p can be deleted from 'other' 437 | |________________________________________________________________________________________________@*/ 438 | inline Lit Clause::subsumes(const Clause& other) const 439 | { 440 | //if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0) 441 | //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0)) 442 | assert(!header.learnt); assert(!other.header.learnt); 443 | assert(header.has_extra); assert(other.header.has_extra); 444 | if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0) 445 | return lit_Error; 446 | 447 | Lit ret = lit_Undef; 448 | const Lit* c = (const Lit*)(*this); 449 | const Lit* d = (const Lit*)other; 450 | 451 | for (unsigned i = 0; i < header.size; i++) { 452 | // search for c[i] or ~c[i] 453 | for (unsigned j = 0; j < other.header.size; j++) 454 | if (c[i] == d[j]) 455 | goto ok; 456 | else if (ret == lit_Undef && c[i] == ~d[j]){ 457 | ret = c[i]; 458 | goto ok; 459 | } 460 | 461 | // did not find it 462 | return lit_Error; 463 | ok:; 464 | } 465 | 466 | return ret; 467 | } 468 | 469 | inline void Clause::strengthen(Lit p) 470 | { 471 | remove(*this, p); 472 | calcAbstraction(); 473 | } 474 | 475 | //================================================================================================= 476 | } 477 | 478 | #endif 479 | -------------------------------------------------------------------------------- /minisat/core/Solver.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[Solver.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Solver_h 22 | #define Minisat_Solver_h 23 | 24 | #include "minisat/mtl/Vec.h" 25 | #include "minisat/mtl/Heap.h" 26 | #include "minisat/mtl/Alg.h" 27 | #include "minisat/mtl/IntMap.h" 28 | #include "minisat/utils/Options.h" 29 | #include "minisat/core/SolverTypes.h" 30 | 31 | 32 | namespace Minisat { 33 | 34 | //================================================================================================= 35 | // Solver -- the main class: 36 | 37 | class Solver { 38 | public: 39 | 40 | // Constructor/Destructor: 41 | // 42 | Solver(); 43 | virtual ~Solver(); 44 | 45 | // Problem specification: 46 | // 47 | Var newVar (lbool upol = l_Undef, bool dvar = true); // Add a new variable with parameters specifying variable mode. 48 | void releaseVar(Lit l); // Make literal true and promise to never refer to variable again. 49 | 50 | bool addClause (const vec& ps); // Add a clause to the solver. 51 | bool addEmptyClause(); // Add the empty clause, making the solver contradictory. 52 | bool addClause (Lit p); // Add a unit clause to the solver. 53 | bool addClause (Lit p, Lit q); // Add a binary clause to the solver. 54 | bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. 55 | bool addClause (Lit p, Lit q, Lit r, Lit s); // Add a quaternary clause to the solver. 56 | bool addClause_( vec& ps); // Add a clause to the solver without making superflous internal copy. Will 57 | // change the passed vector 'ps'. 58 | 59 | // Solving: 60 | // 61 | bool simplify (); // Removes already satisfied clauses. 62 | bool solve (const vec& assumps); // Search for a model that respects a given set of assumptions. 63 | lbool solveLimited (const vec& assumps); // Search for a model that respects a given set of assumptions (With resource constraints). 64 | bool solve (); // Search without assumptions. 65 | bool solve (Lit p); // Search for a model that respects a single assumption. 66 | bool solve (Lit p, Lit q); // Search for a model that respects two assumptions. 67 | bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions. 68 | bool okay () const; // FALSE means solver is in a conflicting state 69 | 70 | bool implies (const vec& assumps, vec& out); 71 | 72 | // Iterate over clauses and top-level assignments: 73 | ClauseIterator clausesBegin() const; 74 | ClauseIterator clausesEnd() const; 75 | TrailIterator trailBegin() const; 76 | TrailIterator trailEnd () const; 77 | 78 | void toDimacs (FILE* f, const vec& assumps); // Write CNF to file in DIMACS-format. 79 | void toDimacs (const char *file, const vec& assumps); 80 | void toDimacs (FILE* f, Clause& c, vec& map, Var& max); 81 | 82 | // Convenience versions of 'toDimacs()': 83 | void toDimacs (const char* file); 84 | void toDimacs (const char* file, Lit p); 85 | void toDimacs (const char* file, Lit p, Lit q); 86 | void toDimacs (const char* file, Lit p, Lit q, Lit r); 87 | 88 | // Variable mode: 89 | // 90 | void setPolarity (Var v, lbool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'. 91 | void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic. 92 | 93 | // Read state: 94 | // 95 | lbool value (Var x) const; // The current value of a variable. 96 | lbool value (Lit p) const; // The current value of a literal. 97 | lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable. 98 | lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable. 99 | int nAssigns () const; // The current number of assigned literals. 100 | int nClauses () const; // The current number of original clauses. 101 | int nLearnts () const; // The current number of learnt clauses. 102 | int nVars () const; // The current number of variables. 103 | int nFreeVars () const; 104 | void printStats () const; // Print some current statistics to standard output. 105 | 106 | // Resource contraints: 107 | // 108 | void setConfBudget(int64_t x); 109 | void setPropBudget(int64_t x); 110 | void budgetOff(); 111 | void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver. 112 | void clearInterrupt(); // Clear interrupt indicator flag. 113 | 114 | // Memory managment: 115 | // 116 | virtual void garbageCollect(); 117 | void checkGarbage(double gf); 118 | void checkGarbage(); 119 | 120 | // Extra results: (read-only member variable) 121 | // 122 | vec model; // If problem is satisfiable, this vector contains the model (if any). 123 | LSet conflict; // If problem is unsatisfiable (possibly under assumptions), 124 | // this vector represent the final conflict clause expressed in the assumptions. 125 | 126 | // Mode of operation: 127 | // 128 | int verbosity; 129 | double var_decay; 130 | double clause_decay; 131 | double random_var_freq; 132 | double random_seed; 133 | bool luby_restart; 134 | int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep). 135 | int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full). 136 | bool rnd_pol; // Use random polarities for branching heuristics. 137 | bool rnd_init_act; // Initialize variable activities with a small random value. 138 | double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered. 139 | int min_learnts_lim; // Minimum number to set the learnts limit to. 140 | 141 | int restart_first; // The initial restart limit. (default 100) 142 | double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5) 143 | double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3) 144 | double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1) 145 | 146 | int learntsize_adjust_start_confl; 147 | double learntsize_adjust_inc; 148 | 149 | // Statistics: (read-only member variable) 150 | // 151 | uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts; 152 | uint64_t dec_vars, num_clauses, num_learnts, clauses_literals, learnts_literals, max_literals, tot_literals; 153 | 154 | protected: 155 | 156 | // Helper structures: 157 | // 158 | struct VarData { CRef reason; int level; }; 159 | static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; } 160 | 161 | struct Watcher { 162 | CRef cref; 163 | Lit blocker; 164 | Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {} 165 | bool operator==(const Watcher& w) const { return cref == w.cref; } 166 | bool operator!=(const Watcher& w) const { return cref != w.cref; } 167 | }; 168 | 169 | struct WatcherDeleted 170 | { 171 | const ClauseAllocator& ca; 172 | WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {} 173 | bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; } 174 | }; 175 | 176 | struct VarOrderLt { 177 | const IntMap& activity; 178 | bool operator () (Var x, Var y) const { return activity[x] > activity[y]; } 179 | VarOrderLt(const IntMap& act) : activity(act) { } 180 | }; 181 | 182 | struct ShrinkStackElem { 183 | uint32_t i; 184 | Lit l; 185 | ShrinkStackElem(uint32_t _i, Lit _l) : i(_i), l(_l){} 186 | }; 187 | 188 | // Solver state: 189 | // 190 | vec clauses; // List of problem clauses. 191 | vec learnts; // List of learnt clauses. 192 | vec trail; // Assignment stack; stores all assigments made in the order they were made. 193 | vec trail_lim; // Separator indices for different decision levels in 'trail'. 194 | vec assumptions; // Current set of assumptions provided to solve by the user. 195 | 196 | VMap activity; // A heuristic measurement of the activity of a variable. 197 | VMap assigns; // The current assignments. 198 | VMap polarity; // The preferred polarity of each variable. 199 | VMap user_pol; // The users preferred polarity of each variable. 200 | VMap decision; // Declares if a variable is eligible for selection in the decision heuristic. 201 | VMap vardata; // Stores reason and level for each variable. 202 | OccLists, WatcherDeleted, MkIndexLit> 203 | watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). 204 | 205 | Heaporder_heap; // A priority queue of variables ordered with respect to the variable activity. 206 | 207 | bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! 208 | double cla_inc; // Amount to bump next clause with. 209 | double var_inc; // Amount to bump next variable with. 210 | int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). 211 | int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'. 212 | int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'. 213 | double progress_estimate;// Set by 'search()'. 214 | bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'. 215 | Var next_var; // Next variable to be created. 216 | ClauseAllocator ca; 217 | 218 | vec released_vars; 219 | vec free_vars; 220 | 221 | // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is 222 | // used, exept 'seen' wich is used in several places. 223 | // 224 | VMap seen; 225 | vecanalyze_stack; 226 | vec analyze_toclear; 227 | vec add_tmp; 228 | 229 | double max_learnts; 230 | double learntsize_adjust_confl; 231 | int learntsize_adjust_cnt; 232 | 233 | // Resource contraints: 234 | // 235 | int64_t conflict_budget; // -1 means no budget. 236 | int64_t propagation_budget; // -1 means no budget. 237 | bool asynch_interrupt; 238 | 239 | // Main internal methods: 240 | // 241 | void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. 242 | Lit pickBranchLit (); // Return the next decision variable. 243 | void newDecisionLevel (); // Begins a new decision level. 244 | void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined. 245 | bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise. 246 | CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause. 247 | void cancelUntil (int level); // Backtrack until a certain level. 248 | void analyze (CRef confl, vec& out_learnt, int& out_btlevel); // (bt = backtrack) 249 | void analyzeFinal (Lit p, LSet& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION? 250 | bool litRedundant (Lit p); // (helper method for 'analyze()') 251 | lbool search (int nof_conflicts); // Search for a given number of conflicts. 252 | lbool solve_ (); // Main solve method (assumptions given in 'assumptions'). 253 | void reduceDB (); // Reduce the set of learnt clauses. 254 | void removeSatisfied (vec& cs); // Shrink 'cs' to contain only non-satisfied clauses. 255 | void rebuildOrderHeap (); 256 | 257 | // Maintaining Variable/Clause activity: 258 | // 259 | void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead. 260 | void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value. 261 | void varBumpActivity (Var v); // Increase a variable with the current 'bump' value. 262 | void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead. 263 | void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value. 264 | 265 | // Operations on clauses: 266 | // 267 | void attachClause (CRef cr); // Attach a clause to watcher lists. 268 | void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists. 269 | void removeClause (CRef cr); // Detach and free a clause. 270 | bool isRemoved (CRef cr) const; // Test if a clause has been removed. 271 | bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. 272 | bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state. 273 | 274 | // Misc: 275 | // 276 | int decisionLevel () const; // Gives the current decisionlevel. 277 | uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels. 278 | CRef reason (Var x) const; 279 | int level (Var x) const; 280 | double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... 281 | bool withinBudget () const; 282 | void relocAll (ClauseAllocator& to); 283 | 284 | // Static helpers: 285 | // 286 | 287 | // Returns a random float 0 <= x < 1. Seed must never be 0. 288 | static inline double drand(double& seed) { 289 | seed *= 1389796; 290 | int q = (int)(seed / 2147483647); 291 | seed -= (double)q * 2147483647; 292 | return seed / 2147483647; } 293 | 294 | // Returns a random integer 0 <= x < size. Seed must never be 0. 295 | static inline int irand(double& seed, int size) { 296 | return (int)(drand(seed) * size); } 297 | }; 298 | 299 | 300 | //================================================================================================= 301 | // Implementation of inline methods: 302 | 303 | inline CRef Solver::reason(Var x) const { return vardata[x].reason; } 304 | inline int Solver::level (Var x) const { return vardata[x].level; } 305 | 306 | inline void Solver::insertVarOrder(Var x) { 307 | if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); } 308 | 309 | inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); } 310 | inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); } 311 | inline void Solver::varBumpActivity(Var v, double inc) { 312 | if ( (activity[v] += inc) > 1e100 ) { 313 | // Rescale: 314 | for (int i = 0; i < nVars(); i++) 315 | activity[i] *= 1e-100; 316 | var_inc *= 1e-100; } 317 | 318 | // Update order_heap with respect to new activity: 319 | if (order_heap.inHeap(v)) 320 | order_heap.decrease(v); } 321 | 322 | inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); } 323 | inline void Solver::claBumpActivity (Clause& c) { 324 | if ( (c.activity() += cla_inc) > 1e20 ) { 325 | // Rescale: 326 | for (int i = 0; i < learnts.size(); i++) 327 | ca[learnts[i]].activity() *= 1e-20; 328 | cla_inc *= 1e-20; } } 329 | 330 | inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); } 331 | inline void Solver::checkGarbage(double gf){ 332 | if (ca.wasted() > ca.size() * gf) 333 | garbageCollect(); } 334 | 335 | // NOTE: enqueue does not set the ok flag! (only public methods do) 336 | inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); } 337 | inline bool Solver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } 338 | inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); } 339 | inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } 340 | inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } 341 | inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } 342 | inline bool Solver::addClause (Lit p, Lit q, Lit r, Lit s){ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); add_tmp.push(s); return addClause_(add_tmp); } 343 | 344 | inline bool Solver::isRemoved (CRef cr) const { return ca[cr].mark() == 1; } 345 | inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; } 346 | inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); } 347 | 348 | inline int Solver::decisionLevel () const { return trail_lim.size(); } 349 | inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); } 350 | inline lbool Solver::value (Var x) const { return assigns[x]; } 351 | inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); } 352 | inline lbool Solver::modelValue (Var x) const { return model[x]; } 353 | inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); } 354 | inline int Solver::nAssigns () const { return trail.size(); } 355 | inline int Solver::nClauses () const { return num_clauses; } 356 | inline int Solver::nLearnts () const { return num_learnts; } 357 | inline int Solver::nVars () const { return next_var; } 358 | // TODO: nFreeVars() is not quite correct, try to calculate right instead of adapting it like below: 359 | inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } 360 | inline void Solver::setPolarity (Var v, lbool b){ user_pol[v] = b; } 361 | inline void Solver::setDecisionVar(Var v, bool b) 362 | { 363 | if ( b && !decision[v]) dec_vars++; 364 | else if (!b && decision[v]) dec_vars--; 365 | 366 | decision[v] = b; 367 | insertVarOrder(v); 368 | } 369 | inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; } 370 | inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; } 371 | inline void Solver::interrupt(){ asynch_interrupt = true; } 372 | inline void Solver::clearInterrupt(){ asynch_interrupt = false; } 373 | inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; } 374 | inline bool Solver::withinBudget() const { 375 | return !asynch_interrupt && 376 | (conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) && 377 | (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); } 378 | 379 | // FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a 380 | // pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or 381 | // all calls to solve must return an 'lbool'. I'm not yet sure which I prefer. 382 | inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; } 383 | inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; } 384 | inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; } 385 | inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; } 386 | inline bool Solver::solve (const vec& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; } 387 | inline lbool Solver::solveLimited (const vec& assumps){ assumps.copyTo(assumptions); return solve_(); } 388 | inline bool Solver::okay () const { return ok; } 389 | 390 | inline ClauseIterator Solver::clausesBegin() const { return ClauseIterator(ca, &clauses[0]); } 391 | inline ClauseIterator Solver::clausesEnd () const { return ClauseIterator(ca, &clauses[clauses.size()]); } 392 | inline TrailIterator Solver::trailBegin () const { return TrailIterator(&trail[0]); } 393 | inline TrailIterator Solver::trailEnd () const { 394 | return TrailIterator(&trail[decisionLevel() == 0 ? trail.size() : trail_lim[0]]); } 395 | 396 | inline void Solver::toDimacs (const char* file){ vec as; toDimacs(file, as); } 397 | inline void Solver::toDimacs (const char* file, Lit p){ vec as; as.push(p); toDimacs(file, as); } 398 | inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec as; as.push(p); as.push(q); toDimacs(file, as); } 399 | inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); } 400 | 401 | 402 | //================================================================================================= 403 | // Debug etc: 404 | 405 | 406 | //================================================================================================= 407 | } 408 | 409 | #endif 410 | -------------------------------------------------------------------------------- /minisat/simp/SimpSolver.cc: -------------------------------------------------------------------------------- 1 | /***********************************************************************************[SimpSolver.cc] 2 | Copyright (c) 2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include "minisat/mtl/Sort.h" 22 | #include "minisat/simp/SimpSolver.h" 23 | #include "minisat/utils/System.h" 24 | 25 | using namespace Minisat; 26 | 27 | //================================================================================================= 28 | // Options: 29 | 30 | 31 | static const char* _cat = "SIMP"; 32 | 33 | static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false); 34 | static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false); 35 | static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true); 36 | static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0); 37 | static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX)); 38 | static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX)); 39 | static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false)); 40 | 41 | 42 | //================================================================================================= 43 | // Constructor/Destructor: 44 | 45 | 46 | SimpSolver::SimpSolver() : 47 | grow (opt_grow) 48 | , clause_lim (opt_clause_lim) 49 | , subsumption_lim (opt_subsumption_lim) 50 | , simp_garbage_frac (opt_simp_garbage_frac) 51 | , use_asymm (opt_use_asymm) 52 | , use_rcheck (opt_use_rcheck) 53 | , use_elim (opt_use_elim) 54 | , extend_model (true) 55 | , merges (0) 56 | , asymm_lits (0) 57 | , eliminated_vars (0) 58 | , elimorder (1) 59 | , use_simplification (true) 60 | , occurs (ClauseDeleted(ca)) 61 | , elim_heap (ElimLt(n_occ)) 62 | , bwdsub_assigns (0) 63 | , n_touched (0) 64 | { 65 | vec dummy(1,lit_Undef); 66 | ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below. 67 | bwdsub_tmpunit = ca.alloc(dummy); 68 | remove_satisfied = false; 69 | } 70 | 71 | 72 | SimpSolver::~SimpSolver() 73 | { 74 | } 75 | 76 | 77 | Var SimpSolver::newVar(lbool upol, bool dvar) { 78 | Var v = Solver::newVar(upol, dvar); 79 | 80 | frozen .insert(v, (char)false); 81 | eliminated.insert(v, (char)false); 82 | 83 | if (use_simplification){ 84 | n_occ .insert( mkLit(v), 0); 85 | n_occ .insert(~mkLit(v), 0); 86 | occurs .init (v); 87 | touched .insert(v, 0); 88 | elim_heap .insert(v); 89 | } 90 | return v; } 91 | 92 | 93 | void SimpSolver::releaseVar(Lit l) 94 | { 95 | assert(!isEliminated(var(l))); 96 | if (!use_simplification && var(l) >= max_simp_var) 97 | // Note: Guarantees that no references to this variable is 98 | // left in model extension datastructure. Could be improved! 99 | Solver::releaseVar(l); 100 | else 101 | // Otherwise, don't allow variable to be reused. 102 | Solver::addClause(l); 103 | } 104 | 105 | 106 | lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp) 107 | { 108 | vec extra_frozen; 109 | lbool result = l_True; 110 | 111 | do_simp &= use_simplification; 112 | 113 | if (do_simp){ 114 | // Assumptions must be temporarily frozen to run variable elimination: 115 | for (int i = 0; i < assumptions.size(); i++){ 116 | Var v = var(assumptions[i]); 117 | 118 | // If an assumption has been eliminated, remember it. 119 | assert(!isEliminated(v)); 120 | 121 | if (!frozen[v]){ 122 | // Freeze and store. 123 | setFrozen(v, true); 124 | extra_frozen.push(v); 125 | } } 126 | 127 | result = lbool(eliminate(turn_off_simp)); 128 | } 129 | 130 | if (result == l_True) 131 | result = Solver::solve_(); 132 | else if (verbosity >= 1) 133 | printf("===============================================================================\n"); 134 | 135 | if (result == l_True && extend_model) 136 | extendModel(); 137 | 138 | if (do_simp) 139 | // Unfreeze the assumptions that were frozen: 140 | for (int i = 0; i < extra_frozen.size(); i++) 141 | setFrozen(extra_frozen[i], false); 142 | 143 | return result; 144 | } 145 | 146 | 147 | 148 | bool SimpSolver::addClause_(vec& ps) 149 | { 150 | #ifndef NDEBUG 151 | for (int i = 0; i < ps.size(); i++) 152 | assert(!isEliminated(var(ps[i]))); 153 | #endif 154 | 155 | int nclauses = clauses.size(); 156 | 157 | if (use_rcheck && implied(ps)) 158 | return true; 159 | 160 | if (!Solver::addClause_(ps)) 161 | return false; 162 | 163 | if (use_simplification && clauses.size() == nclauses + 1){ 164 | CRef cr = clauses.last(); 165 | const Clause& c = ca[cr]; 166 | 167 | // NOTE: the clause is added to the queue immediately and then 168 | // again during 'gatherTouchedClauses()'. If nothing happens 169 | // in between, it will only be checked once. Otherwise, it may 170 | // be checked twice unnecessarily. This is an unfortunate 171 | // consequence of how backward subsumption is used to mimic 172 | // forward subsumption. 173 | subsumption_queue.insert(cr); 174 | for (int i = 0; i < c.size(); i++){ 175 | occurs[var(c[i])].push(cr); 176 | n_occ[c[i]]++; 177 | touched[var(c[i])] = 1; 178 | n_touched++; 179 | if (elim_heap.inHeap(var(c[i]))) 180 | elim_heap.increase(var(c[i])); 181 | } 182 | } 183 | 184 | return true; 185 | } 186 | 187 | 188 | void SimpSolver::removeClause(CRef cr) 189 | { 190 | const Clause& c = ca[cr]; 191 | 192 | if (use_simplification) 193 | for (int i = 0; i < c.size(); i++){ 194 | n_occ[c[i]]--; 195 | updateElimHeap(var(c[i])); 196 | occurs.smudge(var(c[i])); 197 | } 198 | 199 | Solver::removeClause(cr); 200 | } 201 | 202 | 203 | bool SimpSolver::strengthenClause(CRef cr, Lit l) 204 | { 205 | Clause& c = ca[cr]; 206 | assert(decisionLevel() == 0); 207 | assert(use_simplification); 208 | 209 | // FIX: this is too inefficient but would be nice to have (properly implemented) 210 | // if (!find(subsumption_queue, &c)) 211 | subsumption_queue.insert(cr); 212 | 213 | if (c.size() == 2){ 214 | removeClause(cr); 215 | c.strengthen(l); 216 | }else{ 217 | detachClause(cr, true); 218 | c.strengthen(l); 219 | attachClause(cr); 220 | remove(occurs[var(l)], cr); 221 | n_occ[l]--; 222 | updateElimHeap(var(l)); 223 | } 224 | 225 | return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true; 226 | } 227 | 228 | 229 | // Returns FALSE if clause is always satisfied ('out_clause' should not be used). 230 | bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec& out_clause) 231 | { 232 | merges++; 233 | out_clause.clear(); 234 | 235 | bool ps_smallest = _ps.size() < _qs.size(); 236 | const Clause& ps = ps_smallest ? _qs : _ps; 237 | const Clause& qs = ps_smallest ? _ps : _qs; 238 | 239 | for (int i = 0; i < qs.size(); i++){ 240 | if (var(qs[i]) != v){ 241 | for (int j = 0; j < ps.size(); j++) 242 | if (var(ps[j]) == var(qs[i])){ 243 | if (ps[j] == ~qs[i]) 244 | return false; 245 | else 246 | goto next; 247 | } 248 | out_clause.push(qs[i]); 249 | } 250 | next:; 251 | } 252 | 253 | for (int i = 0; i < ps.size(); i++) 254 | if (var(ps[i]) != v) 255 | out_clause.push(ps[i]); 256 | 257 | return true; 258 | } 259 | 260 | 261 | // Returns FALSE if clause is always satisfied. 262 | bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) 263 | { 264 | merges++; 265 | 266 | bool ps_smallest = _ps.size() < _qs.size(); 267 | const Clause& ps = ps_smallest ? _qs : _ps; 268 | const Clause& qs = ps_smallest ? _ps : _qs; 269 | const Lit* __ps = (const Lit*)ps; 270 | const Lit* __qs = (const Lit*)qs; 271 | 272 | size = ps.size()-1; 273 | 274 | for (int i = 0; i < qs.size(); i++){ 275 | if (var(__qs[i]) != v){ 276 | for (int j = 0; j < ps.size(); j++) 277 | if (var(__ps[j]) == var(__qs[i])){ 278 | if (__ps[j] == ~__qs[i]) 279 | return false; 280 | else 281 | goto next; 282 | } 283 | size++; 284 | } 285 | next:; 286 | } 287 | 288 | return true; 289 | } 290 | 291 | 292 | void SimpSolver::gatherTouchedClauses() 293 | { 294 | if (n_touched == 0) return; 295 | 296 | int i,j; 297 | for (i = j = 0; i < subsumption_queue.size(); i++) 298 | if (ca[subsumption_queue[i]].mark() == 0) 299 | ca[subsumption_queue[i]].mark(2); 300 | 301 | for (i = 0; i < nVars(); i++) 302 | if (touched[i]){ 303 | const vec& cs = occurs.lookup(i); 304 | for (j = 0; j < cs.size(); j++) 305 | if (ca[cs[j]].mark() == 0){ 306 | subsumption_queue.insert(cs[j]); 307 | ca[cs[j]].mark(2); 308 | } 309 | touched[i] = 0; 310 | } 311 | 312 | for (i = 0; i < subsumption_queue.size(); i++) 313 | if (ca[subsumption_queue[i]].mark() == 2) 314 | ca[subsumption_queue[i]].mark(0); 315 | 316 | n_touched = 0; 317 | } 318 | 319 | 320 | bool SimpSolver::implied(const vec& c) 321 | { 322 | assert(decisionLevel() == 0); 323 | 324 | trail_lim.push(trail.size()); 325 | for (int i = 0; i < c.size(); i++) 326 | if (value(c[i]) == l_True){ 327 | cancelUntil(0); 328 | return true; 329 | }else if (value(c[i]) != l_False){ 330 | assert(value(c[i]) == l_Undef); 331 | uncheckedEnqueue(~c[i]); 332 | } 333 | 334 | bool result = propagate() != CRef_Undef; 335 | cancelUntil(0); 336 | return result; 337 | } 338 | 339 | 340 | // Backward subsumption + backward subsumption resolution 341 | bool SimpSolver::backwardSubsumptionCheck(bool verbose) 342 | { 343 | int cnt = 0; 344 | int subsumed = 0; 345 | int deleted_literals = 0; 346 | assert(decisionLevel() == 0); 347 | 348 | while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ 349 | 350 | // Empty subsumption queue and return immediately on user-interrupt: 351 | if (asynch_interrupt){ 352 | subsumption_queue.clear(); 353 | bwdsub_assigns = trail.size(); 354 | break; } 355 | 356 | // Check top-level assignments by creating a dummy clause and placing it in the queue: 357 | if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ 358 | Lit l = trail[bwdsub_assigns++]; 359 | ca[bwdsub_tmpunit][0] = l; 360 | ca[bwdsub_tmpunit].calcAbstraction(); 361 | subsumption_queue.insert(bwdsub_tmpunit); } 362 | 363 | CRef cr = subsumption_queue.peek(); subsumption_queue.pop(); 364 | Clause& c = ca[cr]; 365 | 366 | if (c.mark()) continue; 367 | 368 | if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) 369 | printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); 370 | 371 | assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. 372 | 373 | // Find best variable to scan: 374 | Var best = var(c[0]); 375 | for (int i = 1; i < c.size(); i++) 376 | if (occurs[var(c[i])].size() < occurs[best].size()) 377 | best = var(c[i]); 378 | 379 | // Search all candidates: 380 | vec& _cs = occurs.lookup(best); 381 | CRef* cs = (CRef*)_cs; 382 | 383 | for (int j = 0; j < _cs.size(); j++) 384 | if (c.mark()) 385 | break; 386 | else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){ 387 | Lit l = c.subsumes(ca[cs[j]]); 388 | 389 | if (l == lit_Undef) 390 | subsumed++, removeClause(cs[j]); 391 | else if (l != lit_Error){ 392 | deleted_literals++; 393 | 394 | if (!strengthenClause(cs[j], ~l)) 395 | return false; 396 | 397 | // Did current candidate get deleted from cs? Then check candidate at index j again: 398 | if (var(l) == best) 399 | j--; 400 | } 401 | } 402 | } 403 | 404 | return true; 405 | } 406 | 407 | 408 | bool SimpSolver::asymm(Var v, CRef cr) 409 | { 410 | Clause& c = ca[cr]; 411 | assert(decisionLevel() == 0); 412 | 413 | if (c.mark() || satisfied(c)) return true; 414 | 415 | trail_lim.push(trail.size()); 416 | Lit l = lit_Undef; 417 | for (int i = 0; i < c.size(); i++) 418 | if (var(c[i]) != v && value(c[i]) != l_False) 419 | uncheckedEnqueue(~c[i]); 420 | else 421 | l = c[i]; 422 | 423 | if (propagate() != CRef_Undef){ 424 | cancelUntil(0); 425 | asymm_lits++; 426 | if (!strengthenClause(cr, l)) 427 | return false; 428 | }else 429 | cancelUntil(0); 430 | 431 | return true; 432 | } 433 | 434 | 435 | bool SimpSolver::asymmVar(Var v) 436 | { 437 | assert(use_simplification); 438 | 439 | const vec& cls = occurs.lookup(v); 440 | 441 | if (value(v) != l_Undef || cls.size() == 0) 442 | return true; 443 | 444 | for (int i = 0; i < cls.size(); i++) 445 | if (!asymm(v, cls[i])) 446 | return false; 447 | 448 | return backwardSubsumptionCheck(); 449 | } 450 | 451 | 452 | static void mkElimClause(vec& elimclauses, Lit x) 453 | { 454 | elimclauses.push(toInt(x)); 455 | elimclauses.push(1); 456 | } 457 | 458 | 459 | static void mkElimClause(vec& elimclauses, Var v, Clause& c) 460 | { 461 | int first = elimclauses.size(); 462 | int v_pos = -1; 463 | 464 | // Copy clause to elimclauses-vector. Remember position where the 465 | // variable 'v' occurs: 466 | for (int i = 0; i < c.size(); i++){ 467 | elimclauses.push(toInt(c[i])); 468 | if (var(c[i]) == v) 469 | v_pos = i + first; 470 | } 471 | assert(v_pos != -1); 472 | 473 | // Swap the first literal with the 'v' literal, so that the literal 474 | // containing 'v' will occur first in the clause: 475 | uint32_t tmp = elimclauses[v_pos]; 476 | elimclauses[v_pos] = elimclauses[first]; 477 | elimclauses[first] = tmp; 478 | 479 | // Store the length of the clause last: 480 | elimclauses.push(c.size()); 481 | } 482 | 483 | 484 | 485 | bool SimpSolver::eliminateVar(Var v) 486 | { 487 | assert(!frozen[v]); 488 | assert(!isEliminated(v)); 489 | assert(value(v) == l_Undef); 490 | 491 | // Split the occurrences into positive and negative: 492 | // 493 | const vec& cls = occurs.lookup(v); 494 | vec pos, neg; 495 | for (int i = 0; i < cls.size(); i++) 496 | (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]); 497 | 498 | // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no 499 | // clause must exceed the limit on the maximal clause size (if it is set): 500 | // 501 | int cnt = 0; 502 | int clause_size = 0; 503 | 504 | for (int i = 0; i < pos.size(); i++) 505 | for (int j = 0; j < neg.size(); j++) 506 | if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) && 507 | (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim))) 508 | return true; 509 | 510 | // Delete and store old clauses: 511 | eliminated[v] = true; 512 | setDecisionVar(v, false); 513 | eliminated_vars++; 514 | 515 | if (pos.size() > neg.size()){ 516 | for (int i = 0; i < neg.size(); i++) 517 | mkElimClause(elimclauses, v, ca[neg[i]]); 518 | mkElimClause(elimclauses, mkLit(v)); 519 | }else{ 520 | for (int i = 0; i < pos.size(); i++) 521 | mkElimClause(elimclauses, v, ca[pos[i]]); 522 | mkElimClause(elimclauses, ~mkLit(v)); 523 | } 524 | 525 | for (int i = 0; i < cls.size(); i++) 526 | removeClause(cls[i]); 527 | 528 | // Produce clauses in cross product: 529 | vec& resolvent = add_tmp; 530 | for (int i = 0; i < pos.size(); i++) 531 | for (int j = 0; j < neg.size(); j++) 532 | if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent)) 533 | return false; 534 | 535 | // Free occurs list for this variable: 536 | occurs[v].clear(true); 537 | 538 | // Free watchers lists for this variable, if possible: 539 | if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true); 540 | if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true); 541 | 542 | return backwardSubsumptionCheck(); 543 | } 544 | 545 | 546 | bool SimpSolver::substitute(Var v, Lit x) 547 | { 548 | assert(!frozen[v]); 549 | assert(!isEliminated(v)); 550 | assert(value(v) == l_Undef); 551 | 552 | if (!ok) return false; 553 | 554 | eliminated[v] = true; 555 | setDecisionVar(v, false); 556 | const vec& cls = occurs.lookup(v); 557 | 558 | vec& subst_clause = add_tmp; 559 | for (int i = 0; i < cls.size(); i++){ 560 | Clause& c = ca[cls[i]]; 561 | 562 | subst_clause.clear(); 563 | for (int j = 0; j < c.size(); j++){ 564 | Lit p = c[j]; 565 | subst_clause.push(var(p) == v ? x ^ sign(p) : p); 566 | } 567 | 568 | removeClause(cls[i]); 569 | 570 | if (!addClause_(subst_clause)) 571 | return ok = false; 572 | } 573 | 574 | return true; 575 | } 576 | 577 | 578 | void SimpSolver::extendModel() 579 | { 580 | int i, j; 581 | Lit x; 582 | 583 | for (i = elimclauses.size()-1; i > 0; i -= j){ 584 | for (j = elimclauses[i--]; j > 1; j--, i--) 585 | if (modelValue(toLit(elimclauses[i])) != l_False) 586 | goto next; 587 | 588 | x = toLit(elimclauses[i]); 589 | model[var(x)] = lbool(!sign(x)); 590 | next:; 591 | } 592 | } 593 | 594 | 595 | bool SimpSolver::eliminate(bool turn_off_elim) 596 | { 597 | if (!simplify()) 598 | return false; 599 | else if (!use_simplification) 600 | return true; 601 | 602 | // Main simplification loop: 603 | // 604 | while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){ 605 | 606 | gatherTouchedClauses(); 607 | // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns); 608 | if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) && 609 | !backwardSubsumptionCheck(true)){ 610 | ok = false; goto cleanup; } 611 | 612 | // Empty elim_heap and return immediately on user-interrupt: 613 | if (asynch_interrupt){ 614 | assert(bwdsub_assigns == trail.size()); 615 | assert(subsumption_queue.size() == 0); 616 | assert(n_touched == 0); 617 | elim_heap.clear(); 618 | goto cleanup; } 619 | 620 | // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size()); 621 | for (int cnt = 0; !elim_heap.empty(); cnt++){ 622 | Var elim = elim_heap.removeMin(); 623 | 624 | if (asynch_interrupt) break; 625 | 626 | if (isEliminated(elim) || value(elim) != l_Undef) continue; 627 | 628 | if (verbosity >= 2 && cnt % 100 == 0) 629 | printf("elimination left: %10d\r", elim_heap.size()); 630 | 631 | if (use_asymm){ 632 | // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again: 633 | bool was_frozen = frozen[elim]; 634 | frozen[elim] = true; 635 | if (!asymmVar(elim)){ 636 | ok = false; goto cleanup; } 637 | frozen[elim] = was_frozen; } 638 | 639 | // At this point, the variable may have been set by assymetric branching, so check it 640 | // again. Also, don't eliminate frozen variables: 641 | if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){ 642 | ok = false; goto cleanup; } 643 | 644 | checkGarbage(simp_garbage_frac); 645 | } 646 | 647 | assert(subsumption_queue.size() == 0); 648 | } 649 | cleanup: 650 | 651 | // If no more simplification is needed, free all simplification-related data structures: 652 | if (turn_off_elim){ 653 | touched .clear(true); 654 | occurs .clear(true); 655 | n_occ .clear(true); 656 | elim_heap.clear(true); 657 | subsumption_queue.clear(true); 658 | 659 | use_simplification = false; 660 | remove_satisfied = true; 661 | ca.extra_clause_field = false; 662 | max_simp_var = nVars(); 663 | 664 | // Force full cleanup (this is safe and desirable since it only happens once): 665 | rebuildOrderHeap(); 666 | garbageCollect(); 667 | }else{ 668 | // Cheaper cleanup: 669 | checkGarbage(); 670 | } 671 | 672 | if (verbosity >= 1 && elimclauses.size() > 0) 673 | printf("| Eliminated clauses: %10.2f Mb |\n", 674 | double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024)); 675 | 676 | return ok; 677 | } 678 | 679 | 680 | //================================================================================================= 681 | // Garbage Collection methods: 682 | 683 | 684 | void SimpSolver::relocAll(ClauseAllocator& to) 685 | { 686 | if (!use_simplification) return; 687 | 688 | // All occurs lists: 689 | // 690 | for (int i = 0; i < nVars(); i++){ 691 | occurs.clean(i); 692 | vec& cs = occurs[i]; 693 | for (int j = 0; j < cs.size(); j++) 694 | ca.reloc(cs[j], to); 695 | } 696 | 697 | // Subsumption queue: 698 | // 699 | for (int i = subsumption_queue.size(); i > 0; i--){ 700 | CRef cr = subsumption_queue.peek(); subsumption_queue.pop(); 701 | if (ca[cr].mark()) continue; 702 | ca.reloc(cr, to); 703 | subsumption_queue.insert(cr); 704 | } 705 | 706 | // Temporary clause: 707 | // 708 | ca.reloc(bwdsub_tmpunit, to); 709 | } 710 | 711 | 712 | void SimpSolver::garbageCollect() 713 | { 714 | // Initialize the next region to a size corresponding to the estimated utilization degree. This 715 | // is not precise but should avoid some unnecessary reallocations for the new region: 716 | ClauseAllocator to(ca.size() - ca.wasted()); 717 | 718 | to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields. 719 | relocAll(to); 720 | Solver::relocAll(to); 721 | if (verbosity >= 2) 722 | printf("| Garbage collection: %12d bytes => %12d bytes |\n", 723 | ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); 724 | to.moveTo(ca); 725 | } 726 | --------------------------------------------------------------------------------