1.构造观察元并加入观察序列

在internal.hpp中有以下构造函数并声明相关函数

// Operators on watches.
//
void init_watches ();
void connect_watches (bool irredundant_only = false);
void sort_watches ();
void clear_watches ();
void reset_watches (); //在watch.cpp文件中

 1 // Watch literal 'lit' in clause with blocking literal 'blit'.
 2   // Inlined here, since it occurs in the tight inner loop of 'propagate'.
 3   //
 4   inline void watch_literal (int lit, int blit, Clause * c) {
 5     assert (lit != blit);
 6     Watches & ws = watches (lit);
 7     ws.push_back (Watch (blit, c));
 8     LOG (c, "watch %d blit %d in", lit, blit);
 9   }
10 
11   // Add two watches to a clause.  This is used initially during allocation
12   // of a clause and during connecting back all watches after preprocessing.
13   //
14   inline void watch_clause (Clause * c) {
15     const int l0 = c->literals[0];
16     const int l1 = c->literals[1];
17     watch_literal (l0, l1, c);
18     watch_literal (l1, l0, c);
19   }
20 
21   inline void unwatch_clause (Clause * c) {
22     const int l0 = c->literals[0];
23     const int l1 = c->literals[1];
24     remove_watch (watches (l0), c);
25     remove_watch (watches (l1), c);
26   }

 

   
 

观察序列中二值观察元放在前部 void Internal::sort_watches () 

watch.cpp文件

 1 #include "internal.hpp"
 2 
 3 namespace CaDiCaL {
 4 
 5 void Internal::init_watches () {
 6   assert (wtab.empty ());
 7   if (wtab.size () < 2*vsize)
 8     wtab.resize (2*vsize, Watches ());
 9   LOG ("initialized watcher tables");
10 }
11 
12 void Internal::clear_watches () {
13   for (auto lit : lits)
14     watches (lit).clear ();
15 }
16 
17 void Internal::reset_watches () {
18   assert (!wtab.empty ());
19   erase_vector (wtab);
20   LOG ("reset watcher tables");
21 }
22 
23 // This can be quite costly since lots of memory is accessed in a rather
24 // random fashion, and thus we optionally profile it.
25 
26 void Internal::connect_watches (bool irredundant_only) {
27   START (connect);
28   assert (watching ());
29 
30   LOG ("watching all %sclauses", irredundant_only ? "irredundant " : "");
31 
32   // First connect binary clauses.
33   //
34   for (const auto & c : clauses) {
35     if (irredundant_only && c->redundant) continue;
36     if (c->garbage || c->size > 2) continue;
37     watch_clause (c);
38   }
39 
40   // Then connect non-binary clauses.
41   //
42   for (const auto & c : clauses) {
43     if (irredundant_only && c->redundant) continue;
44     if (c->garbage || c->size == 2) continue;
45     watch_clause (c);
46     if (!level) {
47       const int lit0 = c->literals[0];
48       const int lit1 = c->literals[1];
49       const signed char tmp0 = val (lit0);
50       const signed char tmp1 = val (lit1);
51       if (tmp0 > 0) continue;
52       if (tmp1 > 0) continue;
53       if (tmp0 < 0) {
54         const size_t pos0 = var (lit0).trail;
55         if (pos0 < propagated) {
56           propagated = pos0;
57           LOG ("literal %d resets propagated to %zd", lit0, pos0);
58         }
59       }
60       if (tmp1 < 0) {
61         const size_t pos1 = var (lit1).trail;
62         if (pos1 < propagated) {
63           propagated = pos1;
64           LOG ("literal %d resets propagated to %zd", lit1, pos1);
65         }
66       }
67     }
68   }
69 
70   STOP (connect);
71 }
72 
73 void Internal::sort_watches () {
74   assert (watching ());
75   LOG ("sorting watches");
76   Watches saved;
77   for (auto lit : lits) {
78     Watches & ws = watches (lit);
79 
80     const const_watch_iterator end = ws.end ();
81     watch_iterator j = ws.begin ();
82     const_watch_iterator i;
83 
84     assert (saved.empty ());
85 
86     for (i = j; i != end; i++) {
87       const Watch w = *i;
88       if (w.binary ()) *j++ = w;
89       else saved.push_back (w);
90     }
91 
92     std::copy (saved.cbegin (), saved.cend (), j);
93 
94     saved.clear ();
95   }
96 }
97 
98 }

 

涉及void Internal::sort_watches () 使用的函数

lookahead.cpp中  lookahead_probing()

  1 // We run probing on all literals with some differences:
  2 //
  3 // * no limit on the number of propagations. We rely on terminating to stop()
  4 // * we run only one round
  5 //
  6 // The run can be expensive, so we actually first run the cheaper
  7 // occurrence version and only then run lookahead.
  8 //

    我们对所有不同的字面量运行探测:

    对传播次数没有限制。我们依靠终止来停止()。

    我们只运行一轮,这个运行可能很昂贵,所以我们实际上首先运行便宜的发生版本,然后才运行向前看。

  9 int Internal::lookahead_probing() {
 10 
 11   if (!active ())
 12     return 0;
 13 
 14   MSG ("lookahead-probe-round %" PRId64
 15        " without propagations limit and %zu assumptions",
 16        stats.probingrounds, assumptions.size());
 17 
 18   termination_forced = false;
 19 
 20 #ifndef QUIET
 21   int old_failed = stats.failed;
 22   int64_t old_probed = stats.probed;
 23 #endif
 24   int64_t old_hbrs = stats.hbrs;
 25 
 26   if (unsat) return INT_MIN;
 27   if (level) backtrack ();
 28   if (!propagate ()) {
 29     MSG ("empty clause before probing");
 30     learn_empty_clause ();
 31     return INT_MIN;
 32   }
 33 
 34   if (terminating_asked())
 35     return most_occurring_literal();
 36 
 37   decompose ();
 38 
 39   if (ternary ())       // If we derived a binary clause
 40     decompose ();       // then start another round of ELS.
 41 
 42   // Remove duplicated binary clauses and perform in essence hyper unary
 43   // resolution, i.e., derive the unit '2' from '1 2' and '-1 2'.
 44   //
 45   mark_duplicated_binary_clauses_as_garbage ();
 46 
 47   lim.conflicts = -1;
 48 
 49   if (!probes.empty ()) lookahead_flush_probes ();
 50 
 51   // We reset 'propfixed' since there was at least another conflict thus
 52   // a new learned clause, which might produce new propagations (and hyper
 53   // binary resolvents).  During 'generate_probes' we keep the old value.
 54   //
 55   for (int idx = 1; idx <= max_var; idx++)
 56     propfixed (idx) = propfixed (-idx) = -1;
 57 
 58   assert (unsat || propagated == trail.size ());
 59   propagated = propagated2 = trail.size ();
 60 
 61   int probe;
 62   int res = most_occurring_literal();
 63   int max_hbrs = -1;
 64 
 65   set_mode (PROBE);
 66 
 67   MSG("unsat = %d, terminating_asked () = %d ", unsat, terminating_asked ());
 68   while (!unsat &&
 69          !terminating_asked () &&
 70          (probe = lookahead_next_probe ())) {
 71     stats.probed++;
 72     int hbrs;
 73 
 74     probe_assign_decision (probe);
 75     if (probe_propagate ())
 76       hbrs = trail.size(), backtrack();
 77     else hbrs = 0, failed_literal (probe);
 78     if (max_hbrs < hbrs ||
 79         (max_hbrs == hbrs &&
 80          internal->bumped(probe) > internal->bumped(res))) {
 81       res = probe;
 82       max_hbrs = hbrs;
 83     }
 84   }
 85 
 86   reset_mode (PROBE);
 87 
 88   if (unsat) {
 89     MSG ("probing derived empty clause");
 90     res = INT_MIN;
 91   }
 92   else if (propagated < trail.size ()) {
 93     MSG ("probing produced %zd units",
 94          (size_t)(trail.size () - propagated));
 95     if (!propagate ()) {
 96       MSG ("propagating units after probing results in empty clause");
 97       learn_empty_clause ();
 98       res = INT_MIN;
 99     } else sort_watches ();
100   }
101 
102 #ifndef QUIET
103   int failed = stats.failed - old_failed;
104   int64_t probed = stats.probed - old_probed;
105 #endif
106   int64_t hbrs = stats.hbrs - old_hbrs;
107 
108   MSG ("lookahead-probe-round %" PRId64 " probed %" PRId64
109        " and found %d failed literals",
110        stats.probingrounds,
111        probed, failed);
112 
113   if (hbrs)
114     PHASE ("lookahead-probe-round", stats.probingrounds,
115       "found %" PRId64 " hyper binary resolvents", hbrs);
116 
117   MSG ("lookahead literal %d with %d\n", res, max_hbrs);
118 
119   return res;
120 }

 

 在文件transred.cpp中 transred ()

  1 #include "internal.hpp"
  2 
  3 namespace CaDiCaL {
  4 
  5 // Implement transitive reduction in the binary implication graph.  This is
  6 // important for hyper binary resolution, which has the risk to produce too
  7 // many hyper binary resolvents otherwise.  This algorithm only works on
  8 // binary clauses and is usually pretty fast.  It will also find some failed
  9 // literals (in the binary implication graph).
 10 
 11 void Internal::transred () {
 12 
 13   if (unsat) return;
 14   if (terminated_asynchronously ()) return;
 15   if (!stats.current.redundant && !stats.current.irredundant) return;
 16 
 17   assert (opts.transred);
 18   assert (!level);
 19 
 20   START_SIMPLIFIER (transred, TRANSRED);
 21   stats.transreds++;
 22 
 23   // Transitive reduction can not be run to completion for larger formulas
 24   // with many binary clauses.  We bound it in the same way as 'probe_core'.
 25   //
 26   int64_t limit = stats.propagations.search;
 27   limit -= last.transred.propagations;
 28   limit *= 1e-3 * opts.transredreleff;
 29   if (limit < opts.transredmineff) limit = opts.transredmineff;
 30   if (limit > opts.transredmaxeff) limit = opts.transredmaxeff;
 31 
 32   PHASE ("transred", stats.transreds,
 33     "transitive reduction limit of %" PRId64 " propagations", limit);
 34 
 35   const auto end = clauses.end ();
 36   auto i = clauses.begin ();
 37 
 38   // Find first clause not checked for being transitive yet.
 39   //
 40   for (; i != end; i++) {
 41     Clause * c = *i;
 42     if (c->garbage) continue;
 43     if (c->size != 2) continue;
 44     if (c->redundant && c->hyper) continue;
 45     if (!c->transred) break;
 46   }
 47 
 48   // If all candidate clauses have been checked reschedule all.
 49   //
 50   if (i == end) {
 51 
 52     PHASE ("transred", stats.transreds,
 53       "rescheduling all clauses since no clauses to check left");
 54     for (i = clauses.begin (); i != end; i++) {
 55       Clause * c = *i;
 56       if (c->transred) c->transred = false;
 57     }
 58     i = clauses.begin ();
 59   }
 60 
 61   // Move watches of binary clauses to the front. Thus we can stop iterating
 62   // watches as soon a long clause is found during watch traversal.
 63   //
 64   sort_watches ();
 65 
 66   // This working stack plays the same role as the 'trail' during standard
 67   // propagation.
 68   //
 69   vector<int> work;
 70 
 71   int64_t propagations = 0, units = 0, removed = 0;
 72 
 73   while (!unsat &&
 74          i != end &&
 75          !terminated_asynchronously () &&
 76          propagations < limit)
 77   {
 78     Clause * c = *i++;
 79 
 80     // A clause is a candidate for being transitive if it is binary, and not
 81     // the result of hyper binary resolution.  The reason for excluding
 82     // those, is that they come in large numbers, most of them are reduced
 83     // away anyhow and further are non-transitive at the point they are
 84     // added (see the code in 'hyper_binary_resolve' in 'prope.cpp' and
 85     // also check out our CPAIOR paper on tree-based look ahead).
 86     //
 87     if (c->garbage) continue;
 88     if (c->size != 2) continue;
 89     if (c->redundant && c->hyper) continue;
 90     if (c->transred) continue;                  // checked before?
 91     c->transred = true;                         // marked as checked
 92 
 93     LOG (c, "checking transitive reduction of");
 94 
 95     // Find a different path from 'src' to 'dst' in the binary implication
 96     // graph, not using 'c'.  Since this is the same as checking whether
 97     // there is a path from '-dst' to '-src', we can do the reverse search
 98     // if the number of watches of '-dst' is larger than those of 'src'.
 99     //
100     int src = -c->literals[0];
101     int dst = c->literals[1];
102     if (val (src) || val (dst)) continue;
103     if (watches (-src).size () < watches (dst).size ()) {
104       int tmp = dst;
105       dst = -src; src = -tmp;
106     }
107 
108     LOG ("searching path from %d to %d", src, dst);
109 
110     // If the candidate clause is irredundant then we can not use redundant
111     // binary clauses in the implication graph.  See our inprocessing rules
112     // paper, why this restriction is required.
113     //
114     const bool irredundant = !c->redundant;
115 
116     assert (work.empty ());
117     mark (src);
118     work.push_back (src);
119     LOG ("transred assign %d", src);
120 
121     bool transitive = false;            // found path from 'src' to 'dst'?
122     bool failed = false;                // 'src' failed literal?
123 
124     size_t j = 0;                       // 'propagated' in BFS
125 
126     while (!transitive && !failed && j < work.size ()) {
127       const int lit = work[j++];
128       assert (marked (lit) > 0);
129       LOG ("transred propagating %d", lit);
130       propagations++;
131       const Watches & ws = watches (-lit);
132       const const_watch_iterator eow = ws.end ();
133       const_watch_iterator k;
134       for (k = ws.begin (); !transitive && !failed && k != eow; k++) {
135         const Watch & w = *k;
136         if (!w.binary ()) break;        // since we sorted watches above
137         Clause * d = w.clause;
138         if (d == c) continue;
139         if (irredundant && d->redundant) continue;
140         if (d->garbage) continue;
141         const int other = w.blit;
142         if (other == dst) transitive = true;    // 'dst' reached
143         else {
144           const int tmp = marked (other);
145           if (tmp > 0) continue;
146           else if (tmp < 0) {
147             LOG ("found both %d and %d reachable", -other, other);
148             failed = true;
149           } else {
150             mark (other);
151             work.push_back (other);
152             LOG ("transred assign %d", other);
153           }
154         }
155       }
156     }
157 
158     // Unassign all assigned literals (same as '[bp]acktrack').
159     //
160     while (!work.empty ()) {
161       const int lit = work.back ();
162       work.pop_back ();
163       unmark (lit);
164     }
165 
166     if (transitive) {
167       removed++;
168       stats.transitive++;
169       LOG (c, "transitive redundant");
170       mark_garbage (c);
171     } else if (failed) {
172       units++;
173       LOG ("found failed literal %d during transitive reduction", src);
174       stats.failed++;
175       stats.transredunits++;
176       assign_unit (-src);
177       if (!propagate ()) {
178         VERBOSE (1, "propagating new unit results in conflict");
179         learn_empty_clause ();
180       }
181     }
182   }
183 
184   last.transred.propagations = stats.propagations.search;
185   stats.propagations.transred += propagations;
186   erase_vector (work);
187 
188   PHASE ("transred", stats.transreds,
189     "removed %" PRId64 " transitive clauses, found %" PRId64 " units",
190     removed, units);
191 
192   STOP_SIMPLIFIER (transred, TRANSRED);
193   report ('t', !opts.reportall && !(removed + units));
194 }
195 
196 }

 在文件probe.cpp中 probe_round()

 1 bool Internal::probe_round () {
 2 
 3   if (unsat) return false;
 4   if (terminated_asynchronously ()) return false;
 5 
 6   START_SIMPLIFIER (probe, PROBE);
 7   stats.probingrounds++;
 8 
 9   // Probing is limited in terms of non-probing propagations
10   // 'stats.propagations'. We allow a certain percentage 'opts.probereleff'
11   // (say %5) of probing propagations in each probing with a lower bound of
12   // 'opts.probmineff'.
13   //
14   int64_t delta = stats.propagations.search;
15   delta -= last.probe.propagations;
16   delta *= 1e-3 * opts.probereleff;
17   if (delta < opts.probemineff) delta = opts.probemineff;
18   if (delta > opts.probemaxeff) delta = opts.probemaxeff;
19   delta += 2l * active ();
20 
21   PHASE ("probe-round", stats.probingrounds,
22     "probing limit of %" PRId64 " propagations ", delta);
23 
24   int64_t limit = stats.propagations.probe + delta;
25 
26   int old_failed = stats.failed;
27 #ifndef QUIET
28   int64_t old_probed = stats.probed;
29 #endif
30   int64_t old_hbrs = stats.hbrs;
31 
32   if (!probes.empty ()) flush_probes ();
33 
34   // We reset 'propfixed' since there was at least another conflict thus
35   // a new learned clause, which might produce new propagations (and hyper
36   // binary resolvents).  During 'generate_probes' we keep the old value.
37   //
38   for (auto idx : vars)
39     propfixed (idx) = propfixed (-idx) = -1;
40 
41   assert (unsat || propagated == trail.size ());
42   propagated = propagated2 = trail.size ();
43 
44   int probe;
45   while (!unsat &&
46          !terminated_asynchronously () &&
47          stats.propagations.probe < limit &&
48          (probe = next_probe ())) {
49     stats.probed++;
50     LOG ("probing %d", probe);
51     probe_assign_decision (probe);
52     if (probe_propagate ()) backtrack ();
53     else failed_literal (probe);
54   }
55 
56   if (unsat) LOG ("probing derived empty clause");
57   else if (propagated < trail.size ()) {
58     LOG ("probing produced %zd units", (size_t)(trail.size () - propagated));
59     if (!propagate ()) {
60       LOG ("propagating units after probing results in empty clause");
61       learn_empty_clause ();
62     } else sort_watches ();
63   }
64 
65   int failed = stats.failed - old_failed;
66 #ifndef QUIET
67   int64_t probed = stats.probed - old_probed;
68 #endif
69   int64_t hbrs = stats.hbrs - old_hbrs;
70 
71   PHASE ("probe-round", stats.probingrounds,
72     "probed %" PRId64 " and found %d failed literals", probed, failed);
73 
74   if (hbrs)
75     PHASE ("probe-round", stats.probingrounds,
76       "found %" PRId64 " hyper binary resolvents", hbrs);
77 
78   STOP_SIMPLIFIER (probe, PROBE);
79 
80   report ('p', !opts.reportall && !(unsat + failed + hbrs));
81 
82   return !unsat && failed;
83 }

 

 

   
posted on 2023-04-27 10:44  海阔凭鱼跃越  阅读(31)  评论(0编辑  收藏  举报