1 #include "internal.hpp" 2 3namespace CaDiCaL {
4 5// As observed by Chanseok Oh and implemented in MapleSAT solvers too,
6// various mostly satisfiable instances benefit from long quiet phases
7// with less or almost no restarts. We implement this idea by prohibiting
8// the Glucose style restart scheme in a geometric fashion, which is very
9// similar to how originally restarts were scheduled in MiniSAT and earlier
10// solvers. We start with say 1e3 = 1000 (opts.stabilizeinit) conflicts of
11// Glucose restarts. Then in a "stabilizing" phase we disable these
12// until 1e4 = 2000 conflicts (if ‘opts.stabilizefactor‘ is ‘200‘ percent)
13// have passed. After that we switch back to regular Glucose style restarts
14// until again 2 times more conflicts than the previous limit are reached.
15// Actually, in the latest version we still restarts during stabilization
16// but only in a reluctant doubling scheme with a rather high interval.
正如Chanseok Oh所观察到的,并且在MapleSAT求解器中实现的那样,各种最容易满足的实例从长时间的静默阶段中获益, 无需或几乎无需重新启动。为了实现这个想法,我们以几何方式禁止了葡萄糖式重启方案, 这与最初在MiniSAT和早期求解器中安排重启的方式非常相似。 我们开始说1e3 = 1000(选项。稳定init)冲突的葡萄糖重新开始。 然后在“稳定”阶段我们禁用这些,直到1e4 = 2000冲突(如果选择的话)。稳定因素是‘ 200% ‘)已经通过。 之后,我们又回到正常的葡萄糖模式,直到再次发生比之前的极限多2倍的冲突。 实际上,在最新版本中,我们仍然在稳定期间重新启动,但只是在一个相当高间隔的勉强加倍方案。 17 18bool Internal::stabilizing () {
19if (!opts.stabilize) returnfalse;
20if (stable && opts.stabilizeonly) returntrue;
21if (stats.conflicts >= lim.stabilize) {
22 report (stable ? ‘]‘ : ‘}‘);
23if (stable) STOP (stable);
24else STOP (unstable);
25 stable = !stable;
26if (stable) stats.stabphases++;
27 PHASE ("stabilizing", stats.stabphases,
28"reached stabilization limit %" PRId64 " after %" PRId64 " conflicts",
29 lim.stabilize, stats.conflicts);
30 inc.stabilize *= opts.stabilizefactor*1e-2;
31if (inc.stabilize > opts.stabilizemaxint)
32 inc.stabilize = opts.stabilizemaxint;
33 lim.stabilize = stats.conflicts + inc.stabilize;
34if (lim.stabilize <= stats.conflicts)
35 lim.stabilize = stats.conflicts + 1;
36 swap_averages ();
37 PHASE ("stabilizing", stats.stabphases,
38"new stabilization limit %" PRId64 " at conflicts interval %" PRId64 "",
39 lim.stabilize, inc.stabilize);
40 report (stable ? ‘[‘ : ‘{‘);
41if (stable) START (stable);
42else START (unstable);
43 }
44return stable;
45}
46 47// Restarts are scheduled by a variant of the Glucose scheme as presented in
48// our POS‘15 paper using exponential moving averages. There is a slow
49// moving average of the average recent glucose level of learned clauses as
50// well as a fast moving average of those glues. If the end of a base
51// restart conflict interval has passed and the fast moving average is above
52// a certain margin over the slow moving average then we restart. 重新启动计划的葡萄糖方案的一个变体,在我们的POS‘15论文使用指数移动平均。 有一个学习过的子句近期平均葡萄糖水平的缓慢移动平均值,以及这些胶水的快速移动平均值。 如果基线重新启动冲突间隔已经结束,并且快速移动平均线高于慢速移动平均线的一定范围, 那么我们将重新启动。 53 54bool Internal::restarting () {
55if (!opts.restart) returnfalse;
56if ((size_t) level < assumptions.size () + 2) returnfalse;
57if (stabilizing ()) return reluctant;
58if (stats.conflicts <= lim.restart) returnfalse;
59double f = averages.current.glue.fast;
60double margin = (100.0 + opts.restartmargin)/100.0;
61double s = averages.current.glue.slow, l = margin * s;
62 LOG ("EMA glue slow %.2f fast %.2f limit %.2f", s, f, l);
63return l <= f;
64}
65 66// This is Marijn‘s reuse trail idea. Instead of always backtracking to the
67// top we figure out which decisions will be made again anyhow and only
68// backtrack to the level of the last such decision or to the top if no such
69// decision exists top (in which case we do not reuse any level). 70 这是Marijn的再利用路线。我们不总是回溯到顶层,而是找出将再次做出哪些决策, 并且只回溯到上一个此类决策的级别,或者在顶层不存在此类决策的情况下回溯到顶层 (在这种情况下,我们不重用任何级别)。 71int Internal::reuse_trail () {
72if (!opts.restartreusetrail) return assumptions.size ();
73int decision = next_decision_variable ();
74 assert (1 <= decision);
75int res = assumptions.size ();
76if (use_scores ()) {
77while (res < level &&
78 score_smaller (this)(decision, abs (control[res+1].decision)))
79 res++;
80 } else {
81 int64_t limit = bumped (decision);
82while (res < level && bumped (control[res+1].decision) > limit)
83 res++;
84 }
85int reused = res - assumptions.size ();
86if (reused > 0) {
87 stats.reused++;
88 stats.reusedlevels += reused;
89if (stable) stats.reusedstable++;
90 }
91return res;
92}
93 94void Internal::restart () {
95 START (restart);
96 stats.restarts++;
97 stats.restartlevels += level;
98if (stable) stats.restartstable++;
99 LOG ("restart %" PRId64 "", stats.restarts);
100 backtrack (reuse_trail ());
101102 lim.restart = stats.conflicts + opts.restartint;
103 LOG ("new restart limit at %" PRId64 " conflicts", lim.restart);
104105 report (‘R‘, 2);
106 STOP (restart);
107}
108109 }