ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_restart.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9// As observed by Chanseok Oh and implemented in MapleSAT solvers too,
10// various mostly satisfiable instances benefit from long quiet phases
11// with less or almost no restarts. We implement this idea by prohibiting
12// the Glucose style restart scheme in a geometric fashion, which is very
13// similar to how originally restarts were scheduled in MiniSAT and earlier
14// solvers. We start with say 1e3 = 1000 (opts.stabilizeinit) conflicts of
15// Glucose restarts. Then in a "stabilizing" phase we disable these
16// until 1e4 = 2000 conflicts (if 'opts.stabilizefactor' is '200' percent)
17// have passed. After that we switch back to regular Glucose style restarts
18// until again 2 times more conflicts than the previous limit are reached.
19// Actually, in the latest version we still restarts during stabilization
20// but only in a reluctant doubling scheme with a rather high interval.
21
23 if (!opts.stabilize)
24 return false;
25 if (stable && opts.stabilizeonly)
26 return true;
27 if (!inc.stabilize) {
29 if (stats.conflicts <= lim.stabilize)
30 return false;
31 } else if (stats.ticks.search[stable] <= lim.stabilize)
32 return stable;
33 report (stable ? ']' : '}');
34 if (stable)
35 STOP (stable);
36 else
37 STOP (unstable);
38 const int64_t delta_conflicts =
39 stats.conflicts - last.stabilize.conflicts;
40 const int64_t delta_ticks =
41 stats.ticks.search[stable] - last.stabilize.ticks;
42 const char *current_mode = stable ? "stable" : "unstable";
43 const char *next_mode = stable ? "unstable" : "stable";
44 PHASE ("stabilizing", stats.stabphases,
45 "reached %s stabilization limit %" PRId64 " after %" PRId64
46 " conflicts and %" PRId64 " ticks at %" PRId64
47 " conflicts and %" PRId64 " ticks",
48 current_mode, lim.stabilize, delta_conflicts, delta_ticks,
49 stats.conflicts, stats.ticks.search[stable]);
50 if (!inc.stabilize)
51 inc.stabilize = delta_ticks;
52 if (!inc.stabilize) // rare occurence in incremental calls requiring no
53 // ticks
54 inc.stabilize = 1;
55
56 stable = !stable; // Switch!!!!!
57
58 int64_t next_delta_ticks = inc.stabilize;
59 int64_t stabphases = stats.stabphases + 1;
60 next_delta_ticks *= stabphases * stabphases;
61
62 lim.stabilize = stats.ticks.search[stable] + next_delta_ticks;
63 if (lim.stabilize <= stats.ticks.search[stable])
64 lim.stabilize = stats.ticks.search[stable] + 1;
65
66 if (stable)
67 stats.stabphases++;
68
70 PHASE ("stabilizing", stats.stabphases,
71 "next %s stabilization limit %" PRId64
72 " at ticks interval %" PRId64,
73 next_mode, lim.stabilize, next_delta_ticks);
74 report (stable ? '[' : '{');
75 if (stable)
76 START (stable);
77 else
78 START (unstable);
79 return stable;
80}
81
82// Restarts are scheduled by a variant of the Glucose scheme as presented
83// in our POS'15 paper using exponential moving averages. There is a slow
84// moving average of the average recent glucose level of learned clauses
85// as well as a fast moving average of those glues. If the end of a base
86// restart conflict interval has passed and the fast moving average is
87// above a certain margin over the slow moving average then we restart.
88
90 if (!opts.restart)
91 return false;
92 if ((size_t) level < assumptions.size () + 2)
93 return false;
94 if (stabilizing ())
95 return reluctant;
96 if (stats.conflicts <= lim.restart)
97 return false;
98 double f = averages.current.glue.fast;
99 double margin = (100.0 + opts.restartmargin) / 100.0;
100 double s = averages.current.glue.slow, l = margin * s;
101 LOG ("EMA glue slow %.2f fast %.2f limit %.2f", s, f, l);
102 return l <= f;
103}
104
105// This is Marijn's reuse trail idea. Instead of always backtracking to
106// the top we figure out which decisions will be made again anyhow and
107// only backtrack to the level of the last such decision or to the top if
108// no such decision exists top (in which case we do not reuse any level).
109
111 const int trivial_decisions =
112 assumptions.size ()
113 // Plus 1 if the constraint is satisfied via implications of
114 // assumptions and a pseudo-decision level was introduced.
115 + !control[assumptions.size () + 1].decision;
116 if (!opts.restartreusetrail)
117 return trivial_decisions;
118 int next_decision = next_decision_variable ();
119 CADICAL_assert (1 <= next_decision);
120 int res = trivial_decisions;
121 if (use_scores ()) {
122 while (res < level) {
123 int decision = control[res + 1].decision;
124 if (decision && score_smaller (this) (abs (decision), next_decision))
125 break;
126 res++;
127 }
128 } else {
129 int64_t limit = bumped (next_decision);
130 while (res < level) {
131 int decision = control[res + 1].decision;
132 if (decision && bumped (decision) < limit)
133 break;
134 res++;
135 }
136 }
137 int reused = res - trivial_decisions;
138 if (reused > 0) {
139 stats.reused++;
140 stats.reusedlevels += reused;
141 if (stable)
142 stats.reusedstable++;
143 }
144 return res;
145}
146
148 START (restart);
149 stats.restarts++;
150 stats.restartlevels += level;
151 if (stable)
152 stats.restartstable++;
153 LOG ("restart %" PRId64 "", stats.restarts);
155
156 lim.restart = stats.conflicts + opts.restartint;
157 LOG ("new restart limit at %" PRId64 " conflicts", lim.restart);
158
159 report ('R', 2);
160 STOP (restart);
161}
162
163} // namespace CaDiCaL
164
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
#define PHASE(...)
Definition message.hpp:52
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
void report(char type, int verbose_level=0)
bool limit(const char *name, int)
bool use_scores() const
Definition internal.hpp:471
vector< int > assumptions
Definition internal.hpp:261
void backtrack(int target_level=0)
Reluctant reluctant
Definition internal.hpp:198
vector< Level > control
Definition internal.hpp:282
int64_t & bumped(int lit)
Definition internal.hpp:455