GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/minisat/core/Solver.cc Lines: 854 1025 83.3 %
Date: 2021-05-22 Branches: 1180 2808 42.0 %

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/minisat/core/Solver.h"
22
23
#include <math.h>
24
25
#include <iostream>
26
#include <unordered_set>
27
28
#include "base/check.h"
29
#include "base/output.h"
30
#include "options/main_options.h"
31
#include "options/prop_options.h"
32
#include "options/smt_options.h"
33
#include "proof/clause_id.h"
34
#include "prop/minisat/minisat.h"
35
#include "prop/minisat/mtl/Sort.h"
36
#include "prop/theory_proxy.h"
37
38
using namespace cvc5::prop;
39
40
namespace cvc5 {
41
namespace Minisat {
42
43
namespace {
44
/*
45
 * Returns true if the solver should add all clauses at the current assertion
46
 * level.
47
 *
48
 * FIXME: This is a workaround. Currently, our resolution proofs do not
49
 * handle clauses with a lower-than-assertion-level correctly because the
50
 * resolution proofs get removed when popping the context but the SAT solver
51
 * keeps using them.
52
 */
53
8983580
bool assertionLevelOnly()
54
{
55
44069851
  return (options::produceProofs() || options::unsatCores())
56
13249919
         && options::incrementalSolving();
57
}
58
59
//=================================================================================================
60
// Helper functions for decision tree tracing
61
62
// Writes to Trace macro for decision tree tracing
63
static inline void dtviewDecisionHelper(size_t level,
64
                                        const Node& node,
65
                                        const char* decisiontype)
66
{
67
  Trace("dtview") << std::string(level - (options::incrementalSolving() ? 1 : 0), '*')
68
                  << " " << node << " :" << decisiontype << "-DECISION:" << std::endl;
69
}
70
71
// Writes to Trace macro for propagation tracing
72
static inline void dtviewPropagationHeaderHelper(size_t level)
73
{
74
  Trace("dtview::prop") << std::string(level + 1 - (options::incrementalSolving() ? 1 : 0),
75
                                       '*')
76
                        << " /Propagations/" << std::endl;
77
}
78
79
// Writes to Trace macro for propagation tracing
80
static inline void dtviewBoolPropagationHelper(size_t level,
81
                                               Lit& l,
82
                                               cvc5::prop::TheoryProxy* proxy)
83
{
84
  Trace("dtview::prop") << std::string(
85
      level + 1 - (options::incrementalSolving() ? 1 : 0), ' ')
86
                        << ":BOOL-PROP: "
87
                        << proxy->getNode(MinisatSatSolver::toSatLiteral(l))
88
                        << std::endl;
89
}
90
91
// Writes to Trace macro for conflict tracing
92
static inline void dtviewPropConflictHelper(size_t level,
93
                                            Clause& confl,
94
                                            cvc5::prop::TheoryProxy* proxy)
95
{
96
  Trace("dtview::conflict")
97
      << std::string(level + 1 - (options::incrementalSolving() ? 1 : 0), ' ')
98
      << ":PROP-CONFLICT: (or";
99
  for (int i = 0; i < confl.size(); i++)
100
  {
101
    Trace("dtview::conflict")
102
        << " " << proxy->getNode(MinisatSatSolver::toSatLiteral(confl[i]));
103
  }
104
  Trace("dtview::conflict") << ")" << std::endl;
105
}
106
107
}  // namespace
108
109
//=================================================================================================
110
// Options:
111
112
static const char* _cat = "CORE";
113
114
9397
static DoubleOption  opt_var_decay         (_cat, "var-decay",   "The variable activity decay factor",            0.95,     DoubleRange(0, false, 1, false));
115
9397
static DoubleOption  opt_clause_decay      (_cat, "cla-decay",   "The clause activity decay factor",              0.999,    DoubleRange(0, false, 1, false));
116
9397
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));
117
9397
static DoubleOption  opt_random_seed       (_cat, "rnd-seed",    "Used by the random variable selection",         91648253, DoubleRange(0, false, HUGE_VAL, false));
118
9397
static IntOption     opt_ccmin_mode        (_cat, "ccmin-mode",  "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
119
9397
static IntOption     opt_phase_saving      (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
120
9397
static BoolOption    opt_rnd_init_act      (_cat, "rnd-init",    "Randomize the initial activity", false);
121
9397
static BoolOption    opt_luby_restart      (_cat, "luby",        "Use the Luby restart sequence", true);
122
9397
static IntOption     opt_restart_first     (_cat, "rfirst",      "The base restart interval", 25, IntRange(1, INT32_MAX));
123
9397
static DoubleOption  opt_restart_inc       (_cat, "rinc",        "Restart interval increase factor", 3, DoubleRange(1, false, HUGE_VAL, false));
124
9397
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));
125
126
//=================================================================================================
127
// Proof declarations
128
CRef Solver::TCRef_Undef = CRef_Undef;
129
CRef Solver::TCRef_Lazy = CRef_Lazy;
130
131
class ScopedBool
132
{
133
  bool& d_watch;
134
  bool d_oldValue;
135
136
 public:
137
2758796
  ScopedBool(bool& watch, bool newValue) : d_watch(watch), d_oldValue(watch)
138
  {
139
2758796
    watch = newValue;
140
2758796
  }
141
2758796
  ~ScopedBool() { d_watch = d_oldValue; }
142
};
143
144
//=================================================================================================
145
// Constructor/Destructor:
146
147
9494
Solver::Solver(cvc5::prop::TheoryProxy* proxy,
148
               cvc5::context::Context* context,
149
               cvc5::context::UserContext* userContext,
150
               ProofNodeManager* pnm,
151
9494
               bool enableIncremental)
152
    : d_proxy(proxy),
153
      d_context(context),
154
      assertionLevel(0),
155
      d_pfManager(nullptr),
156
      d_enable_incremental(enableIncremental),
157
      minisat_busy(false)
158
      // Parameters (user settable):
159
      //
160
      ,
161
      verbosity(0),
162
      var_decay(opt_var_decay),
163
      clause_decay(opt_clause_decay),
164
      random_var_freq(opt_random_var_freq),
165
      random_seed(opt_random_seed),
166
      luby_restart(opt_luby_restart),
167
      ccmin_mode(opt_ccmin_mode),
168
      phase_saving(opt_phase_saving),
169
      rnd_pol(false),
170
      rnd_init_act(opt_rnd_init_act),
171
      garbage_frac(opt_garbage_frac),
172
      restart_first(opt_restart_first),
173
      restart_inc(opt_restart_inc)
174
175
      // Parameters (the rest):
176
      //
177
      ,
178
      learntsize_factor(1),
179
      learntsize_inc(1.5)
180
181
      // Parameters (experimental):
182
      //
183
      ,
184
      learntsize_adjust_start_confl(100),
185
      learntsize_adjust_inc(1.5)
186
187
      // Statistics: (formerly in 'SolverStats')
188
      //
189
      ,
190
      solves(0),
191
      starts(0),
192
      decisions(0),
193
      rnd_decisions(0),
194
      propagations(0),
195
      conflicts(0),
196
      resources_consumed(0),
197
      dec_vars(0),
198
      clauses_literals(0),
199
      learnts_literals(0),
200
      max_literals(0),
201
      tot_literals(0)
202
203
      ,
204
      ok(true),
205
      cla_inc(1),
206
      var_inc(1),
207
18988
      watches(WatcherDeleted(ca)),
208
      qhead(0),
209
      simpDB_assigns(-1),
210
      simpDB_props(0),
211
18988
      order_heap(VarOrderLt(activity)),
212
      progress_estimate(0),
213
9494
      remove_satisfied(!enableIncremental)
214
215
      // Resource constraints:
216
      //
217
      ,
218
      conflict_budget(-1),
219
      propagation_budget(-1),
220
56964
      asynch_interrupt(false)
221
{
222
9494
  if (pnm)
223
  {
224
2394
    d_pfManager.reset(
225
1197
        new SatProofManager(this, proxy->getCnfStream(), userContext, pnm));
226
  }
227
228
  // Create the constant variables
229
9494
  varTrue = newVar(true, false, false);
230
9494
  varFalse = newVar(false, false, false);
231
232
  // Assert the constants
233
9494
  uncheckedEnqueue(mkLit(varTrue, false));
234
9494
  uncheckedEnqueue(mkLit(varFalse, true));
235
9494
}
236
237
238
9494
Solver::~Solver()
239
{
240
9494
}
241
242
243
//=================================================================================================
244
// Minor methods:
245
246
247
// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
248
// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
249
//
250
910129
Var Solver::newVar(bool sign, bool dvar, bool isTheoryAtom, bool preRegister, bool canErase)
251
{
252
910129
    int v = nVars();
253
254
910129
    watches  .init(mkLit(v, false));
255
910129
    watches  .init(mkLit(v, true ));
256
910129
    assigns  .push(l_Undef);
257
910129
    vardata  .push(VarData(CRef_Undef, -1, -1, assertionLevel, -1));
258
910129
    activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
259
910129
    seen     .push(0);
260
910129
    polarity .push(sign);
261
910129
    decision .push();
262
910129
    trail    .capacity(v+1);
263
    // push whether it corresponds to a theory atom
264
910129
    theory.push(isTheoryAtom);
265
266
910129
    setDecisionVar(v, dvar);
267
268
910129
    Debug("minisat") << "new var " << v << std::endl;
269
270
    // If the variable is introduced at non-zero level, we need to reintroduce it on backtracks
271
910129
    if (preRegister)
272
    {
273
1043276
      Debug("minisat") << "  To register at level " << decisionLevel()
274
521638
                       << std::endl;
275
521638
      variables_to_register.push(VarIntroInfo(v, decisionLevel()));
276
    }
277
278
910129
    return v;
279
}
280
281
4361
void Solver::resizeVars(int newSize) {
282
4361
  Assert(d_enable_incremental);
283
4361
  Assert(decisionLevel() == 0);
284
4361
  Assert(newSize >= 2) << "always keep true/false";
285
4361
  if (newSize < nVars()) {
286
2633
    int shrinkSize = nVars() - newSize;
287
288
    // Resize watches up to the negated last literal
289
2633
    watches.resizeTo(mkLit(newSize-1, true));
290
291
    // Resize all info arrays
292
2633
    assigns.shrink(shrinkSize);
293
2633
    vardata.shrink(shrinkSize);
294
2633
    activity.shrink(shrinkSize);
295
2633
    seen.shrink(shrinkSize);
296
2633
    polarity.shrink(shrinkSize);
297
2633
    decision.shrink(shrinkSize);
298
2633
    theory.shrink(shrinkSize);
299
  }
300
301
4361
  if (Debug.isOn("minisat::pop")) {
302
    for (int i = 0; i < trail.size(); ++ i) {
303
      Assert(var(trail[i]) < nVars());
304
    }
305
  }
306
4361
}
307
308
128909456
CRef Solver::reason(Var x) {
309
128909456
  Trace("pf::sat") << "Solver::reason(" << x << ")" << std::endl;
310
311
  // If we already have a reason, just return it
312
128909456
  if (vardata[x].d_reason != CRef_Lazy)
313
  {
314
128855880
    if (Trace.isOn("pf::sat"))
315
    {
316
      Trace("pf::sat") << "  Solver::reason: " << vardata[x].d_reason << ", ";
317
      if (vardata[x].d_reason == CRef_Undef)
318
      {
319
        Trace("pf::sat") << "CRef_Undef";
320
      }
321
      else
322
      {
323
        for (unsigned i = 0, size = ca[vardata[x].d_reason].size(); i < size;
324
             ++i)
325
        {
326
          Trace("pf::sat") << ca[vardata[x].d_reason][i] << " ";
327
        }
328
      }
329
      Trace("pf::sat") << "\n";
330
    }
331
128855880
    return vardata[x].d_reason;
332
  }
333
  // What's the literal we are trying to explain
334
53576
  Lit l = mkLit(x, value(x) != l_True);
335
336
  // Get the explanation from the theory
337
107152
  SatClause explanation_cl;
338
  // FIXME: at some point return a tag with the theory that spawned you
339
53576
  d_proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l),
340
                              explanation_cl);
341
107152
  vec<Lit> explanation;
342
53576
  MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
343
344
107152
  Trace("pf::sat") << "Solver::reason: explanation_cl = " << explanation_cl
345
53576
                   << std::endl;
346
347
  // Sort the literals by trail index level
348
53576
  lemma_lt lt(*this);
349
53576
  sort(explanation, lt);
350
53576
  Assert(explanation[0] == l);
351
352
  // Compute the assertion level for this clause
353
53576
  int explLevel = 0;
354
53576
  if (assertionLevelOnly())
355
  {
356
1857
    explLevel = assertionLevel;
357
    }
358
    else
359
    {
360
      int i, j;
361
51719
      Lit prev = lit_Undef;
362
366542
      for (i = 0, j = 0; i < explanation.size(); ++i)
363
      {
364
        // This clause is valid theory propagation, so its level is the level of
365
        // the top literal
366
314823
        explLevel = std::max(explLevel, intro_level(var(explanation[i])));
367
368
314823
        Assert(value(explanation[i]) != l_Undef);
369
314823
        Assert(i == 0
370
               || trail_index(var(explanation[0]))
371
                      > trail_index(var(explanation[i])));
372
373
        // Always keep the first literal
374
366542
        if (i == 0)
375
        {
376
51719
          prev = explanation[j++] = explanation[i];
377
51719
          continue;
378
        }
379
        // Ignore duplicate literals
380
263104
        if (explanation[i] == prev)
381
        {
382
          continue;
383
        }
384
        // Ignore zero level literals
385
526208
        if (level(var(explanation[i])) == 0
386
263104
            && user_level(var(explanation[i]) == 0))
387
        {
388
          continue;
389
        }
390
        // Keep this literal
391
263104
        prev = explanation[j++] = explanation[i];
392
      }
393
51719
      explanation.shrink(i - j);
394
395
51719
      Trace("pf::sat") << "Solver::reason: explanation = ";
396
366542
      for (int k = 0; k < explanation.size(); ++k)
397
      {
398
314823
        Trace("pf::sat") << explanation[k] << " ";
399
      }
400
51719
      Trace("pf::sat") << std::endl;
401
402
      // We need an explanation clause so we add a fake literal
403
51719
      if (j == 1)
404
      {
405
        // Add not TRUE to the clause
406
        explanation.push(mkLit(varTrue, true));
407
      }
408
    }
409
410
    // Construct the reason
411
53576
    CRef real_reason = ca.alloc(explLevel, explanation, true);
412
53576
    vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
413
53576
    clauses_removable.push(real_reason);
414
53576
    attachClause(real_reason);
415
416
53576
    return real_reason;
417
}
418
419
2569153
bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
420
{
421
2569153
    if (!ok) return false;
422
423
    // Check if clause is satisfied and remove false/duplicate literals:
424
2569153
    sort(ps);
425
    Lit p; int i, j;
426
427
    // Which user-level to assert this clause at
428
2569153
    int clauseLevel = (removable && !assertionLevelOnly()) ? 0 : assertionLevel;
429
430
    // Check the clause for tautologies and similar
431
2569153
    int falseLiteralsCount = 0;
432
10654477
    for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
433
      // Update the level
434
16549454
      clauseLevel = assertionLevelOnly()
435
15927102
                        ? assertionLevel
436
15927102
                        : std::max(clauseLevel, intro_level(var(ps[i])));
437
      // Tautologies are ignored
438
8274727
      if (ps[i] == ~p) {
439
40533
        id = ClauseIdUndef;
440
        // Clause can be ignored
441
40533
        return true;
442
      }
443
      // Clauses with 0-level true literals are also ignored
444
8234194
      if (value(ps[i]) == l_True && level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
445
148870
        id = ClauseIdUndef;
446
148870
        return true;
447
      }
448
      // Ignore repeated literals
449
8085324
      if (ps[i] == p) {
450
4310
        continue;
451
      }
452
      // If a literal is false at 0 level (both sat and user level) we also
453
      // ignore it, unless we are tracking the SAT solver's reasoning
454
8081014
      if (value(ps[i]) == l_False) {
455
6792257
        if (!options::unsatCores() && !needProof() && level(var(ps[i])) == 0
456
3380265
            && user_level(var(ps[i])) == 0)
457
        {
458
719494
          continue;
459
        }
460
        else
461
        {
462
          // If we decide to keep it, we count it into the false literals
463
1922555
          falseLiteralsCount++;
464
        }
465
      }
466
      // This literal is a keeper
467
7361520
      ps[j++] = p = ps[i];
468
    }
469
470
    // Fit to size
471
2379750
    ps.shrink(i - j);
472
473
    // If we are in solve_ or propagate
474
2379750
    if (minisat_busy)
475
    {
476
733492
      Trace("pf::sat") << "Add clause adding a new lemma: ";
477
3665752
      for (int k = 0; k < ps.size(); ++k) {
478
2932260
        Trace("pf::sat") << ps[k] << " ";
479
      }
480
733492
      Trace("pf::sat") << std::endl;
481
482
733492
      lemmas.push();
483
733492
      ps.copyTo(lemmas.last());
484
733492
      lemmas_removable.push(removable);
485
    } else {
486
1646258
      Assert(decisionLevel() == 0);
487
488
      // If all false, we're in conflict
489
1646258
      if (ps.size() == falseLiteralsCount) {
490
1278
        if (options::unsatCores() || needProof())
491
        {
492
          // Take care of false units here; otherwise, we need to
493
          // construct the clause below to give to the proof manager
494
          // as the final conflict.
495
461
          if(falseLiteralsCount == 1) {
496
443
            if (needProof())
497
            {
498
443
              d_pfManager->finalizeProof(ps[0], true);
499
            }
500
82444
            return ok = false;
501
          }
502
        }
503
        else
504
        {
505
817
          return ok = false;
506
        }
507
      }
508
509
1644998
      CRef cr = CRef_Undef;
510
511
      // If not unit, add the clause
512
1644998
      if (ps.size() > 1) {
513
514
1567929
        lemma_lt lt(*this);
515
1567929
        sort(ps, lt);
516
517
1567929
        cr = ca.alloc(clauseLevel, ps, false);
518
1567929
        clauses_persistent.push(cr);
519
1567929
        attachClause(cr);
520
521
1567929
        if (options::unsatCores() || needProof())
522
        {
523
833581
          if (ps.size() == falseLiteralsCount)
524
          {
525
18
            if (needProof())
526
            {
527
18
              d_pfManager->finalizeProof(ca[cr], true);
528
            }
529
18
            return ok = false;
530
          }
531
        }
532
      }
533
534
      // Check if it propagates
535
1644980
      if (ps.size() == falseLiteralsCount + 1) {
536
80723
        if(assigns[var(ps[0])] == l_Undef) {
537
78800
          Assert(assigns[var(ps[0])] != l_False);
538
78800
          uncheckedEnqueue(ps[0], cr);
539
157600
          Debug("cores") << "i'm registering a unit clause, maybe input"
540
78800
                         << std::endl;
541
78800
          if (ps.size() == 1)
542
          {
543
            // We need to do this so that the closedness check, if being done,
544
            // goes through when we have unit assumptions whose literal has
545
            // already been registered, as the ProofCnfStream will not register
546
            // them and as they are not the result of propagation will be left
547
            // hanging in assumptions accumulator
548
75963
            if (needProof())
549
            {
550
23916
              d_pfManager->registerSatLitAssumption(ps[0]);
551
            }
552
          }
553
78800
          CRef confl = propagate(CHECK_WITHOUT_THEORY);
554
78800
          if(! (ok = (confl == CRef_Undef)) ) {
555
38
            if (needProof())
556
            {
557
13
              if (ca[confl].size() == 1)
558
              {
559
                d_pfManager->finalizeProof(ca[confl][0]);
560
              }
561
              else
562
              {
563
13
                d_pfManager->finalizeProof(ca[confl]);
564
              }
565
            }
566
          }
567
78800
          return ok;
568
        } else {
569
1923
          return ok;
570
        }
571
      }
572
    }
573
574
2297749
    return true;
575
}
576
577
578
2677207
void Solver::attachClause(CRef cr) {
579
2677207
    const Clause& c = ca[cr];
580
2677207
    if (Debug.isOn("minisat"))
581
    {
582
      Debug("minisat") << "Solver::attachClause(" << c << "): ";
583
      for (unsigned i = 0, size = c.size(); i < size; ++i)
584
      {
585
        Debug("minisat") << c[i] << " ";
586
      }
587
      Debug("minisat") << ", level " << c.level() << "\n";
588
    }
589
2677207
    Assert(c.size() > 1);
590
2677207
    watches[~c[0]].push(Watcher(cr, c[1]));
591
2677207
    watches[~c[1]].push(Watcher(cr, c[0]));
592
2677207
    if (c.removable()) learnts_literals += c.size();
593
2152848
    else            clauses_literals += c.size();
594
2677207
}
595
596
597
825137
void Solver::detachClause(CRef cr, bool strict) {
598
825137
    const Clause& c = ca[cr];
599
825137
    Debug("minisat") << "Solver::detachClause(" << c << ")" << std::endl;
600
825137
    if (Debug.isOn("minisat"))
601
    {
602
      Debug("minisat") << "Solver::detachClause(" << c << "), CRef " << cr
603
                       << ", clause ";
604
      for (unsigned i = 0, size = c.size(); i < size; ++i)
605
      {
606
        Debug("minisat") << c[i] << " ";
607
      }
608
609
      Debug("minisat") << "\n";
610
    }
611
825137
    Assert(c.size() > 1);
612
613
825137
    if (strict){
614
89117
        remove(watches[~c[0]], Watcher(cr, c[1]));
615
89117
        remove(watches[~c[1]], Watcher(cr, c[0]));
616
    }else{
617
        // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
618
736020
        watches.smudge(~c[0]);
619
736020
        watches.smudge(~c[1]);
620
    }
621
622
825137
    if (c.removable()) learnts_literals -= c.size();
623
587201
    else            clauses_literals -= c.size(); }
624
625
626
736020
void Solver::removeClause(CRef cr) {
627
736020
    Clause& c = ca[cr];
628
736020
    if (Debug.isOn("minisat"))
629
    {
630
      Debug("minisat") << "Solver::removeClause(" << c << "), CRef " << cr
631
                       << ", clause ";
632
      for (unsigned i = 0, size = c.size(); i < size; ++i)
633
      {
634
        Debug("minisat") << c[i] << " ";
635
      }
636
      Debug("minisat") << "\n";
637
    }
638
736020
    detachClause(cr);
639
    // Don't leave pointers to free'd memory!
640
736020
    if (locked(c))
641
    {
642
      // a locked clause c is one whose first literal c[0] is true and is
643
      // propagated by c itself, i.e. vardata[var(c[0])].d_reason == c. Because
644
      // of this if we need to justify the propagation of c[0], via
645
      // Solver::reason, if it appears in a resolution chain built lazily we
646
      // will be unable to do so after the step below. Thus we eagerly justify
647
      // this propagation here.
648
10348
      if (needProof())
649
      {
650
1928
        Trace("pf::sat")
651
964
            << "Solver::removeClause: eagerly compute propagation of " << c[0]
652
964
            << "\n";
653
964
        d_pfManager->startResChain(c);
654
3515
        for (unsigned i = 1, size = c.size(); i < size; ++i)
655
        {
656
2551
          d_pfManager->addResolutionStep(c[i]);
657
        }
658
964
        d_pfManager->endResChain(c[0]);
659
      }
660
10348
      vardata[var(c[0])].d_reason = CRef_Undef;
661
    }
662
736020
    c.mark(1);
663
736020
    ca.free(cr);
664
736020
}
665
666
667
442205
bool Solver::satisfied(const Clause& c) const {
668
21427829
    for (int i = 0; i < c.size(); i++)
669
21035070
        if (value(c[i]) == l_True)
670
49446
            return true;
671
392759
    return false; }
672
673
674
// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
675
//
676
545417
void Solver::cancelUntil(int level) {
677
545417
    Debug("minisat") << "minisat::cancelUntil(" << level << ")" << std::endl;
678
679
545417
    if (decisionLevel() > level){
680
        // Pop the SMT context
681
2658098
        for (int l = trail_lim.size() - level; l > 0; --l) {
682
2224250
          d_context->pop();
683
        }
684
54596196
        for (int c = trail.size()-1; c >= trail_lim[level]; c--){
685
54162348
            Var      x  = var(trail[c]);
686
54162348
            assigns [x] = l_Undef;
687
54162348
            vardata[x].d_trail_index = -1;
688
108324696
            if ((phase_saving > 1 ||
689
                 ((phase_saving == 1) && c > trail_lim.last())
690
108324696
                 ) && ((polarity[x] & 0x2) == 0)) {
691
53649054
              polarity[x] = sign(trail[c]);
692
            }
693
54162348
            insertVarOrder(x);
694
        }
695
433848
        qhead = trail_lim[level];
696
433848
        trail.shrink(trail.size() - trail_lim[level]);
697
433848
        trail_lim.shrink(trail_lim.size() - level);
698
433848
        flipped.shrink(flipped.size() - level);
699
700
        // Register variables that have not been registered yet
701
433848
        int currentLevel = decisionLevel();
702
782517
        for (int i = variables_to_register.size() - 1;
703
782517
             i >= 0 && variables_to_register[i].d_level > currentLevel;
704
             --i)
705
        {
706
348669
          variables_to_register[i].d_level = currentLevel;
707
697338
          d_proxy->variableNotify(
708
348669
              MinisatSatSolver::toSatVariable(variables_to_register[i].d_var));
709
        }
710
    }
711
545417
}
712
713
14294
void Solver::resetTrail() { cancelUntil(0); }
714
715
//=================================================================================================
716
// Major methods:
717
718
719
2001521
Lit Solver::pickBranchLit()
720
{
721
    Lit nextLit;
722
723
    // Theory requests
724
2001519
    nextLit =
725
2001521
        MinisatSatSolver::toMinisatLit(d_proxy->getNextTheoryDecisionRequest());
726
2019711
    while (nextLit != lit_Undef) {
727
48067
      if(value(var(nextLit)) == l_Undef) {
728
77942
        Debug("theoryDecision")
729
38971
            << "getNextTheoryDecisionRequest(): now deciding on " << nextLit
730
38971
            << std::endl;
731
38971
        decisions++;
732
733
        // org-mode tracing -- theory decision
734
38971
        if (Trace.isOn("dtview"))
735
        {
736
          dtviewDecisionHelper(
737
              d_context->getLevel(),
738
              d_proxy->getNode(MinisatSatSolver::toSatLiteral(nextLit)),
739
              "THEORY");
740
        }
741
742
38971
        if (Trace.isOn("dtview::prop"))
743
        {
744
          dtviewPropagationHeaderHelper(d_context->getLevel());
745
        }
746
747
38971
        return nextLit;
748
      } else {
749
18192
        Debug("theoryDecision")
750
9096
            << "getNextTheoryDecisionRequest(): would decide on " << nextLit
751
9096
            << " but it already has an assignment" << std::endl;
752
      }
753
9096
      nextLit = MinisatSatSolver::toMinisatLit(
754
9096
          d_proxy->getNextTheoryDecisionRequest());
755
    }
756
3925096
    Debug("theoryDecision")
757
1962548
        << "getNextTheoryDecisionRequest(): decide on another literal"
758
1962548
        << std::endl;
759
760
    // DE requests
761
1962548
    bool stopSearch = false;
762
1962548
    nextLit = MinisatSatSolver::toMinisatLit(
763
1962548
        d_proxy->getNextDecisionEngineRequest(stopSearch));
764
1962548
    if(stopSearch) {
765
41528
      return lit_Undef;
766
    }
767
1921020
    if(nextLit != lit_Undef) {
768
597954
      Assert(value(var(nextLit)) == l_Undef)
769
          << "literal to decide already has value";
770
597954
      decisions++;
771
597954
      Var next = var(nextLit);
772
597954
      if(polarity[next] & 0x2) {
773
136221
        nextLit = mkLit(next, polarity[next] & 0x1);
774
      }
775
776
      // org-mode tracing -- decision engine decision
777
597954
      if (Trace.isOn("dtview"))
778
      {
779
        dtviewDecisionHelper(
780
            d_context->getLevel(),
781
            d_proxy->getNode(MinisatSatSolver::toSatLiteral(nextLit)),
782
            "DE");
783
      }
784
785
597954
      if (Trace.isOn("dtview::prop"))
786
      {
787
        dtviewPropagationHeaderHelper(d_context->getLevel());
788
      }
789
790
597954
      return nextLit;
791
    }
792
793
1323066
    Var next = var_Undef;
794
795
    // Random decision:
796
1323066
    if (drand(random_seed) < random_var_freq && !order_heap.empty()){
797
        next = order_heap[irand(random_seed,order_heap.size())];
798
        if (value(next) == l_Undef && decision[next])
799
            rnd_decisions++; }
800
801
    // Activity based decision:
802
10085900
    while (next >= nVars() || next == var_Undef || value(next) != l_Undef || !decision[next]) {
803
4397311
        if (order_heap.empty()){
804
15894
            next = var_Undef;
805
15894
            break;
806
        }else {
807
4381417
            next = order_heap.removeMin();
808
        }
809
810
4381417
        if(!decision[next]) continue;
811
        // Check with decision engine about relevancy
812
8737532
        if (d_proxy->isDecisionRelevant(MinisatSatSolver::toSatVariable(next))
813
4368766
            == false)
814
        {
815
          next = var_Undef;
816
        }
817
    }
818
819
1323066
    if(next == var_Undef) {
820
15894
      return lit_Undef;
821
    } else {
822
1307172
      decisions++;
823
      // Check with decision engine if it can tell polarity
824
      lbool dec_pol = MinisatSatSolver::toMinisatlbool(
825
1307172
          d_proxy->getDecisionPolarity(MinisatSatSolver::toSatVariable(next)));
826
      Lit decisionLit;
827
1307172
      if(dec_pol != l_Undef) {
828
        Assert(dec_pol == l_True || dec_pol == l_False);
829
        decisionLit = mkLit(next, (dec_pol == l_True));
830
      }
831
      else
832
      {
833
        // If it can't use internal heuristic to do that
834
1307172
        decisionLit = mkLit(
835
1307172
            next, rnd_pol ? drand(random_seed) < 0.5 : (polarity[next] & 0x1));
836
      }
837
838
      // org-mode tracing -- decision engine decision
839
1307172
      if (Trace.isOn("dtview"))
840
      {
841
        dtviewDecisionHelper(
842
            d_context->getLevel(),
843
            d_proxy->getNode(MinisatSatSolver::toSatLiteral(decisionLit)),
844
            "DE");
845
      }
846
847
1307172
      if (Trace.isOn("dtview::prop"))
848
      {
849
        dtviewPropagationHeaderHelper(d_context->getLevel());
850
      }
851
852
1307172
      return decisionLit;
853
    }
854
}
855
856
857
/*_________________________________________________________________________________________________
858
|
859
|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->  [void]
860
|
861
|  Description:
862
|    Analyze conflict and produce a reason clause.
863
|
864
|    Pre-conditions:
865
|      * 'out_learnt' is assumed to be cleared.
866
|      * Current decision level must be greater than root level.
867
|
868
|    Post-conditions:
869
|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
870
|      * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
871
|        rest of literals. There may be others from the same level though.
872
|      * returns the maximal level of the resolved clauses
873
|
874
|________________________________________________________________________________________________@*/
875
296839
int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
876
{
877
593678
  Trace("pf::sat") << "Solver::analyze: starting with " << confl
878
296839
                   << " with decision level " << decisionLevel() << "\n";
879
880
296839
  int pathC = 0;
881
296839
  Lit p = lit_Undef;
882
883
  // Generate conflict clause:
884
  //
885
296839
  out_learnt.push();  // (leave room for the asserting literal)
886
296839
  int index = trail.size() - 1;
887
888
296839
  int max_resolution_level = 0;  // Maximal level of the resolved clauses
889
890
296839
    if (needProof())
891
    {
892
31910
      d_pfManager->startResChain(ca[confl]);
893
    }
894
8006768
    do{
895
8303607
      Assert(confl != CRef_Undef);  // (otherwise should be UIP)
896
897
      {
898
        // ! IMPORTANT !
899
        // It is not safe to use c after this block of code because
900
        // resolveOutUnit() below may lead to clauses being allocated, which
901
        // in turn may lead to reallocations that invalidate c.
902
8303607
        Clause& c = ca[confl];
903
8303607
        max_resolution_level = std::max(max_resolution_level, c.level());
904
905
8303607
        if (c.removable()) claBumpActivity(c);
906
      }
907
908
8303607
        if (Trace.isOn("pf::sat"))
909
        {
910
          Trace("pf::sat") << "Solver::analyze: conflict clause ";
911
          for (unsigned i = 0, size = ca[confl].size(); i < size; ++i)
912
          {
913
            Trace("pf::sat") << ca[confl][i] << " ";
914
          }
915
          Trace("pf::sat") << "\n";
916
        }
917
918
8303607
        Trace("pf::sat") << cvc5::push;
919
70837757
        for (int j = (p == lit_Undef) ? 0 : 1, size = ca[confl].size();
920
70837757
             j < size;
921
             j++)
922
        {
923
62534150
          Lit q = ca[confl][j];
924
925
125068300
          Trace("pf::sat") << "Lit " << q
926
125068300
                           << " seen/level: " << (seen[var(q)] ? 1 : 0) << " / "
927
62534150
                           << level(var(q)) << "\n";
928
62534150
          if (!seen[var(q)] && level(var(q)) > 0)
929
          {
930
33012008
            varBumpActivity(var(q));
931
33012008
            seen[var(q)] = 1;
932
33012008
            if (level(var(q)) >= decisionLevel())
933
8303607
              pathC++;
934
            else
935
24708401
              out_learnt.push(q);
936
          }
937
          else
938
          {
939
            // We could be resolving a literal propagated by a clause/theory
940
            // using information from a higher level
941
29522142
            if (!seen[var(q)] && level(var(q)) == 0)
942
            {
943
377502
              max_resolution_level =
944
755004
                  std::max(max_resolution_level, user_level(var(q)));
945
            }
946
947
            // FIXME: can we do it lazily if we actually need the proof?
948
29522142
            if (level(var(q)) == 0 && needProof())
949
            {
950
143321
              d_pfManager->addResolutionStep(q);
951
            }
952
          }
953
        }
954
8303607
        Trace("pf::sat") << cvc5::pop;
955
956
        // Select next clause to look at:
957
40981359
        while (!seen[var(trail[index--])]);
958
8303607
        p     = trail[index+1];
959
8303607
        confl = reason(var(p));
960
8303607
        seen[var(p)] = 0;
961
8303607
        pathC--;
962
963
8303607
        if (pathC > 0 && confl != CRef_Undef && needProof())
964
        {
965
489352
          d_pfManager->addResolutionStep(ca[confl], p);
966
        }
967
968
8303607
    } while (pathC > 0);
969
296839
    out_learnt[0] = ~p;
970
296839
    if (Debug.isOn("newproof::sat"))
971
    {
972
      Debug("newproof::sat") << "finished with learnt clause ";
973
      for (unsigned i = 0, size = out_learnt.size(); i < size; ++i)
974
      {
975
        prop::SatLiteral satLit = toSatLiteral<Minisat::Solver>(out_learnt[i]);
976
        Debug("newproof::sat") << satLit << " ";
977
      }
978
      Debug("newproof::sat") << "\n";
979
    }
980
981
    // Simplify conflict clause:
982
    int i, j;
983
296839
    out_learnt.copyTo(analyze_toclear);
984
296839
    if (ccmin_mode == 2){
985
296839
        uint32_t abstract_level = 0;
986
25005240
        for (i = 1; i < out_learnt.size(); i++)
987
24708401
            abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
988
989
25005240
        for (i = j = 1; i < out_learnt.size(); i++) {
990
24708401
            if (reason(var(out_learnt[i])) == CRef_Undef) {
991
4643204
                out_learnt[j++] = out_learnt[i];
992
            } else {
993
              // Check if the literal is redundant
994
20065197
              if (!litRedundant(out_learnt[i], abstract_level)) {
995
                // Literal is not redundant
996
17659013
                out_learnt[j++] = out_learnt[i];
997
              } else {
998
2406184
                if (needProof())
999
                {
1000
123380
                  Debug("newproof::sat")
1001
61690
                      << "Solver::analyze: redundant lit "
1002
61690
                      << toSatLiteral<Minisat::Solver>(out_learnt[i]) << "\n";
1003
61690
                  d_pfManager->addResolutionStep(out_learnt[i], true);
1004
                }
1005
                // Literal is redundant, to be safe, mark the level as current assertion level
1006
                // TODO: maybe optimize
1007
2406184
                max_resolution_level = std::max(max_resolution_level, user_level(var(out_learnt[i])));
1008
              }
1009
            }
1010
        }
1011
1012
    }else if (ccmin_mode == 1){
1013
        Unreachable();
1014
        for (i = j = 1; i < out_learnt.size(); i++){
1015
            Var x = var(out_learnt[i]);
1016
1017
            if (reason(x) == CRef_Undef)
1018
                out_learnt[j++] = out_learnt[i];
1019
            else{
1020
                Clause& c = ca[reason(var(out_learnt[i]))];
1021
                for (int k = 1; k < c.size(); k++)
1022
                    if (!seen[var(c[k])] && level(var(c[k])) > 0){
1023
                        out_learnt[j++] = out_learnt[i];
1024
                        break; }
1025
            }
1026
        }
1027
    }else
1028
        i = j = out_learnt.size();
1029
1030
296839
    max_literals += out_learnt.size();
1031
296839
    out_learnt.shrink(i - j);
1032
296839
    tot_literals += out_learnt.size();
1033
1034
    // Find correct backtrack level:
1035
    //
1036
296839
    if (out_learnt.size() == 1)
1037
5537
        out_btlevel = 0;
1038
    else{
1039
291302
        int max_i = 1;
1040
        // Find the first literal assigned at the next-highest level:
1041
22302217
        for (int k = 2; k < out_learnt.size(); k++)
1042
22010915
          if (level(var(out_learnt[k])) > level(var(out_learnt[max_i])))
1043
551692
            max_i = k;
1044
        // Swap-in this literal at index 1:
1045
291302
        Lit p2 = out_learnt[max_i];
1046
291302
        out_learnt[max_i] = out_learnt[1];
1047
291302
        out_learnt[1] = p2;
1048
291302
        out_btlevel = level(var(p2));
1049
    }
1050
1051
27810980
    for (int k = 0; k < analyze_toclear.size(); k++)
1052
27514141
      seen[var(analyze_toclear[k])] = 0;  // ('seen[]' is now cleared)
1053
1054
    // Return the maximal resolution level
1055
296839
    return max_resolution_level;
1056
}
1057
1058
1059
// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
1060
// visiting literals at levels that cannot be removed later.
1061
20065197
bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
1062
{
1063
20065197
    analyze_stack.clear(); analyze_stack.push(p);
1064
20065197
    int top = analyze_toclear.size();
1065
49216769
    while (analyze_stack.size() > 0){
1066
32234799
        CRef c_reason = reason(var(analyze_stack.last()));
1067
32234799
        Assert(c_reason != CRef_Undef);
1068
32234799
        Clause& c = ca[c_reason];
1069
32234799
        int c_size = c.size();
1070
32234799
        analyze_stack.pop();
1071
1072
        // Since calling reason might relocate to resize, c is not necesserily the right reference, we must
1073
        // use the allocator each time
1074
137537481
        for (int i = 1; i < c_size; i++){
1075
122961695
          Lit p2 = ca[c_reason][i];
1076
122961695
          if (!seen[var(p2)] && level(var(p2)) > 0)
1077
          {
1078
126751050
            if (reason(var(p2)) != CRef_Undef
1079
63375525
                && (abstractLevel(var(p2)) & abstract_levels) != 0)
1080
            {
1081
45716512
              seen[var(p2)] = 1;
1082
45716512
              analyze_stack.push(p2);
1083
45716512
              analyze_toclear.push(p2);
1084
            }
1085
            else
1086
            {
1087
60866624
              for (int j = top; j < analyze_toclear.size(); j++)
1088
43207611
                seen[var(analyze_toclear[j])] = 0;
1089
17659013
              analyze_toclear.shrink(analyze_toclear.size() - top);
1090
17659013
              return false;
1091
            }
1092
          }
1093
        }
1094
    }
1095
1096
2406184
    return true;
1097
}
1098
1099
1100
/*_________________________________________________________________________________________________
1101
|
1102
|  analyzeFinal : (p : Lit)  ->  [void]
1103
|
1104
|  Description:
1105
|    Specialized analysis procedure to express the final conflict in terms of assumptions.
1106
|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
1107
|    stores the result in 'out_conflict'.
1108
|________________________________________________________________________________________________@*/
1109
2617
void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
1110
{
1111
2617
    out_conflict.clear();
1112
2617
    out_conflict.push(p);
1113
1114
2617
    if (decisionLevel() == 0)
1115
878
        return;
1116
1117
1739
    seen[var(p)] = 1;
1118
1119
105725
    for (int i = trail.size()-1; i >= trail_lim[0]; i--){
1120
103986
        Var x = var(trail[i]);
1121
103986
        if (seen[x]){
1122
24784
            if (reason(x) == CRef_Undef){
1123
10470
              Assert(level(x) > 0);
1124
10470
              out_conflict.push(~trail[i]);
1125
            }else{
1126
14314
                Clause& c = ca[reason(x)];
1127
47703
                for (int j = 1; j < c.size(); j++)
1128
33389
                    if (level(var(c[j])) > 0)
1129
32586
                        seen[var(c[j])] = 1;
1130
            }
1131
24784
            seen[x] = 0;
1132
        }
1133
    }
1134
1135
1739
    seen[var(p)] = 0;
1136
}
1137
1138
54463763
void Solver::uncheckedEnqueue(Lit p, CRef from)
1139
{
1140
54463763
  if (Debug.isOn("minisat"))
1141
  {
1142
    Debug("minisat") << "unchecked enqueue of " << p << " ("
1143
                     << trail_index(var(p)) << ") trail size is "
1144
                     << trail.size() << " cap is " << trail.capacity()
1145
                     << ", reason is " << from << ", ";
1146
    if (from == CRef_Lazy)
1147
    {
1148
      Debug("minisat") << "CRef_Lazy";
1149
    }
1150
    else if (from == CRef_Undef)
1151
    {
1152
      Debug("minisat") << "CRef_Undef";
1153
    }
1154
    else
1155
    {
1156
      for (unsigned i = 0, size = ca[from].size(); i < size; ++i)
1157
      {
1158
        Debug("minisat") << ca[from][i] << " ";
1159
      }
1160
    }
1161
    Debug("minisat") << "\n";
1162
  }
1163
54463763
  Assert(value(p) == l_Undef);
1164
54463763
  Assert(var(p) < nVars());
1165
54463763
  assigns[var(p)] = lbool(!sign(p));
1166
54463763
  vardata[var(p)] = VarData(
1167
      from, decisionLevel(), assertionLevel, intro_level(var(p)), trail.size());
1168
54463763
  trail.push_(p);
1169
54463763
  if (theory[var(p)])
1170
  {
1171
    // Enqueue to the theory
1172
14281088
    d_proxy->enqueueTheoryLiteral(MinisatSatSolver::toSatLiteral(p));
1173
  }
1174
54463763
}
1175
1176
2744724
CRef Solver::propagate(TheoryCheckType type)
1177
{
1178
2744724
    CRef confl = CRef_Undef;
1179
2744724
    recheck = false;
1180
2744724
    theoryConflict = false;
1181
1182
5489448
    ScopedBool scoped_bool(minisat_busy, true);
1183
1184
    // Add lemmas that we're left behind
1185
2744724
    if (lemmas.size() > 0) {
1186
44
      confl = updateLemmas();
1187
44
      if (confl != CRef_Undef) {
1188
        return confl;
1189
      }
1190
    }
1191
1192
    // If this is the final check, no need for Boolean propagation and
1193
    // theory propagation
1194
2744724
    if (type == CHECK_FINAL) {
1195
      // Do the theory check
1196
61722
      theoryCheck(cvc5::theory::Theory::EFFORT_FULL);
1197
      // Pick up the theory propagated literals (there could be some,
1198
      // if new lemmas are added)
1199
61711
      propagateTheory();
1200
      // If there are lemmas (or conflicts) update them
1201
61711
      if (lemmas.size() > 0) {
1202
41747
        recheck = true;
1203
41747
        confl = updateLemmas();
1204
41747
        return confl;
1205
      } else {
1206
19964
        recheck = d_proxy->theoryNeedCheck();
1207
19964
        return confl;
1208
      }
1209
    }
1210
1211
    // Keep running until we have checked everything, we
1212
    // have no conflict and no new literals have been asserted
1213
702866
    do {
1214
        // Propagate on the clauses
1215
3385868
        confl = propagateBool();
1216
        // If no conflict, do the theory check
1217
3385868
        if (confl == CRef_Undef && type != CHECK_WITHOUT_THEORY) {
1218
            // Do the theory check
1219
3014036
            if (type == CHECK_FINAL_FAKE) {
1220
              theoryCheck(cvc5::theory::Theory::EFFORT_FULL);
1221
            } else {
1222
3014036
              theoryCheck(cvc5::theory::Theory::EFFORT_STANDARD);
1223
            }
1224
            // Pick up the theory propagated literals
1225
3014033
            propagateTheory();
1226
            // If there are lemmas (or conflicts) update them
1227
6028066
            if (lemmas.size() > 0) {
1228
189906
              confl = updateLemmas();
1229
            }
1230
        } else {
1231
          // if dumping decision tree, print the conflict
1232
371832
          if (Trace.isOn("dtview::conflict"))
1233
          {
1234
            if (confl != CRef_Undef)
1235
            {
1236
              dtviewPropConflictHelper(decisionLevel(), ca[confl], d_proxy);
1237
            }
1238
          }
1239
          // Even though in conflict, we still need to discharge the lemmas
1240
371832
          if (lemmas.size() > 0) {
1241
            // Remember the trail size
1242
            int oldLevel = decisionLevel();
1243
            // Update the lemmas
1244
            CRef lemmaConflict = updateLemmas();
1245
            // If we get a conflict, we prefer it since it's earlier in the trail
1246
            if (lemmaConflict != CRef_Undef) {
1247
              // Lemma conflict takes precedence, since it's earlier in the trail
1248
              confl = lemmaConflict;
1249
            } else {
1250
              // Otherwise, the Boolean conflict is canceled in the case we popped the trail
1251
              if (oldLevel > decisionLevel()) {
1252
                confl = CRef_Undef;
1253
              }
1254
            }
1255
          }
1256
        }
1257
3385865
    } while (confl == CRef_Undef && qhead < trail.size());
1258
2682999
    return confl;
1259
}
1260
1261
3075744
void Solver::propagateTheory() {
1262
6151488
  SatClause propagatedLiteralsClause;
1263
  // Doesn't actually call propagate(); that's done in theoryCheck() now that combination
1264
  // is online.  This just incorporates those propagations previously discovered.
1265
3075744
  d_proxy->theoryPropagate(propagatedLiteralsClause);
1266
1267
6151488
  vec<Lit> propagatedLiterals;
1268
3075744
  MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals);
1269
1270
3075744
  int oldTrailSize = trail.size();
1271
3075744
  Debug("minisat") << "old trail size is " << oldTrailSize << ", propagating " << propagatedLiterals.size() << " lits..." << std::endl;
1272
9447136
  for (unsigned i = 0, i_end = propagatedLiterals.size(); i < i_end; ++ i) {
1273
6371392
    Debug("minisat") << "Theory propagated: " << propagatedLiterals[i] << std::endl;
1274
    // multiple theories can propagate the same literal
1275
6371392
    Lit p = propagatedLiterals[i];
1276
6371392
    if (value(p) == l_Undef) {
1277
3350552
      uncheckedEnqueue(p, CRef_Lazy);
1278
    } else {
1279
3020840
      if (value(p) == l_False) {
1280
69342
        Debug("minisat") << "Conflict in theory propagation" << std::endl;
1281
138684
        SatClause explanation_cl;
1282
69342
        d_proxy->explainPropagation(MinisatSatSolver::toSatLiteral(p),
1283
                                    explanation_cl);
1284
138684
        vec<Lit> explanation;
1285
69342
        MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
1286
        ClauseId id; // FIXME: mark it as explanation here somehow?
1287
69342
        addClause(explanation, true, id);
1288
      }
1289
    }
1290
  }
1291
3075744
}
1292
1293
/*_________________________________________________________________________________________________
1294
|
1295
|  theoryCheck: [void]  ->  [Clause*]
1296
|
1297
|  Description:
1298
|    Checks all enqueued theory facts for satisfiability. If a conflict arises, the conflicting
1299
|    clause is returned, otherwise NULL.
1300
|
1301
|    Note: the propagation queue might be NOT empty
1302
|________________________________________________________________________________________________@*/
1303
3075758
void Solver::theoryCheck(cvc5::theory::Theory::Effort effort)
1304
{
1305
3075758
  d_proxy->theoryCheck(effort);
1306
3075744
}
1307
1308
/*_________________________________________________________________________________________________
1309
|
1310
|  propagateBool : [void]  ->  [Clause*]
1311
|
1312
|  Description:
1313
|    Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
1314
|    otherwise CRef_Undef.
1315
|
1316
|    Post-conditions:
1317
|      * the propagation queue is empty, even if there was a conflict.
1318
|________________________________________________________________________________________________@*/
1319
3385868
CRef Solver::propagateBool()
1320
{
1321
3385868
    CRef    confl     = CRef_Undef;
1322
3385868
    int     num_props = 0;
1323
3385868
    watches.cleanAll();
1324
1325
102223068
    while (qhead < trail.size()){
1326
49418600
        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
1327
49418600
        vec<Watcher>&  ws  = watches[p];
1328
        Watcher        *i, *j, *end;
1329
49418600
        num_props++;
1330
1331
        // if propagation tracing enabled, print boolean propagation
1332
49418600
        if (Trace.isOn("dtview::prop"))
1333
        {
1334
          dtviewBoolPropagationHelper(decisionLevel(), p, d_proxy);
1335
        }
1336
1337
699622659
        for (i = j = (Watcher*)ws, end = i + ws.size();  i != end;){
1338
            // Try to avoid inspecting the clause:
1339
650204059
            Lit blocker = i->blocker;
1340
1070672866
            if (value(blocker) == l_True){
1341
1286525610
                *j++ = *i++; continue; }
1342
1343
            // Make sure the false literal is data[1]:
1344
229735252
            CRef     cr        = i->cref;
1345
229735252
            Clause&  c         = ca[cr];
1346
229735252
            Lit      false_lit = ~p;
1347
229735252
            if (c[0] == false_lit)
1348
82482033
                c[0] = c[1], c[1] = false_lit;
1349
229735252
            Assert(c[1] == false_lit);
1350
229735252
            i++;
1351
1352
            // If 0th watch is true, then clause is already satisfied.
1353
229735252
            Lit     first = c[0];
1354
229735252
            Watcher w     = Watcher(cr, first);
1355
254854441
            if (first != blocker && value(first) == l_True){
1356
50238378
                *j++ = w; continue; }
1357
1358
            // Look for new watch:
1359
204616063
            Assert(c.size() >= 2);
1360
1074058323
            for (int k = 2; k < c.size(); k++)
1361
1025545048
                if (value(c[k]) != l_False){
1362
156102788
                    c[1] = c[k]; c[k] = false_lit;
1363
156102788
                    watches[~c[1]].push(w);
1364
156102788
                    goto NextClause; }
1365
1366
            // Did not find watch -- clause is unit under assignment:
1367
48513275
            *j++ = w;
1368
48513275
            if (value(first) == l_False){
1369
244295
                confl = cr;
1370
244295
                qhead = trail.size();
1371
                // Copy the remaining watches:
1372
6183705
                while (i < end)
1373
2969705
                    *j++ = *i++;
1374
            }else
1375
48268980
                uncheckedEnqueue(first, cr);
1376
1377
204616063
        NextClause:;
1378
        }
1379
49418600
        ws.shrink(i - j);
1380
    }
1381
3385868
    propagations += num_props;
1382
3385868
    simpDB_props -= num_props;
1383
1384
3385868
    return confl;
1385
}
1386
1387
1388
/*_________________________________________________________________________________________________
1389
|
1390
|  reduceDB : ()  ->  [void]
1391
|
1392
|  Description:
1393
|    Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
1394
|    clauses are clauses that are reason to some assignment. Binary clauses are never removed.
1395
|________________________________________________________________________________________________@*/
1396
struct reduceDB_lt {
1397
    ClauseAllocator& ca;
1398
3110
    reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
1399
4497040
    bool operator () (CRef x, CRef y) {
1400
4497040
        return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
1401
};
1402
3110
void Solver::reduceDB()
1403
{
1404
    int     i, j;
1405
3110
    double  extra_lim = cla_inc / clauses_removable.size();    // Remove any clause below this activity
1406
1407
3110
    sort(clauses_removable, reduceDB_lt(ca));
1408
    // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
1409
    // and clauses with activity smaller than 'extra_lim':
1410
414966
    for (i = j = 0; i < clauses_removable.size(); i++){
1411
411856
        Clause& c = ca[clauses_removable[i]];
1412
411856
        if (c.size() > 2 && !locked(c) && (i < clauses_removable.size() / 2 || c.activity() < extra_lim))
1413
179195
            removeClause(clauses_removable[i]);
1414
        else
1415
232661
            clauses_removable[j++] = clauses_removable[i];
1416
    }
1417
3110
    clauses_removable.shrink(i - j);
1418
3110
    checkGarbage();
1419
3110
}
1420
1421
1422
16885
void Solver::removeSatisfied(vec<CRef>& cs)
1423
{
1424
    int i, j;
1425
459090
    for (i = j = 0; i < cs.size(); i++){
1426
442205
        Clause& c = ca[cs[i]];
1427
442205
        if (satisfied(c)) {
1428
49446
          removeClause(cs[i]);
1429
        }
1430
        else
1431
        {
1432
392759
          cs[j++] = cs[i];
1433
        }
1434
    }
1435
16885
    cs.shrink(i - j);
1436
16885
}
1437
1438
8722
void Solver::removeClausesAboveLevel(vec<CRef>& cs, int level)
1439
{
1440
    int i, j;
1441
838872
    for (i = j = 0; i < cs.size(); i++){
1442
830150
        Clause& c = ca[cs[i]];
1443
830150
        if (c.level() > level) {
1444
253697
          Assert(!locked(c));
1445
253697
          removeClause(cs[i]);
1446
        } else {
1447
576453
            cs[j++] = cs[i];
1448
        }
1449
    }
1450
8722
    cs.shrink(i - j);
1451
8722
}
1452
1453
16885
void Solver::rebuildOrderHeap()
1454
{
1455
33770
    vec<Var> vs;
1456
1955706
    for (Var v = 0; v < nVars(); v++)
1457
1938821
        if (decision[v] && value(v) == l_Undef)
1458
1339352
            vs.push(v);
1459
16885
    order_heap.build(vs);
1460
16885
}
1461
1462
1463
/*_________________________________________________________________________________________________
1464
|
1465
|  simplify : [void]  ->  [bool]
1466
|
1467
|  Description:
1468
|    Simplify the clause database according to the current top-level assigment. Currently, the only
1469
|    thing done here is the removal of satisfied clauses, but more things can be put here.
1470
|________________________________________________________________________________________________@*/
1471
39900
bool Solver::simplify()
1472
{
1473
39900
  Assert(decisionLevel() == 0);
1474
1475
39900
  if (!ok || propagate(CHECK_WITHOUT_THEORY) != CRef_Undef) return ok = false;
1476
1477
39673
  if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) return true;
1478
1479
  // Remove satisfied clauses:
1480
16885
  removeSatisfied(clauses_removable);
1481
16885
  if (remove_satisfied)  // Can be turned off.
1482
    removeSatisfied(clauses_persistent);
1483
16885
  checkGarbage();
1484
16885
  rebuildOrderHeap();
1485
1486
16885
  simpDB_assigns = nAssigns();
1487
16885
  simpDB_props =
1488
16885
      clauses_literals + learnts_literals;  // (shouldn't depend on stats
1489
                                            // really, but it will do for now)
1490
1491
16885
  return true;
1492
}
1493
1494
1495
/*_________________________________________________________________________________________________
1496
|
1497
|  search : (nof_conflicts : int) (params : const SearchParams&)  ->  [lbool]
1498
|
1499
|  Description:
1500
|    Search for a model the specified number of conflicts.
1501
|    NOTE! Use negative value for 'nof_conflicts' indicate infinity.
1502
|
1503
|  Output:
1504
|    'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
1505
|    all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
1506
|    if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
1507
|________________________________________________________________________________________________@*/
1508
15287
lbool Solver::search(int nof_conflicts)
1509
{
1510
15287
  Assert(ok);
1511
  int backtrack_level;
1512
15287
  int conflictC = 0;
1513
30574
  vec<Lit> learnt_clause;
1514
15287
  starts++;
1515
1516
15287
  TheoryCheckType check_type = CHECK_WITH_THEORY;
1517
  for (;;)
1518
  {
1519
    // Propagate and call the theory solvers
1520
2617141
    CRef confl = propagate(check_type);
1521
2617127
    Assert(lemmas.size() == 0);
1522
1523
2617127
    if (confl != CRef_Undef)
1524
    {
1525
299973
      conflicts++;
1526
299973
      conflictC++;
1527
1528
299973
      if (decisionLevel() == 0)
1529
      {
1530
3134
        if (needProof())
1531
        {
1532
828
          if (confl == CRef_Lazy)
1533
          {
1534
44
            d_pfManager->finalizeProof();
1535
          }
1536
          else
1537
          {
1538
784
            d_pfManager->finalizeProof(ca[confl]);
1539
          }
1540
        }
1541
3134
        return l_False;
1542
      }
1543
1544
      // Analyze the conflict
1545
296839
      learnt_clause.clear();
1546
296839
      int max_level = analyze(confl, learnt_clause, backtrack_level);
1547
296839
      cancelUntil(backtrack_level);
1548
1549
      // Assert the conflict clause and the asserting literal
1550
296839
      if (learnt_clause.size() == 1)
1551
      {
1552
5537
        uncheckedEnqueue(learnt_clause[0]);
1553
5537
        if (needProof())
1554
        {
1555
1324
          d_pfManager->endResChain(learnt_clause[0]);
1556
        }
1557
      }
1558
      else
1559
      {
1560
291302
        CRef cr = ca.alloc(assertionLevelOnly() ? assertionLevel : max_level,
1561
                           learnt_clause,
1562
291302
                           true);
1563
291302
        clauses_removable.push(cr);
1564
291302
        attachClause(cr);
1565
291302
        claBumpActivity(ca[cr]);
1566
291302
        uncheckedEnqueue(learnt_clause[0], cr);
1567
291302
        if (needProof())
1568
        {
1569
30586
          d_pfManager->endResChain(ca[cr]);
1570
        }
1571
      }
1572
1573
296839
      varDecayActivity();
1574
296839
      claDecayActivity();
1575
1576
296839
      if (--learntsize_adjust_cnt == 0)
1577
      {
1578
533
        learntsize_adjust_confl *= learntsize_adjust_inc;
1579
533
        learntsize_adjust_cnt = (int)learntsize_adjust_confl;
1580
533
        max_learnts *= learntsize_inc;
1581
1582
533
        if (verbosity >= 1)
1583
          printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
1584
                 (int)conflicts,
1585
                 (int)dec_vars
1586
                     - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]),
1587
                 nClauses(),
1588
                 (int)clauses_literals,
1589
                 (int)max_learnts,
1590
                 nLearnts(),
1591
                 (double)learnts_literals / nLearnts(),
1592
                 progressEstimate() * 100);
1593
      }
1594
1595
350004
      if (theoryConflict && options::sat_refine_conflicts())
1596
      {
1597
        check_type = CHECK_FINAL_FAKE;
1598
      }
1599
      else
1600
      {
1601
296839
        check_type = CHECK_WITH_THEORY;
1602
      }
1603
    }
1604
    else
1605
    {
1606
      // If this was a final check, we are satisfiable
1607
2317154
      if (check_type == CHECK_FINAL)
1608
      {
1609
55380
        bool decisionEngineDone = d_proxy->isDecisionEngineDone();
1610
        // Unless a lemma has added more stuff to the queues
1611
154847
        if (!decisionEngineDone
1612
55380
            && (!order_heap.empty() || qhead < trail.size()))
1613
        {
1614
44087
          check_type = CHECK_WITH_THEORY;
1615
149896
          continue;
1616
        }
1617
11293
        else if (recheck)
1618
        {
1619
          // There some additional stuff added, so we go for another
1620
          // full-check
1621
4300
          continue;
1622
        }
1623
        else
1624
        {
1625
          // Yes, we're truly satisfiable
1626
6993
          return l_True;
1627
        }
1628
      }
1629
2261774
      else if (check_type == CHECK_FINAL_FAKE)
1630
      {
1631
        check_type = CHECK_WITH_THEORY;
1632
      }
1633
1634
4523548
      if ((nof_conflicts >= 0 && conflictC >= nof_conflicts)
1635
4521021
          || !withinBudget(Resource::SatConflictStep))
1636
      {
1637
        // Reached bound on number of conflicts:
1638
2527
        progress_estimate = progressEstimate();
1639
2527
        cancelUntil(0);
1640
        // [mdeters] notify theory engine of restarts for deferred
1641
        // theory processing
1642
2527
        d_proxy->notifyRestart();
1643
2527
        return l_Undef;
1644
      }
1645
1646
      // Simplify the set of problem clauses:
1647
2259247
      if (decisionLevel() == 0 && !simplify())
1648
      {
1649
        return l_False;
1650
      }
1651
1652
2259247
      if (clauses_removable.size() - nAssigns() >= max_learnts)
1653
      {
1654
        // Reduce the set of learnt clauses:
1655
3110
        reduceDB();
1656
      }
1657
1658
2259247
      Lit next = lit_Undef;
1659
2309519
      while (decisionLevel() < assumptions.size())
1660
      {
1661
        // Perform user provided assumption:
1662
282862
        Lit p = assumptions[decisionLevel()];
1663
282862
        if (value(p) == l_True)
1664
        {
1665
          // Dummy decision level:
1666
25136
          newDecisionLevel();
1667
        }
1668
257726
        else if (value(p) == l_False)
1669
        {
1670
2617
          analyzeFinal(~p, d_conflict);
1671
2617
          return l_False;
1672
        }
1673
        else
1674
        {
1675
255109
          next = p;
1676
255109
          break;
1677
        }
1678
      }
1679
1680
2256630
      if (next == lit_Undef)
1681
      {
1682
        // New variable decision:
1683
2001521
        next = pickBranchLit();
1684
1685
2058941
        if (next == lit_Undef)
1686
        {
1687
          // We need to do a full theory check to confirm
1688
114844
          Debug("minisat::search")
1689
57422
              << "Doing a full theory check..." << std::endl;
1690
57422
          check_type = CHECK_FINAL;
1691
57422
          continue;
1692
        }
1693
      }
1694
1695
      // Increase decision level and enqueue 'next'
1696
2199206
      newDecisionLevel();
1697
2199206
      uncheckedEnqueue(next);
1698
    }
1699
2601854
  }
1700
}
1701
1702
1703
2527
double Solver::progressEstimate() const
1704
{
1705
2527
    double  progress = 0;
1706
2527
    double  F = 1.0 / nVars();
1707
1708
182491
    for (int i = 0; i <= decisionLevel(); i++){
1709
179964
        int beg = i == 0 ? 0 : trail_lim[i - 1];
1710
179964
        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
1711
179964
        progress += pow(F, i) * (end - beg);
1712
    }
1713
1714
2527
    return progress / nVars();
1715
}
1716
1717
/*
1718
  Finite subsequences of the Luby-sequence:
1719
1720
  0: 1
1721
  1: 1 1 2
1722
  2: 1 1 2 1 1 2 4
1723
  3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8
1724
  ...
1725
1726
1727
 */
1728
1729
15287
static double luby(double y, int x){
1730
1731
    // Find the finite subsequence that contains index 'x', and the
1732
    // size of that subsequence:
1733
    int size, seq;
1734
15287
    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1);
1735
1736
26687
    while (size-1 != x){
1737
5700
        size = (size-1)>>1;
1738
5700
        seq--;
1739
5700
        x = x % size;
1740
    }
1741
1742
15287
    return pow(y, seq);
1743
}
1744
1745
// NOTE: assumptions passed in member-variable 'assumptions'.
1746
14072
lbool Solver::solve_()
1747
{
1748
14072
    Debug("minisat") << "nvars = " << nVars() << std::endl;
1749
1750
28144
    ScopedBool scoped_bool(minisat_busy, true);
1751
1752
14072
    Assert(decisionLevel() == 0);
1753
1754
14072
    model.clear();
1755
14072
    d_conflict.clear();
1756
14072
    if (!ok){
1757
1312
      minisat_busy = false;
1758
1312
      return l_False;
1759
    }
1760
1761
12760
    solves++;
1762
1763
12760
    max_learnts               = nClauses() * learntsize_factor;
1764
12760
    learntsize_adjust_confl   = learntsize_adjust_start_confl;
1765
12760
    learntsize_adjust_cnt     = (int)learntsize_adjust_confl;
1766
12760
    lbool   status            = l_Undef;
1767
1768
12760
    if (verbosity >= 1){
1769
1
        printf("============================[ Search Statistics ]==============================\n");
1770
1
        printf("| Conflicts |          ORIGINAL         |          LEARNT          | Progress |\n");
1771
1
        printf("|           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl |          |\n");
1772
1
        printf("===============================================================================\n");
1773
    }
1774
1775
    // Search:
1776
12760
    int curr_restarts = 0;
1777
43302
    while (status == l_Undef){
1778
15287
        double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts);
1779
15287
        status = search(rest_base * restart_first);
1780
15271
        if (!withinBudget(Resource::SatConflictStep))
1781
          break;  // FIXME add restart option?
1782
15271
        curr_restarts++;
1783
    }
1784
1785
12744
    if (!withinBudget(Resource::SatConflictStep))
1786
      status = l_Undef;
1787
1788
12744
    if (verbosity >= 1)
1789
1
        printf("===============================================================================\n");
1790
1791
1792
12744
    if (status == l_True){
1793
        // Extend & copy model:
1794
6993
        model.growTo(nVars());
1795
614541
        for (int i = 0; i < nVars(); i++) {
1796
607548
          model[i] = value(i);
1797
607548
          Debug("minisat") << i << " = " << model[i] << std::endl;
1798
        }
1799
    }
1800
5751
    else if (status == l_False && d_conflict.size() == 0)
1801
3134
      ok = false;
1802
1803
12744
    return status;
1804
}
1805
1806
//=================================================================================================
1807
// Writing CNF to DIMACS:
1808
//
1809
// FIXME: this needs to be rewritten completely.
1810
1811
static Var mapVar(Var x, vec<Var>& map, Var& max)
1812
{
1813
    if (map.size() <= x || map[x] == -1){
1814
        map.growTo(x+1, -1);
1815
        map[x] = max++;
1816
    }
1817
    return map[x];
1818
}
1819
1820
1821
void Solver::toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max)
1822
{
1823
    if (satisfied(c)) return;
1824
1825
    for (int i = 0; i < c.size(); i++)
1826
        if (value(c[i]) != l_False)
1827
            fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max)+1);
1828
    fprintf(f, "0\n");
1829
}
1830
1831
1832
void Solver::toDimacs(const char *file, const vec<Lit>& assumps)
1833
{
1834
    FILE* f = fopen(file, "wr");
1835
    if (f == NULL)
1836
        fprintf(stderr, "could not open file %s\n", file), exit(1);
1837
    toDimacs(f, assumps);
1838
    fclose(f);
1839
}
1840
1841
1842
void Solver::toDimacs(FILE* f, const vec<Lit>& assumps)
1843
{
1844
    // Handle case when solver is in contradictory state:
1845
    if (!ok){
1846
        fprintf(f, "p cnf 1 2\n1 0\n-1 0\n");
1847
        return; }
1848
1849
    vec<Var> map; Var max = 0;
1850
1851
    // Cannot use removeClauses here because it is not safe
1852
    // to deallocate them at this point. Could be improved.
1853
    int cnt = 0;
1854
    for (int i = 0; i < clauses_persistent.size(); i++)
1855
        if (!satisfied(ca[clauses_persistent[i]]))
1856
            cnt++;
1857
1858
    for (int i = 0; i < clauses_persistent.size(); i++)
1859
        if (!satisfied(ca[clauses_persistent[i]])){
1860
            Clause& c = ca[clauses_persistent[i]];
1861
            for (int j = 0; j < c.size(); j++)
1862
                if (value(c[j]) != l_False)
1863
                    mapVar(var(c[j]), map, max);
1864
        }
1865
1866
    // Assumptions are added as unit clauses:
1867
    cnt += assumptions.size();
1868
1869
    fprintf(f, "p cnf %d %d\n", max, cnt);
1870
1871
    for (int i = 0; i < assumptions.size(); i++){
1872
      Assert(value(assumptions[i]) != l_False);
1873
      fprintf(f,
1874
              "%s%d 0\n",
1875
              sign(assumptions[i]) ? "-" : "",
1876
              mapVar(var(assumptions[i]), map, max) + 1);
1877
    }
1878
1879
    for (int i = 0; i < clauses_persistent.size(); i++)
1880
        toDimacs(f, ca[clauses_persistent[i]], map, max);
1881
1882
    if (verbosity > 0)
1883
        printf("Wrote %d clauses with %d variables.\n", cnt, max);
1884
}
1885
1886
1887
//=================================================================================================
1888
// Garbage Collection methods:
1889
1890
2721
void Solver::relocAll(ClauseAllocator& to)
1891
{
1892
    // All watchers:
1893
    //
1894
    // for (int i = 0; i < watches.size(); i++)
1895
2721
    watches.cleanAll();
1896
606535
    for (int v = 0; v < nVars(); v++)
1897
1811442
        for (int s = 0; s < 2; s++){
1898
1207628
            Lit p = mkLit(v, s);
1899
            // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
1900
1207628
            vec<Watcher>& ws = watches[p];
1901
3017582
            for (int j = 0; j < ws.size(); j++)
1902
            {
1903
1809954
              ca.reloc(ws[j].cref, to);
1904
            }
1905
        }
1906
1907
    // All reasons:
1908
    //
1909
175067
    for (int i = 0; i < trail.size(); i++){
1910
172346
        Var v = var(trail[i]);
1911
1912
344692
        if (hasReasonClause(v)
1913
172346
            && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
1914
        {
1915
39145
          ca.reloc(vardata[v].d_reason, to);
1916
        }
1917
    }
1918
    // All learnt:
1919
    //
1920
184095
    for (int i = 0; i < clauses_removable.size(); i++)
1921
    {
1922
181374
      ca.reloc(clauses_removable[i], to);
1923
    }
1924
    // All original:
1925
    //
1926
726324
    for (int i = 0; i < clauses_persistent.size(); i++)
1927
    {
1928
723603
      ca.reloc(clauses_persistent[i], to);
1929
    }
1930
2721
}
1931
1932
1933
void Solver::garbageCollect()
1934
{
1935
    // Initialize the next region to a size corresponding to the estimated utilization degree. This
1936
    // is not precise but should avoid some unnecessary reallocations for the new region:
1937
    ClauseAllocator to(ca.size() - ca.wasted());
1938
1939
    relocAll(to);
1940
    if (verbosity >= 2)
1941
        printf("|  Garbage collection:   %12d bytes => %12d bytes             |\n",
1942
               ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
1943
    to.moveTo(ca);
1944
}
1945
1946
4361
void Solver::push()
1947
{
1948
4361
  Assert(d_enable_incremental);
1949
4361
  Assert(decisionLevel() == 0);
1950
1951
4361
  ++assertionLevel;
1952
4361
  Debug("minisat") << "in user push, increasing assertion level to " << assertionLevel << std::endl;
1953
4361
  trail_ok.push(ok);
1954
4361
  assigns_lim.push(assigns.size());
1955
1956
4361
  d_context->push();  // SAT context for cvc5
1957
1958
4361
  Debug("minisat") << "MINISAT PUSH assertionLevel is " << assertionLevel << ", trail.size is " << trail.size() << std::endl;
1959
4361
}
1960
1961
4361
void Solver::pop()
1962
{
1963
4361
  Assert(d_enable_incremental);
1964
1965
4361
  Assert(decisionLevel() == 0);
1966
1967
  // Pop the trail below the user level
1968
4361
  --assertionLevel;
1969
8722
  Debug("minisat") << "in user pop, decreasing assertion level to "
1970
4361
                   << assertionLevel << "\n"
1971
4361
                   << cvc5::push;
1972
  while (true) {
1973
56829
    Debug("minisat") << "== unassigning " << trail.last() << std::endl;
1974
56829
    Var      x  = var(trail.last());
1975
56829
    if (user_level(x) > assertionLevel) {
1976
52468
      assigns[x] = l_Undef;
1977
52468
      vardata[x] = VarData(CRef_Undef, -1, -1, intro_level(x), -1);
1978
52468
      if(phase_saving >= 1 && (polarity[x] & 0x2) == 0)
1979
51481
        polarity[x] = sign(trail.last());
1980
52468
      insertVarOrder(x);
1981
52468
      trail.pop();
1982
    } else {
1983
4361
      break;
1984
    }
1985
52468
  }
1986
1987
  // The head should be at the trail top
1988
4361
  qhead = trail.size();
1989
1990
  // Remove the clauses
1991
4361
  removeClausesAboveLevel(clauses_persistent, assertionLevel);
1992
4361
  removeClausesAboveLevel(clauses_removable, assertionLevel);
1993
4361
  Debug("minisat") << cvc5::pop;
1994
  // Pop the SAT context to notify everyone
1995
4361
  d_context->pop();  // SAT context for cvc5
1996
1997
8722
  Debug("minisat") << "MINISAT POP assertionLevel is " << assertionLevel
1998
4361
                   << ", trail.size is " << trail.size() << "\n";
1999
  // Pop the created variables
2000
4361
  resizeVars(assigns_lim.last());
2001
4361
  assigns_lim.pop();
2002
4361
  variables_to_register.clear();
2003
2004
  // Pop the OK
2005
4361
  ok = trail_ok.last();
2006
4361
  trail_ok.pop();
2007
4361
}
2008
2009
231697
CRef Solver::updateLemmas() {
2010
2011
231697
  Debug("minisat::lemmas") << "Solver::updateLemmas() begin" << std::endl;
2012
2013
  // Avoid adding lemmas indefinitely without resource-out
2014
231697
  d_proxy->spendResource(Resource::LemmaStep);
2015
2016
231697
  CRef conflict = CRef_Undef;
2017
2018
  // Decision level to backtrack to
2019
231697
  int backtrackLevel = decisionLevel();
2020
2021
  // We use this comparison operator
2022
231697
  lemma_lt lt(*this);
2023
2024
  // Check for propagation and level to backtrack to
2025
231697
  int i = 0;
2026
695211
  while (i < lemmas.size()) {
2027
    // We need this loop as when we backtrack, due to registration more lemmas could be added
2028
1698679
    for (; i < lemmas.size(); ++ i)
2029
    {
2030
      // The current lemma
2031
733461
      vec<Lit>& lemma = lemmas[i];
2032
2033
733461
      Trace("pf::sat") << "Solver::updateLemmas: working on lemma: ";
2034
3665670
      for (int k = 0; k < lemma.size(); ++k) {
2035
2932209
        Trace("pf::sat") << lemma[k] << " ";
2036
      }
2037
733461
      Trace("pf::sat") << std::endl;
2038
2039
      // If it's an empty lemma, we have a conflict at zero level
2040
734655
      if (lemma.size() == 0) {
2041
1194
        Assert(!options::unsatCores() && !needProof());
2042
1194
        conflict = CRef_Lazy;
2043
1194
        backtrackLevel = 0;
2044
1194
        Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
2045
1194
        continue;
2046
      }
2047
      // Sort the lemma to be able to attach
2048
732267
      sort(lemma, lt);
2049
      // See if the lemma propagates something
2050
732267
      if (lemma.size() == 1 || value(lemma[1]) == l_False) {
2051
388437
        Debug("minisat::lemmas") << "found unit " << lemma.size() << std::endl;
2052
        // This lemma propagates, see which level we need to backtrack to
2053
388437
        int currentBacktrackLevel = lemma.size() == 1 ? 0 : level(var(lemma[1]));
2054
        // Even if the first literal is true, we should propagate it at this level (unless it's set at a lower level)
2055
388437
        if (value(lemma[0]) != l_True || level(var(lemma[0])) > currentBacktrackLevel) {
2056
378370
          if (currentBacktrackLevel < backtrackLevel) {
2057
132769
            backtrackLevel = currentBacktrackLevel;
2058
          }
2059
        }
2060
      }
2061
    }
2062
2063
    // Pop so that propagation would be current
2064
231757
    Debug("minisat::lemmas") << "Solver::updateLemmas(): backtracking to " << backtrackLevel << " from " << decisionLevel() << std::endl;
2065
231757
    cancelUntil(backtrackLevel);
2066
  }
2067
2068
  // Last index in the trail
2069
231697
  int backtrack_index = trail.size();
2070
2071
  // Attach all the clauses and enqueue all the propagations
2072
965158
  for (int j = 0; j < lemmas.size(); ++j)
2073
  {
2074
    // The current lemma
2075
733461
    vec<Lit>& lemma = lemmas[j];
2076
733461
    bool removable = lemmas_removable[j];
2077
2078
    // Attach it if non-unit
2079
733461
    CRef lemma_ref = CRef_Undef;
2080
733461
    if (lemma.size() > 1) {
2081
      // If the lemmas is removable, we can compute its level by the level
2082
675283
      int clauseLevel = assertionLevel;
2083
675283
      if (removable && !assertionLevelOnly())
2084
      {
2085
170684
        clauseLevel = 0;
2086
1595771
        for (int k = 0; k < lemma.size(); ++k)
2087
        {
2088
1425087
          clauseLevel = std::max(clauseLevel, intro_level(var(lemma[k])));
2089
        }
2090
      }
2091
2092
675283
      lemma_ref = ca.alloc(clauseLevel, lemma, removable);
2093
675283
      if (removable) {
2094
179481
        clauses_removable.push(lemma_ref);
2095
      } else {
2096
495802
        clauses_persistent.push(lemma_ref);
2097
      }
2098
675283
      attachClause(lemma_ref);
2099
    }
2100
2101
    // If the lemma is propagating enqueue its literal (or set the conflict)
2102
733461
    if (conflict == CRef_Undef && value(lemma[0]) != l_True) {
2103
680965
      if (lemma.size() == 1 || (value(lemma[1]) == l_False && trail_index(var(lemma[1])) < backtrack_index)) {
2104
608978
        Trace("pf::sat") << "Solver::updateLemmas: unit theory lemma: "
2105
304489
                         << lemma[0] << std::endl;
2106
304489
        if (value(lemma[0]) == l_False) {
2107
          // We have a conflict
2108
54632
          if (lemma.size() > 1) {
2109
54237
            Debug("minisat::lemmas") << "Solver::updateLemmas(): conflict" << std::endl;
2110
54237
            conflict = lemma_ref;
2111
          } else {
2112
395
            Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
2113
395
            conflict = CRef_Lazy;
2114
395
            if (needProof())
2115
            {
2116
44
              d_pfManager->storeUnitConflict(lemma[0]);
2117
            }
2118
          }
2119
        } else {
2120
249857
          Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
2121
249857
          Debug("minisat::lemmas") << "lemma ref is " << lemma_ref << std::endl;
2122
249857
          uncheckedEnqueue(lemma[0], lemma_ref);
2123
        }
2124
      }
2125
    }
2126
  }
2127
2128
  // Clear the lemmas
2129
231697
  lemmas.clear();
2130
231697
  lemmas_removable.clear();
2131
2132
231697
  if (conflict != CRef_Undef) {
2133
55724
    theoryConflict = true;
2134
  }
2135
2136
231697
  Debug("minisat::lemmas") << "Solver::updateLemmas() end" << std::endl;
2137
2138
231697
  return conflict;
2139
}
2140
2141
3427433
void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to)
2142
{
2143
3427433
  Debug("minisat") << "ClauseAllocator::reloc: cr " << cr << std::endl;
2144
  // FIXME what is this CRef_lazy
2145
3427433
  if (cr == CRef_Lazy) return;
2146
2147
3427433
  Clause& c = operator[](cr);
2148
3427433
  if (c.reloced()) { cr = c.relocation(); return; }
2149
2150
905672
  cr = to.alloc(c.level(), c, c.removable());
2151
905672
  c.relocate(cr);
2152
  // Copy extra data-fields:
2153
  // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
2154
905672
  to[cr].mark(c.mark());
2155
905672
  if (to[cr].removable())         to[cr].activity() = c.activity();
2156
724298
  else if (to[cr].has_extra()) to[cr].calcAbstraction();
2157
}
2158
2159
2287262
inline bool Solver::withinBudget(Resource r) const
2160
{
2161
2287262
  Assert(d_proxy);
2162
  // spendResource sets async_interrupt or throws UnsafeInterruptException
2163
  // depending on whether hard-limit is enabled
2164
2287262
  d_proxy->spendResource(r);
2165
2166
2287262
  bool within_budget =
2167
4574524
      !asynch_interrupt && (conflict_budget < 0 || conflicts < conflict_budget)
2168
4574524
      && (propagation_budget < 0 || propagations < propagation_budget);
2169
2287262
  return within_budget;
2170
}
2171
2172
2394
SatProofManager* Solver::getProofManager()
2173
{
2174
2394
  return isProofEnabled() ? d_pfManager.get() : nullptr;
2175
}
2176
2177
2698
std::shared_ptr<ProofNode> Solver::getProof()
2178
{
2179
2698
  return isProofEnabled() ? d_pfManager->getProof() : nullptr;
2180
}
2181
2182
13724081
bool Solver::isProofEnabled() const { return d_pfManager != nullptr; }
2183
2184
13718989
bool Solver::needProof() const
2185
{
2186
13718989
  return isProofEnabled()
2187
15193634
         && options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS;
2188
}
2189
2190
}  // namespace Minisat
2191
31925021
}  // namespace cvc5