@@ -40,6 +40,214 @@ 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+ if (long_irred_cls.empty ()) {
56+ verb_print (1 , " No need to calculate blocked clauses, since there are only binary irred clauses" );
57+ return ;
58+ }
59+ if (n < 10 ) {
60+ verb_print (1 , " No need to calculate blocked clauses, the number of variables is too low" );
61+ return ;
62+ }
63+ const double start_time = cpu_time ();
64+
65+ // build occ lists
66+ vector<vector<Lit>> id_to_cl;
67+ vector<vector<uint32_t >> occs;
68+ occs.resize (n*2 );
69+ uint32_t clid_bin_start;
70+
71+ if (true ) {
72+ uint32_t clid = 1 ;
73+ id_to_cl.resize (1 );
74+ vector<Lit> tmp;
75+ for (const auto & off: long_irred_cls) {
76+ const Clause& cl = *alloc->ptr (off);
77+ assert (cl.size () > 2 );
78+ tmp.clear ();
79+ tmp.insert (tmp.end (), cl.begin (), cl.end ());
80+ for (const auto & l: cl) occs[l.raw ()].push_back (clid);
81+ id_to_cl.push_back (tmp);
82+ assert (id_to_cl.size ()-1 == clid);
83+ clid++;
84+ }
85+ clid_bin_start = clid;
86+
87+ for (uint32_t v = 1 ; v < n; v++) {
88+ for (uint32_t i = 0 ; i < 2 ; i++) {
89+ Lit l (v, i);
90+ for (const auto & bincl: watches[l].binaries ) {
91+ if (bincl.irred ()) {
92+ tmp.clear ();
93+ tmp.push_back (l);
94+ tmp.push_back (bincl.lit ());
95+ occs[tmp[0 ].raw ()].push_back (clid);
96+ occs[tmp[1 ].raw ()].push_back (clid);
97+ id_to_cl.push_back (tmp);
98+ assert (id_to_cl.size ()-1 == clid);
99+ clid++;
100+ }
101+ }
102+ }
103+ }
104+ }
105+
106+ // System below does NOT work if any literal is already set
107+ // This is guaranteed to be NOT BAD if arjun is run before
108+ bool bad = false ;
109+ for (uint32_t v = 1 ; v < n; v++) {
110+ for (uint32_t i = 0 ; i < 2 ; i++) {
111+ Lit l (v, i);
112+ if (!is_unknown (l)) bad = true ;
113+ }
114+ }
115+ if (bad) {
116+ verb_print (1 , " Some vars are not unknown, cannot calculate blocked clauses" );
117+ return ;
118+ }
119+
120+ uint32_t blocked_tot = 0 ;
121+ vector<char > seen (n*2 , 0 );
122+ vector<char > seen_set (n*2 , 0 );
123+ vector<Lit> seen_set_clear;
124+ vector<Lit> todo_lits;
125+ for (uint32_t v = 1 ; v < n; v++) for (uint32_t i = 0 ; i < 2 ; i++) todo_lits.push_back (Lit (v, i));
126+ std::shuffle (todo_lits.begin (), todo_lits.end (), mtrand);
127+
128+ int64_t todo_total = 400 *1000LL *1000LL ;
129+ uint32_t lit_abandoned = 0 ;
130+ for (const auto & l_set: todo_lits) {
131+ int64_t todo_per_lit = 1000 *1000LL ;
132+ if (todo_total <= 0 ) break ;
133+ bool unsat = false ;
134+ /* cout << "lit set: " << l_set << endl; */
135+ vector<Lit> prop_q;
136+ prop_q.push_back (l_set);
137+ // slow propagation..
138+ SLOW_DEBUG_DO (for (const auto & l: seen_set) assert (l == 0 ));
139+ while (!prop_q.empty ()) {
140+ Lit p = prop_q.back ();
141+ seen_set[p.raw ()] = 1 ;
142+ seen_set_clear.push_back (p);
143+ prop_q.pop_back ();
144+ for (const auto & cl_id: occs[l_set.neg ().raw ()]) {
145+ const auto & cl = id_to_cl[cl_id];
146+ bool sat = false ;
147+ uint32_t unk = 0 ;
148+ Lit lit_unk = Lit ();
149+ for (const auto & l: cl) {
150+ todo_per_lit--;
151+ todo_total--;
152+ if (seen_set[l.raw ()]) {
153+ sat = 1 ;
154+ break ;
155+ }
156+ if (seen[l.neg ().raw ()]) continue ;
157+ unk++;
158+ lit_unk = l;
159+ if (unk > 1 ) break ;
160+ }
161+ if (!sat && unk == 0 ) {
162+ // wow, unsat
163+ unsat = true ;
164+ return ;
165+ }
166+ if (sat) continue ;
167+ if (unk == 1 ) prop_q.push_back (lit_unk);
168+ }
169+ }
170+ if (unsat) goto next;
171+
172+ for (uint32_t clid = 1 ; clid < clid_bin_start; clid++) {
173+ if (todo_per_lit <= 0 ) {lit_abandoned++; goto next;}
174+ const auto & cl = id_to_cl[clid];
175+ assert (cl.size () > 2 );
176+
177+ // already satisfied
178+ bool sat_already = false ;
179+ for (const auto & l: cl) if (seen_set[l.raw ()]) {
180+ sat_already = true ;
181+ break ;
182+ }
183+ if (sat_already) continue ;
184+
185+ // cannot actually be blocked
186+ bool could_be_blocked = false ;
187+ for (const auto & l: cl) if (l.var () >= counter->get_opt_indep_support_end ()) {
188+ could_be_blocked = true ;
189+ break ;
190+ }
191+ if (!could_be_blocked) continue ;
192+ /* cout << "cl to block: " << cl << endl; */
193+
194+ bool blocked = false ;
195+ SLOW_DEBUG_DO (for (const auto & l: seen) assert (l == 0 ));
196+ for (const auto & l: cl) seen[l.raw ()] = 1 ;
197+ for (const auto & l: cl) if (l.var () >= counter->get_opt_indep_support_end ()) {
198+ // could be blocked on this var, i.e. l.var()
199+ // must be blocked relative to all other clauses it could be resolved with
200+ blocked = true ;
201+ for (const auto & clid2: occs[l.neg ().raw ()]) {
202+ bool blocked_rel_this = false ;
203+ const auto & cl2 = id_to_cl[clid2];
204+ for (const auto & l2: cl2) {
205+ todo_per_lit--;
206+ todo_total--;
207+ if (l2.neg () == l) continue ; // resolve on this, skip
208+ /* if (seen[l2.neg().raw()]) { */
209+ if (seen_set[l2.raw ()]|| seen[l2.neg ().raw ()]) {
210+ /* cout << "blocked with cl2 " << cl2 << " on: " << l2
211+ * << " -- actually, set instead? " << (int)(l2 == l_set) << endl; */
212+ blocked_rel_this = true ;
213+ break ;
214+ }
215+ }
216+ if (!blocked_rel_this) {
217+ blocked = false ;
218+ break ;
219+ }
220+ }
221+ if (!blocked) continue ; // try next var
222+ if (blocked) {
223+ /* cout << "BINGO! cl: " << cl << " blocked on: " << l << " given: " << l_set << endl; */
224+ clid_to_blocking_lits[clid].push_back (l_set);
225+ blocked_tot++;
226+ break ;
227+ }
228+ }
229+ for (const auto & l: cl) seen[l.raw ()] = 0 ;
230+ }
231+
232+ next:
233+ for (const auto & l: seen_set_clear) seen_set[l.raw ()] = 0 ;
234+ seen_set_clear.clear ();
235+ }
236+
237+ uint32_t cls_blocked = 0 ;
238+ for (auto & lits: clid_to_blocking_lits) {
239+ if (!lits.empty ()) cls_blocked++;
240+ std::shuffle (lits.begin (), lits.end (), mtrand);
241+ }
242+
243+ verb_print (1 , " Blocked tot: " << blocked_tot
244+ << " lits abandoned: " << lit_abandoned << " global t-out: " << (todo_total <= 0 )
245+ << " t-remain: " << (double )todo_total/(1000.0 *1000.0 ) << " M"
246+ << " avg blocked/lit: " << (double )blocked_tot/(double )(n*2 -2 ) << " T: " << cpu_time ()-start_time);
247+ verb_print (1 , " cls with blocked lits: " << cls_blocked << " / " << long_irred_cls.size ()
248+ << " = " << (double )cls_blocked/(double )long_irred_cls.size ()*100 << " %" );
249+ }
250+
43251// Builds occ lists and sets things up, Done exactly ONCE for a whole counting runkk
44252// this sets up unif_occ
45253void CompAnalyzer::initialize (
@@ -60,7 +268,8 @@ void CompAnalyzer::initialize(
60268 return a.size () < b.size ();
61269 };
62270 auto long_irred_cls = _long_irred_cls;
63- std::sort (long_irred_cls.begin (), long_irred_cls.end (), mysorter);
271+ std::stable_sort (long_irred_cls.begin (), long_irred_cls.end (), mysorter);
272+ calc_blocked (watches, alloc, long_irred_cls);
64273
65274 max_clid = 1 ;
66275 max_tri_clid = 1 ;
@@ -74,17 +283,18 @@ void CompAnalyzer::initialize(
74283 const Clause& cl = *alloc->ptr (off);
75284 assert (cl.size () > 2 );
76285 const uint32_t long_cl_off = long_clauses_data.size ();
286+
77287 if (cl.size () > 3 ) {
78288 Lit blk_lit = cl[cl.size ()/2 ];
79289 for (const auto &l: cl) long_clauses_data.push_back (l);
80290 long_clauses_data.push_back (SENTINEL_LIT);
81-
82291 for (const auto & l: cl) {
83292 const uint32_t var = l.var ();
84293 assert (var < n);
85294 ClData d;
86295 d.id = max_clid;
87296 d.blk_lit = blk_lit;
297+ d.example_blocking = NOT_A_LIT;
88298 d.off = long_cl_off;
89299 unif_occ_long[var].push_back (d);
90300 }
@@ -98,6 +308,7 @@ void CompAnalyzer::initialize(
98308 ClData d;
99309 d.id = max_clid;
100310 d.blk_lit = lits[0 ];
311+ d.example_blocking = NOT_A_LIT;
101312 d.off = lits[1 ].raw ();
102313 unif_occ_long[l.var ()].push_back (d);
103314 }
@@ -183,11 +394,17 @@ void CompAnalyzer::initialize(
183394 }
184395 }
185396
186- // check longs
397+ // check longs & adjust blocking lits to random ones
187398 for (uint32_t v = 0 ; v < unif_occ_long.size (); v++) {
188399 assert (unif_occ_long[v].size () == holder.size_long (v));
189400 for (uint32_t i = 0 ; i < unif_occ_long[v].size (); i++) {
190401 assert (unif_occ_long[v][i] == holder.begin_long (v)[i]);
402+ auto & d = holder.begin_long (v)[i];
403+ auto & blk_lits = clid_to_blocking_lits[d.id ];
404+ if (!blk_lits.empty ()) {
405+ std::uniform_int_distribution<uint32_t > dist (0 , blk_lits.size ()-1 );
406+ d.example_blocking = blk_lits[dist (mtrand)];
407+ }
191408 }
192409 }
193410 }
@@ -342,7 +559,8 @@ void CompAnalyzer::record_comp(const uint32_t var, const uint32_t sup_comp_long_
342559 if (archetype.clause_unvisited_in_sup_comp (d.id )) {
343560 const Lit l1 = d.get_lit1 ();
344561 const Lit l2 = d.get_lit2 ();
345- if (is_true (l1) || is_true (l2)) {
562+ if (is_true (l1) || is_true (l2) ||
563+ (d.example_blocking != NOT_A_LIT && is_true (d.example_blocking ))) {
346564 archetype.clear_cl (d.id );
347565 sat = true ;
348566 /* goto end_sat; */
@@ -355,7 +573,8 @@ void CompAnalyzer::record_comp(const uint32_t var, const uint32_t sup_comp_long_
355573 } else continue ;
356574 } else {
357575 if (archetype.clause_unvisited_in_sup_comp (d.id )) {
358- if (is_true (d.blk_lit )) {
576+ if (is_true (d.blk_lit ) ||
577+ (d.example_blocking != NOT_A_LIT && is_true (d.example_blocking ))) {
359578 archetype.clear_cl (d.id );
360579 sat = true ;
361580 goto end_sat;
@@ -393,6 +612,7 @@ end_sat:;
393612CompAnalyzer::CompAnalyzer (
394613 const LiteralIndexedVector<TriValue> & lit_values,
395614 Counter* _counter) :
615+ mtrand(_counter->get_conf ().seed),
396616 values(lit_values),
397617 conf(_counter->get_conf ()),
398618 indep_support_end(_counter->get_indep_support_end ()),
0 commit comments