├── test ├── helpers │ ├── __init__.py │ ├── pycolortermhelp.py │ ├── inputhelper.py │ ├── processcall.py │ ├── sharpsathelper.py │ └── htmlresume.py ├── sharpSAT ├── res │ ├── modelcounts.txt │ └── cnflist.txt ├── checknumbers.py ├── comparetimes.py └── taketimes.py ├── src ├── component_types │ ├── CMakeLists.txt │ ├── component_archetype.cpp │ ├── base_packed_component.cpp │ ├── simple_unpacked_component.h │ ├── simple_packed_component.h │ ├── cacheable_component.h │ ├── component.h │ ├── base_packed_component.h │ ├── difference_packed_component.h │ └── component_archetype.h ├── CMakeLists.txt ├── solver_config.h ├── primitive_types.h ├── containers.h ├── component_management.cpp ├── main.cpp ├── statistics.cpp ├── containers │ └── binary_heap.h ├── structures.h ├── stack.h ├── component_management.h ├── component_cache.h ├── component_analyzer.cpp ├── component_cache-inl.h ├── new_component_analyzer.cpp ├── component_analyzer.h ├── new_component_analyzer.h ├── alt_component_analyzer.cpp ├── component_cache.cpp ├── instance.h ├── statistics.h ├── alt_component_analyzer.h ├── solver.h ├── instance.cpp └── solver.cpp ├── .gitignore ├── setupdev.sh ├── CMakeLists.txt ├── LICENSE └── README.md /test/helpers/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'thurley' 2 | -------------------------------------------------------------------------------- /test/sharpSAT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcthurley/sharpSAT/HEAD/test/sharpSAT -------------------------------------------------------------------------------- /src/component_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | SET(component_types_SOURCES 4 | base_packed_component.cpp 5 | component_archetype.cpp 6 | ) 7 | 8 | ADD_LIBRARY(component_types ${component_types_SOURCES}) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.d 3 | *.o 4 | *~ 5 | *.tar.gz 6 | *.out 7 | *.pyc 8 | 9 | 10 | # OS generated files # 11 | ###################### 12 | .DS_Store 13 | .DS_Store? 14 | ._* 15 | .Spotlight-V100 16 | .Trashes 17 | ehthumbs.db 18 | Thumbs.db 19 | .idea 20 | -------------------------------------------------------------------------------- /test/helpers/pycolortermhelp.py: -------------------------------------------------------------------------------- 1 | __author__ = 'thurley' 2 | 3 | 4 | from pycolorterm import pycolorterm 5 | 6 | class bcolors: 7 | HEADER = '\033[95m' 8 | OKBLUE = '\033[94m' 9 | OKGREEN = '\033[92m' 10 | WARNING = '\033[93m' 11 | FAIL = '\033[91m' 12 | ENDC = '\033[0m' 13 | -------------------------------------------------------------------------------- /src/component_types/component_archetype.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * component_archetype.cpp 3 | * 4 | * Created on: Feb 9, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #include "component_archetype.h" 9 | 10 | CA_SearchState *ComponentArchetype::seen_ = nullptr; 11 | unsigned ComponentArchetype::seen_byte_size_ = 0; 12 | -------------------------------------------------------------------------------- /setupdev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir build 4 | cd build 5 | 6 | mkdir Release 7 | cd Release 8 | 9 | cmake -DCMAKE_BUILD_TYPE=Release ../.. 10 | 11 | cd .. 12 | mkdir Debug 13 | cd Debug 14 | 15 | cmake -DCMAKE_BUILD_TYPE=Debug ../.. 16 | 17 | cd .. 18 | mkdir Profiling 19 | cd Profiling 20 | 21 | cmake -DCMAKE_BUILD_TYPE=Profiling ../.. 22 | 23 | -------------------------------------------------------------------------------- /test/helpers/inputhelper.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | __author__ = 'thurley' 4 | 5 | 6 | 7 | def read_filelist(filename): 8 | list = [] 9 | with open(filename, "r") as cnflistfile: 10 | for line in cnflistfile: 11 | cnfname = os.path.expandvars(os.path.expanduser(line)) 12 | list.append(cnfname.rstrip()) 13 | return list 14 | 15 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory (component_types) 2 | 3 | SET(SOURCES alt_component_analyzer.cpp 4 | component_analyzer.cpp 5 | component_cache.cpp 6 | component_management.cpp 7 | instance.cpp 8 | new_component_analyzer.cpp 9 | solver.cpp 10 | statistics.cpp) 11 | 12 | 13 | ADD_LIBRARY(libsharpSAT ${SOURCES} component_types) 14 | target_link_libraries (libsharpSAT component_types) 15 | -------------------------------------------------------------------------------- /src/solver_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * basic_types.h 3 | * 4 | * Created on: Jun 24, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef SOLVER_CONFIG_H_ 9 | #define SOLVER_CONFIG_H_ 10 | 11 | 12 | struct SolverConfiguration { 13 | 14 | bool perform_non_chron_back_track = true; 15 | 16 | // TODO component caching cannot be deactivated for now! 17 | bool perform_component_caching = true; 18 | bool perform_failed_lit_test = true; 19 | bool perform_pre_processing = true; 20 | 21 | unsigned long time_bound_seconds = 100000; 22 | 23 | bool verbose = false; 24 | 25 | // quiet = true will override verbose; 26 | bool quiet = false; 27 | }; 28 | 29 | #endif /* SOLVER_CONFIG_H_ */ 30 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (SHARPSAT) 3 | 4 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall") 5 | 6 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -O3 -DNDEBUG -Wall") 7 | 8 | set(CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS_PROFILING} -std=c++11 -O3 -g -DNDEBUG -Wall") 9 | 10 | IF(UNIX) 11 | IF(APPLE) 12 | include_directories(/opt/local/include) 13 | ELSE(APPLE) 14 | 15 | 16 | ENDIF(APPLE) 17 | ELSE(UNIX) 18 | 19 | ENDIF(UNIX) 20 | 21 | 22 | find_library(GMP_LIB gmp) 23 | find_library(GMPXX_LIB gmpxx) 24 | 25 | 26 | add_subdirectory(src) 27 | 28 | add_executable (sharpSAT src/main.cpp) 29 | target_link_libraries (sharpSAT libsharpSAT ${GMP_LIB} ${GMPXX_LIB}) 30 | -------------------------------------------------------------------------------- /src/primitive_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * primitive_types.h 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef PRIMITIVE_TYPES_H_ 9 | #define PRIMITIVE_TYPES_H_ 10 | 11 | #define varsSENTINEL 0 12 | #define clsSENTINEL NOT_A_CLAUSE 13 | 14 | 15 | typedef unsigned VariableIndex; 16 | typedef unsigned ClauseIndex; 17 | typedef unsigned ClauseOfs; 18 | 19 | typedef unsigned CacheEntryID; 20 | 21 | static const ClauseIndex NOT_A_CLAUSE(0); 22 | #define SENTINEL_CL NOT_A_CLAUSE 23 | 24 | 25 | enum SOLVER_StateT { 26 | 27 | NO_STATE, SUCCESS, TIMEOUT, ABORTED 28 | }; 29 | 30 | 31 | #ifdef DEBUG 32 | #define toDEBUGOUT(X) cout << X; 33 | #else 34 | #define toDEBUGOUT(X) 35 | #endif 36 | 37 | 38 | 39 | 40 | #endif /* PRIMITIVE_TYPES_H_ */ 41 | -------------------------------------------------------------------------------- /test/res/modelcounts.txt: -------------------------------------------------------------------------------- 1 | ~/Dropbox/SAT/CNF/logistics/logistics.b.cnf, 452617045003614325571584 2 | ~/Dropbox/SAT/CNF/various/ra.cnf, 18739277038847939886754019920358123424308469030992781557966909983211910963157763678726120154469030856807730587971859910379069462105489708001873004723798633342340521799560185957916958401869207109443355859123561156747098129524433371596461424856004227854241384374972430825095073282950873641 3 | ~/Dropbox/SAT/CNF/various/rb.cnf,538812462750928282721716308734898413194103864553832956073815148020987917365241105816807625188941823391012398976196112157887068449390989186368113511090801920577156367304804512491926215360520651047719401241944845883406098779319363314639309655779343140788696509960447536163784266937815828202118895534508004061478961506257883130142920912100543747226035966976598909666696626176 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 marcthurley 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/res/cnflist.txt: -------------------------------------------------------------------------------- 1 | ~/Dropbox/SAT/CNF/logistics/logistics.a.cnf 2 | ~/Dropbox/SAT/CNF/logistics/logistics.b.cnf 3 | ~/Dropbox/SAT/CNF/logistics/logistics.c.cnf 4 | ~/Dropbox/SAT/CNF/logistics/logistics.d.cnf 5 | ~/Dropbox/SAT/CNF/various/ra.cnf 6 | ~/Dropbox/SAT/CNF/various/rb.cnf 7 | ~/Dropbox/SAT/CNF/various/rc.cnf 8 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-1.cnf 9 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-2.cnf 10 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-3.cnf 11 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-4.cnf 12 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-5.cnf 13 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-6.cnf 14 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-7.cnf 15 | ~/Dropbox/SAT/CNF/bmc/bmc-galileo-8.cnf 16 | ~/Dropbox/SAT/CNF/bmc/bmc-galileo-9.cnf 17 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-10.cnf 18 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-11.cnf 19 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-12.cnf 20 | ~/Dropbox/SAT/CNF/bmc/bmc-ibm-13.cnf 21 | ~/Dropbox/SAT/CNF/Bejing/2bitadd_10.cnf 22 | ~/Dropbox/SAT/CNF/Bejing/2bitadd_11.cnf 23 | ~/Dropbox/SAT/CNF/Bejing/2bitadd_12.cnf 24 | ~/Dropbox/SAT/CNF/Bejing/2bitcomp_5.cnf 25 | ~/Dropbox/SAT/CNF/Bejing/2bitmax_6.cnf 26 | ~/Dropbox/SAT/CNF/Bejing/3blocks.cnf 27 | ~/Dropbox/SAT/CNF/Bejing/4blocks.cnf 28 | ~/Dropbox/SAT/CNF/Bejing/4blocksb.cnf 29 | 30 | 31 | -------------------------------------------------------------------------------- /test/helpers/processcall.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import time 4 | import signal 5 | 6 | __author__ = 'thurley' 7 | 8 | 9 | def wait_timeout(proc, seconds): 10 | """Wait for a process to finish, or raise exception after timeout""" 11 | start = time.time() 12 | end = start + seconds 13 | interval = 0.01 14 | 15 | while True: 16 | result = proc.poll() 17 | #print "waiting" 18 | if result is not None: 19 | return result 20 | if time.time() >= end: 21 | 22 | os.killpg(proc.pid, signal.SIGTERM) 23 | raise RuntimeError("Process timed out") 24 | time.sleep(interval) 25 | 26 | def run_with_timeout(seconds, *popenargs, **kwargs): 27 | if 'stdout' in kwargs: 28 | raise ValueError('stdout argument not allowed, it will be overridden.') 29 | process = subprocess.Popen(stdout=subprocess.PIPE, 30 | preexec_fn=os.setsid, *popenargs, **kwargs) 31 | retcode = wait_timeout(process, seconds) 32 | output, unused_err = process.communicate() 33 | 34 | if retcode: 35 | cmd = kwargs.get("args") 36 | if cmd is None: 37 | cmd = popenargs[0] 38 | raise subprocess.CalledProcessError(retcode, cmd, output=output) 39 | return output 40 | -------------------------------------------------------------------------------- /src/component_types/base_packed_component.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * base_packed_component.cpp 3 | * 4 | * Created on: Feb 4, 2013 5 | * Author: mthurley 6 | */ 7 | #include "base_packed_component.h" 8 | #include 9 | #include 10 | 11 | unsigned BasePackedComponent::_bits_per_clause = 0; 12 | unsigned BasePackedComponent::_bits_per_variable = 0; // bitsperentry 13 | unsigned BasePackedComponent::_variable_mask = 0; 14 | unsigned BasePackedComponent::_clause_mask = 0; // bitsperentry 15 | unsigned BasePackedComponent::_debug_static_val=0; 16 | unsigned BasePackedComponent::_bits_of_data_size=0; 17 | unsigned BasePackedComponent::_data_size_mask = 0; 18 | 19 | 20 | void BasePackedComponent::adjustPackSize(unsigned int maxVarId, 21 | unsigned int maxClId) { 22 | 23 | _bits_per_variable = log2(maxVarId) + 1; 24 | _bits_per_clause = log2(maxClId) + 1; 25 | 26 | _bits_of_data_size = log2(maxVarId + maxClId) + 1; 27 | 28 | _variable_mask = _clause_mask = _data_size_mask = 0; 29 | for (unsigned int i = 0; i < _bits_per_variable; i++) 30 | _variable_mask = (_variable_mask << 1) + 1; 31 | for (unsigned int i = 0; i < _bits_per_clause; i++) 32 | _clause_mask = (_clause_mask << 1) + 1; 33 | for (unsigned int i = 0; i < _bits_of_data_size; i++) 34 | _data_size_mask = (_data_size_mask << 1) + 1; 35 | } 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/containers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * containers.h 3 | * 4 | * Created on: Jun 27, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef CONTAINERS_H_ 9 | #define CONTAINERS_H_ 10 | 11 | #include "structures.h" 12 | 13 | template 14 | class LiteralIndexedVector: protected vector<_T> { 15 | 16 | public: 17 | LiteralIndexedVector(unsigned size = 0) : 18 | vector<_T>(size * 2) { 19 | } 20 | LiteralIndexedVector(unsigned size, 21 | const typename vector<_T>::value_type& __value) : 22 | vector<_T>(size * 2, __value) { 23 | } 24 | inline _T &operator[](const LiteralID lit) { 25 | return *(vector<_T>::begin() + lit.raw()); 26 | } 27 | 28 | inline const _T &operator[](const LiteralID &lit) const { 29 | return *(vector<_T>::begin() + lit.raw()); 30 | } 31 | 32 | inline typename vector<_T>::iterator begin() { 33 | return vector<_T>::begin() + 2; 34 | } 35 | 36 | void resize(unsigned _size) { 37 | vector<_T>::resize(_size * 2); 38 | } 39 | void resize(unsigned _size, const typename vector<_T>::value_type& _value) { 40 | vector<_T>::resize(_size * 2, _value); 41 | } 42 | 43 | void reserve(unsigned _size) { 44 | vector<_T>::reserve(_size * 2); 45 | } 46 | 47 | LiteralID end_lit() { 48 | return LiteralID(size() / 2, false); 49 | } 50 | 51 | using vector<_T>::end; 52 | using vector<_T>::size; 53 | using vector<_T>::clear; 54 | using vector<_T>::push_back; 55 | }; 56 | 57 | #endif /* CONTAINERS_H_ */ 58 | -------------------------------------------------------------------------------- /test/helpers/sharpsathelper.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import time 3 | from helpers.processcall import run_with_timeout 4 | 5 | __author__ = 'thurley' 6 | 7 | 8 | 9 | def run_all_on_list(timeout, cnf_list, binaries): 10 | list = [] 11 | for p in cnf_list: 12 | instance_entry = [p] 13 | for binary in binaries: 14 | time = take_time(binary, p, timeout) 15 | instance_entry.append(time) 16 | list.append(instance_entry) 17 | return list 18 | 19 | 20 | 21 | def run_sharpsat_get_number(binary, arg, timeout): 22 | try: 23 | print("Running " + binary + " " + arg) 24 | output = run_with_timeout(timeout, [binary, arg], stderr=subprocess.STDOUT) 25 | #print(output) 26 | except OSError as E: 27 | print("OS Error") 28 | print(E.message) 29 | #print(output) 30 | return "0" 31 | i = output.find("# solutions") 32 | j = output.find("# END") 33 | try: 34 | return output[i:j].split("\n")[1] 35 | except IndexError as e: 36 | print(e) 37 | print(output) 38 | 39 | 40 | def take_time(binary, arg, timeout): 41 | try: 42 | start = time.time() 43 | number = run_sharpsat_get_number(binary, arg, timeout) 44 | time_taken = time.time() - start 45 | except RuntimeError as e: 46 | time_taken = 2*timeout 47 | except subprocess.CalledProcessError as E: 48 | erroroutput = "sharpSAT exited with exit code" + str(E.returncode) + "\n" + E.output 49 | time_taken = 2*timeout 50 | 51 | stringtime = '--' if time_taken >= timeout else repr(round(time_taken, 3)) 52 | 53 | print("Time " + '\t' + stringtime + "s") 54 | return time_taken -------------------------------------------------------------------------------- /src/component_management.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * component_management.cpp 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #include "component_management.h" 9 | 10 | void ComponentManager::initialize(LiteralIndexedVector & literals, 11 | vector &lit_pool) { 12 | 13 | ana_.initialize(literals, lit_pool); 14 | // BEGIN CACHE INIT 15 | CacheableComponent::adjustPackSize(ana_.max_variable_id(), ana_.max_clause_id()); 16 | 17 | component_stack_.clear(); 18 | component_stack_.reserve(ana_.max_variable_id() + 2); 19 | component_stack_.push_back(new Component()); 20 | component_stack_.push_back(new Component()); 21 | assert(component_stack_.size() == 2); 22 | component_stack_.back()->createAsDummyComponent(ana_.max_variable_id(), 23 | ana_.max_clause_id()); 24 | 25 | 26 | cache_.init(*component_stack_.back()); 27 | } 28 | 29 | 30 | void ComponentManager::removeAllCachePollutionsOf(StackLevel &top) { 31 | // all processed components are found in 32 | // [top.currentRemainingComponent(), component_stack_.size()) 33 | // first, remove the list of descendants from the father 34 | assert(top.remaining_components_ofs() <= component_stack_.size()); 35 | assert(top.super_component() != 0); 36 | assert(cache_.hasEntry(superComponentOf(top).id())); 37 | 38 | if (top.remaining_components_ofs() == component_stack_.size()) 39 | return; 40 | 41 | for (unsigned u = top.remaining_components_ofs(); u < component_stack_.size(); 42 | u++) { 43 | assert(cache_.hasEntry(component_stack_[u]->id())); 44 | cache_.cleanPollutionsInvolving(component_stack_[u]->id()); 45 | } 46 | 47 | #ifdef DEBUG 48 | cache_.test_descendantstree_consistency(); 49 | #endif 50 | } 51 | -------------------------------------------------------------------------------- /test/helpers/htmlresume.py: -------------------------------------------------------------------------------- 1 | __author__ = 'thurley' 2 | 3 | 4 | class Htmlwriter: 5 | # file object 6 | 7 | def __init__(self, filename): 8 | self.f = open(filename, 'w') 9 | 10 | def make_document(self, head, body): 11 | self.f.write("\n") 12 | self.f.write("
" 13 | + head 14 | + "
") 15 | self.f.write("" 16 | + body 17 | + "") 18 | self.f.write("") 19 | 20 | 21 | 22 | 23 | 24 | 25 | def add_tag(tag, text): 26 | return "<" + tag + ">" + text + "" 27 | 28 | def add_tag_w_attr(tag, attributes, text): 29 | return "<" + tag + " " + attributes + ">" + text + "" 30 | 31 | def add_cell(text): 32 | return add_tag("td", text) 33 | 34 | def add_cell_w_attr(attr, text): 35 | return add_tag_w_attr("td", attr, text) 36 | 37 | def add_row(content): 38 | return add_tag("tr", content) 39 | 40 | def produce_html_rows(rowlist): 41 | htmlrows = "" 42 | for row in rowlist: 43 | rowcontent = "" 44 | for cell in row: 45 | rowcontent += add_cell(cell) 46 | htmlrows += add_row(rowcontent) 47 | return htmlrows 48 | 49 | def produce_html_rows_w_classes(rowlist): 50 | htmlrows = "" 51 | for row in rowlist: 52 | rowcontent = "" 53 | for cell in row: 54 | rowcontent += add_cell_w_attr("class=\"" + cell[0] + "\"", cell[1]) 55 | htmlrows += add_row(rowcontent) 56 | return htmlrows 57 | 58 | class Htmltable: 59 | 60 | def __init__(self): 61 | self.head = [[]] 62 | self.content = [[]] 63 | def add_row_w_cell_classes(self, cells): 64 | self.content.append(cells) 65 | 66 | def add_header_w_cell_classes(self, cells): 67 | self.head.append(cells) 68 | 69 | def make(self): 70 | head = add_tag("thead", produce_html_rows_w_classes(self.head)) 71 | content = add_tag("tbody", produce_html_rows_w_classes(self.content)) 72 | return add_tag_w_attr("table", "border=\"0\" cellpadding=\"2\" cellspacing=\"2\" style=\"font-family:arial;width:854px\"", head + content) 73 | -------------------------------------------------------------------------------- /src/component_types/simple_unpacked_component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * simple_unpacked_component.h 3 | * 4 | * Created on: Feb 16, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef SIMPLE_UNPACKED_COMPONENT_H_ 9 | #define SIMPLE_UNPACKED_COMPONENT_H_ 10 | 11 | #include "base_packed_component.h" 12 | #include "component.h" 13 | 14 | 15 | #include "../primitive_types.h" 16 | 17 | class SimpleUnpackedComponent : public BasePackedComponent { 18 | public: 19 | 20 | SimpleUnpackedComponent() { 21 | } 22 | 23 | inline SimpleUnpackedComponent(Component &rComp); 24 | 25 | unsigned num_variables() { 26 | return *(data_+1); 27 | } 28 | 29 | unsigned data_size() const { 30 | return *data_; 31 | } 32 | 33 | unsigned data_only_byte_size() const { 34 | return data_size()* sizeof(unsigned); 35 | } 36 | 37 | unsigned raw_data_byte_size() const { 38 | return data_size()* sizeof(unsigned) 39 | + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t); 40 | } 41 | 42 | bool equals(const SimpleUnpackedComponent &comp) const { 43 | if(hashkey_ != comp.hashkey()) 44 | return false; 45 | unsigned* p = data_; 46 | unsigned* r = comp.data_; 47 | while(p != data_ + data_size()) { 48 | if(*(p++) != *(r++)) 49 | return false; 50 | } 51 | return true; 52 | } 53 | }; 54 | 55 | 56 | SimpleUnpackedComponent::SimpleUnpackedComponent(Component &rComp) { 57 | 58 | unsigned data_size = rComp.num_variables() + rComp.numLongClauses() + 2; 59 | 60 | unsigned *p = data_ = new unsigned[data_size]; 61 | 62 | *p = data_size; 63 | *(++p) = rComp.num_variables(); 64 | unsigned hashkey_vars = 0; 65 | for (auto it = rComp.varsBegin(); *it != varsSENTINEL; it++) { 66 | *(++p) = *it; 67 | hashkey_vars = (hashkey_vars *3) + *it; 68 | } 69 | 70 | unsigned hashkey_clauses = 0; 71 | 72 | for (auto jt = rComp.clsBegin(); *jt != clsSENTINEL; jt++) { 73 | *(++p) = *jt; 74 | hashkey_clauses = (hashkey_clauses *3) + *jt; 75 | } 76 | //*(++p) = 0; 77 | 78 | hashkey_ = hashkey_vars + (((unsigned) hashkey_clauses) << 16); 79 | 80 | assert(p - data_ + 1 == data_size); 81 | 82 | } 83 | 84 | 85 | 86 | #endif /* SIMPLE_UNPACKED_COMPONENT_H_ */ 87 | -------------------------------------------------------------------------------- /test/checknumbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import csv 3 | import os 4 | import subprocess 5 | import sys 6 | from helpers.pycolortermhelp import bcolors 7 | from helpers.sharpsathelper import run_sharpsat_get_number 8 | 9 | SECONDS = 10 10 | 11 | __author__ = 'thurley' 12 | # 13 | 14 | def printPassed(s): 15 | print(bcolors.OKGREEN + "PASSED " + bcolors.ENDC + s) 16 | def printWarn(s): 17 | print(bcolors.WARNING + "WARN " + bcolors.ENDC + s) 18 | def printFAIL(s): 19 | print(bcolors.FAIL + "FAIL " + bcolors.ENDC + s) 20 | 21 | def read_modelcounts(filename): 22 | list = [] 23 | with open(filename, "r") as countscsvfile: 24 | countreader = csv.reader(countscsvfile) 25 | for row in countreader: 26 | cnfname = os.path.expandvars(os.path.expanduser(row[0].rstrip())) 27 | list.append([cnfname, row[1].strip()]) 28 | return list 29 | 30 | def run_on_countlist(binary, countlist): 31 | numfail = 0 32 | for p in countlist: 33 | try: 34 | number = run_sharpsat_get_number(binary, p[0], SECONDS) 35 | if p[1] == number: 36 | printPassed(p[0] + "; " + p[1]) 37 | else: 38 | numfail += 1 39 | printFAIL(p[0]) 40 | print (" expected # " + p[1]) 41 | print (" seen # " + number) 42 | 43 | except subprocess.CalledProcessError as E: 44 | erroroutput = "sharpSAT exited with exit code" + str(E.returncode) + "\n" + E.output 45 | return numfail 46 | 47 | 48 | 49 | PATH_TO_SHARPSAT_BINARY = os.path.expandvars(os.path.expanduser(sys.argv[1])) 50 | 51 | #CSV file containing file, modelcount 52 | CHECKFILE = os.path.expandvars(os.path.expanduser(sys.argv[2])) 53 | 54 | print(sys.argv[1], CHECKFILE) 55 | 56 | counts = read_modelcounts(CHECKFILE) 57 | numfail = run_on_countlist(PATH_TO_SHARPSAT_BINARY, counts) 58 | 59 | if numfail != 0: 60 | print (str(len(counts) - numfail) + " TESTS PASSED " + bcolors.FAIL + str(numfail) + " FAILED" + bcolors.ENDC) 61 | else: 62 | print (bcolors.OKGREEN + "All " + str(len(counts)) + " PASSED " + bcolors.ENDC) 63 | #for r in list: 64 | # print("aw " + r[0] + "; " + r[1]) 65 | 66 | #cmd = [sys.argv[1], sys.argv[2]] 67 | # 68 | #try: 69 | # output = run_with_timeout(10, cmd, stderr=subprocess.STDOUT) 70 | #except subprocess.CalledProcessError as E: 71 | # erroroutput = "sharpSAT exited with exit code" + str(E.returncode) + "\n" + E.output 72 | # 73 | #if len(output) > 0: 74 | # i = output.find("# solutions") 75 | # 76 | # j = output.find("# END") 77 | # 78 | # number = output[i:j].split("\n")[1] 79 | # print output 80 | # print number -------------------------------------------------------------------------------- /src/component_types/simple_packed_component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * simple_packed_component.h 3 | * 4 | * Created on: Feb 4, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef SIMPLE_PACKED_COMPONENT_H_ 9 | #define SIMPLE_PACKED_COMPONENT_H_ 10 | 11 | #include "base_packed_component.h" 12 | #include "component.h" 13 | 14 | 15 | #include "../primitive_types.h" 16 | 17 | class SimplePackedComponent : public BasePackedComponent { 18 | public: 19 | 20 | SimplePackedComponent() { 21 | } 22 | 23 | inline SimplePackedComponent(Component &rComp); 24 | 25 | unsigned num_variables() const{ 26 | uint64_t *p = (uint64_t *) data_; 27 | return (*p >> bits_of_data_size()) & (uint64_t) variable_mask(); 28 | } 29 | 30 | unsigned data_size() const { 31 | return *data_ & _data_size_mask; 32 | } 33 | 34 | unsigned data_only_byte_size() const { 35 | return data_size()* sizeof(unsigned); 36 | } 37 | 38 | unsigned raw_data_byte_size() const { 39 | return data_size()* sizeof(unsigned) 40 | + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t); 41 | } 42 | 43 | bool equals(const SimplePackedComponent &comp) const { 44 | if(hashkey_ != comp.hashkey()) 45 | return false; 46 | unsigned* p = data_; 47 | unsigned* r = comp.data_; 48 | while(p != data_ + data_size()) { 49 | if(*(p++) != *(r++)) 50 | return false; 51 | } 52 | return true; 53 | } 54 | 55 | }; 56 | 57 | SimplePackedComponent::SimplePackedComponent(Component &rComp) { 58 | unsigned data_size_vars = bits_of_data_size() + bits_per_variable() + rComp.num_variables() * bits_per_variable(); 59 | unsigned data_size_clauses = rComp.numLongClauses() * bits_per_clause(); 60 | unsigned data_size = (data_size_vars + data_size_clauses)/bits_per_block(); 61 | 62 | data_size+= ((data_size_vars + data_size_clauses) % bits_per_block())? 1 : 0; 63 | 64 | data_ = new unsigned[data_size]; 65 | 66 | BitStuffer bs(data_); 67 | unsigned hashkey_vars = 0; 68 | unsigned hashkey_clauses = 0; 69 | 70 | assert((data_size >> bits_of_data_size()) == 0); 71 | 72 | bs.stuff(data_size, bits_of_data_size()); 73 | bs.stuff(rComp.num_variables(),bits_per_variable()); 74 | 75 | for (auto it = rComp.varsBegin(); *it != varsSENTINEL; it++) { 76 | hashkey_vars = (hashkey_vars *3) + *it; 77 | bs.stuff(*it, bits_per_variable()); 78 | } 79 | 80 | if (*rComp.clsBegin()) 81 | for (auto jt = rComp.clsBegin(); *jt != clsSENTINEL; jt++) { 82 | hashkey_clauses = (hashkey_clauses *3) + *jt; 83 | bs.stuff(*jt, bits_per_clause()); 84 | } 85 | bs.assert_size(data_size); 86 | 87 | hashkey_ = hashkey_vars + (((unsigned) hashkey_clauses) << 16); 88 | } 89 | 90 | #endif /* SIMPLE_PACKED_COMPONENT_H_ */ 91 | -------------------------------------------------------------------------------- /src/component_types/cacheable_component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cacheable_component.h 3 | * 4 | * Created on: Feb 21, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef CACHEABLE_COMPONENT_H_ 9 | #define CACHEABLE_COMPONENT_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "../primitive_types.h" 15 | 16 | #include "difference_packed_component.h" 17 | //#include "simple_unpacked_component.h" 18 | 19 | 20 | using namespace std; 21 | 22 | #define NIL_ENTRY 0 23 | 24 | class Component; 25 | class ComponentArchetype; 26 | 27 | 28 | // GenericCacheableComponent Adds Structure to PackedComponent that is 29 | // necessary to store it in the cache 30 | // namely, the descendant tree structure that 31 | // allows for the removal of cache pollutions 32 | 33 | template< class T_Component> 34 | class GenericCacheableComponent: public T_Component { 35 | public: 36 | GenericCacheableComponent() { 37 | } 38 | 39 | GenericCacheableComponent(Component &comp) : 40 | T_Component(comp) { 41 | } 42 | 43 | unsigned long SizeInBytes() const { 44 | return sizeof(GenericCacheableComponent) 45 | + T_Component::raw_data_byte_size(); 46 | } 47 | 48 | // the 48 = 16*3 in overhead stems from the three parts of the component 49 | // being dynamically allocated (i.e. the GenericCacheableComponent itself, 50 | // the data_ and the model_count data 51 | unsigned long sys_overhead_SizeInBytes() const { 52 | return sizeof(GenericCacheableComponent) 53 | + T_Component::sys_overhead_raw_data_byte_size() 54 | // + 24; 55 | +48; 56 | } 57 | 58 | // BEGIN Cache Pollution Management 59 | 60 | void set_father(CacheEntryID f) { 61 | father_ = f; 62 | } 63 | const CacheEntryID father() const { 64 | return father_; 65 | } 66 | 67 | void set_next_sibling(CacheEntryID sibling) { 68 | next_sibling_ = sibling; 69 | } 70 | CacheEntryID next_sibling() { 71 | return next_sibling_; 72 | } 73 | 74 | void set_first_descendant(CacheEntryID descendant) { 75 | first_descendant_ = descendant; 76 | } 77 | CacheEntryID first_descendant() { 78 | return first_descendant_; 79 | } 80 | 81 | 82 | 83 | void set_next_bucket_element(CacheEntryID entry) { 84 | next_bucket_element_ = entry; 85 | } 86 | 87 | CacheEntryID next_bucket_element() { 88 | return next_bucket_element_; 89 | } 90 | 91 | private: 92 | 93 | CacheEntryID next_bucket_element_ = 0; 94 | 95 | // theFather and theDescendants: 96 | // each CCacheEntry is a Node in a tree which represents the relationship 97 | // of the components stored 98 | CacheEntryID father_ = 0; 99 | CacheEntryID first_descendant_ = 0; 100 | CacheEntryID next_sibling_ = 0; 101 | 102 | }; 103 | 104 | 105 | 106 | typedef GenericCacheableComponent CacheableComponent; 107 | //typedef GenericCacheableComponent CacheableComponent; 108 | 109 | 110 | 111 | 112 | 113 | #endif /* CACHEABLE_COMPONENT_H_ */ 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ========= 2 | sharpSAT 3 | ========= 4 | 5 | sharpSAT is a #SAT solver based on modern DPLL based SAT solver technology. 6 | This is a new version with several incremental improvements over the 2006 7 | sharpSAT 1.1 which has been published at SAT 2006. 8 | 9 | This version also fixed several bugs - most importantly a counting bug, 10 | that causes sharpSAT to report wrong model counts on some instances. 11 | 12 | ========= 13 | Usage 14 | ========= 15 | 16 | Usage: sharpSAT [options] [CNF_File] 17 | Options: 18 | -noPP turn off preprocessing 19 | -noCC turn off component caching 20 | -noIBCP turn off implicit BCP 21 | -q quiet mode 22 | -t [s] set time bound to s seconds 23 | -cs [n] set max cache size to n MB 24 | 25 | 26 | ========= 27 | Building 28 | ========= 29 | 30 | It suffices to change to the ./Release subdirectory and run 31 | 32 | make 33 | 34 | 35 | NOTE: 36 | 37 | - it is necessary to have at least G++ 4.7 installed for sharpSAT to 38 | compile. This is particularly necessary as we use delegating constructors 39 | 40 | - the GMP bignum package has to be installed in your system 41 | 42 | 43 | 44 | ========= 45 | Changes 46 | ========= 47 | 48 | > 12.08 < 49 | 50 | - rewrote most of the codebase of the solver, including a redesigned SAT solver 51 | foundation based on more recent developments such as MiniSAT and TiniSAT, 52 | e.g. conflict clause minimization is used now 53 | 54 | - disentangled component analysis and the SAT solver part by separating the 55 | datastructures. Although this imposes a small memory overhead it allows 56 | for simpler and faster algorithms both in the SAT solver and in the component 57 | analysis part. 58 | 59 | - the redesign reduced the number of code lines by more than 30% 60 | 61 | - implicit BCP is more efficient now since for every failed literal l found 62 | every literal corresponding to a UIP of the conflict caused by l is asserted 63 | and add a UIP clause for that conflict is added 64 | 65 | - changed the decision heursitics to floating point values, and changed 66 | the VSADS weighting and the activity decay rate. 67 | 68 | - As it does not make sense to use only finite precision, the GMP bignumber 69 | package is now a prerequisite for sharpSAT. This also has to do with the 70 | fact that we use GMP integer arithmetic now instead of GMP floating points 71 | which is both simpler and has a small memory advantage. 72 | 73 | - A new coding of the cached components is introduced which frequently saves 74 | 30 - 50% of cache memory. 75 | 76 | - reduced the memory overhead of cached components to less than 40% of the 77 | original overhead 78 | 79 | - cache size will now be automatically set to at most 95% of the free RAM 80 | available at program start. This can be overridden, however, by setting the 81 | maximum cache size using the "-cs" option 82 | 83 | 84 | BUGFIXES 85 | 86 | - corrected a bug in the use of the GMP bignumber package that caused (among others) 87 | wrong solution counts reported on bmc-ibm-5, bmc-ibm-10, ra, rb, and rc. 88 | 89 | - the solver is fully 64bit compliant now; esepcially the cache size can now be 90 | larger than GB 91 | 92 | - several out-of-memory problems with the old sharpSAT have been resolved 93 | -------------------------------------------------------------------------------- /src/component_types/component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component.h 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef COMPONENT_H_ 9 | #define COMPONENT_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "../primitive_types.h" 15 | 16 | using namespace std; 17 | 18 | class Component { 19 | public: 20 | 21 | void reserveSpace(unsigned int num_variables, unsigned int num_clauses) { 22 | data_.reserve(num_variables + num_clauses + 2); 23 | } 24 | 25 | void set_id(CacheEntryID id) { 26 | id_ = id; 27 | } 28 | 29 | CacheEntryID id() const{ 30 | return id_; 31 | } 32 | 33 | void addVar(const VariableIndex var) { 34 | // the only time a varsSENTINEL is added should be in a 35 | // call to closeVariableData(..) 36 | assert(var != varsSENTINEL); 37 | data_.push_back(var); 38 | } 39 | 40 | void closeVariableData() { 41 | data_.push_back(varsSENTINEL); 42 | clauses_ofs_ = data_.size(); 43 | } 44 | 45 | void addCl(const ClauseIndex cl) { 46 | // the only time a clsSENTINEL is added should be in a 47 | // call to closeClauseData(..) 48 | assert(cl != clsSENTINEL); 49 | data_.push_back(cl); 50 | } 51 | 52 | void closeClauseData() { 53 | data_.push_back(clsSENTINEL); 54 | assert(*(clsBegin()-1) == 0); 55 | } 56 | 57 | vector::const_iterator varsBegin() const { 58 | return data_.begin(); 59 | } 60 | 61 | vector::const_iterator clsBegin() const { 62 | return data_.begin() + clauses_ofs_; 63 | } 64 | 65 | unsigned num_variables() const { 66 | return clauses_ofs_ - 1; 67 | } 68 | 69 | unsigned numLongClauses() const { 70 | return data_.size() - clauses_ofs_ - 1; 71 | } 72 | 73 | bool empty() const { 74 | return data_.empty(); 75 | } 76 | 77 | void createAsDummyComponent(unsigned max_var_id, unsigned max_clause_id) { 78 | data_.clear(); 79 | clauses_ofs_ = 1; 80 | for (unsigned idvar = 1; idvar <= max_var_id; idvar++) 81 | addVar(idvar); 82 | closeVariableData(); 83 | if (max_clause_id > 0) 84 | for (unsigned idcl = 1; idcl <= max_clause_id; idcl++) 85 | addCl(idcl); 86 | closeClauseData(); 87 | } 88 | 89 | void clear() { 90 | clauses_ofs_ = 0; 91 | data_.clear(); 92 | } 93 | 94 | private: 95 | // data_ stores the component data: 96 | // for better cache performance the 97 | // clause and variable data are stored in 98 | // a contiguous piece of memory 99 | // variables SENTINEL clauses SENTINEL 100 | // this order has to be taken care of on filling 101 | // in the data! 102 | vector data_; 103 | unsigned clauses_ofs_ = 0; 104 | // id_ will identify denote the entry in the cacheable component database, 105 | // where a Packed version of this component is stored 106 | // yet this does not imply that the model count of this component is already known 107 | // once the model count is known, a link to the packed component will be stored 108 | // in the hash table 109 | CacheEntryID id_ = 0; 110 | }; 111 | 112 | 113 | 114 | #endif /* COMPONENT_H_ */ 115 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "solver.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | //#include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | 16 | int main(int argc, char *argv[]) { 17 | 18 | string input_file; 19 | Solver theSolver; 20 | 21 | 22 | if (argc <= 1) { 23 | cout << "Usage: sharpSAT [options] [CNF_File]" << endl; 24 | cout << "Options: " << endl; 25 | cout << "\t -noPP \t turn off preprocessing" << endl; 26 | cout << "\t -q \t quiet mode" << endl; 27 | cout << "\t -t [s] \t set time bound to s seconds" << endl; 28 | cout << "\t -noCC \t turn off component caching" << endl; 29 | cout << "\t -cs [n]\t set max cache size to n MB" << endl; 30 | cout << "\t -noIBCP\t turn off implicit BCP" << endl; 31 | cout << "\t" << endl; 32 | 33 | return -1; 34 | } 35 | 36 | for (int i = 1; i < argc; i++) { 37 | if (strcmp(argv[i], "-noCC") == 0) 38 | theSolver.config().perform_component_caching = false; 39 | if (strcmp(argv[i], "-noIBCP") == 0) 40 | theSolver.config().perform_failed_lit_test = false; 41 | if (strcmp(argv[i], "-noPP") == 0) 42 | theSolver.config().perform_pre_processing = false; 43 | else if (strcmp(argv[i], "-q") == 0) 44 | theSolver.config().quiet = true; 45 | else if (strcmp(argv[i], "-v") == 0) 46 | theSolver.config().verbose = true; 47 | else if (strcmp(argv[i], "-t") == 0) { 48 | if (argc <= i + 1) { 49 | cout << " wrong parameters" << endl; 50 | return -1; 51 | } 52 | theSolver.config().time_bound_seconds = atol(argv[i + 1]); 53 | if (theSolver.config().verbose) 54 | cout << "time bound set to" << theSolver.config().time_bound_seconds << "s\n"; 55 | } else if (strcmp(argv[i], "-cs") == 0) { 56 | if (argc <= i + 1) { 57 | cout << " wrong parameters" << endl; 58 | return -1; 59 | } 60 | theSolver.statistics().maximum_cache_size_bytes_ = atol(argv[i + 1]) * (uint64_t) 1000000; 61 | } else 62 | input_file = argv[i]; 63 | } 64 | 65 | theSolver.solve(input_file); 66 | 67 | // cout << sizeof(LiteralID)<<"MALLOC_STATS:" << endl; 68 | // malloc_stats(); 69 | 70 | // rusage ru; 71 | // getrusage(RUSAGE_SELF,&ru); 72 | // 73 | // cout << "\nRus: " << ru.ru_maxrss*1024 << endl; 74 | // cout << "\nMALLINFO:" << endl; 75 | // 76 | // cout << "total " << mallinfo().arena + mallinfo().hblkhd << endl; 77 | // cout << mallinfo().arena << "non-mmapped space allocated from system " << endl; 78 | // cout << mallinfo().ordblks << "number of free chunks " << endl; 79 | // cout << mallinfo().smblks<< "number of fastbin blocks " << endl; 80 | // cout << mallinfo().hblks<< " number of mmapped regions " << endl; 81 | // cout << mallinfo().hblkhd<< "space in mmapped regions " << endl; 82 | // cout << mallinfo().usmblks<< " maximum total allocated space " << endl; 83 | // cout << mallinfo().fsmblks<< "space available in freed fastbin blocks " << endl; 84 | // cout << mallinfo().uordblks<< " total allocated space " << endl; 85 | // cout << mallinfo().fordblks<< "total free space " << endl; 86 | // cout << mallinfo().keepcost<< " top-most, releasable (via malloc_trim) space " << endl; 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /src/statistics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * statistics.cpp 3 | * 4 | * Created on: Feb 13, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #include "statistics.h" 9 | 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | void DataAndStatistics::print_final_solution_count() { 16 | cout << final_solution_count_.get_str(); 17 | } 18 | 19 | void DataAndStatistics::writeToFile(const string & file_name) { 20 | ofstream out(file_name, ios_base::app); 21 | unsigned pos = input_file_.find_last_of("/\\"); 22 | out << "" << endl; 23 | out << "" << input_file_.substr(pos + 1) << "" << endl; 24 | out << "" << num_original_variables_ << "" << endl; 25 | out << "" << num_original_clauses_ << "" << endl; 26 | out << "" << num_decisions_ << "" << endl; 27 | out << "" << time_elapsed_ << "" << endl; 28 | 29 | string s = final_solution_count_.get_str(); 30 | if (final_solution_count_ == 0) 31 | s = "UNSAT"; 32 | out << "" << s << "" << endl; 33 | out << "" << endl; 34 | } 35 | 36 | void DataAndStatistics::printShort() { 37 | if (exit_state_ == TIMEOUT) { 38 | cout << endl << " TIMEOUT !" << endl; 39 | return; 40 | } 41 | cout << endl << endl; 42 | cout << "variables (total / active / free)\t" << num_variables_ << "/" 43 | << num_used_variables_ << "/" << num_variables_ - num_used_variables_ 44 | << endl; 45 | cout << "clauses (removed) \t\t\t" << num_original_clauses_ << " (" 46 | << num_original_clauses_ - num_clauses() << ")" << endl; 47 | cout << "decisions \t\t\t\t" << num_decisions_ << endl; 48 | cout << "conflicts \t\t\t\t" << num_conflicts_ << endl; 49 | cout << "conflict clauses (all/bin/unit) \t"; 50 | cout << num_conflict_clauses(); 51 | cout << "/" << num_binary_conflict_clauses_ << "/" << num_unit_clauses_ 52 | << endl << endl; 53 | cout << "failed literals found by implicit BCP \t " 54 | << num_failed_literals_detected_ << endl; 55 | 56 | 57 | cout << "implicit BCP miss rate \t " << implicitBCP_miss_rate() * 100 << "%"; 58 | cout << endl; 59 | cout << "bytes cache size \t" << cache_bytes_memory_usage() << "\t" 60 | << endl; 61 | 62 | cout << "bytes cache (overall) \t" << overall_cache_bytes_memory_stored() 63 | << "" << endl; 64 | cout << "bytes cache (infra / comps) " 65 | << (cache_infrastructure_bytes_memory_usage_) << "/" 66 | << sum_bytes_cached_components_ << "\t" << endl; 67 | 68 | cout << "bytes pure comp data (curr) " << sum_bytes_pure_cached_component_data_ << "" << endl; 69 | cout << "bytes pure comp data (overall) " <= timeout else repr(round(time, 3)) 16 | 17 | def bold(s, yes): 18 | if yes : 19 | return "" + s + "" 20 | return s 21 | 22 | def store_results(filename, binary1, binary2, list): 23 | f = open(filename, 'w') 24 | 25 | num_instances = len(list) 26 | num_successes1 = 0 27 | total_time1 = 0 28 | sync_total_time1 = 0 29 | num_successes2 = 0 30 | total_time2 = 0 31 | sync_total_time2 = 0 32 | for p in list: 33 | 34 | if p[1] < TIMEOUT: 35 | num_successes1 += 1 36 | total_time1 += p[1] 37 | if p[2] < TIMEOUT: 38 | sync_total_time1 += p[1] 39 | sync_total_time2 += p[2] 40 | 41 | if p[2] < TIMEOUT: 42 | num_successes2 += 1 43 | total_time2 += p[2] 44 | 45 | 46 | total_penalty_time1 = TIMEOUT*(num_instances - num_successes1) 47 | total_penalty_time2 = TIMEOUT*(num_instances - num_successes2) 48 | 49 | 50 | f.write("
\n") 51 | f.write("\n") 52 | f.write("") 53 | f.write("") 54 | f.write("") 55 | f.write("") 56 | f.write("") 57 | f.write("") 58 | f.write("") 59 | f.write("") 60 | f.write("") 61 | onesmaller = total_time1 < total_time2 62 | 63 | f.write("") 64 | onesmaller = sync_total_time1 < sync_total_time2 65 | f.write("") 66 | f.write("") 67 | f.write("") 68 | onesmaller = total_time1 + total_penalty_time1 < total_time2 + total_penalty_time2 69 | f.write("") 70 | f.write("") 71 | f.write("") 72 | f.write("") 73 | f.write("") 74 | for p in list: 75 | 76 | stringtime1 = '--' if p[1] >= TIMEOUT else repr(round(p[1], 3)) 77 | stringtime2 = '--' if p[2] >= TIMEOUT else repr(round(p[2], 3)) 78 | f.write("") 79 | onesmaller = p[1] < p[2] 80 | f.write("") 82 | f.write("") 83 | 84 | f.write("") 85 | f.write("
Name" + binary1 + "" + binary2 + "
Solved" + repr(num_successes1) + "/" + repr(len(list)) + "" + repr(num_successes2) + "/" + repr(len(list)) + "
Time " + bold(repr(round(total_time1, 3)), onesmaller)+ "" + bold(repr(round(total_time2, 3)), not onesmaller) + "
Time (only where both succeeded) " + bold(repr(round(sync_total_time1, 3)), onesmaller)+ "" + bold(repr(round(sync_total_time2, 3)), not onesmaller) + "
Time (with TIMEOUT penalties) " + bold(repr(round(total_time1+total_penalty_time1, 3)), onesmaller)+ "" + bold(repr(round(total_time2+total_penalty_time2, 3)), not onesmaller) + "
" + p[0] + "" + bold(stringtime1, onesmaller) + "" 81 | + bold(stringtime2, not onesmaller) + "
") 86 | f.write("\n") 87 | 88 | 89 | if len(sys.argv) < 3: 90 | print("Usage:") 91 | print("\t /comparetimes.py LIST_FILE BINARY1 BINARY2") 92 | print("\t /comparetimes.py DIRECTORY BINARY1 BINARY2") 93 | exit(0) 94 | 95 | 96 | PATH_TO_SHARPSAT_BINARY1 = os.path.expandvars(os.path.expanduser(sys.argv[2])) 97 | PATH_TO_SHARPSAT_BINARY2 = os.path.expandvars(os.path.expanduser(sys.argv[3])) 98 | 99 | cnflist = read_filelist(os.path.expandvars(os.path.expanduser(sys.argv[1]))) 100 | 101 | compare_data = run_all_on_list(TIMEOUT, cnflist, [PATH_TO_SHARPSAT_BINARY1, PATH_TO_SHARPSAT_BINARY2]) 102 | 103 | store_results("compare_results.html", PATH_TO_SHARPSAT_BINARY1, PATH_TO_SHARPSAT_BINARY2, compare_data) -------------------------------------------------------------------------------- /src/containers/binary_heap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * binary_heap.h 3 | * 4 | * Created on: May 8, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef BINARY_HEAP_H_ 9 | #define BINARY_HEAP_H_ 10 | 11 | #include 12 | #include 13 | 14 | 15 | template 16 | class BinaryHeap { 17 | // the values corresponding to the usigned keys 18 | std::vector values_; 19 | // keys to values, note that a zero key means: not in HEAP 20 | std::vector keys_; 21 | // we have a max heap w.r.t. this comparator 22 | Comparator less_; 23 | public: 24 | BinaryHeap(const Comparator & comp) 25 | : less_(comp){ 26 | } 27 | 28 | inline void init(unsigned num_values); 29 | 30 | inline unsigned deleteMax(); 31 | 32 | 33 | void incorporateIncrease(unsigned value) {//* 34 | assert(keys_[value]); 35 | swim(keys_[value]); 36 | } 37 | 38 | bool contains(unsigned value){ 39 | return value < keys_.size() && keys_[value] > 0; 40 | } 41 | 42 | bool empty(){ 43 | assert(!values_.empty()); 44 | return values_.size() == 1; 45 | } 46 | 47 | inline void insert(unsigned value); 48 | 49 | private: 50 | 51 | bool less(unsigned keyA, unsigned keyB){ 52 | return less_(values_[keyA],values_[keyB]); 53 | } 54 | 55 | unsigned parentKey(unsigned key){ 56 | return key>>1; 57 | } 58 | 59 | inline void swim(unsigned key); 60 | 61 | inline void sink(unsigned key); 62 | 63 | 64 | 65 | /// Test Functions 66 | inline void test_checkRep(); 67 | 68 | }; 69 | 70 | 71 | template 72 | void BinaryHeap::init(unsigned num_values){ 73 | keys_.clear(); 74 | keys_.resize(num_values+1,0); 75 | values_.clear(); 76 | values_.reserve(num_values+1); 77 | values_.push_back(0); 78 | // TODO: add correct initialization 79 | for (unsigned n = 1; n <= num_values; n++) { 80 | insert(n); 81 | } 82 | } 83 | 84 | template 85 | unsigned BinaryHeap::deleteMax(){ //* 86 | assert(values_.size() >=2); 87 | unsigned value = values_[1]; 88 | values_[1] = values_.back(); 89 | keys_[values_.back()] = 1; 90 | keys_[value] = 0; 91 | values_.pop_back(); 92 | if(!empty()) 93 | sink(1); 94 | //test_checkRep(); 95 | return value; 96 | } 97 | 98 | template 99 | void BinaryHeap::insert(unsigned value){//* 100 | assert(!contains(value)); 101 | values_.push_back(value); 102 | keys_[value] = values_.size() - 1; 103 | swim(keys_[value]); 104 | sink(keys_[value]); 105 | 106 | //test_checkRep(); 107 | } 108 | 109 | template 110 | void BinaryHeap::swim(unsigned key){ 111 | assert(key < values_.size()); 112 | unsigned value = values_[key]; 113 | 114 | unsigned parent_key = parentKey(key); 115 | while(key > 1 && less_(values_[parent_key],value)){ 116 | keys_[values_[parent_key]] = key; 117 | values_[key] = values_[parent_key]; 118 | key = parent_key; 119 | parent_key = parentKey(parent_key); 120 | } 121 | values_[key] = value; 122 | keys_[value] = key; 123 | } 124 | 125 | template 126 | void BinaryHeap::sink(unsigned key){ 127 | assert(key < values_.size()); 128 | unsigned value = values_[key]; 129 | while((key<<1) < values_.size()){ 130 | unsigned j = key<<1; 131 | if(j+1 < values_.size() && less(j,j+1)) ++j; 132 | if(!less_(value,values_[j])) break; 133 | values_[key] = values_[j]; 134 | keys_[values_[j]] = key; 135 | key=j; 136 | } 137 | values_[key] = value; 138 | keys_[value] = key; 139 | } 140 | 141 | 142 | //////////////////////////////////////////// 143 | //// Testing 144 | 145 | template 146 | void BinaryHeap::test_checkRep(){ 147 | assert(!values_.empty()); 148 | assert(values_[0] == 0); 149 | for(unsigned k = 1; k < values_.size(); k++){ 150 | unsigned left = k << 1; 151 | unsigned right = (k << 1) + 1; 152 | if(left < values_.size()) assert(!less_(values_[k], values_[left])); 153 | if(right < values_.size()) assert(!less_(values_[k],values_[right])); 154 | } 155 | } 156 | 157 | #endif /* BINARY_HEAP_H_ */ 158 | -------------------------------------------------------------------------------- /src/structures.h: -------------------------------------------------------------------------------- 1 | /* 2 | * structures.h 3 | * 4 | * Created on: Jun 25, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef STRUCTURES_H_ 9 | #define STRUCTURES_H_ 10 | 11 | #include 12 | #include 13 | #include "primitive_types.h" 14 | using namespace std; 15 | 16 | 17 | 18 | #define INVALID_DL -1 19 | 20 | typedef unsigned char TriValue; 21 | #define F_TRI 0 22 | #define T_TRI 1 23 | #define X_TRI 2 24 | 25 | class LiteralID { 26 | public: 27 | 28 | LiteralID() { 29 | value_ = 0; 30 | } 31 | LiteralID(int lit) { 32 | value_ = (abs(lit) << 1) + (unsigned) (lit > 0); 33 | } 34 | 35 | LiteralID(VariableIndex var, bool sign) { 36 | value_ = (var << 1) + (unsigned) sign; 37 | } 38 | 39 | VariableIndex var() const { 40 | return (value_ >> 1); 41 | } 42 | 43 | int toInt() const { 44 | return ((int) value_ >> 1) * ((sign()) ? 1 : -1); 45 | } 46 | 47 | void inc(){++value_;} 48 | 49 | void copyRaw(unsigned int v) { 50 | value_ = v; 51 | } 52 | 53 | bool sign() const { 54 | return (bool) (value_ & 0x01); 55 | } 56 | 57 | bool operator!=(const LiteralID &rL2) const { 58 | return value_ != rL2.value_; 59 | } 60 | 61 | bool operator==(const LiteralID &rL2) const { 62 | return value_ == rL2.value_; 63 | } 64 | 65 | const LiteralID neg() const { 66 | return LiteralID(var(), !sign()); 67 | } 68 | 69 | void print() const { 70 | cout << (sign() ? " " : "-") << var() << " "; 71 | } 72 | 73 | unsigned raw() const { return value_;} 74 | 75 | private: 76 | unsigned value_; 77 | 78 | template friend class LiteralIndexedVector; 79 | }; 80 | 81 | static const LiteralID NOT_A_LIT(0, false); 82 | #define SENTINEL_LIT NOT_A_LIT 83 | 84 | class Literal { 85 | public: 86 | vector binary_links_ = vector(1,SENTINEL_LIT); 87 | vector watch_list_ = vector(1,SENTINEL_CL); 88 | float activity_score_ = 0.0f; 89 | 90 | void increaseActivity(unsigned u = 1){ 91 | activity_score_+= u; 92 | } 93 | 94 | void removeWatchLinkTo(ClauseOfs clause_ofs) { 95 | for (auto it = watch_list_.begin(); it != watch_list_.end(); it++) 96 | if (*it == clause_ofs) { 97 | *it = watch_list_.back(); 98 | watch_list_.pop_back(); 99 | return; 100 | } 101 | } 102 | 103 | void replaceWatchLinkTo(ClauseOfs clause_ofs, ClauseOfs replace_ofs) { 104 | for (auto it = watch_list_.begin(); it != watch_list_.end(); it++) 105 | if (*it == clause_ofs) { 106 | *it = replace_ofs; 107 | return; 108 | } 109 | } 110 | 111 | void addWatchLinkTo(ClauseIndex clause_ofs) { 112 | watch_list_.push_back(clause_ofs); 113 | } 114 | 115 | void addBinLinkTo(LiteralID lit) { 116 | binary_links_.back() = lit; 117 | binary_links_.push_back(SENTINEL_LIT); 118 | } 119 | 120 | void resetWatchList(){ 121 | watch_list_.clear(); 122 | watch_list_.push_back(SENTINEL_CL); 123 | } 124 | 125 | bool hasBinaryLinkTo(LiteralID lit) { 126 | for (auto l : binary_links_) { 127 | if (l == lit) 128 | return true; 129 | } 130 | return false; 131 | } 132 | 133 | bool hasBinaryLinks() { 134 | return !binary_links_.empty(); 135 | } 136 | }; 137 | 138 | class Antecedent { 139 | unsigned int val_; 140 | 141 | public: 142 | Antecedent() { 143 | val_ = 1; 144 | } 145 | 146 | Antecedent(const ClauseOfs cl_ofs) { 147 | val_ = (cl_ofs << 1) | 1; 148 | } 149 | Antecedent(const LiteralID idLit) { 150 | val_ = (idLit.raw() << 1); 151 | } 152 | 153 | bool isAClause() const { 154 | return val_ & 0x01; 155 | } 156 | 157 | ClauseOfs asCl() const { 158 | return val_ >> 1; 159 | } 160 | 161 | LiteralID asLit() { 162 | LiteralID idLit; 163 | idLit.copyRaw(val_ >> 1); 164 | return idLit; 165 | } 166 | // A NON-Antecedent will only be A NOT_A_CLAUSE Clause Id 167 | bool isAnt() { 168 | return val_ != 1; //i.e. NOT a NOT_A_CLAUSE; 169 | } 170 | }; 171 | 172 | 173 | struct Variable { 174 | Antecedent ante; 175 | int decision_level = INVALID_DL; 176 | }; 177 | 178 | // for now Clause Header is just a dummy 179 | // we keep it for possible later changes 180 | class ClauseHeader { 181 | unsigned creation_time_; // number of conflicts seen at creation time 182 | unsigned score_; 183 | unsigned length_; 184 | public: 185 | 186 | void increaseScore() { 187 | score_++; 188 | } 189 | void decayScore() { 190 | score_ >>= 1; 191 | } 192 | unsigned score() { 193 | return score_; 194 | } 195 | 196 | unsigned creation_time() { 197 | return creation_time_; 198 | } 199 | unsigned length(){ return length_;} 200 | void set_length(unsigned length){ length_ = length;} 201 | 202 | void set_creation_time(unsigned time) { 203 | creation_time_ = time; 204 | } 205 | static unsigned overheadInLits(){return sizeof(ClauseHeader)/sizeof(LiteralID);} 206 | }; 207 | 208 | #endif /* STRUCTURES_H_ */ 209 | -------------------------------------------------------------------------------- /src/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stack.h 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef STACK_H_ 9 | #define STACK_H_ 10 | 11 | #include 12 | 13 | class StackLevel { 14 | /// active Component, once initialized, it should not change 15 | const unsigned super_component_ = 0; 16 | // branch 17 | bool active_branch_ = false; 18 | 19 | // offset in the literal stack where to store set lits 20 | const unsigned literal_stack_ofs_ = 0; 21 | 22 | // Solutioncount 23 | mpz_class branch_model_count_[2] = {0,0}; 24 | bool branch_found_unsat_[2] = {false,false}; 25 | 26 | /// remaining Components 27 | 28 | // the start offset in the component stack for 29 | // the remaining components in this decision level 30 | // all remaining components can hence be found in 31 | // [remaining_components_ofs_, "nextLevel".remaining_components_begin_) 32 | const unsigned remaining_components_ofs_ = 0; 33 | 34 | // boundary of the stack marking which components still need to be processed 35 | // all components to be processed can be found in 36 | // [remaining_components_ofs_, unprocessed_components_end_) 37 | // also, all processed, can be found 38 | // in [unprocessed_components_end_, component_stack.size()) 39 | unsigned unprocessed_components_end_ = 0; 40 | public: 41 | 42 | bool hasUnprocessedComponents() { 43 | assert(unprocessed_components_end_ >= remaining_components_ofs_); 44 | return unprocessed_components_end_ > remaining_components_ofs_; 45 | } 46 | void nextUnprocessedComponent() { 47 | assert(unprocessed_components_end_ > remaining_components_ofs_); 48 | unprocessed_components_end_--; 49 | } 50 | 51 | void resetRemainingComps() { 52 | unprocessed_components_end_ = remaining_components_ofs_; 53 | } 54 | unsigned super_component() { 55 | return super_component_; 56 | } 57 | unsigned remaining_components_ofs() { 58 | return remaining_components_ofs_; 59 | } 60 | void set_unprocessed_components_end(unsigned end) { 61 | unprocessed_components_end_ = end; 62 | assert(remaining_components_ofs_ <= unprocessed_components_end_); 63 | } 64 | 65 | StackLevel(unsigned super_comp, unsigned lit_stack_ofs, 66 | unsigned comp_stack_ofs) : 67 | super_component_(super_comp), 68 | literal_stack_ofs_(lit_stack_ofs), 69 | remaining_components_ofs_(comp_stack_ofs), 70 | unprocessed_components_end_(comp_stack_ofs) { 71 | assert(super_comp < comp_stack_ofs); 72 | } 73 | 74 | unsigned currentRemainingComponent() { 75 | assert(remaining_components_ofs_ <= unprocessed_components_end_ - 1); 76 | return unprocessed_components_end_ - 1; 77 | } 78 | bool isSecondBranch() { 79 | return active_branch_; 80 | } 81 | 82 | void changeBranch() { 83 | active_branch_ = true; 84 | } 85 | 86 | bool anotherCompProcessible() { 87 | return (!branch_found_unsat()) && hasUnprocessedComponents(); 88 | } 89 | 90 | unsigned literal_stack_ofs() { 91 | return literal_stack_ofs_; 92 | } 93 | void includeSolution(const mpz_class &solutions) { 94 | if (branch_found_unsat_[active_branch_]) { 95 | assert(branch_model_count_[active_branch_] == 0); 96 | return; 97 | } 98 | if (solutions == 0) 99 | branch_found_unsat_[active_branch_] = true; 100 | if (branch_model_count_[active_branch_] == 0) 101 | branch_model_count_[active_branch_] = solutions; 102 | else 103 | branch_model_count_[active_branch_] *= solutions; 104 | 105 | } 106 | void includeSolution(unsigned solutions) { 107 | if (branch_found_unsat_[active_branch_]) { 108 | assert(branch_model_count_[active_branch_] == 0); 109 | return; 110 | } 111 | if (solutions == 0) 112 | branch_found_unsat_[active_branch_] = true; 113 | if (branch_model_count_[active_branch_] == 0) 114 | branch_model_count_[active_branch_] = solutions; 115 | else 116 | branch_model_count_[active_branch_] *= solutions; 117 | 118 | } 119 | 120 | bool branch_found_unsat() { 121 | return branch_found_unsat_[active_branch_]; 122 | } 123 | void mark_branch_unsat() { 124 | branch_found_unsat_[active_branch_] = true; 125 | } 126 | 127 | // void set_both_branches_unsat(){ 128 | // branch_found_unsat_[0] = 129 | // branch_found_unsat_[1] = true; 130 | // branch_model_count_[0] = branch_model_count_[1] = 0; 131 | // active_branch_ = 1; 132 | // } 133 | const mpz_class getTotalModelCount() const { 134 | return branch_model_count_[0] + branch_model_count_[1]; 135 | } 136 | }; 137 | 138 | class DecisionStack: public vector { 139 | unsigned int failed_literal_test_active = 0; 140 | public: 141 | 142 | //begin for implicit BCP 143 | void startFailedLitTest() { 144 | failed_literal_test_active = true; 145 | } 146 | void stopFailedLitTest() { 147 | failed_literal_test_active = false; 148 | } 149 | //end for implicit BCP 150 | 151 | StackLevel &top() { 152 | assert(size() > 0); 153 | return back(); 154 | } 155 | int get_decision_level() const { 156 | assert(size() > 0); 157 | return size() - 1 + failed_literal_test_active; 158 | } // 0 means pre-1st-decision 159 | 160 | }; 161 | 162 | 163 | 164 | #endif /* STACK_H_ */ 165 | -------------------------------------------------------------------------------- /src/component_management.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component_management.h 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef COMPONENT_MANAGEMENT_H_ 9 | #define COMPONENT_MANAGEMENT_H_ 10 | 11 | 12 | 13 | #include "component_types/component.h" 14 | #include "component_cache.h" 15 | #include "alt_component_analyzer.h" 16 | //#include "component_analyzer.h" 17 | 18 | #include 19 | #include 20 | #include "containers.h" 21 | #include "stack.h" 22 | 23 | #include "solver_config.h" 24 | using namespace std; 25 | 26 | typedef AltComponentAnalyzer ComponentAnalyzer; 27 | 28 | class ComponentManager { 29 | public: 30 | ComponentManager(SolverConfiguration &config, DataAndStatistics &statistics, 31 | LiteralIndexedVector & lit_values) : 32 | config_(config), statistics_(statistics), cache_(statistics), 33 | ana_(statistics,lit_values) { 34 | } 35 | 36 | void initialize(LiteralIndexedVector & literals, 37 | vector &lit_pool); 38 | 39 | unsigned scoreOf(VariableIndex v) { 40 | return ana_.scoreOf(v); 41 | } 42 | 43 | void cacheModelCountOf(unsigned stack_comp_id, const mpz_class &value) { 44 | if (config_.perform_component_caching) 45 | cache_.storeValueOf(component_stack_[stack_comp_id]->id(), value); 46 | } 47 | 48 | Component & superComponentOf(StackLevel &lev) { 49 | assert(component_stack_.size() > lev.super_component()); 50 | return *component_stack_[lev.super_component()]; 51 | } 52 | 53 | unsigned component_stack_size() { 54 | return component_stack_.size(); 55 | } 56 | 57 | void cleanRemainingComponentsOf(StackLevel &top) { 58 | while (component_stack_.size() > top.remaining_components_ofs()) { 59 | if (cache_.hasEntry(component_stack_.back()->id())) 60 | cache_.entry(component_stack_.back()->id()).set_deletable(); 61 | delete component_stack_.back(); 62 | component_stack_.pop_back(); 63 | } 64 | assert(top.remaining_components_ofs() <= component_stack_.size()); 65 | } 66 | 67 | Component & currentRemainingComponentOf(StackLevel &top) { 68 | assert(component_stack_.size() > top.currentRemainingComponent()); 69 | return *component_stack_[top.currentRemainingComponent()]; 70 | } 71 | 72 | // checks for the next yet to explore remaining component of top 73 | // returns true if a non-trivial non-cached component 74 | // has been found and is now stack_.TOS_NextComp() 75 | // returns false if all components have been processed; 76 | inline bool findNextRemainingComponentOf(StackLevel &top); 77 | 78 | inline void recordRemainingCompsFor(StackLevel &top); 79 | 80 | inline void sortComponentStackRange(unsigned start, unsigned end); 81 | 82 | void gatherStatistics(){ 83 | // statistics_.cache_bytes_memory_usage_ = 84 | // cache_.recompute_bytes_memory_usage(); 85 | cache_.compute_byte_size_infrasture(); 86 | } 87 | 88 | void removeAllCachePollutionsOf(StackLevel &top); 89 | 90 | private: 91 | 92 | SolverConfiguration &config_; 93 | DataAndStatistics &statistics_; 94 | 95 | vector component_stack_; 96 | ComponentCache cache_; 97 | ComponentAnalyzer ana_; 98 | }; 99 | 100 | 101 | void ComponentManager::sortComponentStackRange(unsigned start, unsigned end){ 102 | assert(start <= end); 103 | // sort the remaining components for processing 104 | for (unsigned i = start; i < end; i++) 105 | for (unsigned j = i + 1; j < end; j++) { 106 | if (component_stack_[i]->num_variables() 107 | < component_stack_[j]->num_variables()) 108 | swap(component_stack_[i], component_stack_[j]); 109 | } 110 | } 111 | 112 | bool ComponentManager::findNextRemainingComponentOf(StackLevel &top) { 113 | // record Remaining Components if there are none! 114 | if (component_stack_.size() <= top.remaining_components_ofs()) 115 | recordRemainingCompsFor(top); 116 | assert(!top.branch_found_unsat()); 117 | if (top.hasUnprocessedComponents()) 118 | return true; 119 | // if no component remains 120 | // make sure, at least that the current branch is considered SAT 121 | top.includeSolution(1); 122 | return false; 123 | } 124 | 125 | 126 | void ComponentManager::recordRemainingCompsFor(StackLevel &top) { 127 | Component & super_comp = superComponentOf(top); 128 | unsigned new_comps_start_ofs = component_stack_.size(); 129 | 130 | ana_.setupAnalysisContext(top, super_comp); 131 | 132 | for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) 133 | if (ana_.isUnseenAndActive(*vt) && 134 | ana_.exploreRemainingCompOf(*vt)){ 135 | 136 | Component *p_new_comp = ana_.makeComponentFromArcheType(); 137 | CacheableComponent *packed_comp = new CacheableComponent(ana_.getArchetype().current_comp_for_caching_); 138 | if (!cache_.manageNewComponent(top, *packed_comp)){ 139 | component_stack_.push_back(p_new_comp); 140 | p_new_comp->set_id(cache_.storeAsEntry(*packed_comp, super_comp.id())); 141 | } 142 | else { 143 | delete packed_comp; 144 | delete p_new_comp; 145 | } 146 | } 147 | 148 | top.set_unprocessed_components_end(component_stack_.size()); 149 | sortComponentStackRange(new_comps_start_ofs, component_stack_.size()); 150 | } 151 | 152 | #endif /* COMPONENT_MANAGEMENT_H_ */ 153 | -------------------------------------------------------------------------------- /src/component_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component_cache.h 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef COMPONENT_CACHE_H_ 9 | #define COMPONENT_CACHE_H_ 10 | 11 | 12 | #include "component_types/cacheable_component.h" 13 | #include "statistics.h" 14 | 15 | #include 16 | 17 | #include "component_types/component.h" 18 | 19 | #include "stack.h" 20 | 21 | 22 | class ComponentCache { 23 | public: 24 | 25 | ComponentCache(DataAndStatistics &statistics); 26 | 27 | ~ComponentCache() { 28 | // debug_dump_data(); 29 | for (auto &pentry : entry_base_) 30 | if (pentry != nullptr) 31 | delete pentry; 32 | } 33 | 34 | void init(Component &super_comp); 35 | 36 | // compute the size in bytes of the component cache from scratch 37 | // the value is stored in bytes_memory_usage_ 38 | uint64_t compute_byte_size_infrasture(); 39 | 40 | CacheableComponent &entry(CacheEntryID id) { 41 | assert(entry_base_.size() > id); 42 | assert(entry_base_[id] != nullptr); 43 | return *entry_base_[id]; 44 | } 45 | 46 | CacheableComponent &entry(const Component& comp) { 47 | return entry(comp.id()); 48 | } 49 | 50 | bool hasEntry(CacheEntryID id) { 51 | assert(entry_base_.size() > id); 52 | return entry_base_[id]; 53 | } 54 | 55 | // removes the entry id from the hash table 56 | // but not from the entry base 57 | inline void removeFromHashTable(CacheEntryID id); 58 | 59 | // we delete the Component with ID id 60 | // and all its descendants from the cache 61 | inline void cleanPollutionsInvolving(CacheEntryID id); 62 | 63 | // creates a CCacheEntry in the entry base 64 | // which contains a packed copy of comp 65 | // returns the id of the entry created 66 | // stores in the entry the position of 67 | // comp which is a part of the component stack 68 | inline CacheEntryID storeAsEntry(CacheableComponent &ccomp, 69 | CacheEntryID super_comp_id); 70 | 71 | // check quickly if the model count of the component is cached 72 | // if so, incorporate it into the model count of top 73 | // if not, store the packed version of it in the entry_base of the cache 74 | bool manageNewComponent(StackLevel &top, CacheableComponent &packed_comp) { 75 | statistics_.num_cache_look_ups_++; 76 | unsigned table_ofs = packed_comp.hashkey() & table_size_mask_; 77 | 78 | CacheEntryID act_id = table_[table_ofs]; 79 | while(act_id){ 80 | if (entry(act_id).equals(packed_comp)) { 81 | statistics_.incorporate_cache_hit(packed_comp); 82 | top.includeSolution(entry(act_id).model_count()); 83 | return true; 84 | } 85 | act_id = entry(act_id).next_bucket_element(); 86 | } 87 | return false; 88 | } 89 | 90 | 91 | // unchecked erase of an entry from entry_base_ 92 | void eraseEntry(CacheEntryID id) { 93 | statistics_.incorporate_cache_erase(*entry_base_[id]); 94 | delete entry_base_[id]; 95 | entry_base_[id] = nullptr; 96 | free_entry_base_slots_.push_back(id); 97 | } 98 | 99 | 100 | // store the number in model_count as the model count of CacheEntryID id 101 | inline void storeValueOf(CacheEntryID id, const mpz_class &model_count); 102 | 103 | bool deleteEntries(); 104 | 105 | // delete entries, keeping the descendants tree consistent 106 | inline void removeFromDescendantsTree(CacheEntryID id); 107 | 108 | // test function to ensure consistency of the descendant tree 109 | inline void test_descendantstree_consistency(); 110 | void debug_dump_data(); 111 | private: 112 | 113 | void considerCacheResize(){ 114 | if (entry_base_.size() > table_.size()) { 115 | reHashTable(2*table_.size()); 116 | } 117 | } 118 | void reHashTable(unsigned size){ 119 | 120 | table_.clear(); 121 | table_.resize(size,0); 122 | // we assert that table size is a power of 2 123 | // otherwise the table_size_mask_ doesn't work 124 | assert((table_.size() & (table_.size() - 1)) == 0); 125 | table_size_mask_ = table_.size() - 1; 126 | cout << "ts " << table_.size() << " " << table_size_mask_ << endl; 127 | unsigned collisions = 0; 128 | for (unsigned id = 2; id < entry_base_.size(); id++) 129 | if (entry_base_[id] != nullptr ){ 130 | entry_base_[id]->set_next_bucket_element(0); 131 | if(entry_base_[id]->modelCountFound()) { 132 | unsigned table_ofs=tableEntry(id); 133 | collisions += (table_[table_ofs] > 0 ? 1 : 0); 134 | entry_base_[id]->set_next_bucket_element(table_[table_ofs]); 135 | table_[table_ofs] = id; 136 | } 137 | } 138 | cout << "coll " << collisions << endl; 139 | } 140 | 141 | unsigned tableEntry(CacheEntryID id){ 142 | return entry(id).hashkey() & table_size_mask_; 143 | } 144 | void add_descendant(CacheEntryID compid, CacheEntryID descendantid) { 145 | assert(descendantid != entry(compid).first_descendant()); 146 | entry(descendantid).set_next_sibling(entry(compid).first_descendant()); 147 | entry(compid).set_first_descendant(descendantid); 148 | } 149 | 150 | void remove_firstdescendantOf(CacheEntryID compid) { 151 | CacheEntryID desc = entry(compid).first_descendant(); 152 | if (desc != 0) 153 | entry(compid).set_first_descendant(entry(desc).next_sibling()); 154 | } 155 | 156 | vector entry_base_; 157 | vector free_entry_base_slots_; 158 | 159 | // the actual hash table 160 | // by means of which the cache is accessed 161 | vector table_; 162 | 163 | unsigned table_size_mask_; 164 | 165 | DataAndStatistics &statistics_; 166 | 167 | unsigned long my_time_ = 0; 168 | }; 169 | 170 | 171 | #include "component_cache-inl.h" 172 | 173 | 174 | #endif /* COMPONENT_CACHE_H_ */ 175 | -------------------------------------------------------------------------------- /src/component_analyzer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * component_analyzer.cpp 3 | * 4 | * Created on: Feb 7, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #include "component_analyzer.h" 9 | 10 | void STDComponentAnalyzer::initialize(LiteralIndexedVector & literals, 11 | vector &lit_pool) { 12 | 13 | max_variable_id_ = literals.end_lit().var() - 1; 14 | 15 | search_stack_.reserve(max_variable_id_ + 1); 16 | var_frequency_scores_.resize(max_variable_id_ + 1, 0); 17 | variable_occurrence_lists_pool_.clear(); 18 | variable_link_list_offsets_.resize(max_variable_id_ + 1, 0); 19 | 20 | literal_pool_.reserve(lit_pool.size()); 21 | 22 | 23 | map_clause_id_to_ofs_.clear(); 24 | map_clause_id_to_ofs_.push_back(0); 25 | 26 | vector > occs_(max_variable_id_ + 1); 27 | ClauseOfs current_clause_ofs = 0; 28 | max_clause_id_ = 0; 29 | unsigned curr_clause_length = 0; 30 | for (auto it_lit = lit_pool.begin(); it_lit < lit_pool.end(); it_lit++) { 31 | if (*it_lit == SENTINEL_LIT) { 32 | 33 | if (it_lit + 1 == lit_pool.end()) { 34 | literal_pool_.push_back(SENTINEL_LIT); 35 | break; 36 | } 37 | 38 | max_clause_id_++; 39 | literal_pool_.push_back(SENTINEL_LIT); 40 | for (unsigned i = 0; i < CAClauseHeader::overheadInLits(); i++) 41 | literal_pool_.push_back(0); 42 | current_clause_ofs = literal_pool_.size(); 43 | getHeaderOf(current_clause_ofs).clause_id = max_clause_id_; 44 | it_lit += ClauseHeader::overheadInLits(); 45 | curr_clause_length = 0; 46 | 47 | assert(map_clause_id_to_ofs_.size() == max_clause_id_); 48 | map_clause_id_to_ofs_.push_back(current_clause_ofs); 49 | 50 | } else { 51 | assert(it_lit->var() <= max_variable_id_); 52 | literal_pool_.push_back(*it_lit); 53 | curr_clause_length++; 54 | occs_[it_lit->var()].push_back(current_clause_ofs); 55 | } 56 | } 57 | 58 | ComponentArchetype::initArrays(max_variable_id_, max_clause_id_); 59 | // the unified link list 60 | unified_variable_links_lists_pool_.clear(); 61 | unified_variable_links_lists_pool_.push_back(0); 62 | unified_variable_links_lists_pool_.push_back(0); 63 | for (unsigned v = 1; v < occs_.size(); v++) { 64 | variable_link_list_offsets_[v] = unified_variable_links_lists_pool_.size(); 65 | for (auto l : literals[LiteralID(v, false)].binary_links_) 66 | if (l != SENTINEL_LIT) { 67 | unified_variable_links_lists_pool_.push_back(l.var()); 68 | } 69 | for (auto l : literals[LiteralID(v, true)].binary_links_) 70 | if (l != SENTINEL_LIT) { 71 | unified_variable_links_lists_pool_.push_back(l.var()); 72 | } 73 | unified_variable_links_lists_pool_.push_back(0); 74 | unified_variable_links_lists_pool_.insert( 75 | unified_variable_links_lists_pool_.end(), 76 | occs_[v].begin(), 77 | occs_[v].end()); 78 | unified_variable_links_lists_pool_.push_back(0); 79 | } 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | void STDComponentAnalyzer::recordComponentOf(const VariableIndex var) { 88 | 89 | search_stack_.clear(); 90 | search_stack_.push_back(var); 91 | 92 | archetype_.setVar_seen(var); 93 | 94 | for (auto vt = search_stack_.begin(); 95 | vt != search_stack_.end(); vt++) { 96 | // the for-loop is applicable here because componentSearchStack.capacity() == countAllVars() 97 | //BEGIN traverse binary clauses 98 | assert(isActive(*vt)); 99 | unsigned *pvar = beginOfLinkList(*vt); 100 | for (; *pvar; pvar++) { 101 | if(isUnseenAndActive(*pvar)){ 102 | setSeenAndStoreInSearchStack(*pvar); 103 | var_frequency_scores_[*pvar]++; 104 | var_frequency_scores_[*vt]++; 105 | } 106 | } 107 | //END traverse binary clauses 108 | 109 | // start traversing links to long clauses 110 | // not that that list starts right after the 0 termination of the prvious list 111 | // hence pcl_ofs = pvar + 1 112 | for (auto pcl_ofs = pvar + 1; *pcl_ofs != SENTINEL_CL; pcl_ofs++) { 113 | ClauseIndex clID = getClauseID(*pcl_ofs); 114 | if(archetype_.clause_unseen_in_sup_comp(clID)){ 115 | auto itVEnd = search_stack_.end(); 116 | bool all_lits_active = true; 117 | bool appeared = false; 118 | for (auto itL = beginOfClause(*pcl_ofs); *itL != SENTINEL_LIT; itL++) { 119 | assert(itL->var() <= max_variable_id_); 120 | if(archetype_.var_nil(itL->var())){ 121 | assert(!isActive(*itL)); 122 | all_lits_active = false; 123 | if (isResolved(*itL)) 124 | continue; 125 | //BEGIN accidentally entered a satisfied clause: undo the search process 126 | while (search_stack_.end() != itVEnd) { 127 | assert(search_stack_.back() <= max_variable_id_); 128 | archetype_.setVar_in_sup_comp_unseen(search_stack_.back()); 129 | search_stack_.pop_back(); 130 | } 131 | archetype_.setClause_nil(clID); 132 | for (auto itX = beginOfClause(*pcl_ofs); itX != itL; itX++) { 133 | if (var_frequency_scores_[itX->var()] > 0) 134 | var_frequency_scores_[itX->var()]--; 135 | } 136 | //END accidentally entered a satisfied clause: undo the search process 137 | break; 138 | } else { 139 | assert(isActive(*itL)); 140 | if(itL->var() == var) appeared = true; 141 | var_frequency_scores_[itL->var()]++; 142 | if(isUnseenAndActive(itL->var())) 143 | setSeenAndStoreInSearchStack(itL->var()); 144 | } 145 | } 146 | 147 | if (archetype_.clause_nil(clID)) 148 | continue; 149 | archetype_.setClause_seen(clID); 150 | if(all_lits_active) 151 | archetype_.setClause_all_lits_active(clID); 152 | 153 | #ifndef NDEBUG 154 | test_checkArchetypeRepForClause(pcl_ofs); 155 | #endif 156 | } 157 | } 158 | } 159 | } 160 | 161 | -------------------------------------------------------------------------------- /src/component_cache-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component_cache-inl.h 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef COMPONENT_CACHE_INL_H_ 9 | #define COMPONENT_CACHE_INL_H_ 10 | 11 | CacheEntryID ComponentCache::storeAsEntry(CacheableComponent &ccomp, CacheEntryID super_comp_id){ 12 | CacheEntryID id; 13 | 14 | if (statistics_.cache_full()) 15 | deleteEntries(); 16 | 17 | assert(!statistics_.cache_full()); 18 | 19 | ccomp.set_creation_time(my_time_++); 20 | 21 | if (free_entry_base_slots_.empty()) { 22 | if (entry_base_.capacity() == entry_base_.size()) { 23 | entry_base_.reserve(2 * entry_base_.size()); 24 | } 25 | entry_base_.push_back(&ccomp); 26 | id = entry_base_.size() - 1; 27 | } else { 28 | id = free_entry_base_slots_.back(); 29 | assert(id < entry_base_.size()); 30 | assert(entry_base_[id] == nullptr); 31 | free_entry_base_slots_.pop_back(); 32 | entry_base_[id] = &ccomp; 33 | } 34 | 35 | entry(id).set_father(super_comp_id); 36 | add_descendant(super_comp_id, id); 37 | 38 | assert(hasEntry(id)); 39 | assert(hasEntry(super_comp_id)); 40 | 41 | statistics_.incorporate_cache_store(ccomp); 42 | 43 | #ifdef DEBUG 44 | for (unsigned u = 2; u < entry_base_.size(); u++) 45 | if (entry_base_[u] != nullptr) { 46 | assert(entry_base_[u]->father() != id); 47 | assert(entry_base_[u]->first_descendant() != id); 48 | assert(entry_base_[u]->next_sibling() != id); 49 | } 50 | #endif 51 | return id; 52 | } 53 | 54 | void ComponentCache::cleanPollutionsInvolving(CacheEntryID id) { 55 | CacheEntryID father = entry(id).father(); 56 | if (entry(father).first_descendant() == id) { 57 | entry(father).set_first_descendant(entry(id).next_sibling()); 58 | } else { 59 | CacheEntryID act_sibl = entry(father).first_descendant(); 60 | while (act_sibl) { 61 | CacheEntryID next_sibl = entry(act_sibl).next_sibling(); 62 | if (next_sibl == id) { 63 | entry(act_sibl).set_next_sibling(entry(next_sibl).next_sibling()); 64 | break; 65 | } 66 | act_sibl = next_sibl; 67 | } 68 | } 69 | CacheEntryID next_child = entry(id).first_descendant(); 70 | entry(id).set_first_descendant(0); 71 | while (next_child) { 72 | CacheEntryID act_child = next_child; 73 | next_child = entry(act_child).next_sibling(); 74 | cleanPollutionsInvolving(act_child); 75 | } 76 | removeFromHashTable(id); 77 | eraseEntry(id); 78 | } 79 | 80 | void ComponentCache::removeFromHashTable(CacheEntryID id) { 81 | //assert(false); 82 | unsigned act_id = table_[tableEntry(id)]; 83 | if(act_id == id){ 84 | table_[tableEntry(id)] = entry(act_id).next_bucket_element(); 85 | } 86 | else { 87 | while (act_id) { 88 | CacheEntryID next_id = entry(act_id).next_bucket_element(); 89 | if (next_id == id) { 90 | entry(act_id).set_next_bucket_element(entry(next_id).next_bucket_element()); 91 | break; 92 | } 93 | act_id = next_id; 94 | } 95 | } 96 | // CacheBucket *p_bucket = bucketOf(entry(id)); 97 | // if(p_bucket) 98 | // for (auto it = p_bucket->begin(); it != p_bucket->end(); it++) 99 | // if (*it == id) { 100 | // *it = p_bucket->back(); 101 | // p_bucket->pop_back(); 102 | // break; 103 | // } 104 | } 105 | 106 | void ComponentCache::removeFromDescendantsTree(CacheEntryID id) { 107 | assert(hasEntry(id)); 108 | // we need a father for this all to work 109 | assert(entry(id).father()); 110 | assert(hasEntry(entry(id).father())); 111 | // two steps 112 | // 1. remove id from the siblings list 113 | CacheEntryID father = entry(id).father(); 114 | if (entry(father).first_descendant() == id) { 115 | entry(father).set_first_descendant(entry(id).next_sibling()); 116 | } else { 117 | CacheEntryID act_sibl = entry(father).first_descendant(); 118 | while (act_sibl) { 119 | CacheEntryID next_sibl = entry(act_sibl).next_sibling(); 120 | if (next_sibl == id) { 121 | entry(act_sibl).set_next_sibling(entry(next_sibl).next_sibling()); 122 | break; 123 | } 124 | act_sibl = next_sibl; 125 | } 126 | } 127 | 128 | // 2. add the children of this one as 129 | // siblings to the current siblings 130 | CacheEntryID act_child = entry(id).first_descendant(); 131 | while (act_child) { 132 | CacheEntryID next_child = entry(act_child).next_sibling(); 133 | entry(act_child).set_father(father); 134 | entry(act_child).set_next_sibling(entry(father).first_descendant()); 135 | entry(father).set_first_descendant(act_child); 136 | act_child = next_child; 137 | } 138 | } 139 | 140 | void ComponentCache::storeValueOf(CacheEntryID id, const mpz_class &model_count) { 141 | considerCacheResize(); 142 | unsigned table_ofs = tableEntry(id); 143 | // when storing the new model count the size of the model count 144 | // and hence that of the component will change 145 | statistics_.sum_bytes_cached_components_ -= entry(id).SizeInBytes(); 146 | statistics_.overall_bytes_components_stored_ -= entry(id).SizeInBytes(); 147 | 148 | statistics_.sys_overhead_sum_bytes_cached_components_ -= entry(id).sys_overhead_SizeInBytes(); 149 | statistics_.sys_overhead_overall_bytes_components_stored_ -= entry(id).sys_overhead_SizeInBytes(); 150 | 151 | entry(id).set_model_count(model_count,my_time_); 152 | entry(id).set_creation_time(my_time_); 153 | 154 | entry(id).set_next_bucket_element(table_[table_ofs]); 155 | table_[table_ofs] = id; 156 | 157 | statistics_.sum_bytes_cached_components_ += entry(id).SizeInBytes(); 158 | statistics_.overall_bytes_components_stored_ += entry(id).SizeInBytes(); 159 | 160 | statistics_.sys_overhead_sum_bytes_cached_components_ += entry(id).sys_overhead_SizeInBytes(); 161 | statistics_.sys_overhead_overall_bytes_components_stored_ += entry(id).sys_overhead_SizeInBytes(); 162 | 163 | } 164 | 165 | 166 | 167 | 168 | 169 | #endif /* COMPONENT_CACHE_INL_H_ */ 170 | -------------------------------------------------------------------------------- /src/component_types/base_packed_component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * base_packed_component.h 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef BASE_PACKED_COMPONENT_H_ 9 | #define BASE_PACKED_COMPONENT_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | template 18 | class BitStuffer { 19 | public: 20 | BitStuffer(T *data):data_start_(data),p(data){ 21 | *p = 0; 22 | } 23 | 24 | void stuff(const unsigned val, const unsigned num_bits_val){ 25 | assert(num_bits_val > 0); 26 | assert((val >> num_bits_val) == 0); 27 | if(end_of_bits_ == 0) 28 | *p = 0; 29 | assert((*p >> end_of_bits_) == 0); 30 | *p |= val << end_of_bits_; 31 | end_of_bits_ += num_bits_val; 32 | if (end_of_bits_ > _bits_per_block){ 33 | //assert(*p); 34 | end_of_bits_ -= _bits_per_block; 35 | *(++p) = val >> (num_bits_val - end_of_bits_); 36 | assert(!(end_of_bits_ == 0) | (*p == 0)); 37 | } 38 | else if (end_of_bits_ == _bits_per_block){ 39 | end_of_bits_ -= _bits_per_block; 40 | p++; 41 | } 42 | } 43 | 44 | void assert_size(unsigned size){ 45 | if(end_of_bits_ == 0) 46 | p--; 47 | assert(p - data_start_ == size - 1); 48 | } 49 | 50 | private: 51 | T *data_start_ = nullptr; 52 | T *p = nullptr; 53 | // in the current block 54 | // the bit postion just after the last bit written 55 | unsigned end_of_bits_ = 0; 56 | 57 | static const unsigned _bits_per_block = (sizeof(T) << 3); 58 | 59 | }; 60 | 61 | 62 | class BasePackedComponent { 63 | public: 64 | static unsigned bits_per_variable() { 65 | return _bits_per_variable; 66 | } 67 | static unsigned variable_mask() { 68 | return _variable_mask; 69 | } 70 | static unsigned bits_per_clause() { 71 | return _bits_per_clause; 72 | } 73 | 74 | static unsigned bits_per_block(){ 75 | return _bits_per_block; 76 | } 77 | 78 | static unsigned bits_of_data_size(){ 79 | return _bits_of_data_size; 80 | } 81 | 82 | static void adjustPackSize(unsigned int maxVarId, unsigned int maxClId); 83 | 84 | BasePackedComponent() {} 85 | BasePackedComponent(unsigned creation_time): creation_time_(creation_time) {} 86 | 87 | ~BasePackedComponent() { 88 | if (data_) 89 | delete data_; 90 | } 91 | static void outbit(unsigned v){ 92 | for(auto i=0; i<32;i++){ 93 | cout << ((v&2147483648)?"1":"0"); 94 | v&=2147483648-1; 95 | v <<= 1; 96 | } 97 | } 98 | 99 | 100 | static unsigned log2(unsigned v){ 101 | // taken from 102 | // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup 103 | static const char LogTable256[256] = 104 | { 105 | #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n 106 | -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 107 | LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6), 108 | LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7) 109 | }; 110 | 111 | unsigned r; // r will be lg(v) 112 | unsigned int t, tt; // temporaries 113 | 114 | if ((tt = (v >> 16))) 115 | { 116 | r = (t = (tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt]; 117 | } 118 | else 119 | { 120 | r = (t = (v >> 8)) ? 8 + LogTable256[t] : LogTable256[v]; 121 | } 122 | return r; 123 | } 124 | 125 | unsigned creation_time() { 126 | return creation_time_; 127 | } 128 | 129 | const mpz_class &model_count() const { 130 | return model_count_; 131 | } 132 | 133 | unsigned alloc_of_model_count() const{ 134 | return sizeof(mpz_class) 135 | + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t); 136 | } 137 | 138 | void set_creation_time(unsigned time) { 139 | creation_time_ = time; 140 | } 141 | 142 | void set_model_count(const mpz_class &rn, unsigned time) { 143 | model_count_ = rn; 144 | length_solution_period_and_flags_ = (time - creation_time_) | (length_solution_period_and_flags_ & 1); 145 | } 146 | 147 | unsigned hashkey() const { 148 | return hashkey_; 149 | } 150 | 151 | bool modelCountFound(){ 152 | return (length_solution_period_and_flags_ >> 1); 153 | } 154 | 155 | // inline bool equals(const BasePackedComponent &comp) const; 156 | 157 | // a cache entry is deletable 158 | // only if it is not connected to an active 159 | // component in the component stack 160 | bool isDeletable() const { 161 | return length_solution_period_and_flags_ & 1; 162 | } 163 | void set_deletable() { 164 | length_solution_period_and_flags_ |= 1; 165 | } 166 | 167 | void clear() { 168 | // before deleting the contents of this component, 169 | // we should make sure that this component is not present in the component stack anymore! 170 | assert(isDeletable()); 171 | if (data_) 172 | delete data_; 173 | data_ = nullptr; 174 | } 175 | 176 | static unsigned _debug_static_val; 177 | 178 | protected: 179 | // data_ contains in packed form the variable indices 180 | // and clause indices of the component ordered 181 | // structure is 182 | // var var ... clause clause ... 183 | // clauses begin at clauses_ofs_ 184 | unsigned* data_ = nullptr; 185 | 186 | unsigned hashkey_ = 0; 187 | 188 | mpz_class model_count_; 189 | 190 | unsigned creation_time_ = 1; 191 | 192 | 193 | // this is: length_solution_period = length_solution_period_and_flags_ >> 1 194 | // length_solution_period == 0 means unsolved 195 | // and the first bit is "delete_permitted" 196 | unsigned length_solution_period_and_flags_ = 0; 197 | 198 | // deletion is permitted only after 199 | // the copy of this component in the stack 200 | // does not exist anymore 201 | 202 | 203 | protected: 204 | static unsigned _bits_per_clause, _bits_per_variable; // bitsperentry 205 | static unsigned _bits_of_data_size; // number of bits needed to store the data size 206 | static unsigned _data_size_mask; 207 | static unsigned _variable_mask, _clause_mask; 208 | static const unsigned _bits_per_block= (sizeof(unsigned) << 3); 209 | 210 | }; 211 | 212 | #endif /* BASE_PACKED_COMPONENT_H_ */ 213 | -------------------------------------------------------------------------------- /src/new_component_analyzer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * new_component_analyzer.cpp 3 | * 4 | * Created on: Mar 1, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #include "new_component_analyzer.h" 9 | 10 | 11 | 12 | void NewComponentAnalyzer::initialize(LiteralIndexedVector & literals, 13 | vector &lit_pool) { 14 | 15 | max_variable_id_ = literals.end_lit().var() - 1; 16 | 17 | search_stack_.reserve(max_variable_id_ + 1); 18 | var_frequency_scores_.resize(max_variable_id_ + 1, 0); 19 | variable_occurrence_lists_pool_.clear(); 20 | variable_link_list_offsets_.clear(); 21 | variable_link_list_offsets_.resize(max_variable_id_ + 1, 0); 22 | 23 | literal_pool_.reserve(lit_pool.size()); 24 | 25 | 26 | map_clause_id_to_ofs_.clear(); 27 | map_clause_id_to_ofs_.push_back(0); 28 | 29 | vector > occs_(max_variable_id_ + 1); 30 | vector > occ_clauses_(max_variable_id_ + 1); 31 | ClauseOfs current_clause_ofs = 0; 32 | max_clause_id_ = 0; 33 | unsigned curr_clause_length = 0; 34 | auto it_curr_cl_st = lit_pool.begin(); 35 | for (auto it_lit = lit_pool.begin(); it_lit < lit_pool.end(); it_lit++) { 36 | if (*it_lit == SENTINEL_LIT) { 37 | 38 | if (it_lit + 1 == lit_pool.end()) { 39 | literal_pool_.push_back(SENTINEL_LIT); 40 | break; 41 | } 42 | 43 | max_clause_id_++; 44 | literal_pool_.push_back(SENTINEL_LIT); 45 | for (unsigned i = 0; i < CAClauseHeader::overheadInLits(); i++) 46 | literal_pool_.push_back(0); 47 | current_clause_ofs = literal_pool_.size(); 48 | getHeaderOf(current_clause_ofs).clause_id = max_clause_id_; 49 | it_lit += ClauseHeader::overheadInLits(); 50 | it_curr_cl_st = it_lit + 1; 51 | curr_clause_length = 0; 52 | 53 | assert(map_clause_id_to_ofs_.size() == max_clause_id_); 54 | map_clause_id_to_ofs_.push_back(current_clause_ofs); 55 | 56 | } else { 57 | assert(it_lit->var() <= max_variable_id_); 58 | literal_pool_.push_back(*it_lit); 59 | curr_clause_length++; 60 | occs_[it_lit->var()].push_back(max_clause_id_); 61 | //occs_[it_lit->var()].push_back(current_clause_ofs); 62 | occs_[it_lit->var()].push_back(occ_clauses_[it_lit->var()].size()); 63 | pushLitsInto(occ_clauses_[it_lit->var()],lit_pool, it_curr_cl_st - lit_pool.begin(), 64 | *it_lit); 65 | } 66 | } 67 | 68 | ComponentArchetype::initArrays(max_variable_id_, max_clause_id_); 69 | // the unified link list 70 | unified_variable_links_lists_pool_.clear(); 71 | unified_variable_links_lists_pool_.push_back(0); 72 | unified_variable_links_lists_pool_.push_back(0); 73 | for (unsigned v = 1; v < occs_.size(); v++) { 74 | variable_link_list_offsets_[v] = unified_variable_links_lists_pool_.size(); 75 | for (auto l : literals[LiteralID(v, false)].binary_links_) 76 | if (l != SENTINEL_LIT) { 77 | unified_variable_links_lists_pool_.push_back(l.var()); 78 | } 79 | for (auto l : literals[LiteralID(v, true)].binary_links_) 80 | if (l != SENTINEL_LIT) { 81 | unified_variable_links_lists_pool_.push_back(l.var()); 82 | } 83 | unified_variable_links_lists_pool_.push_back(0); 84 | 85 | for(auto it = occs_[v].begin(); it != occs_[v].end(); it+=2){ 86 | unified_variable_links_lists_pool_.push_back(*it); 87 | unified_variable_links_lists_pool_.push_back(*(it + 1) +(occs_[v].end() - it)); 88 | } 89 | 90 | unified_variable_links_lists_pool_.push_back(0); 91 | unified_variable_links_lists_pool_.insert( 92 | unified_variable_links_lists_pool_.end(), 93 | occ_clauses_[v].begin(), 94 | occ_clauses_[v].end()); 95 | } 96 | } 97 | 98 | void NewComponentAnalyzer::recordComponentOf(const VariableIndex var) { 99 | 100 | search_stack_.clear(); 101 | search_stack_.push_back(var); 102 | 103 | archetype_.setVar_seen(var); 104 | 105 | for (auto vt = search_stack_.begin(); 106 | vt != search_stack_.end(); vt++) { 107 | //BEGIN traverse binary clauses 108 | assert(isActive(*vt)); 109 | unsigned *pvar = beginOfLinkList(*vt); 110 | for (; *pvar; pvar++) { 111 | if(isUnseenAndActive(*pvar)){ 112 | setSeenAndStoreInSearchStack(*pvar); 113 | var_frequency_scores_[*pvar]++; 114 | var_frequency_scores_[*vt]++; 115 | } 116 | } 117 | //END traverse binary clauses 118 | 119 | // start traversing links to long clauses 120 | // not that that list starts right after the 0 termination of the prvious list 121 | // hence pcl_ofs = pvar + 1 122 | for (auto pcl_ofs = pvar + 1; *pcl_ofs != SENTINEL_CL; pcl_ofs+=2) { 123 | ClauseIndex clID = *pcl_ofs; 124 | if(archetype_.clause_unseen_in_sup_comp(clID)){ 125 | auto itVEnd = search_stack_.end(); 126 | bool all_lits_active = true; 127 | LiteralID * pstart_cls = reinterpret_cast(pcl_ofs + 1 + *(pcl_ofs+1)); 128 | for (auto itL = pstart_cls; *itL != SENTINEL_LIT; itL++) { 129 | assert(itL->var() <= max_variable_id_); 130 | if(archetype_.var_nil(itL->var())){ 131 | assert(!isActive(*itL)); 132 | all_lits_active = false; 133 | if (isResolved(*itL)) 134 | continue; 135 | //BEGIN accidentally entered a satisfied clause: undo the search process 136 | while (search_stack_.end() != itVEnd) { 137 | assert(search_stack_.back() <= max_variable_id_); 138 | archetype_.setVar_in_sup_comp_unseen(search_stack_.back()); 139 | search_stack_.pop_back(); 140 | } 141 | archetype_.setClause_nil(clID); 142 | while(*itL != SENTINEL_LIT) 143 | if(isActive(*(--itL))) 144 | var_frequency_scores_[itL->var()]--; 145 | //END accidentally entered a satisfied clause: undo the search process 146 | break; 147 | } else { 148 | assert(isActive(*itL)); 149 | var_frequency_scores_[itL->var()]++; 150 | if(isUnseenAndActive(itL->var())) 151 | setSeenAndStoreInSearchStack(itL->var()); 152 | } 153 | } 154 | 155 | if (!archetype_.clause_nil(clID)){ 156 | var_frequency_scores_[*vt]++; 157 | archetype_.setClause_seen(clID,all_lits_active); 158 | } 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/component_analyzer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component_analyzer.h 3 | * 4 | * Created on: Feb 7, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef COMPONENT_ANALYZER_H_ 9 | #define COMPONENT_ANALYZER_H_ 10 | 11 | 12 | 13 | #include "statistics.h" 14 | #include "component_types/component.h" 15 | #include "component_types/base_packed_component.h" 16 | #include "component_types/component_archetype.h" 17 | 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include "containers.h" 24 | #include "stack.h" 25 | 26 | using namespace std; 27 | 28 | 29 | struct CAClauseHeader { 30 | unsigned clause_id = 0; 31 | LiteralID lit_A; 32 | LiteralID lit_B; 33 | 34 | static unsigned overheadInLits() { 35 | return (sizeof(CAClauseHeader) - 2 * sizeof(LiteralID)) / sizeof(LiteralID); 36 | } 37 | }; 38 | 39 | 40 | 41 | 42 | class STDComponentAnalyzer { 43 | public: 44 | STDComponentAnalyzer(DataAndStatistics &statistics, 45 | LiteralIndexedVector & lit_values) : 46 | statistics_(statistics), literal_values_(lit_values) { 47 | } 48 | 49 | unsigned scoreOf(VariableIndex v) { 50 | return var_frequency_scores_[v]; 51 | } 52 | 53 | ComponentArchetype ¤t_archetype(){ 54 | return archetype_; 55 | } 56 | 57 | void initialize(LiteralIndexedVector & literals, 58 | vector &lit_pool); 59 | 60 | 61 | bool isUnseenAndActive(VariableIndex v){ 62 | assert(v <= max_variable_id_); 63 | return archetype_.var_unseen_in_sup_comp(v); 64 | } 65 | 66 | void setSeenAndStoreInSearchStack(VariableIndex v){ 67 | assert(isActive(v)); 68 | search_stack_.push_back(v); 69 | archetype_.setVar_seen(v); 70 | } 71 | 72 | 73 | void setupAnalysisContext(StackLevel &top, Component & super_comp){ 74 | archetype_.reInitialize(top,super_comp); 75 | 76 | for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) 77 | if (isActive(*vt)) { 78 | archetype_.setVar_in_sup_comp_unseen(*vt); 79 | var_frequency_scores_[*vt] = 0; 80 | } 81 | 82 | for (auto itCl = super_comp.clsBegin(); *itCl != clsSENTINEL; itCl++) 83 | archetype_.setClause_in_sup_comp_unseen(*itCl); 84 | } 85 | 86 | // returns true, iff the component found is non-trivial 87 | bool exploreRemainingCompOf(VariableIndex v) { 88 | assert(archetype_.var_unseen_in_sup_comp(v)); 89 | recordComponentOf(v); 90 | 91 | if (search_stack_.size() == 1) { 92 | archetype_.stack_level().includeSolution(2); 93 | archetype_.setVar_in_other_comp(v); 94 | return false; 95 | } 96 | return true; 97 | } 98 | 99 | 100 | inline Component *makeComponentFromArcheType(){ 101 | return archetype_.makeComponentFromState(search_stack_.size()); 102 | } 103 | 104 | unsigned max_clause_id(){ 105 | return max_clause_id_; 106 | } 107 | unsigned max_variable_id(){ 108 | return max_variable_id_; 109 | } 110 | 111 | ComponentArchetype &getArchetype(){ 112 | return archetype_; 113 | } 114 | 115 | //begin DEBUG 116 | void test_checkArchetypeRepForClause(unsigned *pcl_ofs){ 117 | ClauseIndex clID = getClauseID(*pcl_ofs); 118 | bool all_a = true; 119 | for (auto itL = beginOfClause(*pcl_ofs); *itL != SENTINEL_LIT; itL++) { 120 | if(!isActive(*itL)) 121 | all_a = false; 122 | } 123 | assert(all_a == archetype_.clause_all_lits_active(clID)); 124 | } 125 | //end DEBUG 126 | 127 | private: 128 | DataAndStatistics &statistics_; 129 | 130 | // the id of the last clause 131 | // note that clause ID is the clause number, 132 | // different from the offset of the clause in the literal pool 133 | unsigned max_clause_id_ = 0; 134 | unsigned max_variable_id_ = 0; 135 | 136 | // pool of clauses as lists of LiteralIDs 137 | // Note that with a clause begin position p we have 138 | // the clause ID at position p-1 139 | vector literal_pool_; 140 | 141 | // this contains clause offsets of the clauses 142 | // where each variable occurs in; 143 | vector variable_occurrence_lists_pool_; 144 | 145 | // this is a new idea, 146 | // for every variable we have a list 147 | // 0 binarylinks 0 occurrences 0 148 | // this should give better cache behaviour, 149 | // because all links of one variable (binary and nonbinray) are found 150 | // in one contiguous chunk of memory 151 | vector unified_variable_links_lists_pool_; 152 | 153 | vector map_clause_id_to_ofs_; 154 | vector variable_link_list_offsets_; 155 | LiteralIndexedVector & literal_values_; 156 | 157 | vector var_frequency_scores_; 158 | 159 | ComponentArchetype archetype_; 160 | 161 | vector search_stack_; 162 | 163 | bool isResolved(const LiteralID lit) { 164 | return literal_values_[lit] == F_TRI; 165 | } 166 | 167 | bool isSatisfied(const LiteralID lit) { 168 | return literal_values_[lit] == T_TRI; 169 | } 170 | bool isActive(const LiteralID lit) { 171 | return literal_values_[lit] == X_TRI; 172 | } 173 | 174 | bool isSatisfiedByFirstTwoLits(ClauseOfs cl_ofs) { 175 | return isSatisfied(getHeaderOf(cl_ofs).lit_A) || isSatisfied(getHeaderOf(cl_ofs).lit_B); 176 | } 177 | 178 | bool isActive(const VariableIndex v) { 179 | return literal_values_[LiteralID(v, true)] == X_TRI; 180 | } 181 | 182 | unsigned getClauseID(ClauseOfs cl_ofs) { 183 | return reinterpret_cast(&literal_pool_[cl_ofs 184 | - CAClauseHeader::overheadInLits()])->clause_id; 185 | } 186 | 187 | CAClauseHeader &getHeaderOf(ClauseOfs cl_ofs) { 188 | return *reinterpret_cast(&literal_pool_[cl_ofs 189 | - CAClauseHeader::overheadInLits()]); 190 | } 191 | 192 | unsigned *beginOfLinkList(VariableIndex v) { 193 | return &unified_variable_links_lists_pool_[variable_link_list_offsets_[v]]; 194 | } 195 | 196 | vector::iterator beginOfClause(ClauseOfs cl_ofs) { 197 | return literal_pool_.begin() + cl_ofs; 198 | } 199 | 200 | // stores all information about the component of var 201 | // in variables_seen_, clauses_seen_ and 202 | // component_search_stack 203 | // we have an isolated variable iff 204 | // after execution component_search_stack.size()==1 205 | void recordComponentOf(const VariableIndex var); 206 | 207 | }; 208 | 209 | #endif /* COMPONENT_ANALYZER_H_ */ 210 | -------------------------------------------------------------------------------- /test/taketimes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | import sys 4 | 5 | from os import listdir 6 | from helpers.htmlresume import Htmltable, Htmlwriter 7 | from helpers.inputhelper import read_filelist 8 | from helpers.sharpsathelper import run_all_on_list 9 | 10 | __author__ = 'thurley' 11 | 12 | TIMEOUT = 100 # timeout in seconds 13 | 14 | def bold(s, yes): 15 | if yes : 16 | return "" + s + "" 17 | return s 18 | 19 | def store_results(filename, binary, list): 20 | f = open(filename, 'w') 21 | 22 | num_instances = len(list) 23 | num_successes = 0 24 | total_time = 0 25 | for p in list: 26 | 27 | if p[1] < TIMEOUT: 28 | num_successes += 1 29 | total_time += p[1] 30 | 31 | 32 | total_penalty_time = TIMEOUT*(num_instances - num_successes) 33 | 34 | f.write("
\n") 35 | f.write("\n") 36 | f.write("") 37 | f.write("") 38 | f.write("") 39 | f.write("") 40 | f.write("") 41 | f.write("") 42 | f.write("") 43 | f.write("") 44 | f.write("") 45 | f.write("") 46 | f.write("") 47 | f.write("") 48 | f.write("") 49 | f.write("") 50 | f.write("") 51 | for p in list: 52 | 53 | stringtime = '--' if p[1] >= TIMEOUT else repr(round(p[1], 3)) 54 | f.write("") 55 | f.write("") 56 | f.write("") 57 | 58 | f.write("") 59 | f.write("
Name" + binary + "
Solved" + repr(num_successes) + "/" + repr(len(list)) + "
Time " + bold(repr(round(total_time, 3)), False)+ "
Time (with TIMEOUT penalties) " + bold(repr(round(total_time+total_penalty_time, 3)), False)+ "
" + p[0] + "" + bold(stringtime, False) + "
") 60 | f.write("\n") 61 | 62 | def concat(a, list): 63 | l = [a] 64 | l.extend(list) 65 | return l 66 | 67 | def store_results_as_html(filename, binaries, list): 68 | 69 | 70 | htmlwriter = Htmlwriter("test.html") 71 | 72 | htmltable = Htmltable() 73 | 74 | num_instances = len(list) 75 | all_successes = [] 76 | all_total_time = [] 77 | all_with_penalty_time = [] 78 | 79 | opt_successes = 0 80 | opt_total_time = len(list) * TIMEOUT 81 | opt_with_penalty_time = len(list) * TIMEOUT 82 | for i in range(1, len(binaries)+1): 83 | num_successes = 0 84 | total_time = 0 85 | penalty_time = 0 86 | for p in list: 87 | if p[i] < TIMEOUT: 88 | num_successes += 1 89 | total_time += p[i] 90 | else: 91 | penalty_time += TIMEOUT 92 | 93 | if num_successes > opt_successes: 94 | opt_successes = num_successes 95 | if total_time < opt_total_time: 96 | opt_total_time = total_time 97 | if total_time + penalty_time < opt_with_penalty_time: 98 | opt_with_penalty_time = total_time + penalty_time 99 | 100 | all_successes.append(num_successes) 101 | all_total_time.append(total_time) 102 | all_with_penalty_time.append(total_time + penalty_time) 103 | 104 | str_all_successes = [] 105 | str_all_total_time = [] 106 | str_all_with_penalty_time = [] 107 | 108 | for i in range(0, len(all_successes)): 109 | str_all_successes.append(["opt-head" if all_successes[i] >= opt_successes else "", repr(all_successes[i])]) 110 | str_all_total_time.append(["opt-head" if all_total_time[i] <= opt_total_time else "", repr(round(all_total_time[i], 3))]) 111 | str_all_with_penalty_time.append(["opt-head" if all_with_penalty_time[i] <= opt_with_penalty_time else "", repr(round(all_with_penalty_time[i], 3))]) 112 | 113 | head = [["head", "Name"]] 114 | for b in binaries: 115 | head.append(["head", b]) 116 | 117 | htmltable.add_header_w_cell_classes(head) 118 | htmltable.add_header_w_cell_classes(concat(["head", "Solved (out of " + repr(num_instances) + ")"], str_all_successes)) 119 | htmltable.add_header_w_cell_classes(concat(["head", "Time"], str_all_total_time)) 120 | htmltable.add_header_w_cell_classes(concat(["head", "Time (with penalties)"], str_all_with_penalty_time)) 121 | 122 | for p in list: 123 | row_of_times = [] 124 | opt = 1 125 | for i in range(1, len(binaries)+1): 126 | stringtime = '--' if p[i] >= TIMEOUT else repr(round(p[i], 3)) 127 | if (p[i] < p[opt]): 128 | opt = i 129 | row_of_times.append(["", stringtime]) 130 | 131 | for i in range(1, len(binaries)+1): 132 | if (p[i] == p[opt]): 133 | row_of_times[i-1][0] = "optimal" 134 | 135 | htmltable.add_row_w_cell_classes(concat(["", p[0]], row_of_times)) 136 | 137 | htmlwriter.make_document("", htmltable.make()) 138 | 139 | def get_filelist(cnffile_source): 140 | list = [] 141 | if os.path.isdir(cnffile_source): 142 | print("Directory source found. Scanning for .cnf files ...") 143 | #os.chdir(cnffile_source) 144 | for (dpath, dnames, filenames) in os.walk(cnffile_source): 145 | #print(dpath) 146 | for f in filenames: 147 | #print(f + ": " + repr(os.path.isfile(dpath + f))) 148 | if os.path.isfile(dpath + "/" + f) and f.split(".")[len(f.split(".")) - 1] == "cnf": 149 | list.append(dpath + "/" + f) 150 | else: 151 | print("A file with a list of cnf files found.") 152 | list = read_filelist(cnffile_source) 153 | print("DONE") 154 | return list 155 | 156 | 157 | def extract_from_args(): 158 | binaries = [] 159 | for i in range(2, len(sys.argv)): 160 | binaries.append(os.path.expandvars(os.path.expanduser(sys.argv[i]))) 161 | return os.path.expandvars(os.path.expanduser(sys.argv[1])), binaries 162 | 163 | if len(sys.argv) < 3: 164 | print("Usage: ") 165 | print(" taketime.py CNF_SOURCE BINARY1 [BINARY2 [BINARY3 ... ]]") 166 | 167 | 168 | cnffile_source, binaries = extract_from_args() 169 | cnflist = get_filelist(cnffile_source) 170 | 171 | for f in binaries: 172 | print(f) 173 | 174 | compare_data = run_all_on_list(TIMEOUT, cnflist, binaries) 175 | 176 | store_results("results.html", binaries[0], compare_data) 177 | store_results_as_html("test.html", binaries, compare_data) -------------------------------------------------------------------------------- /src/new_component_analyzer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * new_component_analyzer.h 3 | * 4 | * Created on: Mar 1, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef NEW_COMPONENT_ANALYZER_H_ 9 | #define NEW_COMPONENT_ANALYZER_H_ 10 | 11 | 12 | 13 | 14 | 15 | #include "statistics.h" 16 | #include "component_types/component.h" 17 | #include "component_types/base_packed_component.h" 18 | #include "component_types/component_archetype.h" 19 | 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include "containers.h" 26 | #include "stack.h" 27 | 28 | using namespace std; 29 | 30 | 31 | struct CAClauseHeader { 32 | unsigned clause_id = 0; 33 | LiteralID lit_A; 34 | LiteralID lit_B; 35 | 36 | static unsigned overheadInLits() { 37 | return (sizeof(CAClauseHeader) - 2 * sizeof(LiteralID)) / sizeof(LiteralID); 38 | } 39 | }; 40 | 41 | 42 | class NewComponentAnalyzer; 43 | 44 | 45 | class NewComponentAnalyzer { 46 | public: 47 | NewComponentAnalyzer(DataAndStatistics &statistics, 48 | LiteralIndexedVector & lit_values) : 49 | statistics_(statistics), literal_values_(lit_values) { 50 | } 51 | 52 | unsigned scoreOf(VariableIndex v) { 53 | return var_frequency_scores_[v]; 54 | } 55 | 56 | ComponentArchetype ¤t_archetype(){ 57 | return archetype_; 58 | } 59 | 60 | void initialize(LiteralIndexedVector & literals, 61 | vector &lit_pool); 62 | 63 | 64 | bool isUnseenAndActive(VariableIndex v){ 65 | assert(v <= max_variable_id_); 66 | return archetype_.var_unseen_in_sup_comp(v); 67 | } 68 | 69 | void setSeenAndStoreInSearchStack(VariableIndex v){ 70 | assert(isActive(v)); 71 | search_stack_.push_back(v); 72 | archetype_.setVar_seen(v); 73 | } 74 | 75 | 76 | void setupAnalysisContext(StackLevel &top, Component & super_comp){ 77 | archetype_.reInitialize(top,super_comp); 78 | 79 | for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) 80 | if (isActive(*vt)) { 81 | archetype_.setVar_in_sup_comp_unseen(*vt); 82 | var_frequency_scores_[*vt] = 0; 83 | } 84 | 85 | for (auto itCl = super_comp.clsBegin(); *itCl != clsSENTINEL; itCl++) 86 | archetype_.setClause_in_sup_comp_unseen(*itCl); 87 | } 88 | 89 | // returns true, iff the component found is non-trivial 90 | bool exploreRemainingCompOf(VariableIndex v) { 91 | assert(archetype_.var_unseen_in_sup_comp(v)); 92 | recordComponentOf(v); 93 | 94 | if (search_stack_.size() == 1) { 95 | archetype_.stack_level().includeSolution(2); 96 | archetype_.setVar_in_other_comp(v); 97 | return false; 98 | } 99 | return true; 100 | } 101 | 102 | 103 | inline Component *makeComponentFromArcheType(){ 104 | return archetype_.makeComponentFromState(search_stack_.size()); 105 | } 106 | 107 | unsigned max_clause_id(){ 108 | return max_clause_id_; 109 | } 110 | unsigned max_variable_id(){ 111 | return max_variable_id_; 112 | } 113 | 114 | ComponentArchetype &getArchetype(){ 115 | return archetype_; 116 | } 117 | 118 | //begin DEBUG 119 | void test_checkArchetypeRepForClause(unsigned *pcl_ofs){ 120 | ClauseIndex clID = getClauseID(*pcl_ofs); 121 | bool all_a = true; 122 | for (auto itL = beginOfClause(*pcl_ofs); *itL != SENTINEL_LIT; itL++) { 123 | if(!isActive(*itL)) 124 | all_a = false; 125 | } 126 | assert(all_a == archetype_.clause_all_lits_active(clID)); 127 | } 128 | //end DEBUG 129 | 130 | private: 131 | DataAndStatistics &statistics_; 132 | 133 | // the id of the last clause 134 | // note that clause ID is the clause number, 135 | // different from the offset of the clause in the literal pool 136 | unsigned max_clause_id_ = 0; 137 | unsigned max_variable_id_ = 0; 138 | 139 | // pool of clauses as lists of LiteralIDs 140 | // Note that with a clause begin position p we have 141 | // the clause ID at position p-1 142 | vector literal_pool_; 143 | 144 | // this contains clause offsets of the clauses 145 | // where each variable occurs in; 146 | vector variable_occurrence_lists_pool_; 147 | 148 | // this is a new idea, 149 | // for every variable we have a list 150 | // 0 binarylinks 0 occurrences 0 151 | // this should give better cache behaviour, 152 | // because all links of one variable (binary and nonbinray) are found 153 | // in one contiguous chunk of memory 154 | vector unified_variable_links_lists_pool_; 155 | 156 | vector map_clause_id_to_ofs_; 157 | vector variable_link_list_offsets_; 158 | LiteralIndexedVector & literal_values_; 159 | 160 | vector var_frequency_scores_; 161 | 162 | ComponentArchetype archetype_; 163 | 164 | vector search_stack_; 165 | 166 | bool isResolved(const LiteralID lit) { 167 | return literal_values_[lit] == F_TRI; 168 | } 169 | 170 | bool isSatisfied(const LiteralID lit) { 171 | return literal_values_[lit] == T_TRI; 172 | } 173 | bool isActive(const LiteralID lit) { 174 | return literal_values_[lit] == X_TRI; 175 | } 176 | 177 | bool isSatisfiedByFirstTwoLits(ClauseOfs cl_ofs) { 178 | return isSatisfied(getHeaderOf(cl_ofs).lit_A) || isSatisfied(getHeaderOf(cl_ofs).lit_B); 179 | } 180 | 181 | bool isActive(const VariableIndex v) { 182 | return literal_values_[LiteralID(v, true)] == X_TRI; 183 | } 184 | 185 | unsigned getClauseID(ClauseOfs cl_ofs) { 186 | return reinterpret_cast(&literal_pool_[cl_ofs 187 | - CAClauseHeader::overheadInLits()])->clause_id; 188 | } 189 | 190 | CAClauseHeader &getHeaderOf(ClauseOfs cl_ofs) { 191 | return *reinterpret_cast(&literal_pool_[cl_ofs 192 | - CAClauseHeader::overheadInLits()]); 193 | } 194 | 195 | unsigned *beginOfLinkList(VariableIndex v) { 196 | return &unified_variable_links_lists_pool_[variable_link_list_offsets_[v]]; 197 | } 198 | 199 | vector::iterator beginOfClause(ClauseOfs cl_ofs) { 200 | return literal_pool_.begin() + cl_ofs; 201 | } 202 | 203 | // stores all information about the component of var 204 | // in variables_seen_, clauses_seen_ and 205 | // component_search_stack 206 | // we have an isolated variable iff 207 | // after execution component_search_stack.size()==1 208 | void recordComponentOf(const VariableIndex var); 209 | 210 | void pushLitsInto(vector &target, 211 | const vector &lit_pool, 212 | unsigned start_of_cl, 213 | LiteralID & omitLit){ 214 | for (auto it_lit = lit_pool.begin() + start_of_cl; 215 | (*it_lit != SENTINEL_LIT); it_lit++) { 216 | if(it_lit->var() != omitLit.var()) 217 | target.push_back(it_lit->raw()); 218 | } 219 | target.push_back(SENTINEL_LIT.raw()); 220 | } 221 | 222 | }; 223 | 224 | 225 | 226 | #endif /* NEW_COMPONENT_ANALYZER_H_ */ 227 | -------------------------------------------------------------------------------- /src/alt_component_analyzer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * alt_component_analyzer.cpp 3 | * 4 | * Created on: Mar 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | 9 | #include "alt_component_analyzer.h" 10 | 11 | 12 | 13 | void AltComponentAnalyzer::initialize(LiteralIndexedVector & literals, 14 | vector &lit_pool) { 15 | 16 | max_variable_id_ = literals.end_lit().var() - 1; 17 | 18 | search_stack_.reserve(max_variable_id_ + 1); 19 | var_frequency_scores_.resize(max_variable_id_ + 1, 0); 20 | variable_occurrence_lists_pool_.clear(); 21 | variable_link_list_offsets_.clear(); 22 | variable_link_list_offsets_.resize(max_variable_id_ + 1, 0); 23 | 24 | vector > occs(max_variable_id_ + 1); 25 | vector > occ_long_clauses(max_variable_id_ + 1); 26 | vector > occ_ternary_clauses(max_variable_id_ + 1); 27 | 28 | vector tmp; 29 | max_clause_id_ = 0; 30 | unsigned curr_clause_length = 0; 31 | auto it_curr_cl_st = lit_pool.begin(); 32 | 33 | for (auto it_lit = lit_pool.begin(); it_lit < lit_pool.end(); it_lit++) { 34 | if (*it_lit == SENTINEL_LIT) { 35 | 36 | if (it_lit + 1 == lit_pool.end()) 37 | break; 38 | 39 | max_clause_id_++; 40 | it_lit += ClauseHeader::overheadInLits(); 41 | it_curr_cl_st = it_lit + 1; 42 | curr_clause_length = 0; 43 | 44 | } else { 45 | assert(it_lit->var() <= max_variable_id_); 46 | curr_clause_length++; 47 | 48 | getClause(tmp,it_curr_cl_st, *it_lit); 49 | 50 | assert(tmp.size() > 1); 51 | 52 | if(tmp.size() == 2) { 53 | //if(false){ 54 | occ_ternary_clauses[it_lit->var()].push_back(max_clause_id_); 55 | occ_ternary_clauses[it_lit->var()].insert(occ_ternary_clauses[it_lit->var()].end(), 56 | tmp.begin(), tmp.end()); 57 | } else { 58 | occs[it_lit->var()].push_back(max_clause_id_); 59 | occs[it_lit->var()].push_back(occ_long_clauses[it_lit->var()].size()); 60 | occ_long_clauses[it_lit->var()].insert(occ_long_clauses[it_lit->var()].end(), 61 | tmp.begin(), tmp.end()); 62 | occ_long_clauses[it_lit->var()].push_back(SENTINEL_LIT.raw()); 63 | } 64 | 65 | } 66 | } 67 | 68 | ComponentArchetype::initArrays(max_variable_id_, max_clause_id_); 69 | // the unified link list 70 | unified_variable_links_lists_pool_.clear(); 71 | unified_variable_links_lists_pool_.push_back(0); 72 | unified_variable_links_lists_pool_.push_back(0); 73 | for (unsigned v = 1; v < occs.size(); v++) { 74 | // BEGIN data for binary clauses 75 | variable_link_list_offsets_[v] = unified_variable_links_lists_pool_.size(); 76 | for (auto l : literals[LiteralID(v, false)].binary_links_) 77 | if (l != SENTINEL_LIT) 78 | unified_variable_links_lists_pool_.push_back(l.var()); 79 | 80 | for (auto l : literals[LiteralID(v, true)].binary_links_) 81 | if (l != SENTINEL_LIT) 82 | unified_variable_links_lists_pool_.push_back(l.var()); 83 | 84 | unified_variable_links_lists_pool_.push_back(0); 85 | 86 | // BEGIN data for ternary clauses 87 | unified_variable_links_lists_pool_.insert( 88 | unified_variable_links_lists_pool_.end(), 89 | occ_ternary_clauses[v].begin(), 90 | occ_ternary_clauses[v].end()); 91 | 92 | unified_variable_links_lists_pool_.push_back(0); 93 | 94 | // BEGIN data for long clauses 95 | for(auto it = occs[v].begin(); it != occs[v].end(); it+=2){ 96 | unified_variable_links_lists_pool_.push_back(*it); 97 | unified_variable_links_lists_pool_.push_back(*(it + 1) +(occs[v].end() - it)); 98 | } 99 | 100 | unified_variable_links_lists_pool_.push_back(0); 101 | 102 | unified_variable_links_lists_pool_.insert( 103 | unified_variable_links_lists_pool_.end(), 104 | occ_long_clauses[v].begin(), 105 | occ_long_clauses[v].end()); 106 | } 107 | 108 | 109 | 110 | } 111 | 112 | 113 | //void AltComponentAnalyzer::recordComponentOf(const VariableIndex var) { 114 | // 115 | // search_stack_.clear(); 116 | // setSeenAndStoreInSearchStack(var); 117 | // 118 | // for (auto vt = search_stack_.begin(); vt != search_stack_.end(); vt++) { 119 | // //BEGIN traverse binary clauses 120 | // assert(isActive(*vt)); 121 | // unsigned *p = beginOfLinkList(*vt); 122 | // for (; *p; p++) { 123 | // if(isUnseenAndActive(*p)){ 124 | // setSeenAndStoreInSearchStack(*p); 125 | // var_frequency_scores_[*p]++; 126 | // var_frequency_scores_[*vt]++; 127 | // } 128 | // } 129 | // //END traverse binary clauses 130 | // auto s = p; 131 | // for ( p++; *p ; p+=3) { 132 | //// if(archetype_.clause_unseen_in_sup_comp(*p)){ 133 | //// LiteralID * pstart_cls = reinterpret_cast(p + 1); 134 | //// searchThreeClause(*vt,*p, pstart_cls); 135 | //// } 136 | // } 137 | // //END traverse ternary clauses 138 | // 139 | // for (p++; *p ; p +=2) { 140 | // if(archetype_.clause_unseen_in_sup_comp(*p)){ 141 | // LiteralID * pstart_cls = reinterpret_cast(p + 1 + *(p+1)); 142 | // searchClause(*vt,*p, pstart_cls); 143 | // } 144 | // } 145 | // 146 | // for ( s++; *s ; s+=3) { 147 | // if(archetype_.clause_unseen_in_sup_comp(*s)){ 148 | // LiteralID * pstart_cls = reinterpret_cast(s + 1); 149 | // searchThreeClause(*vt,*s, pstart_cls); 150 | // } 151 | // } 152 | // } 153 | //} 154 | 155 | void AltComponentAnalyzer::recordComponentOf(const VariableIndex var) { 156 | 157 | search_stack_.clear(); 158 | setSeenAndStoreInSearchStack(var); 159 | 160 | for (auto vt = search_stack_.begin(); vt != search_stack_.end(); vt++) { 161 | //BEGIN traverse binary clauses 162 | assert(isActive(*vt)); 163 | unsigned *p = beginOfLinkList(*vt); 164 | for (; *p; p++) { 165 | if(manageSearchOccurrenceOf(LiteralID(*p,true))){ 166 | var_frequency_scores_[*p]++; 167 | var_frequency_scores_[*vt]++; 168 | } 169 | } 170 | //END traverse binary clauses 171 | 172 | for ( p++; *p ; p+=3) { 173 | if(archetype_.clause_unseen_in_sup_comp(*p)){ 174 | LiteralID litA = *reinterpret_cast(p + 1); 175 | LiteralID litB = *(reinterpret_cast(p + 1) + 1); 176 | if(isSatisfied(litA)|| isSatisfied(litB)) 177 | archetype_.setClause_nil(*p); 178 | else { 179 | var_frequency_scores_[*vt]++; 180 | manageSearchOccurrenceAndScoreOf(litA); 181 | manageSearchOccurrenceAndScoreOf(litB); 182 | archetype_.setClause_seen(*p,isActive(litA) & 183 | isActive(litB)); 184 | } 185 | } 186 | } 187 | //END traverse ternary clauses 188 | 189 | for (p++; *p ; p +=2) 190 | if(archetype_.clause_unseen_in_sup_comp(*p)) 191 | searchClause(*vt,*p, reinterpret_cast(p + 1 + *(p+1))); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/component_cache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * component_cache.cpp 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #include "component_cache.h" 9 | 10 | #include 11 | 12 | #ifdef __linux__ 13 | 14 | #include 15 | #include 16 | 17 | uint64_t freeram() { 18 | 19 | struct sysinfo info; 20 | sysinfo(&info); 21 | 22 | return info.freeram *(uint64_t) info.mem_unit; 23 | } 24 | 25 | #elif __APPLE__ && __MACH__ 26 | 27 | #include 28 | #include 29 | 30 | 31 | uint64_t freeram() { 32 | 33 | int mib[2]; 34 | int64_t physical_memory; 35 | mib[0] = CTL_HW; 36 | mib[1] = HW_MEMSIZE; 37 | size_t length = sizeof(int64_t); 38 | sysctl(mib, 2, &physical_memory, &length, NULL, 0); 39 | 40 | return physical_memory; 41 | } 42 | 43 | #else 44 | 45 | #endif 46 | 47 | 48 | 49 | #include "stack.h" 50 | 51 | 52 | ComponentCache::ComponentCache(DataAndStatistics &statistics) : 53 | statistics_(statistics) { 54 | } 55 | 56 | void ComponentCache::init(Component &super_comp) { 57 | 58 | cout << sizeof(CacheableComponent) << " " << sizeof(mpz_class) << endl; 59 | CacheableComponent &packed_super_comp = *new CacheableComponent(super_comp); 60 | my_time_ = 1; 61 | 62 | entry_base_.clear(); 63 | entry_base_.reserve(2000000); 64 | entry_base_.push_back(new CacheableComponent()); // dummy Element 65 | table_.clear(); 66 | table_.resize(1024*1024, 0); 67 | table_size_mask_ = table_.size() - 1; 68 | 69 | free_entry_base_slots_.clear(); 70 | free_entry_base_slots_.reserve(10000); 71 | 72 | uint64_t free_ram = freeram(); 73 | uint64_t max_cache_bound = 95 * (free_ram / 100); 74 | 75 | if (statistics_.maximum_cache_size_bytes_ == 0) { 76 | statistics_.maximum_cache_size_bytes_ = max_cache_bound; 77 | } 78 | 79 | if (statistics_.maximum_cache_size_bytes_ > free_ram) { 80 | cout << endl <<" WARNING: Maximum cache size larger than free RAM available" << endl; 81 | cout << " Free RAM " << free_ram / 1000000 << "MB" << endl; 82 | } 83 | 84 | cout << "Maximum cache size:\t" 85 | << statistics_.maximum_cache_size_bytes_ / 1000000 << " MB" << endl 86 | << endl; 87 | 88 | assert(!statistics_.cache_full()); 89 | 90 | if (entry_base_.capacity() == entry_base_.size()) 91 | entry_base_.reserve(2 * entry_base_.size()); 92 | 93 | entry_base_.push_back(&packed_super_comp); 94 | 95 | statistics_.incorporate_cache_store(packed_super_comp); 96 | 97 | super_comp.set_id(1); 98 | } 99 | 100 | void ComponentCache::test_descendantstree_consistency() { 101 | for (unsigned id = 2; id < entry_base_.size(); id++) 102 | if (entry_base_[id] != nullptr) { 103 | CacheEntryID act_child = entry(id).first_descendant(); 104 | while (act_child) { 105 | CacheEntryID next_child = entry(act_child).next_sibling(); 106 | assert(entry(act_child).father() == id); 107 | 108 | act_child = next_child; 109 | } 110 | CacheEntryID father = entry(id).father(); 111 | CacheEntryID act_sib = entry(father).first_descendant(); 112 | 113 | bool found = false; 114 | 115 | while (act_sib) { 116 | CacheEntryID next_sib = entry(act_sib).next_sibling(); 117 | if (act_sib == id) 118 | found = true; 119 | act_sib = next_sib; 120 | } 121 | assert(found); 122 | } 123 | } 124 | 125 | 126 | 127 | 128 | 129 | bool ComponentCache::deleteEntries() { 130 | assert(statistics_.cache_full()); 131 | 132 | vector scores; 133 | for (auto it = entry_base_.begin() + 1; it != entry_base_.end(); it++) 134 | if (*it != nullptr && (*it)->isDeletable()) { 135 | scores.push_back((double) (*it)->creation_time()); 136 | } 137 | sort(scores.begin(), scores.end()); 138 | double cutoff = scores[scores.size() / 2]; 139 | 140 | //cout << "cutoff" << cutoff << " entries: "<< entry_base_.size()<< endl; 141 | 142 | // first : go through the EntryBase and mark the entries to be deleted as deleted (i.e. EMPTY 143 | // note we start at index 2, 144 | // since index 1 is the whole formula, 145 | // should always stay here! 146 | for (unsigned id = 2; id < entry_base_.size(); id++) 147 | if (entry_base_[id] != nullptr && 148 | entry_base_[id]->isDeletable() && 149 | (double) entry_base_[id]->creation_time() <= cutoff) { 150 | removeFromDescendantsTree(id); 151 | eraseEntry(id); 152 | 153 | } 154 | // then go through the Hash Table and erase all Links to empty entries 155 | 156 | 157 | #ifdef DEBUG 158 | test_descendantstree_consistency(); 159 | #endif 160 | 161 | reHashTable(table_.size()); 162 | statistics_.sum_size_cached_components_ = 0; 163 | statistics_.sum_bytes_cached_components_ = 0; 164 | statistics_.sys_overhead_sum_bytes_cached_components_ =0; 165 | 166 | statistics_.sum_bytes_pure_cached_component_data_ = 0; 167 | 168 | for (unsigned id = 2; id < entry_base_.size(); id++) 169 | if (entry_base_[id] != nullptr) { 170 | statistics_.sum_size_cached_components_ += 171 | entry_base_[id]->num_variables(); 172 | statistics_.sum_bytes_cached_components_ += 173 | entry_base_[id]->SizeInBytes(); 174 | statistics_.sum_bytes_pure_cached_component_data_ += 175 | entry_base_[id]->data_only_byte_size(); 176 | statistics_.sys_overhead_sum_bytes_cached_components_ += 177 | entry_base_[id]->sys_overhead_SizeInBytes(); 178 | } 179 | 180 | statistics_.num_cached_components_ = entry_base_.size(); 181 | compute_byte_size_infrasture(); 182 | 183 | //cout << " \t entries: "<< entry_base_.size() - free_entry_base_slots_.size()<< endl; 184 | return true; 185 | } 186 | 187 | 188 | uint64_t ComponentCache::compute_byte_size_infrasture() { 189 | statistics_.cache_infrastructure_bytes_memory_usage_ = 190 | sizeof(ComponentCache) 191 | + sizeof(CacheEntryID)* table_.capacity() 192 | + sizeof(CacheableComponent *)* entry_base_.capacity() 193 | + sizeof(CacheEntryID) * free_entry_base_slots_.capacity(); 194 | return statistics_.cache_infrastructure_bytes_memory_usage_; 195 | } 196 | 197 | void ComponentCache::debug_dump_data(){ 198 | cout << "sizeof (CacheableComponent *, CacheEntryID) " 199 | << sizeof(CacheableComponent *) << ", " 200 | << sizeof(CacheEntryID) << endl; 201 | cout << "table (size/capacity) " << table_.size() 202 | << "/" << table_.capacity() << endl; 203 | cout << "entry_base_ (size/capacity) " << entry_base_.size() 204 | << "/" << entry_base_.capacity() << endl; 205 | cout << "free_entry_base_slots_ (size/capacity) " << free_entry_base_slots_.size() 206 | << "/" << free_entry_base_slots_.capacity() << endl; 207 | 208 | // uint64_t size_model_counts = 0; 209 | uint64_t alloc_model_counts = 0; 210 | for (auto &pentry : entry_base_) 211 | if (pentry != nullptr){ 212 | // size_model_counts += pentry->size_of_model_count(); 213 | alloc_model_counts += pentry->alloc_of_model_count(); 214 | } 215 | cout << "model counts size " << alloc_model_counts << endl; 216 | } 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /src/component_types/difference_packed_component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * difference_packed_component.h 3 | * 4 | * Created on: Feb 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef DIFFERENCE_PACKED_COMPONENT_H_ 9 | #define DIFFERENCE_PACKED_COMPONENT_H_ 10 | 11 | #include "base_packed_component.h" 12 | #include "component.h" 13 | 14 | #include 15 | 16 | 17 | 18 | class DifferencePackedComponent:public BasePackedComponent { 19 | public: 20 | 21 | DifferencePackedComponent() { 22 | } 23 | 24 | inline DifferencePackedComponent(Component &rComp); 25 | 26 | unsigned num_variables() const{ 27 | uint64_t *p = (uint64_t *) data_; 28 | return (*p >> bits_of_data_size()) & (uint64_t) variable_mask(); 29 | 30 | } 31 | 32 | unsigned data_size() const { 33 | return *data_ & _data_size_mask; 34 | } 35 | 36 | unsigned data_only_byte_size() const { 37 | return data_size()* sizeof(unsigned); 38 | } 39 | 40 | unsigned raw_data_byte_size() const { 41 | return data_size()* sizeof(unsigned) 42 | + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t); 43 | } 44 | 45 | // raw data size with the overhead 46 | // for the supposed 16byte alignment of malloc 47 | unsigned sys_overhead_raw_data_byte_size() const { 48 | unsigned ds = data_size()* sizeof(unsigned); 49 | unsigned ms = model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t); 50 | // unsigned mask = 0xfffffff8; 51 | // return (ds & mask) + ((ds & 7)?8:0) 52 | // +(ms & mask) + ((ms & 7)?8:0); 53 | unsigned mask = 0xfffffff0; 54 | return (ds & mask) + ((ds & 15)?16:0) 55 | +(ms & mask) + ((ms & 15)?16:0); 56 | } 57 | 58 | bool equals(const DifferencePackedComponent &comp) const { 59 | if(hashkey_ != comp.hashkey()) 60 | return false; 61 | unsigned* p = data_; 62 | unsigned* r = comp.data_; 63 | while(p != data_ + data_size()) { 64 | if(*(p++) != *(r++)) 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | private: 71 | 72 | }; 73 | 74 | 75 | 76 | DifferencePackedComponent::DifferencePackedComponent(Component &rComp) { 77 | 78 | unsigned max_var_diff = 0; 79 | unsigned hashkey_vars = *rComp.varsBegin(); 80 | for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++) { 81 | hashkey_vars = (hashkey_vars * 3) + *it; 82 | if ((*it - *(it - 1)) - 1 > max_var_diff) 83 | max_var_diff = (*it - *(it - 1)) - 1 ; 84 | } 85 | 86 | unsigned hashkey_clauses = *rComp.clsBegin(); 87 | unsigned max_clause_diff = 0; 88 | if (*rComp.clsBegin()) { 89 | for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++) { 90 | hashkey_clauses = hashkey_clauses*3 + *jt; 91 | if (*jt - *(jt - 1) - 1 > max_clause_diff) 92 | max_clause_diff = *jt - *(jt - 1) - 1; 93 | } 94 | } 95 | 96 | hashkey_ = hashkey_vars + ((unsigned) hashkey_clauses << 11) + ((unsigned) hashkey_clauses >> 23); 97 | 98 | //VERIFIED the definition of bits_per_var_diff and bits_per_clause_diff 99 | unsigned bits_per_var_diff = log2(max_var_diff) + 1; 100 | unsigned bits_per_clause_diff = log2(max_clause_diff) + 1; 101 | 102 | assert(bits_per_var_diff <= 31); 103 | assert(bits_per_clause_diff <= 31); 104 | 105 | unsigned data_size_vars = bits_of_data_size() + 2*bits_per_variable() + 5; 106 | 107 | data_size_vars += (rComp.num_variables() - 1) * bits_per_var_diff ; 108 | 109 | unsigned data_size_clauses = 0; 110 | if(*rComp.clsBegin()) 111 | data_size_clauses += bits_per_clause() + 5 112 | + (rComp.numLongClauses() - 1) * bits_per_clause_diff; 113 | 114 | unsigned data_size = (data_size_vars + data_size_clauses)/bits_per_block(); 115 | data_size+= ((data_size_vars + data_size_clauses) % bits_per_block())? 1 : 0; 116 | 117 | data_ = new unsigned[data_size]; 118 | 119 | assert((data_size >> bits_of_data_size()) == 0); 120 | BitStuffer bs(data_); 121 | 122 | bs.stuff(data_size, bits_of_data_size()); 123 | bs.stuff(rComp.num_variables(), bits_per_variable()); 124 | bs.stuff(bits_per_var_diff, 5); 125 | bs.stuff(*rComp.varsBegin(), bits_per_variable()); 126 | 127 | if(bits_per_var_diff) 128 | for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++) 129 | bs.stuff(*it - *(it - 1) - 1, bits_per_var_diff); 130 | 131 | 132 | if (*rComp.clsBegin()) { 133 | bs.stuff(bits_per_clause_diff, 5); 134 | bs.stuff(*rComp.clsBegin(), bits_per_clause()); 135 | if(bits_per_clause_diff) 136 | for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++) 137 | bs.stuff(*jt - *(jt - 1) - 1, bits_per_clause_diff); 138 | } 139 | 140 | // to check wheter the "END" block of bits_per_clause() 141 | // many zeros fits into the current 142 | //bs.end_check(bits_per_clause()); 143 | // this will tell us if we computed the data_size 144 | // correctly 145 | bs.assert_size(data_size); 146 | } 147 | 148 | 149 | //DifferencePackedComponent::DifferencePackedComponent(Component &rComp) { 150 | // 151 | // unsigned max_var_diff = 0; 152 | // unsigned hashkey_vars = *rComp.varsBegin(); 153 | // for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++) { 154 | // hashkey_vars = (hashkey_vars * 3) + *it; 155 | // if ((*it - *(it - 1)) > max_var_diff) 156 | // max_var_diff = (*it - *(it - 1)) ; 157 | // } 158 | // 159 | // unsigned hashkey_clauses = *rComp.clsBegin(); 160 | // unsigned max_clause_diff = 0; 161 | // if (*rComp.clsBegin()) { 162 | // for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++) { 163 | // hashkey_clauses = hashkey_clauses * 3 + *jt; 164 | // if (*jt - *(jt - 1) > max_clause_diff) 165 | // max_clause_diff = *jt - *(jt - 1); 166 | // } 167 | // } 168 | // 169 | // hashkey_ = hashkey_vars + (((unsigned) hashkey_clauses) << 16); 170 | // 171 | // //VERIFIED the definition of bits_per_var_diff and bits_per_clause_diff 172 | // unsigned bits_per_var_diff = log2(max_var_diff) + 1; 173 | // unsigned bits_per_clause_diff = log2(max_clause_diff) + 1; 174 | // 175 | // unsigned data_size_vars = 2*bits_per_variable() + 5; 176 | // 177 | // data_size_vars += (rComp.num_variables() - 1) * bits_per_var_diff ; 178 | // 179 | // unsigned data_size_clauses = bits_per_clause(); 180 | // if(*rComp.clsBegin()) 181 | // data_size_clauses += bits_per_clause() + 5 182 | // + (rComp.numLongClauses() - 1) * bits_per_clause_diff; 183 | // 184 | // unsigned data_size = (data_size_vars + data_size_clauses)/bits_per_block(); 185 | // data_size+= ((data_size_vars + data_size_clauses) % bits_per_block())? 1 : 0; 186 | // 187 | // data_ = new unsigned[data_size]; 188 | // 189 | // BitStuffer bs(data_); 190 | // 191 | // bs.stuff(rComp.num_variables(), bits_per_variable()); 192 | // bs.stuff(bits_per_var_diff, 5); 193 | // bs.stuff(*rComp.varsBegin(), bits_per_variable()); 194 | // 195 | // for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++) 196 | // bs.stuff(*it - *(it - 1), bits_per_var_diff); 197 | // 198 | // if (*rComp.clsBegin()) { 199 | // bs.stuff(bits_per_clause_diff, 5); 200 | // bs.stuff(*rComp.clsBegin(), bits_per_clause()); 201 | // for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++) 202 | // bs.stuff(*jt - *(jt - 1), bits_per_clause_diff); 203 | // } 204 | // 205 | // // to check wheter the "END" block of bits_per_clause() 206 | // // many zeros fits into the current 207 | // bs.end_check(bits_per_clause()); 208 | // // this will tell us if we computed the data_size 209 | // // correctly 210 | // bs.assert_size(data_size); 211 | //} 212 | 213 | #endif /* DIFFERENCE_PACKED_COMPONENT_H_ */ 214 | -------------------------------------------------------------------------------- /src/component_types/component_archetype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * component_archetype.h 3 | * 4 | * Created on: Feb 9, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef COMPONENT_ARCHETYPE_H_ 9 | #define COMPONENT_ARCHETYPE_H_ 10 | 11 | 12 | #include "../primitive_types.h" 13 | #include "component.h" 14 | 15 | 16 | #include "cacheable_component.h" 17 | 18 | 19 | 20 | 21 | 22 | #include 23 | #include 24 | 25 | 26 | 27 | #include 28 | // State values for variables found during component 29 | // analysis (CA) 30 | typedef unsigned char CA_SearchState; 31 | #define CA_NIL 0 32 | #define CA_VAR_IN_SUP_COMP_UNSEEN 1 33 | #define CA_VAR_SEEN 2 34 | #define CA_VAR_IN_OTHER_COMP 4 35 | 36 | #define CA_VAR_MASK 7 37 | 38 | #define CA_CL_IN_SUP_COMP_UNSEEN 8 39 | #define CA_CL_SEEN 16 40 | #define CA_CL_IN_OTHER_COMP 32 41 | #define CA_CL_ALL_LITS_ACTIVE 64 42 | 43 | #define CA_CL_MASK 120 44 | 45 | class StackLevel; 46 | 47 | class ComponentArchetype { 48 | public: 49 | ComponentArchetype() { 50 | } 51 | ComponentArchetype(StackLevel &stack_level, Component &super_comp) : 52 | p_super_comp_(&super_comp), p_stack_level_(&stack_level) { 53 | } 54 | 55 | void reInitialize(StackLevel &stack_level, Component &super_comp) { 56 | p_super_comp_ = &super_comp; 57 | p_stack_level_ = &stack_level; 58 | clearArrays(); 59 | current_comp_for_caching_.reserveSpace(super_comp.num_variables(),super_comp.numLongClauses()); 60 | } 61 | 62 | Component &super_comp() { 63 | return *p_super_comp_; 64 | } 65 | 66 | StackLevel & stack_level() { 67 | return *p_stack_level_; 68 | } 69 | 70 | void setVar_in_sup_comp_unseen(VariableIndex v) { 71 | seen_[v] = CA_VAR_IN_SUP_COMP_UNSEEN | (seen_[v] & CA_CL_MASK); 72 | } 73 | 74 | void setClause_in_sup_comp_unseen(ClauseIndex cl) { 75 | seen_[cl] = CA_CL_IN_SUP_COMP_UNSEEN | (seen_[cl] & CA_VAR_MASK); 76 | } 77 | 78 | void setVar_nil(VariableIndex v) { 79 | seen_[v] &= CA_CL_MASK; 80 | } 81 | 82 | void setClause_nil(ClauseIndex cl) { 83 | seen_[cl] &= CA_VAR_MASK; 84 | } 85 | 86 | void setVar_seen(VariableIndex v) { 87 | seen_[v] = CA_VAR_SEEN | (seen_[v] & CA_CL_MASK); 88 | } 89 | 90 | void setClause_seen(ClauseIndex cl) { 91 | setClause_nil(cl); 92 | seen_[cl] = CA_CL_SEEN | (seen_[cl] & CA_VAR_MASK); 93 | } 94 | 95 | void setClause_seen(ClauseIndex cl, bool all_lits_act) { 96 | setClause_nil(cl); 97 | seen_[cl] = CA_CL_SEEN | (all_lits_act?CA_CL_ALL_LITS_ACTIVE:0) | (seen_[cl] & CA_VAR_MASK); 98 | } 99 | 100 | void setVar_in_other_comp(VariableIndex v) { 101 | seen_[v] = CA_VAR_IN_OTHER_COMP | (seen_[v] & CA_CL_MASK); 102 | } 103 | 104 | void setClause_in_other_comp(ClauseIndex cl) { 105 | seen_[cl] = CA_CL_IN_OTHER_COMP | (seen_[cl] & CA_VAR_MASK); 106 | } 107 | 108 | bool var_seen(VariableIndex v) { 109 | return seen_[v] & CA_VAR_SEEN; 110 | } 111 | 112 | bool clause_seen(ClauseIndex cl) { 113 | return seen_[cl] & CA_CL_SEEN; 114 | } 115 | 116 | bool clause_all_lits_active(ClauseIndex cl) { 117 | return seen_[cl] & CA_CL_ALL_LITS_ACTIVE; 118 | } 119 | void setClause_all_lits_active(ClauseIndex cl) { 120 | seen_[cl] |= CA_CL_ALL_LITS_ACTIVE; 121 | } 122 | 123 | bool var_nil(VariableIndex v) { 124 | return (seen_[v] & CA_VAR_MASK) == 0; 125 | } 126 | 127 | bool clause_nil(ClauseIndex cl) { 128 | return (seen_[cl] & CA_CL_MASK) == 0; 129 | } 130 | 131 | bool var_unseen_in_sup_comp(VariableIndex v) { 132 | return seen_[v] & CA_VAR_IN_SUP_COMP_UNSEEN; 133 | } 134 | 135 | bool clause_unseen_in_sup_comp(ClauseIndex cl) { 136 | return seen_[cl] & CA_CL_IN_SUP_COMP_UNSEEN; 137 | } 138 | 139 | bool var_seen_in_peer_comp(VariableIndex v) { 140 | return seen_[v] & CA_VAR_IN_OTHER_COMP; 141 | } 142 | 143 | bool clause_seen_in_peer_comp(ClauseIndex cl) { 144 | return seen_[cl] & CA_CL_IN_OTHER_COMP; 145 | } 146 | 147 | static void initArrays(unsigned max_variable_id, unsigned max_clause_id) { 148 | unsigned seen_size = std::max(max_variable_id,max_clause_id) + 1; 149 | seen_ = new CA_SearchState[seen_size]; 150 | seen_byte_size_ = sizeof(CA_SearchState) * (seen_size); 151 | clearArrays(); 152 | 153 | } 154 | 155 | static void clearArrays() { 156 | memset(seen_, CA_NIL, seen_byte_size_); 157 | } 158 | 159 | 160 | Component *makeComponentFromState(unsigned stack_size) { 161 | Component *p_new_comp = new Component(); 162 | p_new_comp->reserveSpace(stack_size, super_comp().numLongClauses()); 163 | current_comp_for_caching_.clear(); 164 | 165 | for (auto v_it = super_comp().varsBegin(); *v_it != varsSENTINEL; v_it++) 166 | if (var_seen(*v_it)) { //we have to put a var into our component 167 | p_new_comp->addVar(*v_it); 168 | current_comp_for_caching_.addVar(*v_it); 169 | setVar_in_other_comp(*v_it); 170 | } 171 | p_new_comp->closeVariableData(); 172 | current_comp_for_caching_.closeVariableData(); 173 | 174 | for (auto it_cl = super_comp().clsBegin(); *it_cl != clsSENTINEL; it_cl++) 175 | if (clause_seen(*it_cl)) { 176 | p_new_comp->addCl(*it_cl); 177 | if(!clause_all_lits_active(*it_cl)) 178 | current_comp_for_caching_.addCl(*it_cl); 179 | setClause_in_other_comp(*it_cl); 180 | } 181 | p_new_comp->closeClauseData(); 182 | current_comp_for_caching_.closeClauseData(); 183 | return p_new_comp; 184 | } 185 | // Component *makeComponentFromState(unsigned stack_size) { 186 | // Component *p_new_comp = new Component(); 187 | // p_new_comp->reserveSpace(stack_size, super_comp().numLongClauses()); 188 | // 189 | // for (auto v_it = super_comp().varsBegin(); *v_it != varsSENTINEL; v_it++) 190 | // if (var_seen(*v_it)) { //we have to put a var into our component 191 | // p_new_comp->addVar(*v_it); 192 | // setVar_in_other_comp(*v_it); 193 | // } 194 | // p_new_comp->closeVariableData(); 195 | // 196 | // for (auto it_cl = super_comp().clsBegin(); *it_cl != clsSENTINEL; it_cl++) 197 | // if (clause_seen(*it_cl)) { 198 | // p_new_comp->addCl(*it_cl); 199 | // setClause_in_other_comp(*it_cl); 200 | // } 201 | // p_new_comp->closeClauseData(); 202 | // return p_new_comp; 203 | // } 204 | 205 | inline void createComponents(Component &ret_comp, CacheableComponent ret_cache_comp, 206 | unsigned stack_size); 207 | 208 | Component current_comp_for_caching_; 209 | private: 210 | Component *p_super_comp_; 211 | StackLevel *p_stack_level_; 212 | 213 | static CA_SearchState *seen_; 214 | static unsigned seen_byte_size_; 215 | 216 | }; 217 | 218 | 219 | 220 | 221 | 222 | void ComponentArchetype::createComponents(Component &ret_comp, 223 | CacheableComponent ret_cache_comp, 224 | unsigned stack_size){ 225 | 226 | // ret_comp.reserveSpace(stack_size, super_comp().numLongClauses()); 227 | // current_comp_for_caching_.clear(); 228 | // 229 | // VariableIndex prev_var = 0; 230 | // for (auto v_it = super_comp().varsBegin(); *v_it != varsSENTINEL; v_it++) 231 | // if (var_seen(*v_it)) { //we have to put a var into our component 232 | // ret_comp.addVar(*v_it); 233 | // current_comp_for_caching_.addVar(*v_it - prev_var - 1); 234 | // prev_var = *v_it; 235 | // setVar_in_other_comp(*v_it); 236 | // } 237 | // ret_comp.closeVariableData(); 238 | // current_comp_for_caching_.closeVariableData(); 239 | // 240 | // ClauseIndex prev_cl = 0; 241 | // for (auto it_cl = super_comp().clsBegin(); *it_cl != clsSENTINEL; it_cl++) 242 | // if (clause_seen(*it_cl)) { 243 | // ret_comp.addCl(*it_cl); 244 | // if(!clause_all_lits_active(*it_cl)){ 245 | // current_comp_for_caching_.addCl(*it_cl - prev_cl - 1); 246 | // prev_cl = *it_cl; 247 | // } 248 | // setClause_in_other_comp(*it_cl); 249 | // } 250 | // ret_comp.closeClauseData(); 251 | // //current_comp_for_caching_.closeClauseData(); 252 | // return p_new_comp; 253 | 254 | } 255 | 256 | 257 | #endif /* COMPONENT_ARCHETYPE_H_ */ 258 | -------------------------------------------------------------------------------- /src/instance.h: -------------------------------------------------------------------------------- 1 | /* 2 | * instance.h 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #ifndef INSTANCE_H_ 9 | #define INSTANCE_H_ 10 | 11 | #include "statistics.h" 12 | #include "structures.h" 13 | #include "containers.h" 14 | 15 | #include 16 | 17 | class Instance { 18 | protected: 19 | 20 | void unSet(LiteralID lit) { 21 | var(lit).ante = Antecedent(NOT_A_CLAUSE); 22 | var(lit).decision_level = INVALID_DL; 23 | literal_values_[lit] = X_TRI; 24 | literal_values_[lit.neg()] = X_TRI; 25 | } 26 | 27 | Antecedent & getAntecedent(LiteralID lit) { 28 | return variables_[lit.var()].ante; 29 | } 30 | 31 | bool hasAntecedent(LiteralID lit) { 32 | return variables_[lit.var()].ante.isAnt(); 33 | } 34 | 35 | bool isAntecedentOf(ClauseOfs ante_cl, LiteralID lit) { 36 | return var(lit).ante.isAClause() && (var(lit).ante.asCl() == ante_cl); 37 | } 38 | 39 | bool isolated(VariableIndex v) { 40 | LiteralID lit(v, false); 41 | return (literal(lit).binary_links_.size() <= 1) 42 | & occurrence_lists_[lit].empty() 43 | & (literal(lit.neg()).binary_links_.size() <= 1) 44 | & occurrence_lists_[lit.neg()].empty(); 45 | } 46 | 47 | bool free(VariableIndex v) { 48 | return isolated(v) & isActive(v); 49 | } 50 | 51 | bool deleteConflictClauses(); 52 | bool markClauseDeleted(ClauseOfs cl_ofs); 53 | 54 | // Compact the literal pool erasing all the clause 55 | // information from deleted clauses 56 | void compactConflictLiteralPool(); 57 | 58 | // we assert that the formula is consistent 59 | // and has not been found UNSAT yet 60 | // hard wires all assertions in the literal stack into the formula 61 | // removes all set variables and essentially reinitiallizes all 62 | // further data 63 | void compactClauses(); 64 | void compactVariables(); 65 | void cleanClause(ClauseOfs cl_ofs); 66 | 67 | ///////////////////////////////////////////////////////// 68 | // END access to variables and literals 69 | ///////////////////////////////////////////////////////// 70 | 71 | 72 | unsigned int num_conflict_clauses() const { 73 | return conflict_clauses_.size(); 74 | } 75 | 76 | unsigned int num_variables() { 77 | return variables_.size() - 1; 78 | } 79 | 80 | bool createfromFile(const string &file_name); 81 | 82 | DataAndStatistics statistics_; 83 | 84 | /** literal_pool_: the literals of all clauses are stored here 85 | * INVARIANT: first and last entries of literal_pool_ are a SENTINEL_LIT 86 | * 87 | * Clauses begin with a ClauseHeader structure followed by the literals 88 | * terminated by SENTINEL_LIT 89 | */ 90 | vector literal_pool_; 91 | 92 | // this is to determine the starting offset of 93 | // conflict clauses 94 | unsigned original_lit_pool_size_; 95 | 96 | LiteralIndexedVector literals_; 97 | 98 | LiteralIndexedVector > occurrence_lists_; 99 | 100 | vector conflict_clauses_; 101 | vector unit_clauses_; 102 | 103 | vector variables_; 104 | LiteralIndexedVector literal_values_; 105 | 106 | void decayActivities() { 107 | for (auto l_it = literals_.begin(); l_it != literals_.end(); l_it++) 108 | l_it->activity_score_ *= 0.5; 109 | 110 | for(auto clause_ofs: conflict_clauses_) 111 | getHeaderOf(clause_ofs).decayScore(); 112 | 113 | } 114 | // void decayActivities(); 115 | 116 | void updateActivities(ClauseOfs clause_ofs) { 117 | getHeaderOf(clause_ofs).increaseScore(); 118 | for (auto it = beginOf(clause_ofs); *it != SENTINEL_LIT; it++) { 119 | literal(*it).increaseActivity(); 120 | } 121 | } 122 | 123 | bool isUnitClause(const LiteralID lit) { 124 | for (auto l : unit_clauses_) 125 | if (l == lit) 126 | return true; 127 | return false; 128 | } 129 | 130 | bool existsUnitClauseOf(VariableIndex v) { 131 | for (auto l : unit_clauses_) 132 | if (l.var() == v) 133 | return true; 134 | return false; 135 | } 136 | 137 | // addUnitClause checks whether lit or lit.neg() is already a 138 | // unit clause 139 | // a negative return value implied that the Instance is UNSAT 140 | bool addUnitClause(const LiteralID lit) { 141 | for (auto l : unit_clauses_) { 142 | if (l == lit) 143 | return true; 144 | if (l == lit.neg()) 145 | return false; 146 | } 147 | unit_clauses_.push_back(lit); 148 | return true; 149 | } 150 | 151 | inline ClauseIndex addClause(vector &literals); 152 | 153 | // adds a UIP Conflict Clause 154 | // and returns it as an Antecedent to the first 155 | // literal stored in literals 156 | inline Antecedent addUIPConflictClause(vector &literals); 157 | 158 | inline bool addBinaryClause(LiteralID litA, LiteralID litB); 159 | 160 | ///////////////////////////////////////////////////////// 161 | // BEGIN access to variables, literals, clauses 162 | ///////////////////////////////////////////////////////// 163 | 164 | inline Variable &var(const LiteralID lit) { 165 | return variables_[lit.var()]; 166 | } 167 | 168 | Literal & literal(LiteralID lit) { 169 | return literals_[lit]; 170 | } 171 | 172 | inline bool isSatisfied(const LiteralID &lit) const { 173 | return literal_values_[lit] == T_TRI; 174 | } 175 | 176 | bool isResolved(LiteralID lit) { 177 | return literal_values_[lit] == F_TRI; 178 | } 179 | 180 | bool isActive(LiteralID lit) const { 181 | return literal_values_[lit] == X_TRI; 182 | } 183 | 184 | vector::const_iterator beginOf(ClauseOfs cl_ofs) const { 185 | return literal_pool_.begin() + cl_ofs; 186 | } 187 | vector::iterator beginOf(ClauseOfs cl_ofs) { 188 | return literal_pool_.begin() + cl_ofs; 189 | } 190 | 191 | decltype(literal_pool_.begin()) conflict_clauses_begin() { 192 | return literal_pool_.begin() + original_lit_pool_size_; 193 | } 194 | 195 | ClauseHeader &getHeaderOf(ClauseOfs cl_ofs) { 196 | return *reinterpret_cast(&literal_pool_[cl_ofs 197 | - ClauseHeader::overheadInLits()]); 198 | } 199 | 200 | bool isSatisfied(ClauseOfs cl_ofs) { 201 | for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++) 202 | if (isSatisfied(*lt)) 203 | return true; 204 | return false; 205 | } 206 | }; 207 | 208 | ClauseIndex Instance::addClause(vector &literals) { 209 | if (literals.size() == 1) { 210 | //TODO Deal properly with the situation that opposing unit clauses are learned 211 | assert(!isUnitClause(literals[0].neg())); 212 | unit_clauses_.push_back(literals[0]); 213 | return 0; 214 | } 215 | if (literals.size() == 2) { 216 | addBinaryClause(literals[0], literals[1]); 217 | return 0; 218 | } 219 | for (unsigned i = 0; i < ClauseHeader::overheadInLits(); i++) 220 | literal_pool_.push_back(0); 221 | ClauseOfs cl_ofs = literal_pool_.size(); 222 | 223 | for (auto l : literals) { 224 | literal_pool_.push_back(l); 225 | literal(l).increaseActivity(1); 226 | } 227 | // make an end: SENTINEL_LIT 228 | literal_pool_.push_back(SENTINEL_LIT); 229 | literal(literals[0]).addWatchLinkTo(cl_ofs); 230 | literal(literals[1]).addWatchLinkTo(cl_ofs); 231 | getHeaderOf(cl_ofs).set_creation_time(statistics_.num_conflicts_); 232 | return cl_ofs; 233 | } 234 | 235 | 236 | Antecedent Instance::addUIPConflictClause(vector &literals) { 237 | Antecedent ante(NOT_A_CLAUSE); 238 | statistics_.num_clauses_learned_++; 239 | ClauseOfs cl_ofs = addClause(literals); 240 | if (cl_ofs != 0) { 241 | conflict_clauses_.push_back(cl_ofs); 242 | getHeaderOf(cl_ofs).set_length(literals.size()); 243 | ante = Antecedent(cl_ofs); 244 | } else if (literals.size() == 2){ 245 | ante = Antecedent(literals.back()); 246 | statistics_.num_binary_conflict_clauses_++; 247 | } else if (literals.size() == 1) 248 | statistics_.num_unit_clauses_++; 249 | return ante; 250 | } 251 | 252 | bool Instance::addBinaryClause(LiteralID litA, LiteralID litB) { 253 | if (literal(litA).hasBinaryLinkTo(litB)) 254 | return false; 255 | literal(litA).addBinLinkTo(litB); 256 | literal(litB).addBinLinkTo(litA); 257 | literal(litA).increaseActivity(); 258 | literal(litB).increaseActivity(); 259 | return true; 260 | } 261 | 262 | 263 | #endif /* INSTANCE_H_ */ 264 | -------------------------------------------------------------------------------- /src/statistics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * statistics.h 3 | * 4 | * Created on: Feb 13, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef STATISTICS_H_ 9 | #define STATISTICS_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include "structures.h" 18 | #include "component_types/cacheable_component.h" 19 | 20 | #include "primitive_types.h" 21 | 22 | using namespace std; 23 | 24 | class DataAndStatistics { 25 | public: 26 | string input_file_; 27 | double time_elapsed_ = 0.0; 28 | uint64_t maximum_cache_size_bytes_ = 0; 29 | 30 | SOLVER_StateT exit_state_ = NO_STATE; 31 | // different variable counts 32 | // number of variables and clauses before preprocessing 33 | unsigned long num_original_variables_ = 0; 34 | unsigned long num_original_clauses_ = 0; 35 | unsigned long num_original_binary_clauses_ = 0; 36 | unsigned long num_original_unit_clauses_ = 0; 37 | 38 | // number of variables remaining 39 | unsigned long num_variables_ = 0; 40 | // number of variables that actually occurs in clauses 41 | unsigned long num_used_variables_ = 0; 42 | unsigned long num_free_variables_ = 0; 43 | 44 | /// different clause counts 45 | 46 | // number of clauses after preprocessing 47 | unsigned long num_long_clauses_ = 0; 48 | unsigned long num_binary_clauses_ = 0; 49 | 50 | unsigned long num_long_conflict_clauses_ = 0; 51 | unsigned long num_binary_conflict_clauses_ = 0; 52 | 53 | unsigned long times_conflict_clauses_cleaned_ = 0; 54 | 55 | unsigned long num_unit_clauses_ = 0; 56 | 57 | /// number of all decisions made 58 | unsigned long num_decisions_ = 0; 59 | /// number of all implications derived 60 | unsigned long num_implications_ = 0; 61 | // number of all failed literal detections 62 | unsigned long num_failed_literals_detected_ = 0; 63 | unsigned long num_failed_literal_tests_ = 0; 64 | // number of all conflicts occurred 65 | unsigned long num_conflicts_ = 0; 66 | 67 | // number of clauses overall learned 68 | unsigned num_clauses_learned_ = 0; 69 | 70 | 71 | /* cache statistics */ 72 | uint64_t num_cache_hits_ = 0; 73 | uint64_t num_cache_look_ups_ = 0; 74 | uint64_t sum_cache_hit_sizes_ = 0; 75 | 76 | uint64_t num_cached_components_ = 0; 77 | uint64_t sum_size_cached_components_ = 0; 78 | 79 | // the number of bytes occupied by all 80 | // components 81 | uint64_t sum_bytes_cached_components_ = 0; 82 | // the same number, summing over all components ever stored 83 | uint64_t overall_bytes_components_stored_ = 0; 84 | 85 | // the above numbers, but without any overhead, 86 | // counting only the pure data size of the components - without model counts 87 | uint64_t sum_bytes_pure_cached_component_data_ = 0; 88 | // the same number, summing over all components ever stored 89 | uint64_t overall_bytes_pure_stored_component_data_ = 0; 90 | 91 | 92 | uint64_t sys_overhead_sum_bytes_cached_components_ = 0; 93 | // the same number, summing over all components ever stored 94 | uint64_t sys_overhead_overall_bytes_components_stored_ = 0; 95 | 96 | uint64_t cache_infrastructure_bytes_memory_usage_ = 0; 97 | 98 | 99 | uint64_t overall_num_cache_stores_ = 0; 100 | /*end statistics */ 101 | 102 | bool cache_full(){ 103 | return cache_bytes_memory_usage() >= maximum_cache_size_bytes_; 104 | } 105 | 106 | uint64_t cache_bytes_memory_usage(){ 107 | return cache_infrastructure_bytes_memory_usage_ 108 | + sum_bytes_cached_components_; 109 | } 110 | 111 | uint64_t overall_cache_bytes_memory_stored(){ 112 | return cache_infrastructure_bytes_memory_usage_ 113 | + overall_bytes_components_stored_; 114 | } 115 | 116 | void incorporate_cache_store(CacheableComponent &ccomp){ 117 | sum_bytes_cached_components_ += ccomp.SizeInBytes(); 118 | sum_size_cached_components_ += ccomp.num_variables(); 119 | num_cached_components_++; 120 | overall_bytes_components_stored_ += ccomp.SizeInBytes(); 121 | overall_num_cache_stores_ += ccomp.num_variables(); 122 | sys_overhead_sum_bytes_cached_components_ += ccomp.sys_overhead_SizeInBytes(); 123 | sys_overhead_overall_bytes_components_stored_ += ccomp.sys_overhead_SizeInBytes(); 124 | 125 | 126 | sum_bytes_pure_cached_component_data_ += ccomp.data_only_byte_size(); 127 | overall_bytes_pure_stored_component_data_ += ccomp.data_only_byte_size(); 128 | } 129 | void incorporate_cache_erase(CacheableComponent &ccomp){ 130 | sum_bytes_cached_components_ -= ccomp.SizeInBytes(); 131 | sum_size_cached_components_ -= ccomp.num_variables(); 132 | num_cached_components_--; 133 | sum_bytes_pure_cached_component_data_ -= ccomp.data_only_byte_size(); 134 | 135 | sys_overhead_sum_bytes_cached_components_ -= ccomp.sys_overhead_SizeInBytes(); 136 | } 137 | 138 | void incorporate_cache_hit(CacheableComponent &ccomp){ 139 | num_cache_hits_++; 140 | sum_cache_hit_sizes_ += ccomp.num_variables(); 141 | } 142 | unsigned long cache_MB_memory_usage() { 143 | return cache_bytes_memory_usage() / 1000000; 144 | } 145 | mpz_class final_solution_count_ = 0; 146 | 147 | double implicitBCP_miss_rate() { 148 | if(num_failed_literal_tests_ == 0) return 0.0; 149 | return (num_failed_literal_tests_ - num_failed_literals_detected_) / (double) num_failed_literal_tests_; 150 | } 151 | unsigned long num_clauses() { 152 | return num_long_clauses_ + num_binary_clauses_ + num_unit_clauses_; 153 | } 154 | unsigned long num_conflict_clauses() { 155 | return num_long_conflict_clauses_ + num_binary_conflict_clauses_; 156 | } 157 | 158 | unsigned long clause_deletion_interval() { 159 | return 10000 + 10 * times_conflict_clauses_cleaned_; 160 | } 161 | 162 | void set_final_solution_count(const mpz_class &count) { 163 | // set final_solution_count_ = count * 2^(num_variables_ - num_used_variables_) 164 | mpz_mul_2exp(final_solution_count_.get_mpz_t (),count.get_mpz_t (), num_variables_ - num_used_variables_); 165 | } 166 | 167 | const mpz_class &final_solution_count() const { 168 | return final_solution_count_; 169 | } 170 | 171 | void incorporateConflictClauseData(const vector &clause) { 172 | if (clause.size() == 1) 173 | num_unit_clauses_++; 174 | else if (clause.size() == 2) 175 | num_binary_conflict_clauses_++; 176 | num_long_conflict_clauses_++; 177 | } 178 | void incorporateClauseData(const vector &clause) { 179 | if (clause.size() == 1) 180 | num_unit_clauses_++; 181 | else if (clause.size() == 2) 182 | num_binary_clauses_++; 183 | else 184 | num_long_clauses_++; 185 | } 186 | 187 | void print_final_solution_count(); 188 | void writeToFile(const string & file_name); 189 | 190 | void printShort(); 191 | 192 | void printShortFormulaInfo() { 193 | cout << "variables (all/used/free): \t"; 194 | cout << num_variables_ << "/" << num_used_variables_ << "/"; 195 | cout << num_variables_ - num_used_variables_ << endl; 196 | 197 | cout << "clauses (all/long/binary/unit): "; 198 | cout << num_clauses() << "/" << num_long_clauses_; 199 | cout << "/" << num_binary_clauses_ << "/" << num_unit_clauses_ << endl; 200 | } 201 | unsigned getTime() { 202 | return num_decisions_; 203 | } 204 | 205 | double avgCachedSize() { 206 | if (num_cache_hits_ == 0) 207 | return 0.0; 208 | return (double) sum_size_cached_components_ 209 | / (double) num_cached_components_; 210 | } 211 | 212 | double avgCacheHitSize() { 213 | if (num_cache_hits_ == 0) 214 | return 0.0; 215 | return (double) sum_cache_hit_sizes_ / (double) num_cache_hits_; 216 | } 217 | 218 | long double getAvgComponentSize() { 219 | return sum_size_cached_components_ / (long double) num_cached_components_; 220 | } 221 | 222 | unsigned long cached_component_count() { 223 | return num_cached_components_; 224 | } 225 | 226 | unsigned long cache_hits() { 227 | return num_cache_hits_; 228 | } 229 | 230 | double cache_miss_rate() { 231 | if(num_cache_look_ups_ == 0) return 0.0; 232 | return (num_cache_look_ups_ - num_cache_hits_) 233 | / (double) num_cache_look_ups_; 234 | } 235 | 236 | long double getAvgCacheHitSize() { 237 | if(num_cache_hits_ == 0) return 0.0; 238 | return sum_cache_hit_sizes_ / (long double) num_cache_hits_; 239 | } 240 | }; 241 | 242 | #endif /* STATISTICS_H_ */ 243 | -------------------------------------------------------------------------------- /src/alt_component_analyzer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * alt_component_analyzer.h 3 | * 4 | * Created on: Mar 5, 2013 5 | * Author: mthurley 6 | */ 7 | 8 | #ifndef ALT_COMPONENT_ANALYZER_H_ 9 | #define ALT_COMPONENT_ANALYZER_H_ 10 | 11 | 12 | 13 | #include "statistics.h" 14 | #include "component_types/component.h" 15 | #include "component_types/base_packed_component.h" 16 | #include "component_types/component_archetype.h" 17 | 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include "containers.h" 24 | #include "stack.h" 25 | 26 | using namespace std; 27 | 28 | class AltComponentAnalyzer { 29 | public: 30 | AltComponentAnalyzer(DataAndStatistics &statistics, 31 | LiteralIndexedVector & lit_values) : 32 | statistics_(statistics), literal_values_(lit_values) { 33 | } 34 | 35 | unsigned scoreOf(VariableIndex v) { 36 | return var_frequency_scores_[v]; 37 | } 38 | 39 | ComponentArchetype ¤t_archetype(){ 40 | return archetype_; 41 | } 42 | 43 | void initialize(LiteralIndexedVector & literals, 44 | vector &lit_pool); 45 | 46 | 47 | bool isUnseenAndActive(VariableIndex v){ 48 | assert(v <= max_variable_id_); 49 | return archetype_.var_unseen_in_sup_comp(v); 50 | } 51 | 52 | // manages the literal whenever it occurs in component analysis 53 | // returns true iff the underlying variable was unseen before 54 | // 55 | bool manageSearchOccurrenceOf(LiteralID lit){ 56 | if(archetype_.var_unseen_in_sup_comp(lit.var())){ 57 | search_stack_.push_back(lit.var()); 58 | archetype_.setVar_seen(lit.var()); 59 | return true; 60 | } 61 | return false; 62 | } 63 | bool manageSearchOccurrenceAndScoreOf(LiteralID lit){ 64 | var_frequency_scores_[lit.var()]+= isActive(lit); 65 | return manageSearchOccurrenceOf(lit); 66 | } 67 | 68 | void setSeenAndStoreInSearchStack(VariableIndex v){ 69 | assert(isActive(v)); 70 | search_stack_.push_back(v); 71 | archetype_.setVar_seen(v); 72 | } 73 | 74 | 75 | void setupAnalysisContext(StackLevel &top, Component & super_comp){ 76 | archetype_.reInitialize(top,super_comp); 77 | 78 | for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) 79 | if (isActive(*vt)) { 80 | archetype_.setVar_in_sup_comp_unseen(*vt); 81 | var_frequency_scores_[*vt] = 0; 82 | } 83 | 84 | for (auto itCl = super_comp.clsBegin(); *itCl != clsSENTINEL; itCl++) 85 | archetype_.setClause_in_sup_comp_unseen(*itCl); 86 | } 87 | 88 | // returns true, iff the component found is non-trivial 89 | bool exploreRemainingCompOf(VariableIndex v) { 90 | assert(archetype_.var_unseen_in_sup_comp(v)); 91 | recordComponentOf(v); 92 | 93 | if (search_stack_.size() == 1) { 94 | archetype_.stack_level().includeSolution(2); 95 | archetype_.setVar_in_other_comp(v); 96 | return false; 97 | } 98 | return true; 99 | } 100 | 101 | 102 | inline Component *makeComponentFromArcheType(){ 103 | return archetype_.makeComponentFromState(search_stack_.size()); 104 | } 105 | 106 | unsigned max_clause_id(){ 107 | return max_clause_id_; 108 | } 109 | unsigned max_variable_id(){ 110 | return max_variable_id_; 111 | } 112 | 113 | ComponentArchetype &getArchetype(){ 114 | return archetype_; 115 | } 116 | 117 | private: 118 | DataAndStatistics &statistics_; 119 | 120 | // the id of the last clause 121 | // note that clause ID is the clause number, 122 | // different from the offset of the clause in the literal pool 123 | unsigned max_clause_id_ = 0; 124 | unsigned max_variable_id_ = 0; 125 | 126 | // this contains clause offsets of the clauses 127 | // where each variable occurs in; 128 | vector variable_occurrence_lists_pool_; 129 | 130 | // this is a new idea, 131 | // for every variable we have a list 132 | // 0 binarylinks 0 occurrences 0 133 | // this should give better cache behaviour, 134 | // because all links of one variable (binary and nonbinray) are found 135 | // in one contiguous chunk of memory 136 | vector unified_variable_links_lists_pool_; 137 | 138 | 139 | vector variable_link_list_offsets_; 140 | 141 | LiteralIndexedVector & literal_values_; 142 | 143 | vector var_frequency_scores_; 144 | 145 | ComponentArchetype archetype_; 146 | 147 | vector search_stack_; 148 | 149 | bool isResolved(const LiteralID lit) { 150 | return literal_values_[lit] == F_TRI; 151 | } 152 | 153 | bool isSatisfied(const LiteralID lit) { 154 | return literal_values_[lit] == T_TRI; 155 | } 156 | bool isActive(const LiteralID lit) { 157 | return literal_values_[lit] == X_TRI; 158 | } 159 | 160 | bool isActive(const VariableIndex v) { 161 | return literal_values_[LiteralID(v, true)] == X_TRI; 162 | } 163 | 164 | unsigned *beginOfLinkList(VariableIndex v) { 165 | return &unified_variable_links_lists_pool_[variable_link_list_offsets_[v]]; 166 | } 167 | 168 | // stores all information about the component of var 169 | // in variables_seen_, clauses_seen_ and 170 | // component_search_stack 171 | // we have an isolated variable iff 172 | // after execution component_search_stack.size()==1 173 | void recordComponentOf(const VariableIndex var); 174 | 175 | 176 | void getClause(vector &tmp, 177 | vector::iterator & it_start_of_cl, 178 | LiteralID & omitLit){ 179 | tmp.clear(); 180 | for (auto it_lit = it_start_of_cl;*it_lit != SENTINEL_LIT; it_lit++) { 181 | if(it_lit->var() != omitLit.var()) 182 | tmp.push_back(it_lit->raw()); 183 | } 184 | } 185 | 186 | 187 | void searchClause(VariableIndex vt, ClauseIndex clID, LiteralID * pstart_cls){ 188 | auto itVEnd = search_stack_.end(); 189 | bool all_lits_active = true; 190 | for (auto itL = pstart_cls; *itL != SENTINEL_LIT; itL++) { 191 | assert(itL->var() <= max_variable_id_); 192 | if(!archetype_.var_nil(itL->var())) 193 | manageSearchOccurrenceAndScoreOf(*itL); 194 | else { 195 | assert(!isActive(*itL)); 196 | all_lits_active = false; 197 | if (isResolved(*itL)) 198 | continue; 199 | //BEGIN accidentally entered a satisfied clause: undo the search process 200 | while (search_stack_.end() != itVEnd) { 201 | assert(search_stack_.back() <= max_variable_id_); 202 | archetype_.setVar_in_sup_comp_unseen(search_stack_.back()); 203 | search_stack_.pop_back(); 204 | } 205 | archetype_.setClause_nil(clID); 206 | while(*itL != SENTINEL_LIT) 207 | if(isActive(*(--itL))) 208 | var_frequency_scores_[itL->var()]--; 209 | //END accidentally entered a satisfied clause: undo the search process 210 | break; 211 | } 212 | } 213 | 214 | if (!archetype_.clause_nil(clID)){ 215 | var_frequency_scores_[vt]++; 216 | archetype_.setClause_seen(clID,all_lits_active); 217 | } 218 | } 219 | 220 | 221 | // void searchThreeClause(VariableIndex vt, ClauseIndex clID, LiteralID * pstart_cls){ 222 | // auto itVEnd = search_stack_.end(); 223 | // bool all_lits_active = true; 224 | // // LiteralID * pstart_cls = reinterpret_cast(p + 1 + *(p+1)); 225 | // for (auto itL = pstart_cls; itL != pstart_cls+2; itL++) { 226 | // assert(itL->var() <= max_variable_id_); 227 | // if(archetype_.var_nil(itL->var())){ 228 | // assert(!isActive(*itL)); 229 | // all_lits_active = false; 230 | // if (isResolved(*itL)) 231 | // continue; 232 | // //BEGIN accidentally entered a satisfied clause: undo the search process 233 | // while (search_stack_.end() != itVEnd) { 234 | // assert(search_stack_.back() <= max_variable_id_); 235 | // archetype_.setVar_in_sup_comp_unseen(search_stack_.back()); 236 | // search_stack_.pop_back(); 237 | // } 238 | // archetype_.setClause_nil(clID); 239 | // while(itL != pstart_cls - 1) 240 | // if(isActive(*(--itL))) 241 | // var_frequency_scores_[itL->var()]--; 242 | // //END accidentally entered a satisfied clause: undo the search process 243 | // break; 244 | // } else { 245 | // assert(isActive(*itL)); 246 | // var_frequency_scores_[itL->var()]++; 247 | // if(isUnseenAndActive(itL->var())) 248 | // setSeenAndStoreInSearchStack(itL->var()); 249 | // } 250 | // } 251 | // 252 | // if (!archetype_.clause_nil(clID)){ 253 | // var_frequency_scores_[vt]++; 254 | // archetype_.setClause_seen(clID,all_lits_active); 255 | // } 256 | // } 257 | }; 258 | 259 | 260 | #endif /* ALT_COMPONENT_ANALYZER_H_ */ 261 | -------------------------------------------------------------------------------- /src/solver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * solver.h 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: marc 6 | */ 7 | 8 | #ifndef SOLVER_H_ 9 | #define SOLVER_H_ 10 | 11 | 12 | #include "statistics.h" 13 | #include "instance.h" 14 | #include "component_management.h" 15 | 16 | 17 | 18 | #include "solver_config.h" 19 | 20 | #include 21 | 22 | enum retStateT { 23 | EXIT, RESOLVED, PROCESS_COMPONENT, BACKTRACK 24 | }; 25 | 26 | 27 | 28 | class StopWatch { 29 | public: 30 | 31 | StopWatch(); 32 | 33 | bool timeBoundBroken() { 34 | timeval actual_time; 35 | gettimeofday(&actual_time, NULL); 36 | return actual_time.tv_sec - start_time_.tv_sec > time_bound_; 37 | } 38 | 39 | bool start() { 40 | bool ret = gettimeofday(&last_interval_start_, NULL); 41 | start_time_ = stop_time_ = last_interval_start_; 42 | return !ret; 43 | } 44 | 45 | bool stop() { 46 | return gettimeofday(&stop_time_, NULL) == 0; 47 | } 48 | 49 | double getElapsedSeconds() { 50 | timeval r = getElapsedTime(); 51 | return r.tv_sec + (double) r.tv_usec / 1000000; 52 | } 53 | 54 | bool interval_tick() { 55 | timeval actual_time; 56 | gettimeofday(&actual_time, NULL); 57 | if (actual_time.tv_sec - last_interval_start_.tv_sec 58 | > interval_length_.tv_sec) { 59 | gettimeofday(&last_interval_start_, NULL); 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | void setTimeBound(long int seconds) { 66 | time_bound_ = seconds; 67 | } 68 | long int getTimeBound(); 69 | 70 | private: 71 | timeval start_time_; 72 | timeval stop_time_; 73 | 74 | long int time_bound_; 75 | 76 | timeval interval_length_; 77 | timeval last_interval_start_; 78 | 79 | // if we have started and then stopped the watch, this returns 80 | // the elapsed time 81 | // otherwise, time elapsed from start_time_ till now is returned 82 | timeval getElapsedTime(); 83 | }; 84 | 85 | class Solver: public Instance { 86 | public: 87 | Solver() { 88 | stopwatch_.setTimeBound(config_.time_bound_seconds); 89 | } 90 | 91 | void solve(const string & file_name); 92 | 93 | SolverConfiguration &config() { 94 | return config_; 95 | } 96 | 97 | DataAndStatistics &statistics() { 98 | return statistics_; 99 | } 100 | void setTimeBound(long int i) { 101 | stopwatch_.setTimeBound(i); 102 | } 103 | 104 | private: 105 | SolverConfiguration config_; 106 | 107 | DecisionStack stack_; // decision stack 108 | vector literal_stack_; 109 | 110 | StopWatch stopwatch_; 111 | 112 | ComponentManager comp_manager_ = ComponentManager(config_, 113 | statistics_, literal_values_); 114 | 115 | // the last time conflict clauses have been deleted 116 | unsigned long last_ccl_deletion_time_ = 0; 117 | // the last time the conflict clause storage has been compacted 118 | unsigned long last_ccl_cleanup_time_ = 0; 119 | 120 | bool simplePreProcess(); 121 | bool prepFailedLiteralTest(); 122 | // we assert that the formula is consistent 123 | // and has not been found UNSAT yet 124 | // hard wires all assertions in the literal stack into the formula 125 | // removes all set variables and essentially reinitiallizes all 126 | // further data 127 | void HardWireAndCompact(); 128 | 129 | SOLVER_StateT countSAT(); 130 | 131 | void decideLiteral(); 132 | bool bcp(); 133 | 134 | 135 | void decayActivitiesOf(Component & comp) { 136 | for (auto it = comp.varsBegin(); *it != varsSENTINEL; it++) { 137 | literal(LiteralID(*it,true)).activity_score_ *=0.5; 138 | literal(LiteralID(*it,false)).activity_score_ *=0.5; 139 | } 140 | } 141 | /// this method performs Failed literal tests online 142 | bool implicitBCP(); 143 | 144 | // this is the actual BCP algorithm 145 | // starts propagating all literal in literal_stack_ 146 | // beginingg at offset start_at_stack_ofs 147 | bool BCP(unsigned start_at_stack_ofs); 148 | 149 | retStateT backtrack(); 150 | 151 | // if on the current decision level 152 | // a second branch can be visited, RESOLVED is returned 153 | // otherwise returns BACKTRACK 154 | retStateT resolveConflict(); 155 | 156 | ///////////////////////////////////////////// 157 | // BEGIN small helper functions 158 | ///////////////////////////////////////////// 159 | 160 | float scoreOf(VariableIndex v) { 161 | float score = comp_manager_.scoreOf(v); 162 | score += 10.0 * literal(LiteralID(v, true)).activity_score_; 163 | score += 10.0 * literal(LiteralID(v, false)).activity_score_; 164 | // score += (10*stack_.get_decision_level()) * literal(LiteralID(v, true)).activity_score_; 165 | // score += (10*stack_.get_decision_level()) * literal(LiteralID(v, false)).activity_score_; 166 | 167 | return score; 168 | } 169 | 170 | bool setLiteralIfFree(LiteralID lit, 171 | Antecedent ant = Antecedent(NOT_A_CLAUSE)) { 172 | if (literal_values_[lit] != X_TRI) 173 | return false; 174 | var(lit).decision_level = stack_.get_decision_level(); 175 | var(lit).ante = ant; 176 | literal_stack_.push_back(lit); 177 | if (ant.isAClause() && ant.asCl() != NOT_A_CLAUSE) 178 | getHeaderOf(ant.asCl()).increaseScore(); 179 | literal_values_[lit] = T_TRI; 180 | literal_values_[lit.neg()] = F_TRI; 181 | return true; 182 | } 183 | 184 | void printOnlineStats(); 185 | 186 | void print(vector &vec); 187 | void print(vector &vec); 188 | 189 | 190 | void setConflictState(LiteralID litA, LiteralID litB) { 191 | violated_clause.clear(); 192 | violated_clause.push_back(litA); 193 | violated_clause.push_back(litB); 194 | } 195 | void setConflictState(ClauseOfs cl_ofs) { 196 | getHeaderOf(cl_ofs).increaseScore(); 197 | violated_clause.clear(); 198 | for (auto it = beginOf(cl_ofs); *it != SENTINEL_LIT; it++) 199 | violated_clause.push_back(*it); 200 | } 201 | 202 | vector::const_iterator TOSLiteralsBegin() { 203 | return literal_stack_.begin() + stack_.top().literal_stack_ofs(); 204 | } 205 | 206 | void initStack(unsigned int resSize) { 207 | stack_.clear(); 208 | stack_.reserve(resSize); 209 | literal_stack_.clear(); 210 | literal_stack_.reserve(resSize); 211 | // initialize the stack to contain at least level zero 212 | stack_.push_back(StackLevel(1, 0, 2)); 213 | stack_.back().changeBranch(); 214 | } 215 | 216 | const LiteralID &TOS_decLit() { 217 | assert(stack_.top().literal_stack_ofs() < literal_stack_.size()); 218 | return literal_stack_[stack_.top().literal_stack_ofs()]; 219 | } 220 | 221 | void reactivateTOS() { 222 | for (auto it = TOSLiteralsBegin(); it != literal_stack_.end(); it++) 223 | unSet(*it); 224 | comp_manager_.cleanRemainingComponentsOf(stack_.top()); 225 | literal_stack_.resize(stack_.top().literal_stack_ofs()); 226 | stack_.top().resetRemainingComps(); 227 | } 228 | 229 | bool fail_test(LiteralID lit) { 230 | unsigned sz = literal_stack_.size(); 231 | // we increase the decLev artificially 232 | // s.t. after the tentative BCP call, we can learn a conflict clause 233 | // relative to the assignment of *jt 234 | stack_.startFailedLitTest(); 235 | setLiteralIfFree(lit); 236 | 237 | assert(!hasAntecedent(lit)); 238 | 239 | bool bSucceeded = BCP(sz); 240 | if (!bSucceeded) 241 | recordAllUIPCauses(); 242 | 243 | stack_.stopFailedLitTest(); 244 | 245 | while (literal_stack_.size() > sz) { 246 | unSet(literal_stack_.back()); 247 | literal_stack_.pop_back(); 248 | } 249 | return bSucceeded; 250 | } 251 | ///////////////////////////////////////////// 252 | // BEGIN conflict analysis 253 | ///////////////////////////////////////////// 254 | 255 | // if the state name is CONFLICT, 256 | // then violated_clause contains the clause determining the conflict; 257 | vector violated_clause; 258 | // this is an array of all the clauses found 259 | // during the most recent conflict analysis 260 | // it might contain more than 2 clauses 261 | // but always will have: 262 | // uip_clauses_.front() the 1UIP clause found 263 | // uip_clauses_.back() the lastUIP clause found 264 | // possible clauses in between will be other UIP clauses 265 | vector > uip_clauses_; 266 | 267 | // the assertion level of uip_clauses_.back() 268 | // or (if the decision variable did not have an antecedent 269 | // before) then assertionLevel_ == DL; 270 | int assertion_level_ = 0; 271 | 272 | // build conflict clauses from most recent conflict 273 | // as stored in state_.violated_clause 274 | // solver state must be CONFLICT to work; 275 | // this first method record only the last UIP clause 276 | // so as to create clause that asserts the current decision 277 | // literal 278 | void recordLastUIPCauses(); 279 | void recordAllUIPCauses(); 280 | 281 | void minimizeAndStoreUIPClause(LiteralID uipLit, 282 | vector & tmp_clause, bool seen[]); 283 | void storeUIPClause(LiteralID uipLit, vector & tmp_clause); 284 | int getAssertionLevel() const { 285 | return assertion_level_; 286 | } 287 | 288 | ///////////////////////////////////////////// 289 | // END conflict analysis 290 | ///////////////////////////////////////////// 291 | }; 292 | 293 | #endif /* SOLVER_H_ */ 294 | -------------------------------------------------------------------------------- /src/instance.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * instance.cpp 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: Marc Thurley 6 | */ 7 | 8 | #include "instance.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | void Instance::cleanClause(ClauseOfs cl_ofs) { 17 | bool satisfied = false; 18 | for (auto it = beginOf(cl_ofs); *it != SENTINEL_LIT; it++) 19 | if (isSatisfied(*it)) { 20 | satisfied = true; 21 | break; 22 | } 23 | // mark the clause as empty if satisfied 24 | if (satisfied) { 25 | *beginOf(cl_ofs) = SENTINEL_LIT; 26 | return; 27 | } 28 | auto jt = beginOf(cl_ofs); 29 | auto it = beginOf(cl_ofs); 30 | // from now, all inactive literals are resolved 31 | for (; *it != SENTINEL_LIT; it++, jt++) { 32 | while (*jt != SENTINEL_LIT && !isActive(*jt)) 33 | jt++; 34 | *it = *jt; 35 | if (*jt == SENTINEL_LIT) 36 | break; 37 | } 38 | unsigned length = it - beginOf(cl_ofs); 39 | // if it has become a unit clause, it should have already been asserted 40 | if (length == 1) { 41 | *beginOf(cl_ofs) = SENTINEL_LIT; 42 | // if it has become binary, transform it to binary and delete it 43 | } else if (length == 2) { 44 | addBinaryClause(*beginOf(cl_ofs), *(beginOf(cl_ofs) + 1)); 45 | *beginOf(cl_ofs) = SENTINEL_LIT; 46 | } 47 | } 48 | 49 | void Instance::compactClauses() { 50 | vector clause_ofs; 51 | clause_ofs.reserve(statistics_.num_long_clauses_); 52 | 53 | // clear watch links and occurrence lists 54 | for (auto it_lit = literal_pool_.begin(); it_lit != literal_pool_.end(); 55 | it_lit++) { 56 | if (*it_lit == SENTINEL_LIT) { 57 | if (it_lit + 1 == literal_pool_.end()) 58 | break; 59 | it_lit += ClauseHeader::overheadInLits(); 60 | clause_ofs.push_back(1 + it_lit - literal_pool_.begin()); 61 | } 62 | } 63 | 64 | for (auto ofs : clause_ofs) 65 | cleanClause(ofs); 66 | 67 | for (auto &l : literals_) 68 | l.resetWatchList(); 69 | 70 | occurrence_lists_.clear(); 71 | occurrence_lists_.resize(variables_.size()); 72 | 73 | vector tmp_pool = literal_pool_; 74 | literal_pool_.clear(); 75 | literal_pool_.push_back(SENTINEL_LIT); 76 | ClauseOfs new_ofs; 77 | unsigned num_clauses = 0; 78 | for (auto ofs : clause_ofs) { 79 | auto it = (tmp_pool.begin() + ofs); 80 | if (*it != SENTINEL_LIT) { 81 | for (unsigned i = 0; i < ClauseHeader::overheadInLits(); i++) 82 | literal_pool_.push_back(0); 83 | new_ofs = literal_pool_.size(); 84 | literal(*it).addWatchLinkTo(new_ofs); 85 | literal(*(it + 1)).addWatchLinkTo(new_ofs); 86 | num_clauses++; 87 | for (; *it != SENTINEL_LIT; it++) { 88 | literal_pool_.push_back(*it); 89 | occurrence_lists_[*it].push_back(new_ofs); 90 | } 91 | literal_pool_.push_back(SENTINEL_LIT); 92 | } 93 | } 94 | 95 | vector tmp_bin; 96 | unsigned bin_links = 0; 97 | for (auto &l : literals_) { 98 | tmp_bin.clear(); 99 | for (auto it = l.binary_links_.begin(); *it != SENTINEL_LIT; it++) 100 | if (isActive(*it)) 101 | tmp_bin.push_back(*it); 102 | bin_links += tmp_bin.size(); 103 | tmp_bin.push_back(SENTINEL_LIT); 104 | l.binary_links_ = tmp_bin; 105 | } 106 | statistics_.num_long_clauses_ = num_clauses; 107 | statistics_.num_binary_clauses_ = bin_links >> 1; 108 | } 109 | 110 | void Instance::compactVariables() { 111 | vector var_map(variables_.size(), 0); 112 | unsigned last_ofs = 0; 113 | unsigned num_isolated = 0; 114 | LiteralIndexedVector > _tmp_bin_links(1); 115 | LiteralIndexedVector _tmp_values = literal_values_; 116 | 117 | for (auto l : literals_) 118 | _tmp_bin_links.push_back(l.binary_links_); 119 | 120 | assert(_tmp_bin_links.size() == literals_.size()); 121 | for (unsigned v = 1; v < variables_.size(); v++) 122 | if (isActive(v)) { 123 | if (isolated(v)) { 124 | num_isolated++; 125 | continue; 126 | } 127 | last_ofs++; 128 | var_map[v] = last_ofs; 129 | } 130 | 131 | variables_.clear(); 132 | variables_.resize(last_ofs + 1); 133 | occurrence_lists_.clear(); 134 | occurrence_lists_.resize(variables_.size()); 135 | literals_.clear(); 136 | literals_.resize(variables_.size()); 137 | literal_values_.clear(); 138 | literal_values_.resize(variables_.size(), X_TRI); 139 | 140 | unsigned bin_links = 0; 141 | LiteralID newlit; 142 | for (auto l = LiteralID(0, false); l != _tmp_bin_links.end_lit(); l.inc()) { 143 | if (var_map[l.var()] != 0) { 144 | newlit = LiteralID(var_map[l.var()], l.sign()); 145 | for (auto it = _tmp_bin_links[l].begin(); *it != SENTINEL_LIT; it++) { 146 | assert(var_map[it->var()] != 0); 147 | literals_[newlit].addBinLinkTo( 148 | LiteralID(var_map[it->var()], it->sign())); 149 | } 150 | bin_links += literals_[newlit].binary_links_.size() - 1; 151 | } 152 | } 153 | 154 | vector clause_ofs; 155 | clause_ofs.reserve(statistics_.num_long_clauses_); 156 | // clear watch links and occurrence lists 157 | for (auto it_lit = literal_pool_.begin(); it_lit != literal_pool_.end(); 158 | it_lit++) { 159 | if (*it_lit == SENTINEL_LIT) { 160 | if (it_lit + 1 == literal_pool_.end()) 161 | break; 162 | it_lit += ClauseHeader::overheadInLits(); 163 | clause_ofs.push_back(1 + it_lit - literal_pool_.begin()); 164 | } 165 | } 166 | 167 | for (auto ofs : clause_ofs) { 168 | literal(LiteralID(var_map[beginOf(ofs)->var()], beginOf(ofs)->sign())).addWatchLinkTo( 169 | ofs); 170 | literal(LiteralID(var_map[(beginOf(ofs) + 1)->var()], 171 | (beginOf(ofs) + 1)->sign())).addWatchLinkTo(ofs); 172 | for (auto it_lit = beginOf(ofs); *it_lit != SENTINEL_LIT; it_lit++) { 173 | *it_lit = LiteralID(var_map[it_lit->var()], it_lit->sign()); 174 | occurrence_lists_[*it_lit].push_back(ofs); 175 | } 176 | } 177 | 178 | literal_values_.clear(); 179 | literal_values_.resize(variables_.size(), X_TRI); 180 | unit_clauses_.clear(); 181 | 182 | statistics_.num_variables_ = variables_.size() - 1 + num_isolated; 183 | 184 | statistics_.num_used_variables_ = num_variables(); 185 | statistics_.num_free_variables_ = num_isolated; 186 | } 187 | 188 | void Instance::compactConflictLiteralPool(){ 189 | auto write_pos = conflict_clauses_begin(); 190 | vector tmp_conflict_clauses = conflict_clauses_; 191 | conflict_clauses_.clear(); 192 | for(auto clause_ofs: tmp_conflict_clauses){ 193 | auto read_pos = beginOf(clause_ofs) - ClauseHeader::overheadInLits(); 194 | for(unsigned i = 0; i < ClauseHeader::overheadInLits(); i++) 195 | *(write_pos++) = *(read_pos++); 196 | ClauseOfs new_ofs = write_pos - literal_pool_.begin(); 197 | conflict_clauses_.push_back(new_ofs); 198 | // first substitute antecedent if clause_ofs implied something 199 | if(isAntecedentOf(clause_ofs, *beginOf(clause_ofs))) 200 | var(*beginOf(clause_ofs)).ante = Antecedent(new_ofs); 201 | 202 | // now redo the watches 203 | literal(*beginOf(clause_ofs)).replaceWatchLinkTo(clause_ofs,new_ofs); 204 | literal(*(beginOf(clause_ofs)+1)).replaceWatchLinkTo(clause_ofs,new_ofs); 205 | // next, copy clause data 206 | assert(read_pos == beginOf(clause_ofs)); 207 | while(*read_pos != SENTINEL_LIT) 208 | *(write_pos++) = *(read_pos++); 209 | *(write_pos++) = SENTINEL_LIT; 210 | } 211 | literal_pool_.erase(write_pos,literal_pool_.end()); 212 | } 213 | 214 | 215 | //bool Instance::deleteConflictClauses() { 216 | // statistics_.times_conflict_clauses_cleaned_++; 217 | // vector tmp_conflict_clauses = conflict_clauses_; 218 | // conflict_clauses_.clear(); 219 | // vector tmp_ratios; 220 | // double score, lifetime; 221 | // for(auto clause_ofs: tmp_conflict_clauses){ 222 | // score = getHeaderOf(clause_ofs).score(); 223 | // lifetime = statistics_.num_conflicts_ - getHeaderOf(clause_ofs).creation_time(); 224 | // tmp_ratios.push_back(score/lifetime/(getHeaderOf(clause_ofs).length())); 225 | // } 226 | // vector tmp_ratiosB = tmp_ratios; 227 | // 228 | // sort(tmp_ratiosB.begin(), tmp_ratiosB.end()); 229 | // 230 | // double cutoff = tmp_ratiosB[tmp_ratiosB.size()/2]; 231 | // 232 | // for(unsigned i = 0; i < tmp_conflict_clauses.size(); i++){ 233 | // if(tmp_ratios[i] < cutoff){ 234 | // if(!markClauseDeleted(tmp_conflict_clauses[i])) 235 | // conflict_clauses_.push_back(tmp_conflict_clauses[i]); 236 | // } else 237 | // conflict_clauses_.push_back(tmp_conflict_clauses[i]); 238 | // } 239 | // return true; 240 | //} 241 | 242 | bool Instance::deleteConflictClauses() { 243 | statistics_.times_conflict_clauses_cleaned_++; 244 | vector tmp_conflict_clauses = conflict_clauses_; 245 | conflict_clauses_.clear(); 246 | vector tmp_ratios; 247 | double score, lifetime; 248 | for(auto clause_ofs: tmp_conflict_clauses){ 249 | score = getHeaderOf(clause_ofs).score(); 250 | lifetime = statistics_.num_conflicts_ - getHeaderOf(clause_ofs).creation_time(); 251 | // tmp_ratios.push_back(score/lifetime); 252 | tmp_ratios.push_back(score); 253 | 254 | } 255 | vector tmp_ratiosB = tmp_ratios; 256 | 257 | sort(tmp_ratiosB.begin(), tmp_ratiosB.end()); 258 | 259 | double cutoff = tmp_ratiosB[tmp_ratiosB.size()/2]; 260 | 261 | for(unsigned i = 0; i < tmp_conflict_clauses.size(); i++){ 262 | if(tmp_ratios[i] < cutoff){ 263 | if(!markClauseDeleted(tmp_conflict_clauses[i])) 264 | conflict_clauses_.push_back(tmp_conflict_clauses[i]); 265 | } else 266 | conflict_clauses_.push_back(tmp_conflict_clauses[i]); 267 | } 268 | return true; 269 | } 270 | 271 | 272 | bool Instance::markClauseDeleted(ClauseOfs cl_ofs){ 273 | // only first literal may possibly have cl_ofs as antecedent 274 | if(isAntecedentOf(cl_ofs, *beginOf(cl_ofs))) 275 | return false; 276 | 277 | literal(*beginOf(cl_ofs)).removeWatchLinkTo(cl_ofs); 278 | literal(*(beginOf(cl_ofs)+1)).removeWatchLinkTo(cl_ofs); 279 | return true; 280 | } 281 | 282 | 283 | bool Instance::createfromFile(const string &file_name) { 284 | unsigned int nVars, nCls; 285 | int lit; 286 | unsigned max_ignore = 1000000; 287 | unsigned clauses_added = 0; 288 | LiteralID llit; 289 | vector literals; 290 | string idstring; 291 | char c; 292 | 293 | // clear everything 294 | literal_pool_.clear(); 295 | literal_pool_.push_back(SENTINEL_LIT); 296 | 297 | variables_.clear(); 298 | variables_.push_back(Variable()); //initializing the Sentinel 299 | literal_values_.clear(); 300 | unit_clauses_.clear(); 301 | 302 | ///BEGIN File input 303 | ifstream input_file(file_name); 304 | if (!input_file) { 305 | cerr << "Cannot open file: " << file_name << endl; 306 | exit(0); 307 | } 308 | 309 | struct stat filestatus; 310 | stat(file_name.c_str(), &filestatus); 311 | 312 | literals.reserve(10000); 313 | while (input_file >> c && c != 'p') 314 | input_file.ignore(max_ignore, '\n'); 315 | if (!(input_file >> idstring && idstring == "cnf" && input_file >> nVars 316 | && input_file >> nCls)) { 317 | cerr << "Invalid CNF file" << endl; 318 | exit(0); 319 | } 320 | 321 | variables_.resize(nVars + 1); 322 | literal_values_.resize(nVars + 1, X_TRI); 323 | literal_pool_.reserve(filestatus.st_size); 324 | conflict_clauses_.reserve(2*nCls); 325 | occurrence_lists_.clear(); 326 | occurrence_lists_.resize(nVars + 1); 327 | 328 | literals_.clear(); 329 | literals_.resize(nVars + 1); 330 | 331 | while ((input_file >> c) && clauses_added < nCls) { 332 | input_file.unget(); //extracted a nonspace character to determine if we have a clause, so put it back 333 | if ((c == '-') || isdigit(c)) { 334 | literals.clear(); 335 | bool skip_clause = false; 336 | while ((input_file >> lit) && lit != 0) { 337 | bool duplicate_literal = false; 338 | for (auto i : literals) { 339 | if (i.toInt() == lit) { 340 | duplicate_literal = true; 341 | break; 342 | } 343 | if (i.toInt() == -lit) { 344 | skip_clause = true; 345 | break; 346 | } 347 | } 348 | if (!duplicate_literal) { 349 | literals.push_back(lit); 350 | } 351 | } 352 | if (!skip_clause) { 353 | assert(!literals.empty()); 354 | clauses_added++; 355 | statistics_.incorporateClauseData(literals); 356 | ClauseOfs cl_ofs = addClause(literals); 357 | if (literals.size() >= 3) 358 | for (auto l : literals) 359 | occurrence_lists_[l].push_back(cl_ofs); 360 | } 361 | } 362 | input_file.ignore(max_ignore, '\n'); 363 | } 364 | ///END NEW 365 | input_file.close(); 366 | // /// END FILE input 367 | 368 | statistics_.num_variables_ = statistics_.num_original_variables_ = nVars; 369 | statistics_.num_used_variables_ = num_variables(); 370 | statistics_.num_free_variables_ = nVars - num_variables(); 371 | 372 | statistics_.num_original_clauses_ = nCls; 373 | 374 | statistics_.num_original_binary_clauses_ = statistics_.num_binary_clauses_; 375 | statistics_.num_original_unit_clauses_ = statistics_.num_unit_clauses_ = 376 | unit_clauses_.size(); 377 | 378 | original_lit_pool_size_ = literal_pool_.size(); 379 | return true; 380 | } 381 | 382 | -------------------------------------------------------------------------------- /src/solver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * solver.cpp 3 | * 4 | * Created on: Aug 23, 2012 5 | * Author: marc 6 | */ 7 | #include "solver.h" 8 | #include 9 | 10 | #include 11 | 12 | 13 | StopWatch::StopWatch() { 14 | interval_length_.tv_sec = 60; 15 | gettimeofday(&last_interval_start_, NULL); 16 | start_time_ = stop_time_ = last_interval_start_; 17 | } 18 | 19 | timeval StopWatch::getElapsedTime() { 20 | timeval r; 21 | timeval other_time = stop_time_; 22 | if (stop_time_.tv_sec == start_time_.tv_sec 23 | && stop_time_.tv_usec == start_time_.tv_usec) 24 | gettimeofday(&other_time, NULL); 25 | long int ad = 0; 26 | long int bd = 0; 27 | 28 | if (other_time.tv_usec < start_time_.tv_usec) { 29 | ad = 1; 30 | bd = 1000000; 31 | } 32 | r.tv_sec = other_time.tv_sec - ad - start_time_.tv_sec; 33 | r.tv_usec = other_time.tv_usec + bd - start_time_.tv_usec; 34 | return r; 35 | } 36 | 37 | 38 | 39 | void Solver::print(vector &vec) { 40 | for (auto l : vec) 41 | cout << l.toInt() << " "; 42 | cout << endl; 43 | } 44 | 45 | void Solver::print(vector &vec) { 46 | for (auto l : vec) 47 | cout << l << " "; 48 | cout << endl; 49 | } 50 | 51 | bool Solver::simplePreProcess() { 52 | 53 | if (!config_.perform_pre_processing) 54 | return true; 55 | assert(literal_stack_.size() == 0); 56 | unsigned start_ofs = 0; 57 | //BEGIN process unit clauses 58 | for (auto lit : unit_clauses_) 59 | setLiteralIfFree(lit); 60 | //END process unit clauses 61 | bool succeeded = BCP(start_ofs); 62 | 63 | if (succeeded) 64 | succeeded &= prepFailedLiteralTest(); 65 | 66 | if (succeeded) 67 | HardWireAndCompact(); 68 | return succeeded; 69 | } 70 | 71 | bool Solver::prepFailedLiteralTest() { 72 | unsigned last_size; 73 | do { 74 | last_size = literal_stack_.size(); 75 | for (unsigned v = 1; v < variables_.size(); v++) 76 | if (isActive(v)) { 77 | unsigned sz = literal_stack_.size(); 78 | setLiteralIfFree(LiteralID(v, true)); 79 | bool res = BCP(sz); 80 | while (literal_stack_.size() > sz) { 81 | unSet(literal_stack_.back()); 82 | literal_stack_.pop_back(); 83 | } 84 | 85 | if (!res) { 86 | sz = literal_stack_.size(); 87 | setLiteralIfFree(LiteralID(v, false)); 88 | if (!BCP(sz)) 89 | return false; 90 | } else { 91 | 92 | sz = literal_stack_.size(); 93 | setLiteralIfFree(LiteralID(v, false)); 94 | bool resb = BCP(sz); 95 | while (literal_stack_.size() > sz) { 96 | unSet(literal_stack_.back()); 97 | literal_stack_.pop_back(); 98 | } 99 | if (!resb) { 100 | sz = literal_stack_.size(); 101 | setLiteralIfFree(LiteralID(v, true)); 102 | if (!BCP(sz)) 103 | return false; 104 | } 105 | } 106 | } 107 | } while (literal_stack_.size() > last_size); 108 | 109 | return true; 110 | } 111 | 112 | void Solver::HardWireAndCompact() { 113 | compactClauses(); 114 | compactVariables(); 115 | literal_stack_.clear(); 116 | 117 | for (auto l = LiteralID(1, false); l != literals_.end_lit(); l.inc()) { 118 | literal(l).activity_score_ = literal(l).binary_links_.size() - 1; 119 | literal(l).activity_score_ += occurrence_lists_[l].size(); 120 | } 121 | 122 | statistics_.num_unit_clauses_ = unit_clauses_.size(); 123 | 124 | statistics_.num_original_binary_clauses_ = statistics_.num_binary_clauses_; 125 | statistics_.num_original_unit_clauses_ = statistics_.num_unit_clauses_ = 126 | unit_clauses_.size(); 127 | initStack(num_variables()); 128 | original_lit_pool_size_ = literal_pool_.size(); 129 | } 130 | 131 | void Solver::solve(const string &file_name) { 132 | stopwatch_.start(); 133 | statistics_.input_file_ = file_name; 134 | 135 | createfromFile(file_name); 136 | initStack(num_variables()); 137 | 138 | if (!config_.quiet) { 139 | cout << "Solving " << file_name << endl; 140 | statistics_.printShortFormulaInfo(); 141 | } 142 | if (!config_.quiet) 143 | cout << endl << "Preprocessing .." << flush; 144 | bool notfoundUNSAT = simplePreProcess(); 145 | if (!config_.quiet) 146 | cout << " DONE" << endl; 147 | 148 | if (notfoundUNSAT) { 149 | 150 | if (!config_.quiet) { 151 | statistics_.printShortFormulaInfo(); 152 | } 153 | 154 | last_ccl_deletion_time_ = last_ccl_cleanup_time_ = 155 | statistics_.getTime(); 156 | 157 | violated_clause.reserve(num_variables()); 158 | 159 | comp_manager_.initialize(literals_, literal_pool_); 160 | 161 | statistics_.exit_state_ = countSAT(); 162 | 163 | statistics_.set_final_solution_count(stack_.top().getTotalModelCount()); 164 | statistics_.num_long_conflict_clauses_ = num_conflict_clauses(); 165 | 166 | } else { 167 | statistics_.exit_state_ = SUCCESS; 168 | statistics_.set_final_solution_count(0.0); 169 | cout << endl << " FOUND UNSAT DURING PREPROCESSING " << endl; 170 | } 171 | 172 | stopwatch_.stop(); 173 | statistics_.time_elapsed_ = stopwatch_.getElapsedSeconds(); 174 | 175 | comp_manager_.gatherStatistics(); 176 | statistics_.writeToFile("data.out"); 177 | if (!config_.quiet) 178 | statistics_.printShort(); 179 | } 180 | 181 | SOLVER_StateT Solver::countSAT() { 182 | retStateT state = RESOLVED; 183 | 184 | while (true) { 185 | while (comp_manager_.findNextRemainingComponentOf(stack_.top())) { 186 | decideLiteral(); 187 | if (stopwatch_.timeBoundBroken()) 188 | return TIMEOUT; 189 | if (stopwatch_.interval_tick()) 190 | printOnlineStats(); 191 | 192 | while (!bcp()) { 193 | state = resolveConflict(); 194 | if (state == BACKTRACK) 195 | break; 196 | } 197 | if (state == BACKTRACK) 198 | break; 199 | } 200 | 201 | state = backtrack(); 202 | if (state == EXIT) 203 | return SUCCESS; 204 | while (state != PROCESS_COMPONENT && !bcp()) { 205 | state = resolveConflict(); 206 | if (state == BACKTRACK) { 207 | state = backtrack(); 208 | if (state == EXIT) 209 | return SUCCESS; 210 | } 211 | } 212 | } 213 | return SUCCESS; 214 | } 215 | 216 | void Solver::decideLiteral() { 217 | // establish another decision stack level 218 | stack_.push_back( 219 | StackLevel(stack_.top().currentRemainingComponent(), 220 | literal_stack_.size(), 221 | comp_manager_.component_stack_size())); 222 | float max_score = -1; 223 | float score; 224 | unsigned max_score_var = 0; 225 | for (auto it = 226 | comp_manager_.superComponentOf(stack_.top()).varsBegin(); 227 | *it != varsSENTINEL; it++) { 228 | score = scoreOf(*it); 229 | if (score > max_score) { 230 | max_score = score; 231 | max_score_var = *it; 232 | } 233 | } 234 | // this assert should always hold, 235 | // if not then there is a bug in the logic of countSAT(); 236 | assert(max_score_var != 0); 237 | 238 | LiteralID theLit(max_score_var, 239 | literal(LiteralID(max_score_var, true)).activity_score_ 240 | > literal(LiteralID(max_score_var, false)).activity_score_); 241 | 242 | setLiteralIfFree(theLit); 243 | statistics_.num_decisions_++; 244 | 245 | if (statistics_.num_decisions_ % 128 == 0) 246 | // if (statistics_.num_conflicts_ % 128 == 0) 247 | decayActivities(); 248 | // decayActivitiesOf(comp_manager_.superComponentOf(stack_.top())); 249 | assert( 250 | stack_.top().remaining_components_ofs() <= comp_manager_.component_stack_size()); 251 | } 252 | 253 | retStateT Solver::backtrack() { 254 | assert( 255 | stack_.top().remaining_components_ofs() <= comp_manager_.component_stack_size()); 256 | do { 257 | if (stack_.top().branch_found_unsat()) 258 | comp_manager_.removeAllCachePollutionsOf(stack_.top()); 259 | else if (stack_.top().anotherCompProcessible()) 260 | return PROCESS_COMPONENT; 261 | 262 | if (!stack_.top().isSecondBranch()) { 263 | LiteralID aLit = TOS_decLit(); 264 | assert(stack_.get_decision_level() > 0); 265 | stack_.top().changeBranch(); 266 | reactivateTOS(); 267 | setLiteralIfFree(aLit.neg(), NOT_A_CLAUSE); 268 | return RESOLVED; 269 | } 270 | // OTHERWISE: backtrack further 271 | comp_manager_.cacheModelCountOf(stack_.top().super_component(), 272 | stack_.top().getTotalModelCount()); 273 | 274 | if (stack_.get_decision_level() <= 0) 275 | break; 276 | reactivateTOS(); 277 | 278 | assert(stack_.size()>=2); 279 | (stack_.end() - 2)->includeSolution(stack_.top().getTotalModelCount()); 280 | stack_.pop_back(); 281 | // step to the next component not yet processed 282 | stack_.top().nextUnprocessedComponent(); 283 | 284 | assert( 285 | stack_.top().remaining_components_ofs() < comp_manager_.component_stack_size()+1); 286 | 287 | } while (stack_.get_decision_level() >= 0); 288 | return EXIT; 289 | } 290 | 291 | retStateT Solver::resolveConflict() { 292 | recordLastUIPCauses(); 293 | 294 | if (statistics_.num_clauses_learned_ - last_ccl_deletion_time_ 295 | > statistics_.clause_deletion_interval()) { 296 | deleteConflictClauses(); 297 | last_ccl_deletion_time_ = statistics_.num_clauses_learned_; 298 | } 299 | 300 | if (statistics_.num_clauses_learned_ - last_ccl_cleanup_time_ > 100000) { 301 | compactConflictLiteralPool(); 302 | last_ccl_cleanup_time_ = statistics_.num_clauses_learned_; 303 | } 304 | 305 | statistics_.num_conflicts_++; 306 | 307 | assert( 308 | stack_.top().remaining_components_ofs() <= comp_manager_.component_stack_size()); 309 | 310 | assert(uip_clauses_.size() == 1); 311 | 312 | // DEBUG 313 | if (uip_clauses_.back().size() == 0) 314 | cout << " EMPTY CLAUSE FOUND" << endl; 315 | // END DEBUG 316 | 317 | stack_.top().mark_branch_unsat(); 318 | //BEGIN Backtracking 319 | // maybe the other branch had some solutions 320 | if (stack_.top().isSecondBranch()) { 321 | return BACKTRACK; 322 | } 323 | 324 | Antecedent ant(NOT_A_CLAUSE); 325 | // this has to be checked since using implicit BCP 326 | // and checking literals there not exhaustively 327 | // we cannot guarantee that uip_clauses_.back().front() == TOS_decLit().neg() 328 | // this is because we might have checked a literal 329 | // during implict BCP which has been a failed literal 330 | // due only to assignments made at lower decision levels 331 | if (uip_clauses_.back().front() == TOS_decLit().neg()) { 332 | assert(TOS_decLit().neg() == uip_clauses_.back()[0]); 333 | var(TOS_decLit().neg()).ante = addUIPConflictClause( 334 | uip_clauses_.back()); 335 | ant = var(TOS_decLit()).ante; 336 | } 337 | // // RRR 338 | // else if(var(uip_clauses_.back().front()).decision_level 339 | // < stack_.get_decision_level() 340 | // && assertion_level_ < stack_.get_decision_level()){ 341 | // stack_.top().set_both_branches_unsat(); 342 | // return BACKTRACK; 343 | // } 344 | // 345 | // 346 | // // RRR 347 | assert(stack_.get_decision_level() > 0); 348 | assert(stack_.top().branch_found_unsat()); 349 | 350 | // we do not have to remove pollutions here, 351 | // since conflicts only arise directly before 352 | // remaining components are stored 353 | // hence 354 | assert( 355 | stack_.top().remaining_components_ofs() == comp_manager_.component_stack_size()); 356 | 357 | stack_.top().changeBranch(); 358 | LiteralID lit = TOS_decLit(); 359 | reactivateTOS(); 360 | setLiteralIfFree(lit.neg(), ant); 361 | //END Backtracking 362 | return RESOLVED; 363 | } 364 | 365 | bool Solver::bcp() { 366 | // the asserted literal has been set, so we start 367 | // bcp on that literal 368 | unsigned start_ofs = literal_stack_.size() - 1; 369 | 370 | //BEGIN process unit clauses 371 | for (auto lit : unit_clauses_) 372 | setLiteralIfFree(lit); 373 | //END process unit clauses 374 | 375 | bool bSucceeded = BCP(start_ofs); 376 | 377 | if (config_.perform_failed_lit_test && bSucceeded) { 378 | bSucceeded = implicitBCP(); 379 | } 380 | return bSucceeded; 381 | } 382 | 383 | bool Solver::BCP(unsigned start_at_stack_ofs) { 384 | for (unsigned int i = start_at_stack_ofs; i < literal_stack_.size(); i++) { 385 | LiteralID unLit = literal_stack_[i].neg(); 386 | //BEGIN Propagate Bin Clauses 387 | for (auto bt = literal(unLit).binary_links_.begin(); 388 | *bt != SENTINEL_LIT; bt++) { 389 | if (isResolved(*bt)) { 390 | setConflictState(unLit, *bt); 391 | return false; 392 | } 393 | setLiteralIfFree(*bt, Antecedent(unLit)); 394 | } 395 | //END Propagate Bin Clauses 396 | for (auto itcl = literal(unLit).watch_list_.rbegin(); 397 | *itcl != SENTINEL_CL; itcl++) { 398 | bool isLitA = (*beginOf(*itcl) == unLit); 399 | auto p_watchLit = beginOf(*itcl) + 1 - isLitA; 400 | auto p_otherLit = beginOf(*itcl) + isLitA; 401 | 402 | if (isSatisfied(*p_otherLit)) 403 | continue; 404 | auto itL = beginOf(*itcl) + 2; 405 | while (isResolved(*itL)) 406 | itL++; 407 | // either we found a free or satisfied lit 408 | if (*itL != SENTINEL_LIT) { 409 | literal(*itL).addWatchLinkTo(*itcl); 410 | swap(*itL, *p_watchLit); 411 | *itcl = literal(unLit).watch_list_.back(); 412 | literal(unLit).watch_list_.pop_back(); 413 | } else { 414 | // or p_unLit stays resolved 415 | // and we have hence no free literal left 416 | // for p_otherLit remain poss: Active or Resolved 417 | if (setLiteralIfFree(*p_otherLit, Antecedent(*itcl))) { // implication 418 | if (isLitA) 419 | swap(*p_otherLit, *p_watchLit); 420 | } else { 421 | setConflictState(*itcl); 422 | return false; 423 | } 424 | } 425 | } 426 | } 427 | return true; 428 | } 429 | 430 | //bool Solver::implicitBCP() { 431 | // static vector test_lits(num_variables()); 432 | // static LiteralIndexedVector viewed_lits(num_variables() + 1, 433 | // 0); 434 | // 435 | // unsigned stack_ofs = stack_.top().literal_stack_ofs(); 436 | // while (stack_ofs < literal_stack_.size()) { 437 | // test_lits.clear(); 438 | // for (auto it = literal_stack_.begin() + stack_ofs; 439 | // it != literal_stack_.end(); it++) { 440 | // for (auto cl_ofs : occurrence_lists_[it->neg()]) 441 | // if (!isSatisfied(cl_ofs)) { 442 | // for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++) 443 | // if (isActive(*lt) && !viewed_lits[lt->neg()]) { 444 | // test_lits.push_back(lt->neg()); 445 | // viewed_lits[lt->neg()] = true; 446 | // 447 | // } 448 | // } 449 | // } 450 | // 451 | // stack_ofs = literal_stack_.size(); 452 | // for (auto jt = test_lits.begin(); jt != test_lits.end(); jt++) 453 | // viewed_lits[*jt] = false; 454 | // 455 | // statistics_.num_failed_literal_tests_ += test_lits.size(); 456 | // 457 | // for (auto lit : test_lits) 458 | // if (isActive(lit)) { 459 | // unsigned sz = literal_stack_.size(); 460 | // // we increase the decLev artificially 461 | // // s.t. after the tentative BCP call, we can learn a conflict clause 462 | // // relative to the assignment of *jt 463 | // stack_.startFailedLitTest(); 464 | // setLiteralIfFree(lit); 465 | // 466 | // assert(!hasAntecedent(lit)); 467 | // 468 | // bool bSucceeded = BCP(sz); 469 | // if (!bSucceeded) 470 | // recordAllUIPCauses(); 471 | // 472 | // stack_.stopFailedLitTest(); 473 | // 474 | // while (literal_stack_.size() > sz) { 475 | // unSet(literal_stack_.back()); 476 | // literal_stack_.pop_back(); 477 | // } 478 | // 479 | // if (!bSucceeded) { 480 | // statistics_.num_failed_literals_detected_++; 481 | // sz = literal_stack_.size(); 482 | // for (auto it = uip_clauses_.rbegin(); it != uip_clauses_.rend(); 483 | // it++) { 484 | // setLiteralIfFree(it->front(), addUIPConflictClause(*it)); 485 | // } 486 | // if (!BCP(sz)) 487 | // return false; 488 | // } 489 | // } 490 | // } 491 | // return true; 492 | //} 493 | 494 | // this is IBCP 30.08 495 | bool Solver::implicitBCP() { 496 | static vector test_lits(num_variables()); 497 | static LiteralIndexedVector viewed_lits(num_variables() + 1, 498 | 0); 499 | 500 | unsigned stack_ofs = stack_.top().literal_stack_ofs(); 501 | unsigned num_curr_lits = 0; 502 | while (stack_ofs < literal_stack_.size()) { 503 | test_lits.clear(); 504 | for (auto it = literal_stack_.begin() + stack_ofs; 505 | it != literal_stack_.end(); it++) { 506 | for (auto cl_ofs : occurrence_lists_[it->neg()]) 507 | if (!isSatisfied(cl_ofs)) { 508 | for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++) 509 | if (isActive(*lt) && !viewed_lits[lt->neg()]) { 510 | test_lits.push_back(lt->neg()); 511 | viewed_lits[lt->neg()] = true; 512 | 513 | } 514 | } 515 | } 516 | num_curr_lits = literal_stack_.size() - stack_ofs; 517 | stack_ofs = literal_stack_.size(); 518 | for (auto jt = test_lits.begin(); jt != test_lits.end(); jt++) 519 | viewed_lits[*jt] = false; 520 | 521 | vector scores; 522 | scores.clear(); 523 | for (auto jt = test_lits.begin(); jt != test_lits.end(); jt++) { 524 | scores.push_back(literal(*jt).activity_score_); 525 | } 526 | sort(scores.begin(), scores.end()); 527 | num_curr_lits = 10 + num_curr_lits / 20; 528 | float threshold = 0.0; 529 | if (scores.size() > num_curr_lits) { 530 | threshold = scores[scores.size() - num_curr_lits]; 531 | } 532 | 533 | statistics_.num_failed_literal_tests_ += test_lits.size(); 534 | 535 | for (auto lit : test_lits) 536 | if (isActive(lit) && threshold <= literal(lit).activity_score_) { 537 | unsigned sz = literal_stack_.size(); 538 | // we increase the decLev artificially 539 | // s.t. after the tentative BCP call, we can learn a conflict clause 540 | // relative to the assignment of *jt 541 | stack_.startFailedLitTest(); 542 | setLiteralIfFree(lit); 543 | 544 | assert(!hasAntecedent(lit)); 545 | 546 | bool bSucceeded = BCP(sz); 547 | if (!bSucceeded) 548 | recordAllUIPCauses(); 549 | 550 | stack_.stopFailedLitTest(); 551 | 552 | while (literal_stack_.size() > sz) { 553 | unSet(literal_stack_.back()); 554 | literal_stack_.pop_back(); 555 | } 556 | 557 | if (!bSucceeded) { 558 | statistics_.num_failed_literals_detected_++; 559 | sz = literal_stack_.size(); 560 | for (auto it = uip_clauses_.rbegin(); 561 | it != uip_clauses_.rend(); it++) { 562 | // DEBUG 563 | if (it->size() == 0) 564 | cout << "EMPTY CLAUSE FOUND" << endl; 565 | // END DEBUG 566 | setLiteralIfFree(it->front(), 567 | addUIPConflictClause(*it)); 568 | } 569 | if (!BCP(sz)) 570 | return false; 571 | } 572 | } 573 | } 574 | 575 | // BEGIN TEST 576 | // float max_score = -1; 577 | // float score; 578 | // unsigned max_score_var = 0; 579 | // for (auto it = 580 | // component_analyzer_.superComponentOf(stack_.top()).varsBegin(); 581 | // *it != varsSENTINEL; it++) 582 | // if (isActive(*it)) { 583 | // score = scoreOf(*it); 584 | // if (score > max_score) { 585 | // max_score = score; 586 | // max_score_var = *it; 587 | // } 588 | // } 589 | // LiteralID theLit(max_score_var, 590 | // literal(LiteralID(max_score_var, true)).activity_score_ 591 | // > literal(LiteralID(max_score_var, false)).activity_score_); 592 | // if (!fail_test(theLit.neg())) { 593 | // cout << "."; 594 | // 595 | // statistics_.num_failed_literals_detected_++; 596 | // unsigned sz = literal_stack_.size(); 597 | // for (auto it = uip_clauses_.rbegin(); it != uip_clauses_.rend(); it++) { 598 | // setLiteralIfFree(it->front(), addUIPConflictClause(*it)); 599 | // } 600 | // if (!BCP(sz)) 601 | // return false; 602 | // 603 | // } 604 | // END 605 | return true; 606 | } 607 | 608 | /////////////////////////////////////////////////////////////////////////////////////////////// 609 | // BEGIN module conflictAnalyzer 610 | /////////////////////////////////////////////////////////////////////////////////////////////// 611 | 612 | void Solver::minimizeAndStoreUIPClause(LiteralID uipLit, 613 | vector & tmp_clause, bool seen[]) { 614 | static deque clause; 615 | clause.clear(); 616 | assertion_level_ = 0; 617 | for (auto lit : tmp_clause) { 618 | if (existsUnitClauseOf(lit.var())) 619 | continue; 620 | bool resolve_out = false; 621 | if (hasAntecedent(lit)) { 622 | resolve_out = true; 623 | if (getAntecedent(lit).isAClause()) { 624 | for (auto it = beginOf(getAntecedent(lit).asCl()) + 1; 625 | *it != SENTINEL_CL; it++) 626 | if (!seen[it->var()]) { 627 | resolve_out = false; 628 | break; 629 | } 630 | } else if (!seen[getAntecedent(lit).asLit().var()]) { 631 | resolve_out = false; 632 | } 633 | } 634 | 635 | if (!resolve_out) { 636 | // uipLit should be the sole literal of this Decision Level 637 | if (var(lit).decision_level >= assertion_level_) { 638 | assertion_level_ = var(lit).decision_level; 639 | clause.push_front(lit); 640 | } else 641 | clause.push_back(lit); 642 | } 643 | } 644 | 645 | if(uipLit.var()) 646 | assert(var(uipLit).decision_level == stack_.get_decision_level()); 647 | 648 | //assert(uipLit.var() != 0); 649 | if (uipLit.var() != 0) 650 | clause.push_front(uipLit); 651 | uip_clauses_.push_back(vector(clause.begin(), clause.end())); 652 | } 653 | 654 | void Solver::recordLastUIPCauses() { 655 | // note: 656 | // variables of lower dl: if seen we dont work with them anymore 657 | // variables of this dl: if seen we incorporate their 658 | // antecedent and set to unseen 659 | bool seen[num_variables() + 1]; 660 | memset(seen, false, sizeof(bool) * (num_variables() + 1)); 661 | 662 | static vector tmp_clause; 663 | tmp_clause.clear(); 664 | 665 | assertion_level_ = 0; 666 | uip_clauses_.clear(); 667 | 668 | unsigned lit_stack_ofs = literal_stack_.size(); 669 | int DL = stack_.get_decision_level(); 670 | unsigned lits_at_current_dl = 0; 671 | 672 | for (auto l : violated_clause) { 673 | if (var(l).decision_level == 0 || existsUnitClauseOf(l.var())) 674 | continue; 675 | if (var(l).decision_level < DL) 676 | tmp_clause.push_back(l); 677 | else 678 | lits_at_current_dl++; 679 | literal(l).increaseActivity(); 680 | seen[l.var()] = true; 681 | } 682 | 683 | LiteralID curr_lit; 684 | while (lits_at_current_dl) { 685 | assert(lit_stack_ofs != 0); 686 | curr_lit = literal_stack_[--lit_stack_ofs]; 687 | 688 | if (!seen[curr_lit.var()]) 689 | continue; 690 | 691 | seen[curr_lit.var()] = false; 692 | 693 | if (lits_at_current_dl-- == 1) { 694 | // perform UIP stuff 695 | if (!hasAntecedent(curr_lit)) { 696 | // this should be the decision literal when in first branch 697 | // or it is a literal decided to explore in failed literal testing 698 | //assert(stack_.TOS_decLit() == curr_lit); 699 | // cout << "R" << curr_lit.toInt() << "S" 700 | // << var(curr_lit).ante.isAnt() << " " << endl; 701 | break; 702 | } 703 | } 704 | 705 | assert(hasAntecedent(curr_lit)); 706 | 707 | //cout << "{" << curr_lit.toInt() << "}"; 708 | if (getAntecedent(curr_lit).isAClause()) { 709 | updateActivities(getAntecedent(curr_lit).asCl()); 710 | assert(curr_lit == *beginOf(getAntecedent(curr_lit).asCl())); 711 | 712 | for (auto it = beginOf(getAntecedent(curr_lit).asCl()) + 1; 713 | *it != SENTINEL_CL; it++) { 714 | if (seen[it->var()] || (var(*it).decision_level == 0) 715 | || existsUnitClauseOf(it->var())) 716 | continue; 717 | if (var(*it).decision_level < DL) 718 | tmp_clause.push_back(*it); 719 | else 720 | lits_at_current_dl++; 721 | seen[it->var()] = true; 722 | } 723 | } else { 724 | LiteralID alit = getAntecedent(curr_lit).asLit(); 725 | literal(alit).increaseActivity(); 726 | literal(curr_lit).increaseActivity(); 727 | if (!seen[alit.var()] && !(var(alit).decision_level == 0) 728 | && !existsUnitClauseOf(alit.var())) { 729 | if (var(alit).decision_level < DL) 730 | tmp_clause.push_back(alit); 731 | else 732 | lits_at_current_dl++; 733 | seen[alit.var()] = true; 734 | } 735 | } 736 | curr_lit = NOT_A_LIT; 737 | } 738 | 739 | // cout << "T" << curr_lit.toInt() << "U " 740 | // << var(curr_lit).decision_level << ", " << stack_.get_decision_level() << endl; 741 | // cout << "V" << var(curr_lit).ante.isAnt() << " " << endl; 742 | minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen); 743 | 744 | // if (var(curr_lit).decision_level > assertion_level_) 745 | // assertion_level_ = var(curr_lit).decision_level; 746 | } 747 | 748 | void Solver::recordAllUIPCauses() { 749 | // note: 750 | // variables of lower dl: if seen we dont work with them anymore 751 | // variables of this dl: if seen we incorporate their 752 | // antecedent and set to unseen 753 | bool seen[num_variables() + 1]; 754 | memset(seen, false, sizeof(bool) * (num_variables() + 1)); 755 | 756 | static vector tmp_clause; 757 | tmp_clause.clear(); 758 | 759 | assertion_level_ = 0; 760 | uip_clauses_.clear(); 761 | 762 | unsigned lit_stack_ofs = literal_stack_.size(); 763 | int DL = stack_.get_decision_level(); 764 | unsigned lits_at_current_dl = 0; 765 | 766 | for (auto l : violated_clause) { 767 | if (var(l).decision_level == 0 || existsUnitClauseOf(l.var())) 768 | continue; 769 | if (var(l).decision_level < DL) 770 | tmp_clause.push_back(l); 771 | else 772 | lits_at_current_dl++; 773 | literal(l).increaseActivity(); 774 | seen[l.var()] = true; 775 | } 776 | unsigned n = 0; 777 | LiteralID curr_lit; 778 | while (lits_at_current_dl) { 779 | assert(lit_stack_ofs != 0); 780 | curr_lit = literal_stack_[--lit_stack_ofs]; 781 | 782 | if (!seen[curr_lit.var()]) 783 | continue; 784 | 785 | seen[curr_lit.var()] = false; 786 | 787 | if (lits_at_current_dl-- == 1) { 788 | n++; 789 | if (!hasAntecedent(curr_lit)) { 790 | // this should be the decision literal when in first branch 791 | // or it is a literal decided to explore in failed literal testing 792 | //assert(stack_.TOS_decLit() == curr_lit); 793 | break; 794 | } 795 | // perform UIP stuff 796 | minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen); 797 | } 798 | 799 | assert(hasAntecedent(curr_lit)); 800 | 801 | if (getAntecedent(curr_lit).isAClause()) { 802 | updateActivities(getAntecedent(curr_lit).asCl()); 803 | assert(curr_lit == *beginOf(getAntecedent(curr_lit).asCl())); 804 | 805 | for (auto it = beginOf(getAntecedent(curr_lit).asCl()) + 1; 806 | *it != SENTINEL_CL; it++) { 807 | if (seen[it->var()] || (var(*it).decision_level == 0) 808 | || existsUnitClauseOf(it->var())) 809 | continue; 810 | if (var(*it).decision_level < DL) 811 | tmp_clause.push_back(*it); 812 | else 813 | lits_at_current_dl++; 814 | seen[it->var()] = true; 815 | } 816 | } else { 817 | LiteralID alit = getAntecedent(curr_lit).asLit(); 818 | literal(alit).increaseActivity(); 819 | literal(curr_lit).increaseActivity(); 820 | if (!seen[alit.var()] && !(var(alit).decision_level == 0) 821 | && !existsUnitClauseOf(alit.var())) { 822 | if (var(alit).decision_level < DL) 823 | tmp_clause.push_back(alit); 824 | else 825 | lits_at_current_dl++; 826 | seen[alit.var()] = true; 827 | } 828 | } 829 | } 830 | if (!hasAntecedent(curr_lit)) { 831 | minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen); 832 | } 833 | // if (var(curr_lit).decision_level > assertion_level_) 834 | // assertion_level_ = var(curr_lit).decision_level; 835 | } 836 | 837 | void Solver::printOnlineStats() { 838 | if (config_.quiet) 839 | return; 840 | 841 | cout << endl; 842 | cout << "time elapsed: " << stopwatch_.getElapsedSeconds() << "s" << endl; 843 | if(config_.verbose) { 844 | cout << "conflict clauses (all / bin / unit) \t"; 845 | cout << num_conflict_clauses(); 846 | cout << "/" << statistics_.num_binary_conflict_clauses_ << "/" 847 | << unit_clauses_.size() << endl; 848 | cout << "failed literals found by implicit BCP \t " 849 | << statistics_.num_failed_literals_detected_ << endl; 850 | ; 851 | 852 | cout << "implicit BCP miss rate \t " 853 | << statistics_.implicitBCP_miss_rate() * 100 << "%"; 854 | cout << endl; 855 | 856 | comp_manager_.gatherStatistics(); 857 | 858 | cout << "cache size " << statistics_.cache_MB_memory_usage() << "MB" << endl; 859 | cout << "components (stored / hits) \t\t" 860 | << statistics_.cached_component_count() << "/" 861 | << statistics_.cache_hits() << endl; 862 | cout << "avg. variable count (stored / hits) \t" 863 | << statistics_.getAvgComponentSize() << "/" 864 | << statistics_.getAvgCacheHitSize(); 865 | cout << endl; 866 | cout << "cache miss rate " << statistics_.cache_miss_rate() * 100 << "%" 867 | << endl; 868 | } 869 | } 870 | 871 | --------------------------------------------------------------------------------