@@ -40,6 +40,207 @@ inline std::ostream& operator<<(std::ostream& os, const ClData& d)
4040 return os;
4141}
4242
43+ void CompAnalyzer::calc_blocked (
44+ const LiteralIndexedVector<LitWatchList> & watches,
45+ const ClauseAllocator* alloc, const vector<ClauseOfs>& long_irred_cls)
46+ {
47+ const uint32_t n = max_var+1 ;
48+ clid_to_blocking_lits.resize (long_irred_cls.size ()+1 );
49+ if (!conf.do_blocked_clauses ) return ;
50+
51+ if (counter->get_opt_indep_support_end () >= max_var+1 ) {
52+ verb_print (1 , " No need to calculate blocked clauses, as all vars are opt independent" );
53+ return ;
54+ }
55+ const double start_time = cpu_time ();
56+
57+ // build occ lists
58+ vector<vector<Lit>> id_to_cl;
59+ vector<vector<uint32_t >> occs;
60+ occs.resize (n*2 );
61+ uint32_t clid_bin_start;
62+
63+ if (true ) {
64+ uint32_t clid = 1 ;
65+ id_to_cl.resize (1 );
66+ vector<Lit> tmp;
67+ for (const auto & off: long_irred_cls) {
68+ const Clause& cl = *alloc->ptr (off);
69+ assert (cl.size () > 2 );
70+ tmp.clear ();
71+ tmp.insert (tmp.end (), cl.begin (), cl.end ());
72+ for (const auto & l: cl) occs[l.raw ()].push_back (clid);
73+ id_to_cl.push_back (tmp);
74+ assert (id_to_cl.size ()-1 == clid);
75+ clid++;
76+ }
77+ clid_bin_start = clid;
78+
79+ for (uint32_t v = 1 ; v < n; v++) {
80+ for (uint32_t i = 0 ; i < 2 ; i++) {
81+ Lit l (v, i);
82+ for (const auto & bincl: watches[l].binaries ) {
83+ if (bincl.irred ()) {
84+ tmp.clear ();
85+ tmp.push_back (l);
86+ tmp.push_back (bincl.lit ());
87+ occs[tmp[0 ].raw ()].push_back (clid);
88+ occs[tmp[1 ].raw ()].push_back (clid);
89+ id_to_cl.push_back (tmp);
90+ assert (id_to_cl.size ()-1 == clid);
91+ clid++;
92+ }
93+ }
94+ }
95+ }
96+ }
97+
98+ // System below does NOT work if any literal is already set
99+ // This is guaranteed to be NOT BAD if arjun is run before
100+ bool bad = false ;
101+ for (uint32_t v = 1 ; v < n; v++) {
102+ for (uint32_t i = 0 ; i < 2 ; i++) {
103+ Lit l (v, i);
104+ if (!is_unknown (l)) bad = true ;
105+ }
106+ }
107+ if (bad) {
108+ verb_print (1 , " Some vars are not unknown, cannot calculate blocked clauses" );
109+ return ;
110+ }
111+
112+ uint32_t blocked_tot = 0 ;
113+ vector<char > seen (n*2 , 0 );
114+ vector<char > seen_set (n*2 , 0 );
115+ vector<Lit> seen_set_clear;
116+ vector<Lit> todo_lits;
117+ for (uint32_t v = 1 ; v < n; v++) for (uint32_t i = 0 ; i < 2 ; i++) todo_lits.push_back (Lit (v, i));
118+ std::shuffle (todo_lits.begin (), todo_lits.end (), mtrand);
119+
120+ int64_t todo_total = 400 *1000LL *1000LL ;
121+ uint32_t lit_abandoned = 0 ;
122+ for (const auto & l_set: todo_lits) {
123+ int64_t todo_per_lit = 1000 *1000LL ;
124+ if (todo_total <= 0 ) break ;
125+ bool unsat = false ;
126+ /* cout << "lit set: " << l_set << endl; */
127+ vector<Lit> prop_q;
128+ prop_q.push_back (l_set);
129+ // slow propagation..
130+ SLOW_DEBUG_DO (for (const auto & l: seen_set) assert (l == 0 ));
131+ while (!prop_q.empty ()) {
132+ Lit p = prop_q.back ();
133+ seen_set[p.raw ()] = 1 ;
134+ seen_set_clear.push_back (p);
135+ prop_q.pop_back ();
136+ for (const auto & cl_id: occs[l_set.neg ().raw ()]) {
137+ const auto & cl = id_to_cl[cl_id];
138+ bool sat = false ;
139+ uint32_t unk = 0 ;
140+ Lit lit_unk = Lit ();
141+ for (const auto & l: cl) {
142+ todo_per_lit--;
143+ todo_total--;
144+ if (seen_set[l.raw ()]) {
145+ sat = 1 ;
146+ break ;
147+ }
148+ if (seen[l.neg ().raw ()]) continue ;
149+ unk++;
150+ lit_unk = l;
151+ if (unk > 1 ) break ;
152+ }
153+ if (!sat && unk == 0 ) {
154+ // wow, unsat
155+ unsat = true ;
156+ return ;
157+ }
158+ if (sat) continue ;
159+ if (unk == 1 ) prop_q.push_back (lit_unk);
160+ }
161+ }
162+ if (unsat) goto next;
163+
164+ for (uint32_t clid = 1 ; clid < clid_bin_start; clid++) {
165+ if (todo_per_lit <= 0 ) {lit_abandoned++; goto next;}
166+ const auto & cl = id_to_cl[clid];
167+ assert (cl.size () > 2 );
168+
169+ // already satisfied
170+ bool sat_already = false ;
171+ for (const auto & l: cl) if (seen_set[l.raw ()]) {
172+ sat_already = true ;
173+ break ;
174+ }
175+ if (sat_already) continue ;
176+
177+ // cannot actually be blocked
178+ bool could_be_blocked = false ;
179+ for (const auto & l: cl) if (l.var () >= counter->get_opt_indep_support_end ()) {
180+ could_be_blocked = true ;
181+ break ;
182+ }
183+ if (!could_be_blocked) continue ;
184+ /* cout << "cl to block: " << cl << endl; */
185+
186+ bool blocked = false ;
187+ SLOW_DEBUG_DO (for (const auto & l: seen) assert (l == 0 ));
188+ for (const auto & l: cl) seen[l.raw ()] = 1 ;
189+ for (const auto & l: cl) if (l.var () >= counter->get_opt_indep_support_end ()) {
190+ // could be blocked on this var, i.e. l.var()
191+ // must be blocked relative to all other clauses it could be resolved with
192+ blocked = true ;
193+ for (const auto & clid2: occs[l.neg ().raw ()]) {
194+ bool blocked_rel_this = false ;
195+ const auto & cl2 = id_to_cl[clid2];
196+ for (const auto & l2: cl2) {
197+ todo_per_lit--;
198+ todo_total--;
199+ if (l2.neg () == l) continue ; // resolve on this, skip
200+ /* if (seen[l2.neg().raw()]) { */
201+ if (seen_set[l2.raw ()]|| seen[l2.neg ().raw ()]) {
202+ /* cout << "blocked with cl2 " << cl2 << " on: " << l2
203+ * << " -- actually, set instead? " << (int)(l2 == l_set) << endl; */
204+ blocked_rel_this = true ;
205+ break ;
206+ }
207+ }
208+ if (!blocked_rel_this) {
209+ blocked = false ;
210+ break ;
211+ }
212+ }
213+ if (!blocked) continue ; // try next var
214+ if (blocked) {
215+ /* cout << "BINGO! cl: " << cl << " blocked on: " << l << " given: " << l_set << endl; */
216+ clid_to_blocking_lits[clid].push_back (l_set);
217+ blocked_tot++;
218+ break ;
219+ }
220+ }
221+ for (const auto & l: cl) seen[l.raw ()] = 0 ;
222+ }
223+
224+ next:
225+ for (const auto & l: seen_set_clear) seen_set[l.raw ()] = 0 ;
226+ seen_set_clear.clear ();
227+ }
228+
229+ uint32_t cls_blocked = 0 ;
230+ for (auto & lits: clid_to_blocking_lits) {
231+ if (!lits.empty ()) cls_blocked++;
232+ std::shuffle (lits.begin (), lits.end (), mtrand);
233+ }
234+
235+ verb_print (1 , " Blocked tot: " << blocked_tot
236+ << " lits abandoned: " << lit_abandoned << " global t-out: " << (todo_total <= 0 )
237+ << " t-remain: " << (double )todo_total/(1000.0 *1000.0 ) << " M"
238+ << " avg blocked/lit: " << (double )blocked_tot/(double )(n*2 -2 ) << " T: " << cpu_time ()-start_time);
239+ verb_print (1 , " cls with blocked lits: " << cls_blocked << " / " << long_irred_cls.size ()
240+ << " = " << (double )cls_blocked/(double )long_irred_cls.size ()*100 << " %" );
241+
242+ }
243+
43244// Builds occ lists and sets things up, Done exactly ONCE for a whole counting runkk
44245// this sets up unif_occ
45246void CompAnalyzer::initialize (
@@ -60,7 +261,8 @@ void CompAnalyzer::initialize(
60261 return a.size () < b.size ();
61262 };
62263 auto long_irred_cls = _long_irred_cls;
63- std::sort (long_irred_cls.begin (), long_irred_cls.end (), mysorter);
264+ std::stable_sort (long_irred_cls.begin (), long_irred_cls.end (), mysorter);
265+ calc_blocked (watches, alloc, long_irred_cls);
64266
65267 max_clid = 1 ;
66268 max_tri_clid = 1 ;
@@ -74,17 +276,18 @@ void CompAnalyzer::initialize(
74276 const Clause& cl = *alloc->ptr (off);
75277 assert (cl.size () > 2 );
76278 const uint32_t long_cl_off = long_clauses_data.size ();
279+
77280 if (cl.size () > 3 ) {
78281 Lit blk_lit = cl[cl.size ()/2 ];
79282 for (const auto &l: cl) long_clauses_data.push_back (l);
80283 long_clauses_data.push_back (SENTINEL_LIT);
81-
82284 for (const auto & l: cl) {
83285 const uint32_t var = l.var ();
84286 assert (var < n);
85287 ClData d;
86288 d.id = max_clid;
87289 d.blk_lit = blk_lit;
290+ d.example_blocking = NOT_A_LIT;
88291 d.off = long_cl_off;
89292 unif_occ_long[var].push_back (d);
90293 }
@@ -98,6 +301,7 @@ void CompAnalyzer::initialize(
98301 ClData d;
99302 d.id = max_clid;
100303 d.blk_lit = lits[0 ];
304+ d.example_blocking = NOT_A_LIT;
101305 d.off = lits[1 ].raw ();
102306 unif_occ_long[l.var ()].push_back (d);
103307 }
@@ -183,11 +387,17 @@ void CompAnalyzer::initialize(
183387 }
184388 }
185389
186- // check longs
390+ // check longs & adjust blocking lits to random ones
187391 for (uint32_t v = 0 ; v < unif_occ_long.size (); v++) {
188392 assert (unif_occ_long[v].size () == holder.size_long (v));
189393 for (uint32_t i = 0 ; i < unif_occ_long[v].size (); i++) {
190394 assert (unif_occ_long[v][i] == holder.begin_long (v)[i]);
395+ auto & d = holder.begin_long (v)[i];
396+ auto & blk_lits = clid_to_blocking_lits[d.id ];
397+ if (!blk_lits.empty ()) {
398+ std::uniform_int_distribution<uint32_t > dist (0 , blk_lits.size ()-1 );
399+ d.example_blocking = blk_lits[dist (mtrand)];
400+ }
191401 }
192402 }
193403 }
@@ -342,7 +552,8 @@ void CompAnalyzer::record_comp(const uint32_t var, const uint32_t sup_comp_long_
342552 if (archetype.clause_unvisited_in_sup_comp (d.id )) {
343553 const Lit l1 = d.get_lit1 ();
344554 const Lit l2 = d.get_lit2 ();
345- if (is_true (l1) || is_true (l2)) {
555+ if (is_true (l1) || is_true (l2) ||
556+ (d.example_blocking != NOT_A_LIT && is_true (d.example_blocking ))) {
346557 archetype.clear_cl (d.id );
347558 sat = true ;
348559 /* goto end_sat; */
@@ -355,7 +566,8 @@ void CompAnalyzer::record_comp(const uint32_t var, const uint32_t sup_comp_long_
355566 } else continue ;
356567 } else {
357568 if (archetype.clause_unvisited_in_sup_comp (d.id )) {
358- if (is_true (d.blk_lit )) {
569+ if (is_true (d.blk_lit ) ||
570+ (d.example_blocking != NOT_A_LIT && is_true (d.example_blocking ))) {
359571 archetype.clear_cl (d.id );
360572 sat = true ;
361573 goto end_sat;
@@ -393,6 +605,7 @@ end_sat:;
393605CompAnalyzer::CompAnalyzer (
394606 const LiteralIndexedVector<TriValue> & lit_values,
395607 Counter* _counter) :
608+ mtrand(_counter->get_conf ().seed),
396609 values(lit_values),
397610 conf(_counter->get_conf ()),
398611 indep_support_end(_counter->get_indep_support_end ()),
0 commit comments