GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/bvminisat/core/Solver.cc Lines: 361 651 55.5 %
Date: 2021-08-01 Branches: 356 1413 25.2 %

Line Exec Source
1
/***************************************************************************************[Solver.cc]
2
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
3
Copyright (c) 2007-2010, Niklas Sorensson
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
associated documentation files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in all copies or
12
substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
**************************************************************************************************/
20
21
#include "prop/bvminisat/core/Solver.h"
22
23
#include <math.h>
24
25
#include <iostream>
26
#include <vector>
27
28
#include "base/check.h"
29
#include "base/exception.h"
30
#include "base/output.h"
31
#include "options/bv_options.h"
32
#include "options/smt_options.h"
33
#include "prop/bvminisat/mtl/Sort.h"
34
#include "theory/interrupted.h"
35
#include "util/utility.h"
36
37
namespace cvc5 {
38
namespace BVMinisat {
39
40
#define OUTPUT_TAG "bvminisat: [a=" << assumptions.size() << ",l=" << decisionLevel() << "] "
41
42
std::ostream& operator << (std::ostream& out, const BVMinisat::Lit& l) {
43
  out << (sign(l) ? "-" : "") << var(l) + 1;
44
  return out;
45
}
46
47
std::ostream& operator << (std::ostream& out, const BVMinisat::Clause& c) {
48
  for (int i = 0; i < c.size(); i++) {
49
    if (i > 0) {
50
      out << " ";
51
    }
52
    out << c[i];
53
  }
54
  return out;
55
}
56
57
58
//=================================================================================================
59
// Options:
60
61
62
static const char* _cat = "CORE";
63
64
9760
static DoubleOption  opt_var_decay         (_cat, "var-decay",   "The variable activity decay factor",            0.95,     DoubleRange(0, false, 1, false));
65
9760
static DoubleOption  opt_clause_decay      (_cat, "cla-decay",   "The clause activity decay factor",              0.999,    DoubleRange(0, false, 1, false));
66
9760
static DoubleOption  opt_random_var_freq   (_cat, "rnd-freq",    "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true));
67
9760
static DoubleOption  opt_random_seed       (_cat, "rnd-seed",    "Used by the random variable selection",         91648253, DoubleRange(0, false, HUGE_VAL, false));
68
9760
static IntOption     opt_ccmin_mode        (_cat, "ccmin-mode",  "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
69
9760
static IntOption     opt_phase_saving      (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
70
9760
static BoolOption    opt_rnd_init_act      (_cat, "rnd-init",    "Randomize the initial activity", false);
71
9760
static BoolOption    opt_luby_restart      (_cat, "luby",        "Use the Luby restart sequence", true);
72
9760
static IntOption     opt_restart_first     (_cat, "rfirst",      "The base restart interval", 25, IntRange(1, INT32_MAX));
73
9760
static DoubleOption  opt_restart_inc       (_cat, "rinc",        "Restart interval increase factor", 3, DoubleRange(1, false, HUGE_VAL, false));
74
9760
static DoubleOption  opt_garbage_frac      (_cat, "gc-frac",     "The fraction of wasted memory allowed before a garbage collection is triggered",  0.20, DoubleRange(0, false, HUGE_VAL, false));
75
76
//=================================================================================================
77
// Proof declarations
78
CRef Solver::TCRef_Undef = CRef_Undef;
79
CRef Solver::TCRef_Lazy = CRef_Undef - 1; // no real lazy ref here
80
81
82
//=================================================================================================
83
// Constructor/Destructor:
84
85
2
Solver::Solver(cvc5::context::Context* context)
86
    :
87
88
      // Parameters (user settable):
89
      //
90
      d_notify(nullptr),
91
      c(context),
92
      verbosity(0),
93
      var_decay(opt_var_decay),
94
      clause_decay(opt_clause_decay),
95
      random_var_freq(opt_random_var_freq),
96
      random_seed(opt_random_seed),
97
      luby_restart(opt_luby_restart),
98
      ccmin_mode(opt_ccmin_mode),
99
      phase_saving(opt_phase_saving),
100
      rnd_pol(false),
101
      rnd_init_act(opt_rnd_init_act),
102
      garbage_frac(opt_garbage_frac),
103
      restart_first(opt_restart_first),
104
      restart_inc(opt_restart_inc)
105
106
      // Parameters (the rest):
107
      //
108
      ,
109
      learntsize_factor((double)1 / (double)3),
110
      learntsize_inc(1.5)
111
112
      // Parameters (experimental):
113
      //
114
      ,
115
      learntsize_adjust_start_confl(100),
116
      learntsize_adjust_inc(1.5)
117
118
      // Statistics: (formerly in 'SolverStats')
119
      //
120
      ,
121
      solves(0),
122
      starts(0),
123
      decisions(0),
124
      rnd_decisions(0),
125
      propagations(0),
126
      conflicts(0),
127
      dec_vars(0),
128
      clauses_literals(0),
129
      learnts_literals(0),
130
      max_literals(0),
131
      tot_literals(0)
132
133
      ,
134
      need_to_propagate(false),
135
      only_bcp(false),
136
      clause_added(false),
137
      ok(true),
138
      cla_inc(1),
139
      var_inc(1),
140
4
      watches(WatcherDeleted(ca)),
141
      qhead(0),
142
      simpDB_assigns(-1),
143
      simpDB_props(0),
144
4
      order_heap(VarOrderLt(activity)),
145
      progress_estimate(0),
146
      remove_satisfied(true)
147
148
      ,
149
      ca()
150
151
      // even though these are temporaries and technically should be set
152
      // before calling, lets initialize them. this will reduces chances of
153
      // non-determinism in portfolio (parallel) solver if variables are
154
      // being (incorrectly) used without initialization.
155
      ,
156
      seen(),
157
      analyze_stack(),
158
      analyze_toclear(),
159
      add_tmp(),
160
      max_learnts(0.0),
161
      learntsize_adjust_confl(0.0),
162
      learntsize_adjust_cnt(0)
163
164
      // Resource constraints:
165
      //
166
      ,
167
      conflict_budget(-1),
168
      propagation_budget(-1),
169
10
      asynch_interrupt(false)
170
{
171
  // Create the constant variables
172
2
  varTrue = newVar(true, false);
173
2
  varFalse = newVar(false, false);
174
175
  // Assert the constants
176
2
  uncheckedEnqueue(mkLit(varTrue, false));
177
2
  uncheckedEnqueue(mkLit(varFalse, true));
178
2
}
179
180
181
2
Solver::~Solver()
182
{
183
2
}
184
185
186
//=================================================================================================
187
// Minor methods:
188
189
190
// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be
191
// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
192
//
193
286
Var Solver::newVar(bool sign, bool dvar)
194
{
195
286
    int v = nVars();
196
286
    watches  .init(mkLit(v, false));
197
286
    watches  .init(mkLit(v, true ));
198
286
    assigns  .push(l_Undef);
199
286
    vardata  .push(mkVarData(CRef_Undef, 0));
200
286
    marker   .push(0);
201
    //activity .push(0);
202
286
    activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
203
286
    seen     .push(0);
204
286
    polarity .push(sign);
205
286
    decision .push();
206
286
    trail    .capacity(v+1);
207
286
    setDecisionVar(v, dvar);
208
209
286
    return v;
210
}
211
212
213
1238
bool Solver::addClause_(vec<Lit>& ps, ClauseId& id)
214
{
215
1238
    if (decisionLevel() > 0) {
216
      cancelUntil(0);
217
    }
218
219
1238
    if (!ok) {
220
      id = ClauseIdUndef;
221
      return false;
222
    }
223
224
    // Check if clause is satisfied and remove false/duplicate literals:
225
    // TODO proof for duplicate literals removal?
226
1238
    sort(ps);
227
    Lit p; int i, j;
228
1238
    int falseLiteralsCount = 0;
229
230
5172
    for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
231
      // tautologies are ignored
232
3934
      if (value(ps[i]) == l_True || ps[i] == ~p) {
233
        id = ClauseIdUndef;
234
        return true;
235
      }
236
237
      // Ignore repeated literals
238
3934
      if (ps[i] == p) {
239
        continue;
240
      }
241
242
3934
      if (value(ps[i]) == l_False) {
243
        continue;
244
      }
245
3934
      ps[j++] = p = ps[i];
246
    }
247
248
1238
    ps.shrink(i - j);
249
250
1238
    clause_added = true;
251
252
1238
    if(falseLiteralsCount == 0) {
253
1238
      if (ps.size() == 0) {
254
        return ok = false;
255
      }
256
1238
      else if (ps.size() == 1){
257
4
        uncheckedEnqueue(ps[0]);
258
4
        CRef confl_ref = propagate();
259
4
        ok = (confl_ref == CRef_Undef);
260
4
        return ok;
261
      } else {
262
1234
        CRef cr = ca.alloc(ps, false);
263
1234
        clauses.push(cr);
264
1234
        attachClause(cr);
265
      }
266
1234
      return ok;
267
    }
268
    return ok;
269
}
270
271
1470
void Solver::attachClause(CRef cr) {
272
1470
  const Clause& clause = ca[cr];
273
1470
  Assert(clause.size() > 1);
274
1470
  watches[~clause[0]].push(Watcher(cr, clause[1]));
275
1470
  watches[~clause[1]].push(Watcher(cr, clause[0]));
276
1470
  if (clause.learnt())
277
158
    learnts_literals += clause.size();
278
  else
279
1312
    clauses_literals += clause.size();
280
1470
}
281
282
820
void Solver::detachClause(CRef cr, bool strict) {
283
820
  const Clause& clause = ca[cr];
284
285
820
  Assert(clause.size() > 1);
286
287
820
  if (strict)
288
  {
289
78
    remove(watches[~clause[0]], Watcher(cr, clause[1]));
290
78
    remove(watches[~clause[1]], Watcher(cr, clause[0]));
291
    }else{
292
        // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
293
742
        watches.smudge(~clause[0]);
294
742
        watches.smudge(~clause[1]);
295
    }
296
297
820
    if (clause.learnt())
298
38
      learnts_literals -= clause.size();
299
    else
300
782
      clauses_literals -= clause.size();
301
820
}
302
303
742
void Solver::removeClause(CRef cr) {
304
742
  Clause& clause = ca[cr];
305
742
  detachClause(cr);
306
  // Don't leave pointers to free'd memory!
307
742
  if (locked(clause)) vardata[var(clause[0])].reason = CRef_Undef;
308
742
  clause.mark(1);
309
742
  ca.free(cr);
310
742
}
311
312
106
bool Solver::satisfied(const Clause& clause) const
313
{
314
452
  for (int i = 0; i < clause.size(); i++)
315
384
    if (value(clause[i]) == l_True) return true;
316
68
  return false;
317
}
318
319
// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
320
//
321
178
void Solver::cancelUntil(int level) {
322
178
    if (decisionLevel() > level){
323
176
      Debug("bvminisat::explain") << OUTPUT_TAG << " backtracking to " << level << std::endl;
324
3378
      for (int clause = trail.size() - 1; clause >= trail_lim[level]; clause--)
325
      {
326
3202
        Var x = var(trail[clause]);
327
3202
        assigns[x] = l_Undef;
328
3202
        if (marker[x] == 2) marker[x] = 1;
329
6404
        if (phase_saving > 1
330
3202
            || ((phase_saving == 1) && clause > trail_lim.last()))
331
        {
332
3202
          polarity[x] = sign(trail[clause]);
333
        }
334
3202
        insertVarOrder(x);
335
      }
336
176
        qhead = trail_lim[level];
337
176
        trail.shrink(trail.size() - trail_lim[level]);
338
176
        trail_lim.shrink(trail_lim.size() - level);
339
    }
340
178
}
341
342
343
//=================================================================================================
344
// Major methods:
345
346
347
876
Lit Solver::pickBranchLit()
348
{
349
876
    Var next = var_Undef;
350
351
    // Random decision:
352
876
    if (drand(random_seed) < random_var_freq && !order_heap.empty()){
353
        next = order_heap[irand(random_seed,order_heap.size())];
354
        if (value(next) == l_Undef && decision[next])
355
            rnd_decisions++; }
356
357
    // Activity based decision:
358
4568
    while (next == var_Undef || value(next) != l_Undef || !decision[next])
359
1846
        if (order_heap.empty()){
360
            next = var_Undef;
361
            break;
362
        }else
363
1846
            next = order_heap.removeMin();
364
365
876
    return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]);
366
}
367
368
/*_________________________________________________________________________________________________
369
|
370
|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->
371
[void]
372
|
373
|  Description:
374
|    Analyze conflict and produce a reason clause.
375
|
376
|    Pre-conditions:
377
|      * 'out_learnt' is assumed to be cleared.
378
|      * Current decision level must be greater than root level.
379
|
380
|    Post-conditions:
381
|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
382
|      * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision
383
level of the |        rest of literals. There may be others from the same level
384
though.
385
|
386
|________________________________________________________________________________________________@*/
387
172
void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip)
388
{
389
172
    int pathC = 0;
390
172
    Lit p     = lit_Undef;
391
392
    // Generate conflict clause:
393
    //
394
172
    out_learnt.push();      // (leave room for the asserting literal)
395
172
    int index   = trail.size() - 1;
396
397
172
    bool done = false;
398
399
492
    do{
400
664
      Assert(confl != CRef_Undef);  // (otherwise should be UIP)
401
664
      Clause& clause = ca[confl];
402
403
664
      if (clause.learnt()) claBumpActivity(clause);
404
405
2728
      for (int j = (p == lit_Undef) ? 0 : 1; j < clause.size(); j++)
406
      {
407
2064
        Lit q = clause[j];
408
409
2064
        if (!seen[var(q)] && level(var(q)) > 0)
410
        {
411
1168
          varBumpActivity(var(q));
412
1168
          seen[var(q)] = 1;
413
1168
          if (level(var(q)) >= decisionLevel())
414
664
            pathC++;
415
          else
416
504
            out_learnt.push(q);
417
        }
418
      }
419
420
        // Select next clause to look at:
421
788
        while (!seen[var(trail[index--])]);
422
664
        p     = trail[index+1];
423
664
        confl = reason(var(p));
424
664
        seen[var(p)] = 0;
425
664
        pathC--;
426
427
664
        switch (uip) {
428
664
        case UIP_FIRST:
429
664
          done = pathC == 0;
430
664
          break;
431
        case UIP_LAST:
432
          done = confl == CRef_Undef || (pathC == 0 && marker[var(p)] == 2);
433
          break;
434
        default:
435
          Unreachable();
436
          break;
437
        }
438
664
    } while (!done);
439
172
    out_learnt[0] = ~p;
440
441
    // Simplify conflict clause:
442
    //
443
    int i1, j;
444
172
    out_learnt.copyTo(analyze_toclear);
445
172
    if (ccmin_mode == 2){
446
        uint32_t abstract_level = 0;
447
        for (i1 = 1; i1 < out_learnt.size(); i1++)
448
          abstract_level |= abstractLevel(
449
              var(out_learnt[i1]));  // (maintain an abstraction of levels
450
                                     // involved in conflict)
451
452
        for (i1 = j = 1; i1 < out_learnt.size(); i1++)
453
        {
454
          if (reason(var(out_learnt[i1])) == CRef_Undef)
455
          {
456
            out_learnt[j++] = out_learnt[i1];
457
          }
458
          else
459
          {
460
            // Check if the literal is redundant
461
            if (!litRedundant(out_learnt[i1], abstract_level))
462
            {
463
              // Literal is not redundant
464
              out_learnt[j++] = out_learnt[i1];
465
            }
466
          }
467
        }
468
172
    }else if (ccmin_mode == 1){
469
        Unreachable();
470
        for (i1 = j = 1; i1 < out_learnt.size(); i1++)
471
        {
472
          Var x = var(out_learnt[i1]);
473
474
          if (reason(x) == CRef_Undef)
475
            out_learnt[j++] = out_learnt[i1];
476
          else
477
          {
478
            Clause& clause = ca[reason(var(out_learnt[i1]))];
479
            for (int k = 1; k < clause.size(); k++)
480
              if (!seen[var(clause[k])] && level(var(clause[k])) > 0)
481
              {
482
                out_learnt[j++] = out_learnt[i1];
483
                break;
484
              }
485
          }
486
        }
487
    }else
488
172
      i1 = j = out_learnt.size();
489
490
172
    max_literals += out_learnt.size();
491
172
    out_learnt.shrink(i1 - j);
492
172
    tot_literals += out_learnt.size();
493
494
172
    for (int i2 = 0; i2 < out_learnt.size(); ++i2)
495
    {
496
172
      if (marker[var(out_learnt[i2])] == 0)
497
      {
498
172
        break;
499
      }
500
    }
501
502
    // Find correct backtrack level:
503
    //
504
172
    if (out_learnt.size() == 1) {
505
14
      out_btlevel = 0;
506
    }
507
    else{
508
158
        int max_i = 1;
509
        // Find the first literal assigned at the next-highest level:
510
504
        for (int i3 = 2; i3 < out_learnt.size(); i3++)
511
346
          if (level(var(out_learnt[i3])) > level(var(out_learnt[max_i])))
512
76
            max_i = i3;
513
        // Swap-in this literal at i1 1:
514
158
        Lit p2 = out_learnt[max_i];
515
158
        out_learnt[max_i] = out_learnt[1];
516
158
        out_learnt[1] = p2;
517
158
        out_btlevel = level(var(p2));
518
    }
519
520
848
    for (int j2 = 0; j2 < analyze_toclear.size(); j2++)
521
676
      seen[var(analyze_toclear[j2])] = 0;  // ('seen[]' is now cleared)
522
172
}
523
524
525
// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
526
// visiting literals at levels that cannot be removed later.
527
bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
528
{
529
    analyze_stack.clear(); analyze_stack.push(p);
530
    int top = analyze_toclear.size();
531
    while (analyze_stack.size() > 0){
532
        CRef c_reason = reason(var(analyze_stack.last()));
533
        Assert(c_reason != CRef_Undef);
534
        Clause& clause = ca[c_reason];
535
        int c_size = clause.size();
536
        analyze_stack.pop();
537
538
        for (int i = 1; i < c_size; i++){
539
          Lit p2 = clause[i];
540
          if (!seen[var(p2)] && level(var(p2)) > 0)
541
          {
542
            if (reason(var(p2)) != CRef_Undef
543
                && (abstractLevel(var(p2)) & abstract_levels) != 0)
544
            {
545
              seen[var(p2)] = 1;
546
              analyze_stack.push(p2);
547
              analyze_toclear.push(p2);
548
            }
549
            else
550
            {
551
              for (int j = top; j < analyze_toclear.size(); j++)
552
                seen[var(analyze_toclear[j])] = 0;
553
              analyze_toclear.shrink(analyze_toclear.size() - top);
554
              return false;
555
            }
556
          }
557
        }
558
    }
559
560
    return true;
561
}
562
563
/**
564
 * Specialized analyzeFinal procedure where we test the consistency
565
 * of the assumptions before backtracking bellow the assumption level.
566
 *
567
 * @param p the original uip (may be unit)
568
 * @param confl_clause the conflict clause
569
 * @param out_conflict the conflict in terms of assumptions we are building
570
 */
571
void Solver::analyzeFinal2(Lit p, CRef confl_clause, vec<Lit>& out_conflict) {
572
  Assert(confl_clause != CRef_Undef);
573
  Assert(decisionLevel() == assumptions.size());
574
  Assert(level(var(p)) == assumptions.size());
575
576
  out_conflict.clear();
577
578
  Clause& cl = ca[confl_clause];
579
  for (int i = 0; i < cl.size(); ++i) {
580
    seen[var(cl[i])] = 1;
581
  }
582
583
  int end = trail_lim[0];
584
  for (int i = trail.size() - 1; i >= end; i--) {
585
    Var x = var(trail[i]);
586
    if (seen[x]) {
587
      if (reason(x) == CRef_Undef) {
588
        // we skip p if was a learnt unit
589
        if (x != var(p)) {
590
          if (marker[x] == 2) {
591
            Assert(level(x) > 0);
592
            out_conflict.push(~trail[i]);
593
          }
594
        }
595
      } else {
596
        Clause& clause = ca[reason(x)];
597
598
        for (int j = 1; j < clause.size(); j++)
599
        {
600
          if (level(var(clause[j])) > 0) seen[var(clause[j])] = 1;
601
        }
602
      }
603
      seen[x] = 0;
604
    }
605
    Assert(seen[x] == 0);
606
  }
607
  Assert(out_conflict.size());
608
}
609
610
/*_________________________________________________________________________________________________
611
|
612
|  analyzeFinal : (p : Lit)  ->  [void]
613
|
614
|  Description:
615
|    Specialized analysis procedure to express the final conflict in terms of
616
assumptions. |    Calculates the (possibly empty) set of assumptions that led to
617
the assignment of 'p', and |    stores the result in 'out_conflict'.
618
|________________________________________________________________________________________________@*/
619
void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
620
{
621
    out_conflict.clear();
622
    if (marker[var(p)] == 2) {
623
      out_conflict.push(p);
624
    }
625
626
    if (decisionLevel() == 0)
627
    {
628
      return;
629
    }
630
631
    seen[var(p)] = 1;
632
    int end = trail_lim[0];
633
634
    for (int i = trail.size()-1; i >= end; i--){
635
        Var x = var(trail[i]);
636
        if (seen[x]) {
637
            if (reason(x) == CRef_Undef) {
638
              Assert(marker[x] == 2);
639
              Assert(level(x) > 0);
640
              if (~trail[i] != p)
641
              {
642
                out_conflict.push(~trail[i]);
643
              }
644
            } else {
645
              Clause& clause = ca[reason(x)];
646
              for (int j = 1; j < clause.size(); j++)
647
              {
648
                if (level(var(clause[j])) > 0)
649
                {
650
                  seen[var(clause[j])] = 1;
651
                }
652
              }
653
            }
654
            seen[x] = 0;
655
        }
656
    }
657
658
    seen[var(p)] = 0;
659
    Assert(out_conflict.size());
660
}
661
662
663
3282
void Solver::uncheckedEnqueue(Lit p, CRef from)
664
{
665
3282
  Assert(value(p) == l_Undef);
666
3282
  assigns[var(p)] = lbool(!sign(p));
667
3282
  vardata[var(p)] = mkVarData(from, decisionLevel());
668
3282
  trail.push_(p);
669
3282
  if (decisionLevel() <= assumptions.size() && marker[var(p)] == 1)
670
  {
671
    if (d_notify)
672
    {
673
      Debug("bvminisat::explain")
674
          << OUTPUT_TAG << "propagating " << p << std::endl;
675
      d_notify->notify(p);
676
    }
677
  }
678
3282
}
679
680
void Solver::popAssumption() {
681
    assumptions.pop();
682
    conflict.clear();
683
    cancelUntil(assumptions.size());
684
}
685
686
lbool Solver::propagateAssumptions() {
687
  only_bcp = true;
688
  ccmin_mode = 0;
689
  return search(-1);
690
}
691
692
lbool Solver::assertAssumption(Lit p, bool propagate) {
693
  // TODO need to somehow mark the assumption as unit in the current context?
694
  // it's not always unit though, but this would be useful for debugging
695
696
  // Assert(marker[var(p)] == 1);
697
698
  if (decisionLevel() > assumptions.size()) {
699
    cancelUntil(assumptions.size());
700
  }
701
702
  conflict.clear();
703
704
  // add to the assumptions
705
  if (c->getLevel() > 0) {
706
    assumptions.push(p);
707
  } else {
708
    ClauseId id;
709
    if (!addClause(p, id)) {
710
      conflict.push(~p);
711
      return l_False;
712
    }
713
  }
714
715
  // run the propagation
716
  if (propagate) {
717
    only_bcp = true;
718
    ccmin_mode = 0;
719
    lbool result = search(-1);
720
    return result;
721
  } else {
722
    return l_True;
723
  }
724
}
725
726
void Solver::addMarkerLiteral(Var var) {
727
  // make sure it wasn't already marked
728
  Assert(marker[var] == 0);
729
  marker[var] = 1;
730
}
731
732
/*_________________________________________________________________________________________________
733
|
734
|  propagate : [void]  ->  [Clause*]
735
|
736
|  Description:
737
|    Propagates all enqueued facts. If a conflict arises, the conflicting clause
738
is returned, |    otherwise CRef_Undef.
739
|
740
|    Post-conditions:
741
|      * the propagation queue is empty, even if there was a conflict.
742
|________________________________________________________________________________________________@*/
743
1114
CRef Solver::propagate()
744
{
745
1114
    CRef    confl     = CRef_Undef;
746
1114
    int     num_props = 0;
747
1114
    watches.cleanAll();
748
749
7194
    while (qhead < trail.size()){
750
3040
        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
751
3040
        vec<Watcher>&  ws  = watches[p];
752
        Watcher        *i, *j, *end;
753
3040
        num_props++;
754
755
14402
        for (i = j = (Watcher*)ws, end = i + ws.size();  i != end;){
756
            // Try to avoid inspecting the clause:
757
11362
            Lit blocker = i->blocker;
758
17238
            if (value(blocker) == l_True){
759
18352
                *j++ = *i++; continue; }
760
761
            // Make sure the false literal is data[1]:
762
5486
            CRef     cr        = i->cref;
763
5486
            Clause& clause = ca[cr];
764
5486
            Lit      false_lit = ~p;
765
5486
            if (clause[0] == false_lit)
766
2350
              clause[0] = clause[1], clause[1] = false_lit;
767
5486
            Assert(clause[1] == false_lit);
768
5486
            i++;
769
770
            // If 0th watch is true, then clause is already satisfied.
771
5486
            Lit first = clause[0];
772
5486
            Watcher w     = Watcher(cr, first);
773
6210
            if (first != blocker && value(first) == l_True){
774
1448
                *j++ = w; continue; }
775
776
            // Look for new watch:
777
10888
            for (int k = 2; k < clause.size(); k++)
778
8488
              if (value(clause[k]) != l_False)
779
              {
780
2362
                clause[1] = clause[k];
781
2362
                clause[k] = false_lit;
782
2362
                watches[~clause[1]].push(w);
783
2362
                goto NextClause;
784
              }
785
786
            // Did not find watch -- clause is unit under assignment:
787
2400
            *j++ = w;
788
2400
            if (value(first) == l_False){
789
174
                confl = cr;
790
174
                qhead = trail.size();
791
                // Copy the remaining watches:
792
766
                while (i < end)
793
296
                    *j++ = *i++;
794
            }else
795
2226
                uncheckedEnqueue(first, cr);
796
797
4762
        NextClause:;
798
        }
799
3040
        ws.shrink(i - j);
800
    }
801
1114
    propagations += num_props;
802
1114
    simpDB_props -= num_props;
803
804
1114
    return confl;
805
}
806
807
/*_________________________________________________________________________________________________
808
|
809
|  reduceDB : ()  ->  [void]
810
|
811
|  Description:
812
|    Remove half of the learnt clauses, minus the clauses locked by the current
813
assignment. Locked |    clauses are clauses that are reason to some assignment.
814
Binary clauses are never removed.
815
|________________________________________________________________________________________________@*/
816
struct reduceDB_lt
817
{
818
  ClauseAllocator& ca;
819
  reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
820
  bool operator()(CRef x, CRef y)
821
  {
822
    return ca[x].size() > 2
823
           && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity());
824
  }
825
};
826
void Solver::reduceDB()
827
{
828
    int     i, j;
829
    double  extra_lim = cla_inc / learnts.size();    // Remove any clause below this activity
830
831
    sort(learnts, reduceDB_lt(ca));
832
    // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
833
    // and clauses with activity smaller than 'extra_lim':
834
    for (i = j = 0; i < learnts.size(); i++){
835
      Clause& clause = ca[learnts[i]];
836
      if (clause.size() > 2 && !locked(clause)
837
          && (i < learnts.size() / 2 || clause.activity() < extra_lim))
838
        removeClause(learnts[i]);
839
      else
840
        learnts[j++] = learnts[i];
841
    }
842
    learnts.shrink(i - j);
843
    checkGarbage();
844
}
845
846
847
4
void Solver::removeSatisfied(vec<CRef>& cs)
848
{
849
    int i, j;
850
110
    for (i = j = 0; i < cs.size(); i++){
851
106
      Clause& clause = ca[cs[i]];
852
106
      if (satisfied(clause))
853
      {
854
38
        removeClause(cs[i]);
855
      }
856
        else
857
68
            cs[j++] = cs[i];
858
    }
859
4
    cs.shrink(i - j);
860
4
}
861
862
863
4
void Solver::rebuildOrderHeap()
864
{
865
8
    vec<Var> vs;
866
576
    for (Var v = 0; v < nVars(); v++)
867
572
        if (decision[v] && value(v) == l_Undef)
868
368
            vs.push(v);
869
4
    order_heap.build(vs);
870
4
}
871
872
/*_________________________________________________________________________________________________
873
|
874
|  simplify : [void]  ->  [bool]
875
|
876
|  Description:
877
|    Simplify the clause database according to the current top-level assigment.
878
Currently, the only |    thing done here is the removal of satisfied clauses,
879
but more things can be put here.
880
|________________________________________________________________________________________________@*/
881
20
bool Solver::simplify()
882
{
883
20
  Assert(decisionLevel() == 0);
884
885
20
  if (!ok || propagate() != CRef_Undef) return ok = false;
886
887
20
  if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) return true;
888
889
4
  d_notify->spendResource(Resource::BvSatSimplifyStep);
890
891
  // Remove satisfied clauses:
892
4
  removeSatisfied(learnts);
893
4
  if (remove_satisfied)  // Can be turned off.
894
    removeSatisfied(clauses);
895
4
  checkGarbage();
896
4
  rebuildOrderHeap();
897
898
4
  simpDB_assigns = nAssigns();
899
4
  simpDB_props =
900
4
      clauses_literals + learnts_literals;  // (shouldn't depend on stats
901
                                            // really, but it will do for now)
902
903
4
  return true;
904
}
905
906
/*_________________________________________________________________________________________________
907
|
908
|  search : (nof_conflicts : int) (params : const SearchParams&)  ->  [lbool]
909
|
910
|  Description:
911
|    Search for a model the specified number of conflicts.
912
|    NOTE! Use negative value for 'nof_conflicts' indicate infinity.
913
|
914
|  Output:
915
|    'l_True' if a partial assigment that is consistent with respect to the
916
clauseset is found. If |    all variables are decision variables, this means
917
that the clause set is satisfiable. 'l_False' |    if the clause set is
918
unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
919
|________________________________________________________________________________________________@*/
920
6
lbool Solver::search(int nof_conflicts, UIP uip)
921
{
922
6
  Assert(ok);
923
  int backtrack_level;
924
6
  int conflictC = 0;
925
12
  vec<Lit> learnt_clause;
926
6
  starts++;
927
928
  for (;;)
929
  {
930
1054
    d_notify->safePoint(Resource::BvSatPropagateStep);
931
1054
    CRef confl = propagate();
932
1054
    if (confl != CRef_Undef)
933
    {
934
      // CONFLICT
935
174
      conflicts++;
936
174
      conflictC++;
937
938
174
      if (decisionLevel() == 0)
939
      {
940
        // can this happen for bv?
941
2
        return l_False;
942
      }
943
944
172
      learnt_clause.clear();
945
172
      analyze(confl, learnt_clause, backtrack_level, uip);
946
947
172
      Lit p = learnt_clause[0];
948
      // bool assumption = marker[var(p)] == 2;
949
950
172
      CRef cr = CRef_Undef;
951
172
      if (learnt_clause.size() > 1)
952
      {
953
158
        cr = ca.alloc(learnt_clause, true);
954
158
        learnts.push(cr);
955
158
        attachClause(cr);
956
158
        claBumpActivity(ca[cr]);
957
      }
958
959
172
      if (learnt_clause.size() == 1)
960
      {
961
        // learning a unit clause
962
      }
963
964
      //  if the uip was an assumption we are unsat
965
172
      if (level(var(p)) <= assumptions.size())
966
      {
967
        for (int i = 0; i < learnt_clause.size(); ++i)
968
        {
969
          Assert(level(var(learnt_clause[i])) <= decisionLevel());
970
          seen[var(learnt_clause[i])] = 1;
971
        }
972
973
        analyzeFinal(p, conflict);
974
        Debug("bvminisat::search")
975
            << OUTPUT_TAG << " conflict on assumptions " << std::endl;
976
        return l_False;
977
      }
978
979
344
      if (!cvc5::options::bvEagerExplanations())
980
      {
981
        // check if uip leads to a conflict
982
172
        if (backtrack_level < assumptions.size())
983
        {
984
          cancelUntil(assumptions.size());
985
          uncheckedEnqueue(p, cr);
986
987
          CRef new_confl = propagate();
988
          if (new_confl != CRef_Undef)
989
          {
990
            // we have a conflict we now need to explain it
991
            analyzeFinal2(p, new_confl, conflict);
992
            return l_False;
993
          }
994
        }
995
      }
996
997
172
      cancelUntil(backtrack_level);
998
172
      uncheckedEnqueue(p, cr);
999
1000
172
      varDecayActivity();
1001
172
      claDecayActivity();
1002
1003
172
      if (--learntsize_adjust_cnt == 0)
1004
      {
1005
        learntsize_adjust_confl *= learntsize_adjust_inc;
1006
        learntsize_adjust_cnt = (int)learntsize_adjust_confl;
1007
        max_learnts *= learntsize_inc;
1008
1009
        if (verbosity >= 1)
1010
          printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
1011
                 (int)conflicts,
1012
                 (int)dec_vars
1013
                     - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]),
1014
                 nClauses(),
1015
                 (int)clauses_literals,
1016
                 (int)max_learnts,
1017
                 nLearnts(),
1018
                 (double)learnts_literals / nLearnts(),
1019
                 progressEstimate() * 100);
1020
      }
1021
    }
1022
    else
1023
    {
1024
      // NO CONFLICT
1025
      bool isWithinBudget;
1026
      try
1027
      {
1028
880
        isWithinBudget =
1029
            withinBudget(Resource::BvSatConflictsStep);
1030
      }
1031
      catch (const cvc5::theory::Interrupted& e)
1032
      {
1033
        // do some clean-up and rethrow
1034
        cancelUntil(assumptions.size());
1035
        throw e;
1036
      }
1037
1038
2622
      if ((decisionLevel() > assumptions.size() && nof_conflicts >= 0
1039
862
           && conflictC >= nof_conflicts)
1040
1756
          || !isWithinBudget)
1041
      {
1042
        // Reached bound on number of conflicts:
1043
4
        Debug("bvminisat::search") << OUTPUT_TAG << " restarting " << std::endl;
1044
4
        progress_estimate = progressEstimate();
1045
4
        cancelUntil(assumptions.size());
1046
4
        return l_Undef;
1047
      }
1048
1049
      // Simplify the set of problem clauses:
1050
876
      if (decisionLevel() == 0 && !simplify())
1051
      {
1052
        Debug("bvminisat::search")
1053
            << OUTPUT_TAG << " base level conflict, we're unsat" << std::endl;
1054
        return l_False;
1055
      }
1056
1057
      // We can't erase clauses if there is unprocessed assumptions, there might
1058
      // be some propagationg we need to redu
1059
1752
      if (decisionLevel() >= assumptions.size()
1060
876
          && learnts.size() - nAssigns() >= max_learnts)
1061
      {
1062
        // Reduce the set of learnt clauses:
1063
        Debug("bvminisat::search")
1064
            << OUTPUT_TAG << " cleaning up database" << std::endl;
1065
        reduceDB();
1066
      }
1067
1068
876
      Lit next = lit_Undef;
1069
876
      while (decisionLevel() < assumptions.size())
1070
      {
1071
        // Perform user provided assumption:
1072
        Lit p = assumptions[decisionLevel()];
1073
        if (value(p) == l_True)
1074
        {
1075
          // Dummy decision level:
1076
          newDecisionLevel();
1077
        }
1078
        else if (value(p) == l_False)
1079
        {
1080
          marker[var(p)] = 2;
1081
1082
          analyzeFinal(~p, conflict);
1083
          Debug("bvminisat::search")
1084
              << OUTPUT_TAG << " assumption false, we're unsat" << std::endl;
1085
          return l_False;
1086
        }
1087
        else
1088
        {
1089
          marker[var(p)] = 2;
1090
          next = p;
1091
          break;
1092
        }
1093
      }
1094
1095
876
      if (next == lit_Undef)
1096
      {
1097
876
        if (only_bcp)
1098
        {
1099
          Debug("bvminisat::search")
1100
              << OUTPUT_TAG << " only bcp, skipping rest of the problem"
1101
              << std::endl;
1102
          return l_True;
1103
        }
1104
1105
        // New variable decision:
1106
876
        decisions++;
1107
876
        next = pickBranchLit();
1108
1109
876
        if (next == lit_Undef)
1110
        {
1111
          Debug("bvminisat::search")
1112
              << OUTPUT_TAG << " satisfiable" << std::endl;
1113
          // Model found:
1114
          return l_True;
1115
        }
1116
      }
1117
1118
      // Increase decision level and enqueue 'next'
1119
876
      newDecisionLevel();
1120
876
      uncheckedEnqueue(next);
1121
    }
1122
1048
  }
1123
}
1124
1125
1126
4
double Solver::progressEstimate() const
1127
{
1128
4
    double  progress = 0;
1129
4
    double  F = 1.0 / nVars();
1130
1131
54
    for (int i = 0; i <= decisionLevel(); i++){
1132
50
        int beg = i == 0 ? 0 : trail_lim[i - 1];
1133
50
        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
1134
50
        progress += pow(F, i) * (end - beg);
1135
    }
1136
1137
4
    return progress / nVars();
1138
}
1139
1140
/*
1141
  Finite subsequences of the Luby-sequence:
1142
1143
  0: 1
1144
  1: 1 1 2
1145
  2: 1 1 2 1 1 2 4
1146
  3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8
1147
  ...
1148
1149
1150
 */
1151
1152
6
static double luby(double y, int x){
1153
1154
    // Find the finite subsequence that contains index 'x', and the
1155
    // size of that subsequence:
1156
    int size, seq;
1157
6
    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1);
1158
1159
10
    while (size-1 != x){
1160
2
        size = (size-1)>>1;
1161
2
        seq--;
1162
2
        x = x % size;
1163
    }
1164
1165
6
    return pow(y, seq);
1166
}
1167
1168
// NOTE: assumptions passed in member-variable 'assumptions'.
1169
2
lbool Solver::solve_()
1170
{
1171
2
    Debug("bvminisat") <<"BVMinisat::Solving learned clauses " << learnts.size() <<"\n";
1172
2
    Debug("bvminisat") <<"BVMinisat::Solving assumptions " << assumptions.size() <<"\n";
1173
1174
2
    model.clear();
1175
2
    conflict.clear();
1176
1177
2
    ccmin_mode = 0;
1178
1179
2
    if (!ok) return l_False;
1180
1181
2
    solves++;
1182
1183
2
    max_learnts               = nClauses() * learntsize_factor;
1184
2
    learntsize_adjust_confl   = learntsize_adjust_start_confl;
1185
2
    learntsize_adjust_cnt     = (int)learntsize_adjust_confl;
1186
2
    lbool   status            = l_Undef;
1187
1188
2
    if (verbosity >= 1){
1189
        printf("============================[ Search Statistics ]==============================\n");
1190
        printf("| Conflicts |          ORIGINAL         |          LEARNT          | Progress |\n");
1191
        printf("|           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl |          |\n");
1192
        printf("===============================================================================\n");
1193
    }
1194
1195
    // Search:
1196
2
    int curr_restarts = 0;
1197
14
    while (status == l_Undef){
1198
6
        double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts);
1199
6
        status = search(rest_base * restart_first);
1200
6
        if (!withinBudget(Resource::BvSatConflictsStep)) break;
1201
6
        curr_restarts++;
1202
    }
1203
1204
2
    if (verbosity >= 1)
1205
        printf("===============================================================================\n");
1206
1207
2
    if (status == l_True){
1208
        // Extend & copy model:
1209
        // model.growTo(nVars());
1210
        // for (int i = 0; i < nVars(); i++) model[i] = value(i);
1211
2
    }else if (status == l_False && conflict.size() == 0)
1212
2
        ok = false;
1213
1214
2
    return status;
1215
}
1216
1217
//=================================================================================================
1218
// Bitvector propagations
1219
//
1220
1221
void Solver::explain(Lit p, std::vector<Lit>& explanation) {
1222
  Debug("bvminisat::explain") << OUTPUT_TAG << "starting explain of " << p << std::endl;
1223
1224
  // top level fact, no explanation necessary
1225
  if (level(var(p)) == 0) {
1226
    return;
1227
  }
1228
1229
  seen[var(p)] = 1;
1230
1231
  // if we are called at decisionLevel = 0 trail_lim is empty
1232
  int bottom = trail_lim[0];
1233
  for (int i = trail.size()-1; i >= bottom; i--){
1234
    Var x = var(trail[i]);
1235
    if (seen[x]) {
1236
      if (reason(x) == CRef_Undef) {
1237
        if (marker[x] == 2) {
1238
          Assert(level(x) > 0);
1239
          explanation.push_back(trail[i]);
1240
        } else {
1241
          Assert(level(x) == 0);
1242
         }
1243
      } else {
1244
        Clause& clause = ca[reason(x)];
1245
        for (int j = 1; j < clause.size(); j++)
1246
        {
1247
          if (level(var(clause[j])) > 0)
1248
          {
1249
            seen[var(clause[j])] = 1;
1250
          }
1251
        }
1252
      }
1253
      seen[x] = 0;
1254
    }
1255
  }
1256
  seen[var(p)] = 0;
1257
}
1258
1259
//=================================================================================================
1260
// Writing CNF to DIMACS:
1261
//
1262
// FIXME: this needs to be rewritten completely.
1263
1264
static Var mapVar(Var x, vec<Var>& map, Var& max)
1265
{
1266
    if (map.size() <= x || map[x] == -1){
1267
        map.growTo(x+1, -1);
1268
        map[x] = max++;
1269
    }
1270
    return map[x];
1271
}
1272
1273
void Solver::toDimacs(FILE* f, Clause& clause, vec<Var>& map, Var& max)
1274
{
1275
  if (satisfied(clause)) return;
1276
1277
  for (int i = 0; i < clause.size(); i++)
1278
    if (value(clause[i]) != l_False)
1279
      fprintf(f,
1280
              "%s%d ",
1281
              sign(clause[i]) ? "-" : "",
1282
              mapVar(var(clause[i]), map, max) + 1);
1283
  fprintf(f, "0\n");
1284
}
1285
1286
1287
void Solver::toDimacs(const char *file, const vec<Lit>& assumps)
1288
{
1289
    FILE* f = fopen(file, "wr");
1290
    if (f == NULL)
1291
        fprintf(stderr, "could not open file %s\n", file), exit(1);
1292
    toDimacs(f, assumps);
1293
    fclose(f);
1294
}
1295
1296
1297
void Solver::toDimacs(FILE* f, const vec<Lit>& assumps)
1298
{
1299
    // Handle case when solver is in contradictory state:
1300
    if (!ok){
1301
        fprintf(f, "p cnf 1 2\n1 0\n-1 0\n");
1302
        return; }
1303
1304
    vec<Var> map; Var max = 0;
1305
1306
    // Cannot use removeClauses here because it is not safe
1307
    // to deallocate them at this point. Could be improved.
1308
    int cnt = 0;
1309
    for (int i = 0; i < clauses.size(); i++)
1310
        if (!satisfied(ca[clauses[i]]))
1311
            cnt++;
1312
1313
    for (int i = 0; i < clauses.size(); i++)
1314
        if (!satisfied(ca[clauses[i]])){
1315
          Clause& clause = ca[clauses[i]];
1316
          for (int j = 0; j < clause.size(); j++)
1317
            if (value(clause[j]) != l_False) mapVar(var(clause[j]), map, max);
1318
        }
1319
1320
    // Assumptions are added as unit clauses:
1321
    cnt += assumps.size();
1322
1323
    fprintf(f, "p cnf %d %d\n", max, cnt);
1324
1325
    for (int i = 0; i < assumps.size(); i++){
1326
      Assert(value(assumps[i]) != l_False);
1327
      fprintf(f,
1328
              "%s%d 0\n",
1329
              sign(assumps[i]) ? "-" : "",
1330
              mapVar(var(assumps[i]), map, max) + 1);
1331
    }
1332
1333
    for (int i = 0; i < clauses.size(); i++)
1334
        toDimacs(f, ca[clauses[i]], map, max);
1335
1336
    if (verbosity > 0)
1337
        printf("Wrote %d clauses with %d variables.\n", cnt, max);
1338
}
1339
1340
1341
//=================================================================================================
1342
// Garbage Collection methods:
1343
1344
2
void Solver::relocAll(ClauseAllocator& to)
1345
{
1346
    // All watchers:
1347
    //
1348
    // for (int i = 0; i < watches.size(); i++)
1349
2
    watches.cleanAll();
1350
288
    for (int v = 0; v < nVars(); v++)
1351
858
        for (int s = 0; s < 2; s++){
1352
572
            Lit p = mkLit(v, s);
1353
            // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
1354
572
            vec<Watcher>& ws = watches[p];
1355
572
            for (int j = 0; j < ws.size(); j++) ca.reloc(ws[j].cref, to);
1356
        }
1357
1358
    // All reasons:
1359
    //
1360
46
    for (int i = 0; i < trail.size(); i++){
1361
44
        Var v = var(trail[i]);
1362
1363
44
        if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
1364
          ca.reloc(vardata[v].reason, to);
1365
    }
1366
1367
    // All learnt:
1368
    //
1369
2
    for (int i = 0; i < learnts.size(); i++) ca.reloc(learnts[i], to);
1370
1371
    // All original:
1372
    //
1373
2
    for (int i = 0; i < clauses.size(); i++) ca.reloc(clauses[i], to);
1374
2
}
1375
1376
1377
void Solver::garbageCollect()
1378
{
1379
    // Initialize the next region to a size corresponding to the estimated utilization degree. This
1380
    // is not precise but should avoid some unnecessary reallocations for the new region:
1381
    ClauseAllocator to(ca.size() - ca.wasted());
1382
    Debug("bvminisat") << " BVMinisat::Garbage collection \n";
1383
    relocAll(to);
1384
    if (verbosity >= 2)
1385
      printf(
1386
          "|  Garbage collection:   %12d bytes => %12d bytes             |\n",
1387
          ca.size() * ClauseAllocator::Unit_Size,
1388
          to.size() * ClauseAllocator::Unit_Size);
1389
    to.moveTo(ca);
1390
}
1391
1392
3368
void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to)
1393
{
1394
3368
  Clause& c = operator[](cr);
1395
3368
  if (c.reloced()) { cr = c.relocation(); return; }
1396
1397
548
  cr = to.alloc(c, c.learnt());
1398
548
  c.relocate(cr);
1399
1400
  // Copy extra data-fields:
1401
  // (This could be cleaned-up. Generalize Clause-constructor to be applicable
1402
  // here instead?)
1403
548
  to[cr].mark(c.mark());
1404
548
  if (to[cr].learnt())         to[cr].activity() = c.activity();
1405
548
  else if (to[cr].has_extra()) to[cr].calcAbstraction();
1406
}
1407
1408
2
void Solver::setNotify(Notify* toNotify) { d_notify = toNotify; }
1409
886
bool Solver::withinBudget(Resource r) const
1410
{
1411
886
  AlwaysAssert(d_notify);
1412
886
  d_notify->safePoint(r);
1413
1414
1772
  return !asynch_interrupt &&
1415
2658
         (conflict_budget < 0 || conflicts < conflict_budget) &&
1416
886
         (propagation_budget < 0 ||
1417
886
          propagations < propagation_budget);
1418
}
1419
1420
}  // namespace BVMinisat
1421
29452
}  // namespace cvc5