1 /******************************************
2 Copyright (c) 2016, Mate Soos
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 ***********************************************/
22
23 #include "subsumeimplicit.h"
24 #include "clausecleaner.h"
25 #include "time_mem.h"
26 #include "solver.h"
27 #include "watchalgos.h"
28 #include "clauseallocator.h"
29 #include "sqlstats.h"
30
31 #include <cmath>
32 #include <iomanip>
33 using std::cout;
34 using std::endl;
35 using namespace CMSat;
36
SubsumeImplicit(Solver * _solver)37 SubsumeImplicit::SubsumeImplicit(Solver* _solver) :
38 solver(_solver)
39 {
40 }
41
try_subsume_bin(const Lit lit,Watched * i,Watched * & j,int64_t * timeAvail,TouchList * touched)42 void SubsumeImplicit::try_subsume_bin(
43 const Lit lit
44 , Watched* i
45 , Watched*& j
46 , int64_t *timeAvail
47 , TouchList* touched
48 ) {
49 //Subsume bin with bin
50 if (i->lit2() == lastLit2) {
51 //The sorting algorithm prefers irred to red, so it is
52 //impossible to have irred before red
53 assert(!(i->red() == false && lastRed == true));
54
55 runStats.remBins++;
56 assert(i->lit2().var() != lit.var());
57 *timeAvail -= 30;
58 *timeAvail -= solver->watches[i->lit2()].size();
59 removeWBin(solver->watches, i->lit2(), lit, i->red());
60 if (touched) {
61 touched->touch(i->lit2());
62 }
63 if (i->red()) {
64 solver->binTri.redBins--;
65 } else {
66 solver->binTri.irredBins--;
67 }
68 (*solver->drat) << del << lit << i->lit2() << fin;
69
70 return;
71 } else {
72 lastBin = j;
73 lastLit2 = i->lit2();
74 lastRed = i->red();
75 *j++ = *i;
76 }
77 }
78
subsume_at_watch(const uint32_t at,int64_t * timeAvail,TouchList * touched)79 uint32_t SubsumeImplicit::subsume_at_watch(const uint32_t at,
80 int64_t* timeAvail,
81 TouchList* touched)
82 {
83 runStats.numWatchesLooked++;
84 const Lit lit = Lit::toLit(at);
85 watch_subarray ws = solver->watches[lit];
86
87 if (ws.size() > 1) {
88 *timeAvail -= (int64_t)(ws.size()*std::ceil(std::log((double)ws.size())) + 20);
89 std::sort(ws.begin(), ws.end(), WatchSorterBinTriLong());
90 }
91 /*cout << "---> Before" << endl;
92 print_watch_list(ws, lit);*/
93
94 Watched* i = ws.begin();
95 Watched* j = i;
96 clear();
97
98 for (Watched* end = ws.end(); i != end; i++) {
99 if (*timeAvail < 0) {
100 *j++ = *i;
101 continue;
102 }
103
104 switch(i->getType()) {
105 case CMSat::watch_clause_t:
106 *j++ = *i;
107 break;
108
109 case CMSat::watch_binary_t:
110 try_subsume_bin(lit, i, j, timeAvail, touched);
111 break;
112
113 default:
114 assert(false);
115 break;
116 }
117 }
118 ws.shrink(i-j);
119 return i-j;
120 }
121
subsume_implicit(const bool check_stats,std::string caller)122 void SubsumeImplicit::subsume_implicit(const bool check_stats, std::string caller)
123 {
124 assert(solver->okay());
125 const double myTime = cpuTime();
126 const uint64_t orig_timeAvailable =
127 1000LL*1000LL*solver->conf.subsume_implicit_time_limitM
128 *solver->conf.global_timeout_multiplier;
129 timeAvailable = orig_timeAvailable;
130 runStats.clear();
131
132 //For randomization, we must have at least 1
133 if (solver->watches.size() == 0) {
134 return;
135 }
136
137 //Randomize starting point
138 const size_t rnd_start = solver->mtrand.randInt(solver->watches.size()-1);
139 size_t numDone = 0;
140 for (;numDone < solver->watches.size() && timeAvailable > 0 && !solver->must_interrupt_asap()
141 ;numDone++
142 ) {
143 const size_t at = (rnd_start + numDone) % solver->watches.size();
144 subsume_at_watch(at, &timeAvailable);
145 }
146
147 const double time_used = cpuTime() - myTime;
148 const bool time_out = (timeAvailable <= 0);
149 const double time_remain = float_div(timeAvailable, orig_timeAvailable);
150 runStats.numCalled++;
151 runStats.time_used += time_used;
152 runStats.time_out += time_out;
153 if (solver->conf.verbosity) {
154 runStats.print_short(solver, caller.c_str());
155 }
156 if (solver->sqlStats) {
157 solver->sqlStats->time_passed(
158 solver
159 , std::string("subsume implicit")+caller
160 , time_used
161 , time_out
162 , time_remain
163 );
164 }
165
166 if (check_stats) {
167 #ifdef DEBUG_IMPLICIT_STATS
168 solver->check_stats();
169 #endif
170 }
171
172 globalStats += runStats;
173 }
174
operator +=(const SubsumeImplicit::Stats & other)175 SubsumeImplicit::Stats SubsumeImplicit::Stats::operator+=(const SubsumeImplicit::Stats& other)
176 {
177 numCalled+= other.numCalled;
178 time_out += other.time_out;
179 time_used += other.time_used;
180 remBins += other.remBins;
181 numWatchesLooked += other.numWatchesLooked;
182
183 return *this;
184 }
185
print_short(const Solver * _solver,const char * caller) const186 void SubsumeImplicit::Stats::print_short(const Solver* _solver, const char* caller) const
187 {
188 cout
189 << "c [impl sub" << caller << "]"
190 << " bin: " << remBins
191 << _solver->conf.print_times(time_used, time_out)
192 << " w-visit: " << numWatchesLooked
193 << endl;
194 }
195
print(const char * caller) const196 void SubsumeImplicit::Stats::print(const char* caller) const
197 {
198 cout << "c -------- IMPLICIT SUB " << caller << " STATS --------" << endl;
199 print_stats_line("c time"
200 , time_used
201 , float_div(time_used, numCalled)
202 , "per call"
203 );
204
205 print_stats_line("c timed out"
206 , time_out
207 , stats_line_percent(time_out, numCalled)
208 , "% of calls"
209 );
210
211 print_stats_line("c rem bins"
212 , remBins
213 );
214 cout << "c -------- IMPLICIT SUB STATS END --------" << endl;
215 }
216
get_stats() const217 SubsumeImplicit::Stats SubsumeImplicit::get_stats() const
218 {
219 return globalStats;
220 }
221
mem_used() const222 double SubsumeImplicit::mem_used() const
223 {
224 double mem = sizeof(SubsumeImplicit);
225 mem += tmplits.size()*sizeof(Lit);
226
227 return mem;
228 }
229