GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/minisat/core/Solver.cc Lines: 854 1025 83.3 %
Date: 2021-05-21 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
8539636
bool assertionLevelOnly()
54
{
55
42600354
  return (options::produceProofs() || options::unsatCores())
56
12363913
         && 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
9245
static DoubleOption  opt_var_decay         (_cat, "var-decay",   "The variable activity decay factor",            0.95,     DoubleRange(0, false, 1, false));
115
9245
static DoubleOption  opt_clause_decay      (_cat, "cla-decay",   "The clause activity decay factor",              0.999,    DoubleRange(0, false, 1, false));
116
9245
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
9245
static DoubleOption  opt_random_seed       (_cat, "rnd-seed",    "Used by the random variable selection",         91648253, DoubleRange(0, false, HUGE_VAL, false));
118
9245
static IntOption     opt_ccmin_mode        (_cat, "ccmin-mode",  "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
119
9245
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
9245
static BoolOption    opt_rnd_init_act      (_cat, "rnd-init",    "Randomize the initial activity", false);
121
9245
static BoolOption    opt_luby_restart      (_cat, "luby",        "Use the Luby restart sequence", true);
122
9245
static IntOption     opt_restart_first     (_cat, "rfirst",      "The base restart interval", 25, IntRange(1, INT32_MAX));
123
9245
static DoubleOption  opt_restart_inc       (_cat, "rinc",        "Restart interval increase factor", 3, DoubleRange(1, false, HUGE_VAL, false));
124
9245
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
2715726
  ScopedBool(bool& watch, bool newValue) : d_watch(watch), d_oldValue(watch)
138
  {
139
2715726
    watch = newValue;
140
2715726
  }
141
2715726
  ~ScopedBool() { d_watch = d_oldValue; }
142
};
143
144
//=================================================================================================
145
// Constructor/Destructor:
146
147
8988
Solver::Solver(cvc5::prop::TheoryProxy* proxy,
148
               cvc5::context::Context* context,
149
               cvc5::context::UserContext* userContext,
150
               ProofNodeManager* pnm,
151
8988
               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
17976
      watches(WatcherDeleted(ca)),
208
      qhead(0),
209
      simpDB_assigns(-1),
210
      simpDB_props(0),
211
17976
      order_heap(VarOrderLt(activity)),
212
      progress_estimate(0),
213
8988
      remove_satisfied(!enableIncremental)
214
215
      // Resource constraints:
216
      //
217
      ,
218
      conflict_budget(-1),
219
      propagation_budget(-1),
220
53928
      asynch_interrupt(false)
221
{
222
8988
  if (pnm)
223
  {
224
2438
    d_pfManager.reset(
225
1219
        new SatProofManager(this, proxy->getCnfStream(), userContext, pnm));
226
  }
227
228
  // Create the constant variables
229
8988
  varTrue = newVar(true, false, false);
230
8988
  varFalse = newVar(false, false, false);
231
232
  // Assert the constants
233
8988
  uncheckedEnqueue(mkLit(varTrue, false));
234
8988
  uncheckedEnqueue(mkLit(varFalse, true));
235
8988
}
236
237
238
8988
Solver::~Solver()
239
{
240
8988
}
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
856163
Var Solver::newVar(bool sign, bool dvar, bool isTheoryAtom, bool preRegister, bool canErase)
251
{
252
856163
    int v = nVars();
253
254
856163
    watches  .init(mkLit(v, false));
255
856163
    watches  .init(mkLit(v, true ));
256
856163
    assigns  .push(l_Undef);
257
856163
    vardata  .push(VarData(CRef_Undef, -1, -1, assertionLevel, -1));
258
856163
    activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
259
856163
    seen     .push(0);
260
856163
    polarity .push(sign);
261
856163
    decision .push();
262
856163
    trail    .capacity(v+1);
263
    // push whether it corresponds to a theory atom
264
856163
    theory.push(isTheoryAtom);
265
266
856163
    setDecisionVar(v, dvar);
267
268
856163
    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
856163
    if (preRegister)
272
    {
273
1014480
      Debug("minisat") << "  To register at level " << decisionLevel()
274
507240
                       << std::endl;
275
507240
      variables_to_register.push(VarIntroInfo(v, decisionLevel()));
276
    }
277
278
856163
    return v;
279
}
280
281
3596
void Solver::resizeVars(int newSize) {
282
3596
  Assert(d_enable_incremental);
283
3596
  Assert(decisionLevel() == 0);
284
3596
  Assert(newSize >= 2) << "always keep true/false";
285
3596
  if (newSize < nVars()) {
286
2126
    int shrinkSize = nVars() - newSize;
287
288
    // Resize watches up to the negated last literal
289
2126
    watches.resizeTo(mkLit(newSize-1, true));
290
291
    // Resize all info arrays
292
2126
    assigns.shrink(shrinkSize);
293
2126
    vardata.shrink(shrinkSize);
294
2126
    activity.shrink(shrinkSize);
295
2126
    seen.shrink(shrinkSize);
296
2126
    polarity.shrink(shrinkSize);
297
2126
    decision.shrink(shrinkSize);
298
2126
    theory.shrink(shrinkSize);
299
  }
300
301
3596
  if (Debug.isOn("minisat::pop")) {
302
    for (int i = 0; i < trail.size(); ++ i) {
303
      Assert(var(trail[i]) < nVars());
304
    }
305
  }
306
3596
}
307
308
128679782
CRef Solver::reason(Var x) {
309
128679782
  Trace("pf::sat") << "Solver::reason(" << x << ")" << std::endl;
310
311
  // If we already have a reason, just return it
312
128679782
  if (vardata[x].d_reason != CRef_Lazy)
313
  {
314
128627716
    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
128627716
    return vardata[x].d_reason;
332
  }
333
  // What's the literal we are trying to explain
334
52066
  Lit l = mkLit(x, value(x) != l_True);
335
336
  // Get the explanation from the theory
337
104132
  SatClause explanation_cl;
338
  // FIXME: at some point return a tag with the theory that spawned you
339
52066
  d_proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l),
340
                              explanation_cl);
341
104132
  vec<Lit> explanation;
342
52066
  MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
343
344
104132
  Trace("pf::sat") << "Solver::reason: explanation_cl = " << explanation_cl
345
52066
                   << std::endl;
346
347
  // Sort the literals by trail index level
348
52066
  lemma_lt lt(*this);
349
52066
  sort(explanation, lt);
350
52066
  Assert(explanation[0] == l);
351
352
  // Compute the assertion level for this clause
353
52066
  int explLevel = 0;
354
52066
  if (assertionLevelOnly())
355
  {
356
889
    explLevel = assertionLevel;
357
    }
358
    else
359
    {
360
      int i, j;
361
51177
      Lit prev = lit_Undef;
362
362585
      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
311408
        explLevel = std::max(explLevel, intro_level(var(explanation[i])));
367
368
311408
        Assert(value(explanation[i]) != l_Undef);
369
311408
        Assert(i == 0
370
               || trail_index(var(explanation[0]))
371
                      > trail_index(var(explanation[i])));
372
373
        // Always keep the first literal
374
362585
        if (i == 0)
375
        {
376
51177
          prev = explanation[j++] = explanation[i];
377
51177
          continue;
378
        }
379
        // Ignore duplicate literals
380
260231
        if (explanation[i] == prev)
381
        {
382
          continue;
383
        }
384
        // Ignore zero level literals
385
520462
        if (level(var(explanation[i])) == 0
386
260231
            && user_level(var(explanation[i]) == 0))
387
        {
388
          continue;
389
        }
390
        // Keep this literal
391
260231
        prev = explanation[j++] = explanation[i];
392
      }
393
51177
      explanation.shrink(i - j);
394
395
51177
      Trace("pf::sat") << "Solver::reason: explanation = ";
396
362585
      for (int k = 0; k < explanation.size(); ++k)
397
      {
398
311408
        Trace("pf::sat") << explanation[k] << " ";
399
      }
400
51177
      Trace("pf::sat") << std::endl;
401
402
      // We need an explanation clause so we add a fake literal
403
51177
      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
52066
    CRef real_reason = ca.alloc(explLevel, explanation, true);
412
52066
    vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
413
52066
    clauses_removable.push(real_reason);
414
52066
    attachClause(real_reason);
415
416
52066
    return real_reason;
417
}
418
419
2415329
bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
420
{
421
2415329
    if (!ok) return false;
422
423
    // Check if clause is satisfied and remove false/duplicate literals:
424
2415329
    sort(ps);
425
    Lit p; int i, j;
426
427
    // Which user-level to assert this clause at
428
2415329
    int clauseLevel = (removable && !assertionLevelOnly()) ? 0 : assertionLevel;
429
430
    // Check the clause for tautologies and similar
431
2415329
    int falseLiteralsCount = 0;
432
10080010
    for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
433
      // Update the level
434
15701252
      clauseLevel = assertionLevelOnly()
435
15463987
                        ? assertionLevel
436
15463987
                        : std::max(clauseLevel, intro_level(var(ps[i])));
437
      // Tautologies are ignored
438
7850626
      if (ps[i] == ~p) {
439
38139
        id = ClauseIdUndef;
440
        // Clause can be ignored
441
38139
        return true;
442
      }
443
      // Clauses with 0-level true literals are also ignored
444
7812487
      if (value(ps[i]) == l_True && level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
445
147806
        id = ClauseIdUndef;
446
147806
        return true;
447
      }
448
      // Ignore repeated literals
449
7664681
      if (ps[i] == p) {
450
3487
        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
7661194
      if (value(ps[i]) == l_False) {
455
6637593
        if (!options::unsatCores() && !needProof() && level(var(ps[i])) == 0
456
3302977
            && user_level(var(ps[i])) == 0)
457
        {
458
719389
          continue;
459
        }
460
        else
461
        {
462
          // If we decide to keep it, we count it into the false literals
463
1845477
          falseLiteralsCount++;
464
        }
465
      }
466
      // This literal is a keeper
467
6941805
      ps[j++] = p = ps[i];
468
    }
469
470
    // Fit to size
471
2229384
    ps.shrink(i - j);
472
473
    // If we are in solve_ or propagate
474
2229384
    if (minisat_busy)
475
    {
476
714981
      Trace("pf::sat") << "Add clause adding a new lemma: ";
477
3551994
      for (int k = 0; k < ps.size(); ++k) {
478
2837013
        Trace("pf::sat") << ps[k] << " ";
479
      }
480
714981
      Trace("pf::sat") << std::endl;
481
482
714981
      lemmas.push();
483
714981
      ps.copyTo(lemmas.last());
484
714981
      lemmas_removable.push(removable);
485
    } else {
486
1514403
      Assert(decisionLevel() == 0);
487
488
      // If all false, we're in conflict
489
1514403
      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
465
          if(falseLiteralsCount == 1) {
496
447
            if (needProof())
497
            {
498
447
              d_pfManager->finalizeProof(ps[0], true);
499
            }
500
82396
            return ok = false;
501
          }
502
        }
503
        else
504
        {
505
813
          return ok = false;
506
        }
507
      }
508
509
1513143
      CRef cr = CRef_Undef;
510
511
      // If not unit, add the clause
512
1513143
      if (ps.size() > 1) {
513
514
1436126
        lemma_lt lt(*this);
515
1436126
        sort(ps, lt);
516
517
1436126
        cr = ca.alloc(clauseLevel, ps, false);
518
1436126
        clauses_persistent.push(cr);
519
1436126
        attachClause(cr);
520
521
1436126
        if (options::unsatCores() || needProof())
522
        {
523
701817
          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
1513125
      if (ps.size() == falseLiteralsCount + 1) {
536
80671
        if(assigns[var(ps[0])] == l_Undef) {
537
78748
          Assert(assigns[var(ps[0])] != l_False);
538
78748
          uncheckedEnqueue(ps[0], cr);
539
157496
          Debug("cores") << "i'm registering a unit clause, maybe input"
540
78748
                         << std::endl;
541
78748
          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
75911
            if (needProof())
549
            {
550
23914
              d_pfManager->registerSatLitAssumption(ps[0]);
551
            }
552
          }
553
78748
          CRef confl = propagate(CHECK_WITHOUT_THEORY);
554
78748
          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
78748
          return ok;
568
        } else {
569
1923
          return ok;
570
        }
571
      }
572
    }
573
574
2147435
    return true;
575
}
576
577
578
2521728
void Solver::attachClause(CRef cr) {
579
2521728
    const Clause& c = ca[cr];
580
2521728
    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
2521728
    Assert(c.size() > 1);
590
2521728
    watches[~c[0]].push(Watcher(cr, c[1]));
591
2521728
    watches[~c[1]].push(Watcher(cr, c[0]));
592
2521728
    if (c.removable()) learnts_literals += c.size();
593
2010189
    else            clauses_literals += c.size();
594
2521728
}
595
596
597
739025
void Solver::detachClause(CRef cr, bool strict) {
598
739025
    const Clause& c = ca[cr];
599
739025
    Debug("minisat") << "Solver::detachClause(" << c << ")" << std::endl;
600
739025
    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
739025
    Assert(c.size() > 1);
612
613
739025
    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
649908
        watches.smudge(~c[0]);
619
649908
        watches.smudge(~c[1]);
620
    }
621
622
739025
    if (c.removable()) learnts_literals -= c.size();
623
510203
    else            clauses_literals -= c.size(); }
624
625
626
649908
void Solver::removeClause(CRef cr) {
627
649908
    Clause& c = ca[cr];
628
649908
    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
649908
    detachClause(cr);
639
    // Don't leave pointers to free'd memory!
640
649908
    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
10339
      if (needProof())
649
      {
650
1930
        Trace("pf::sat")
651
965
            << "Solver::removeClause: eagerly compute propagation of " << c[0]
652
965
            << "\n";
653
965
        d_pfManager->startResChain(c);
654
3517
        for (unsigned i = 1, size = c.size(); i < size; ++i)
655
        {
656
2552
          d_pfManager->addResolutionStep(c[i]);
657
        }
658
965
        d_pfManager->endResChain(c[0]);
659
      }
660
10339
      vardata[var(c[0])].d_reason = CRef_Undef;
661
    }
662
649908
    c.mark(1);
663
649908
    ca.free(cr);
664
649908
}
665
666
667
438544
bool Solver::satisfied(const Clause& c) const {
668
21384985
    for (int i = 0; i < c.size(); i++)
669
20995847
        if (value(c[i]) == l_True)
670
49406
            return true;
671
389138
    return false; }
672
673
674
// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
675
//
676
532095
void Solver::cancelUntil(int level) {
677
532095
    Debug("minisat") << "minisat::cancelUntil(" << level << ")" << std::endl;
678
679
532095
    if (decisionLevel() > level){
680
        // Pop the SMT context
681
2611497
        for (int l = trail_lim.size() - level; l > 0; --l) {
682
2186889
          d_context->pop();
683
        }
684
54251667
        for (int c = trail.size()-1; c >= trail_lim[level]; c--){
685
53827059
            Var      x  = var(trail[c]);
686
53827059
            assigns [x] = l_Undef;
687
53827059
            vardata[x].d_trail_index = -1;
688
107654118
            if ((phase_saving > 1 ||
689
                 ((phase_saving == 1) && c > trail_lim.last())
690
107654118
                 ) && ((polarity[x] & 0x2) == 0)) {
691
53317132
              polarity[x] = sign(trail[c]);
692
            }
693
53827059
            insertVarOrder(x);
694
        }
695
424608
        qhead = trail_lim[level];
696
424608
        trail.shrink(trail.size() - trail_lim[level]);
697
424608
        trail_lim.shrink(trail_lim.size() - level);
698
424608
        flipped.shrink(flipped.size() - level);
699
700
        // Register variables that have not been registered yet
701
424608
        int currentLevel = decisionLevel();
702
756868
        for (int i = variables_to_register.size() - 1;
703
756868
             i >= 0 && variables_to_register[i].d_level > currentLevel;
704
             --i)
705
        {
706
332260
          variables_to_register[i].d_level = currentLevel;
707
664520
          d_proxy->variableNotify(
708
332260
              MinisatSatSolver::toSatVariable(variables_to_register[i].d_var));
709
        }
710
    }
711
532095
}
712
713
12732
void Solver::resetTrail() { cancelUntil(0); }
714
715
//=================================================================================================
716
// Major methods:
717
718
719
1980387
Lit Solver::pickBranchLit()
720
{
721
    Lit nextLit;
722
723
    // Theory requests
724
1980385
    nextLit =
725
1980387
        MinisatSatSolver::toMinisatLit(d_proxy->getNextTheoryDecisionRequest());
726
1998577
    while (nextLit != lit_Undef) {
727
47895
      if(value(var(nextLit)) == l_Undef) {
728
77598
        Debug("theoryDecision")
729
38799
            << "getNextTheoryDecisionRequest(): now deciding on " << nextLit
730
38799
            << std::endl;
731
38799
        decisions++;
732
733
        // org-mode tracing -- theory decision
734
38799
        if (Trace.isOn("dtview"))
735
        {
736
          dtviewDecisionHelper(
737
              d_context->getLevel(),
738
              d_proxy->getNode(MinisatSatSolver::toSatLiteral(nextLit)),
739
              "THEORY");
740
        }
741
742
38799
        if (Trace.isOn("dtview::prop"))
743
        {
744
          dtviewPropagationHeaderHelper(d_context->getLevel());
745
        }
746
747
38799
        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
3883172
    Debug("theoryDecision")
757
1941586
        << "getNextTheoryDecisionRequest(): decide on another literal"
758
1941586
        << std::endl;
759
760
    // DE requests
761
1941586
    bool stopSearch = false;
762
1941586
    nextLit = MinisatSatSolver::toMinisatLit(
763
1941586
        d_proxy->getNextDecisionEngineRequest(stopSearch));
764
1941586
    if(stopSearch) {
765
40669
      return lit_Undef;
766
    }
767
1900917
    if(nextLit != lit_Undef) {
768
585690
      Assert(value(var(nextLit)) == l_Undef)
769
          << "literal to decide already has value";
770
585690
      decisions++;
771
585690
      Var next = var(nextLit);
772
585690
      if(polarity[next] & 0x2) {
773
135319
        nextLit = mkLit(next, polarity[next] & 0x1);
774
      }
775
776
      // org-mode tracing -- decision engine decision
777
585690
      if (Trace.isOn("dtview"))
778
      {
779
        dtviewDecisionHelper(
780
            d_context->getLevel(),
781
            d_proxy->getNode(MinisatSatSolver::toSatLiteral(nextLit)),
782
            "DE");
783
      }
784
785
585690
      if (Trace.isOn("dtview::prop"))
786
      {
787
        dtviewPropagationHeaderHelper(d_context->getLevel());
788
      }
789
790
585690
      return nextLit;
791
    }
792
793
1315227
    Var next = var_Undef;
794
795
    // Random decision:
796
1315227
    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
9919777
    while (next >= nVars() || next == var_Undef || value(next) != l_Undef || !decision[next]) {
803
4317542
        if (order_heap.empty()){
804
15267
            next = var_Undef;
805
15267
            break;
806
        }else {
807
4302275
            next = order_heap.removeMin();
808
        }
809
810
4302275
        if(!decision[next]) continue;
811
        // Check with decision engine about relevancy
812
8579248
        if (d_proxy->isDecisionRelevant(MinisatSatSolver::toSatVariable(next))
813
4289624
            == false)
814
        {
815
          next = var_Undef;
816
        }
817
    }
818
819
1315227
    if(next == var_Undef) {
820
15267
      return lit_Undef;
821
    } else {
822
1299960
      decisions++;
823
      // Check with decision engine if it can tell polarity
824
      lbool dec_pol = MinisatSatSolver::toMinisatlbool(
825
1299960
          d_proxy->getDecisionPolarity(MinisatSatSolver::toSatVariable(next)));
826
      Lit decisionLit;
827
1299960
      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
1299960
        decisionLit = mkLit(
835
1299960
            next, rnd_pol ? drand(random_seed) < 0.5 : (polarity[next] & 0x1));
836
      }
837
838
      // org-mode tracing -- decision engine decision
839
1299960
      if (Trace.isOn("dtview"))
840
      {
841
        dtviewDecisionHelper(
842
            d_context->getLevel(),
843
            d_proxy->getNode(MinisatSatSolver::toSatLiteral(decisionLit)),
844
            "DE");
845
      }
846
847
1299960
      if (Trace.isOn("dtview::prop"))
848
      {
849
        dtviewPropagationHeaderHelper(d_context->getLevel());
850
      }
851
852
1299960
      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
292432
int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
876
{
877
584864
  Trace("pf::sat") << "Solver::analyze: starting with " << confl
878
292432
                   << " with decision level " << decisionLevel() << "\n";
879
880
292432
  int pathC = 0;
881
292432
  Lit p = lit_Undef;
882
883
  // Generate conflict clause:
884
  //
885
292432
  out_learnt.push();  // (leave room for the asserting literal)
886
292432
  int index = trail.size() - 1;
887
888
292432
  int max_resolution_level = 0;  // Maximal level of the resolved clauses
889
890
292432
    if (needProof())
891
    {
892
31948
      d_pfManager->startResChain(ca[confl]);
893
    }
894
7974691
    do{
895
8267123
      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
8267123
        Clause& c = ca[confl];
903
8267123
        max_resolution_level = std::max(max_resolution_level, c.level());
904
905
8267123
        if (c.removable()) claBumpActivity(c);
906
      }
907
908
8267123
        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
8267123
        Trace("pf::sat") << cvc5::push;
919
70662411
        for (int j = (p == lit_Undef) ? 0 : 1, size = ca[confl].size();
920
70662411
             j < size;
921
             j++)
922
        {
923
62395288
          Lit q = ca[confl][j];
924
925
124790576
          Trace("pf::sat") << "Lit " << q
926
124790576
                           << " seen/level: " << (seen[var(q)] ? 1 : 0) << " / "
927
62395288
                           << level(var(q)) << "\n";
928
62395288
          if (!seen[var(q)] && level(var(q)) > 0)
929
          {
930
32927908
            varBumpActivity(var(q));
931
32927908
            seen[var(q)] = 1;
932
32927908
            if (level(var(q)) >= decisionLevel())
933
8267123
              pathC++;
934
            else
935
24660785
              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
29467380
            if (!seen[var(q)] && level(var(q)) == 0)
942
            {
943
372461
              max_resolution_level =
944
744922
                  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
29467380
            if (level(var(q)) == 0 && needProof())
949
            {
950
143411
              d_pfManager->addResolutionStep(q);
951
            }
952
          }
953
        }
954
8267123
        Trace("pf::sat") << cvc5::pop;
955
956
        // Select next clause to look at:
957
40887562
        while (!seen[var(trail[index--])]);
958
8267123
        p     = trail[index+1];
959
8267123
        confl = reason(var(p));
960
8267123
        seen[var(p)] = 0;
961
8267123
        pathC--;
962
963
8267123
        if (pathC > 0 && confl != CRef_Undef && needProof())
964
        {
965
489514
          d_pfManager->addResolutionStep(ca[confl], p);
966
        }
967
968
8267123
    } while (pathC > 0);
969
292432
    out_learnt[0] = ~p;
970
292432
    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
292432
    out_learnt.copyTo(analyze_toclear);
984
292432
    if (ccmin_mode == 2){
985
292432
        uint32_t abstract_level = 0;
986
24953217
        for (i = 1; i < out_learnt.size(); i++)
987
24660785
            abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
988
989
24953217
        for (i = j = 1; i < out_learnt.size(); i++) {
990
24660785
            if (reason(var(out_learnt[i])) == CRef_Undef) {
991
4634721
                out_learnt[j++] = out_learnt[i];
992
            } else {
993
              // Check if the literal is redundant
994
20026064
              if (!litRedundant(out_learnt[i], abstract_level)) {
995
                // Literal is not redundant
996
17623830
                out_learnt[j++] = out_learnt[i];
997
              } else {
998
2402234
                if (needProof())
999
                {
1000
123432
                  Debug("newproof::sat")
1001
61716
                      << "Solver::analyze: redundant lit "
1002
61716
                      << toSatLiteral<Minisat::Solver>(out_learnt[i]) << "\n";
1003
61716
                  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
2402234
                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
292432
    max_literals += out_learnt.size();
1031
292432
    out_learnt.shrink(i - j);
1032
292432
    tot_literals += out_learnt.size();
1033
1034
    // Find correct backtrack level:
1035
    //
1036
292432
    if (out_learnt.size() == 1)
1037
5415
        out_btlevel = 0;
1038
    else{
1039
287017
        int max_i = 1;
1040
        // Find the first literal assigned at the next-highest level:
1041
22258551
        for (int k = 2; k < out_learnt.size(); k++)
1042
21971534
          if (level(var(out_learnt[k])) > level(var(out_learnt[max_i])))
1043
549397
            max_i = k;
1044
        // Swap-in this literal at index 1:
1045
287017
        Lit p2 = out_learnt[max_i];
1046
287017
        out_learnt[max_i] = out_learnt[1];
1047
287017
        out_learnt[1] = p2;
1048
287017
        out_btlevel = level(var(p2));
1049
    }
1050
1051
27752872
    for (int k = 0; k < analyze_toclear.size(); k++)
1052
27460440
      seen[var(analyze_toclear[k])] = 0;  // ('seen[]' is now cleared)
1053
1054
    // Return the maximal resolution level
1055
292432
    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
20026064
bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
1062
{
1063
20026064
    analyze_stack.clear(); analyze_stack.push(p);
1064
20026064
    int top = analyze_toclear.size();
1065
49125374
    while (analyze_stack.size() > 0){
1066
32173485
        CRef c_reason = reason(var(analyze_stack.last()));
1067
32173485
        Assert(c_reason != CRef_Undef);
1068
32173485
        Clause& c = ca[c_reason];
1069
32173485
        int c_size = c.size();
1070
32173485
        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
137403041
        for (int i = 1; i < c_size; i++){
1075
122853386
          Lit p2 = ca[c_reason][i];
1076
122853386
          if (!seen[var(p2)] && level(var(p2)) > 0)
1077
          {
1078
126606178
            if (reason(var(p2)) != CRef_Undef
1079
63303089
                && (abstractLevel(var(p2)) & abstract_levels) != 0)
1080
            {
1081
45679259
              seen[var(p2)] = 1;
1082
45679259
              analyze_stack.push(p2);
1083
45679259
              analyze_toclear.push(p2);
1084
            }
1085
            else
1086
            {
1087
60795866
              for (int j = top; j < analyze_toclear.size(); j++)
1088
43172036
                seen[var(analyze_toclear[j])] = 0;
1089
17623830
              analyze_toclear.shrink(analyze_toclear.size() - top);
1090
17623830
              return false;
1091
            }
1092
          }
1093
        }
1094
    }
1095
1096
2402234
    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
1913
void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
1110
{
1111
1913
    out_conflict.clear();
1112
1913
    out_conflict.push(p);
1113
1114
1913
    if (decisionLevel() == 0)
1115
783
        return;
1116
1117
1130
    seen[var(p)] = 1;
1118
1119
81780
    for (int i = trail.size()-1; i >= trail_lim[0]; i--){
1120
80650
        Var x = var(trail[i]);
1121
80650
        if (seen[x]){
1122
19185
            if (reason(x) == CRef_Undef){
1123
8583
              Assert(level(x) > 0);
1124
8583
              out_conflict.push(~trail[i]);
1125
            }else{
1126
10602
                Clause& c = ca[reason(x)];
1127
37435
                for (int j = 1; j < c.size(); j++)
1128
26833
                    if (level(var(c[j])) > 0)
1129
26059
                        seen[var(c[j])] = 1;
1130
            }
1131
19185
            seen[x] = 0;
1132
        }
1133
    }
1134
1135
1130
    seen[var(p)] = 0;
1136
}
1137
1138
54126612
void Solver::uncheckedEnqueue(Lit p, CRef from)
1139
{
1140
54126612
  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
54126612
  Assert(value(p) == l_Undef);
1164
54126612
  Assert(var(p) < nVars());
1165
54126612
  assigns[var(p)] = lbool(!sign(p));
1166
54126612
  vardata[var(p)] = VarData(
1167
      from, decisionLevel(), assertionLevel, intro_level(var(p)), trail.size());
1168
54126612
  trail.push_(p);
1169
54126612
  if (theory[var(p)])
1170
  {
1171
    // Enqueue to the theory
1172
14080470
    d_proxy->enqueueTheoryLiteral(MinisatSatSolver::toSatLiteral(p));
1173
  }
1174
54126612
}
1175
1176
2703212
CRef Solver::propagate(TheoryCheckType type)
1177
{
1178
2703212
    CRef confl = CRef_Undef;
1179
2703212
    recheck = false;
1180
2703212
    theoryConflict = false;
1181
1182
5406424
    ScopedBool scoped_bool(minisat_busy, true);
1183
1184
    // Add lemmas that we're left behind
1185
2703212
    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
2703212
    if (type == CHECK_FINAL) {
1195
      // Do the theory check
1196
60238
      theoryCheck(cvc5::theory::Theory::EFFORT_FULL);
1197
      // Pick up the theory propagated literals (there could be some,
1198
      // if new lemmas are added)
1199
60227
      propagateTheory();
1200
      // If there are lemmas (or conflicts) update them
1201
60227
      if (lemmas.size() > 0) {
1202
41303
        recheck = true;
1203
41303
        confl = updateLemmas();
1204
41303
        return confl;
1205
      } else {
1206
18924
        recheck = d_proxy->theoryNeedCheck();
1207
18924
        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
688590
    do {
1214
        // Propagate on the clauses
1215
3331564
        confl = propagateBool();
1216
        // If no conflict, do the theory check
1217
3331564
        if (confl == CRef_Undef && type != CHECK_WITHOUT_THEORY) {
1218
            // Do the theory check
1219
2963670
            if (type == CHECK_FINAL_FAKE) {
1220
              theoryCheck(cvc5::theory::Theory::EFFORT_FULL);
1221
            } else {
1222
2963670
              theoryCheck(cvc5::theory::Theory::EFFORT_STANDARD);
1223
            }
1224
            // Pick up the theory propagated literals
1225
2963667
            propagateTheory();
1226
            // If there are lemmas (or conflicts) update them
1227
5927334
            if (lemmas.size() > 0) {
1228
183046
              confl = updateLemmas();
1229
            }
1230
        } else {
1231
          // if dumping decision tree, print the conflict
1232
367894
          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
367894
          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
3331561
    } while (confl == CRef_Undef && qhead < trail.size());
1258
2642971
    return confl;
1259
}
1260
1261
3023894
void Solver::propagateTheory() {
1262
6047788
  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
3023894
  d_proxy->theoryPropagate(propagatedLiteralsClause);
1266
1267
6047788
  vec<Lit> propagatedLiterals;
1268
3023894
  MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals);
1269
1270
3023894
  int oldTrailSize = trail.size();
1271
3023894
  Debug("minisat") << "old trail size is " << oldTrailSize << ", propagating " << propagatedLiterals.size() << " lits..." << std::endl;
1272
9239965
  for (unsigned i = 0, i_end = propagatedLiterals.size(); i < i_end; ++ i) {
1273
6216071
    Debug("minisat") << "Theory propagated: " << propagatedLiterals[i] << std::endl;
1274
    // multiple theories can propagate the same literal
1275
6216071
    Lit p = propagatedLiterals[i];
1276
6216071
    if (value(p) == l_Undef) {
1277
3310018
      uncheckedEnqueue(p, CRef_Lazy);
1278
    } else {
1279
2906053
      if (value(p) == l_False) {
1280
68908
        Debug("minisat") << "Conflict in theory propagation" << std::endl;
1281
137816
        SatClause explanation_cl;
1282
68908
        d_proxy->explainPropagation(MinisatSatSolver::toSatLiteral(p),
1283
                                    explanation_cl);
1284
137816
        vec<Lit> explanation;
1285
68908
        MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
1286
        ClauseId id; // FIXME: mark it as explanation here somehow?
1287
68908
        addClause(explanation, true, id);
1288
      }
1289
    }
1290
  }
1291
3023894
}
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
3023908
void Solver::theoryCheck(cvc5::theory::Theory::Effort effort)
1304
{
1305
3023908
  d_proxy->theoryCheck(effort);
1306
3023894
}
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
3331564
CRef Solver::propagateBool()
1320
{
1321
3331564
    CRef    confl     = CRef_Undef;
1322
3331564
    int     num_props = 0;
1323
3331564
    watches.cleanAll();
1324
1325
101539524
    while (qhead < trail.size()){
1326
49103980
        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
1327
49103980
        vec<Watcher>&  ws  = watches[p];
1328
        Watcher        *i, *j, *end;
1329
49103980
        num_props++;
1330
1331
        // if propagation tracing enabled, print boolean propagation
1332
49103980
        if (Trace.isOn("dtview::prop"))
1333
        {
1334
          dtviewBoolPropagationHelper(decisionLevel(), p, d_proxy);
1335
        }
1336
1337
698628379
        for (i = j = (Watcher*)ws, end = i + ws.size();  i != end;){
1338
            // Try to avoid inspecting the clause:
1339
649524399
            Lit blocker = i->blocker;
1340
1069697557
            if (value(blocker) == l_True){
1341
1285613114
                *j++ = *i++; continue; }
1342
1343
            // Make sure the false literal is data[1]:
1344
229351241
            CRef     cr        = i->cref;
1345
229351241
            Clause&  c         = ca[cr];
1346
229351241
            Lit      false_lit = ~p;
1347
229351241
            if (c[0] == false_lit)
1348
82351214
                c[0] = c[1], c[1] = false_lit;
1349
229351241
            Assert(c[1] == false_lit);
1350
229351241
            i++;
1351
1352
            // If 0th watch is true, then clause is already satisfied.
1353
229351241
            Lit     first = c[0];
1354
229351241
            Watcher w     = Watcher(cr, first);
1355
254444881
            if (first != blocker && value(first) == l_True){
1356
50187280
                *j++ = w; continue; }
1357
1358
            // Look for new watch:
1359
204257601
            Assert(c.size() >= 2);
1360
1073464558
            for (int k = 2; k < c.size(); k++)
1361
1025205639
                if (value(c[k]) != l_False){
1362
155998682
                    c[1] = c[k]; c[k] = false_lit;
1363
155998682
                    watches[~c[1]].push(w);
1364
155998682
                    goto NextClause; }
1365
1366
            // Did not find watch -- clause is unit under assignment:
1367
48258919
            *j++ = w;
1368
48258919
            if (value(first) == l_False){
1369
242310
                confl = cr;
1370
242310
                qhead = trail.size();
1371
                // Copy the remaining watches:
1372
6175116
                while (i < end)
1373
2966403
                    *j++ = *i++;
1374
            }else
1375
48016609
                uncheckedEnqueue(first, cr);
1376
1377
204257601
        NextClause:;
1378
        }
1379
49103980
        ws.shrink(i - j);
1380
    }
1381
3331564
    propagations += num_props;
1382
3331564
    simpDB_props -= num_props;
1383
1384
3331564
    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
2877
    reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
1399
4356912
    bool operator () (CRef x, CRef y) {
1400
4356912
        return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
1401
};
1402
2877
void Solver::reduceDB()
1403
{
1404
    int     i, j;
1405
2877
    double  extra_lim = cla_inc / clauses_removable.size();    // Remove any clause below this activity
1406
1407
2877
    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
399620
    for (i = j = 0; i < clauses_removable.size(); i++){
1411
396743
        Clause& c = ca[clauses_removable[i]];
1412
396743
        if (c.size() > 2 && !locked(c) && (i < clauses_removable.size() / 2 || c.activity() < extra_lim))
1413
172126
            removeClause(clauses_removable[i]);
1414
        else
1415
224617
            clauses_removable[j++] = clauses_removable[i];
1416
    }
1417
2877
    clauses_removable.shrink(i - j);
1418
2877
    checkGarbage();
1419
2877
}
1420
1421
1422
16233
void Solver::removeSatisfied(vec<CRef>& cs)
1423
{
1424
    int i, j;
1425
454777
    for (i = j = 0; i < cs.size(); i++){
1426
438544
        Clause& c = ca[cs[i]];
1427
438544
        if (satisfied(c)) {
1428
49406
          removeClause(cs[i]);
1429
        }
1430
        else
1431
        {
1432
389138
          cs[j++] = cs[i];
1433
        }
1434
    }
1435
16233
    cs.shrink(i - j);
1436
16233
}
1437
1438
7192
void Solver::removeClausesAboveLevel(vec<CRef>& cs, int level)
1439
{
1440
    int i, j;
1441
618657
    for (i = j = 0; i < cs.size(); i++){
1442
611465
        Clause& c = ca[cs[i]];
1443
611465
        if (c.level() > level) {
1444
174694
          Assert(!locked(c));
1445
174694
          removeClause(cs[i]);
1446
        } else {
1447
436771
            cs[j++] = cs[i];
1448
        }
1449
    }
1450
7192
    cs.shrink(i - j);
1451
7192
}
1452
1453
16233
void Solver::rebuildOrderHeap()
1454
{
1455
32466
    vec<Var> vs;
1456
1888148
    for (Var v = 0; v < nVars(); v++)
1457
1871915
        if (decision[v] && value(v) == l_Undef)
1458
1276503
            vs.push(v);
1459
16233
    order_heap.build(vs);
1460
16233
}
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
37995
bool Solver::simplify()
1472
{
1473
37995
  Assert(decisionLevel() == 0);
1474
1475
37995
  if (!ok || propagate(CHECK_WITHOUT_THEORY) != CRef_Undef) return ok = false;
1476
1477
37772
  if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) return true;
1478
1479
  // Remove satisfied clauses:
1480
16233
  removeSatisfied(clauses_removable);
1481
16233
  if (remove_satisfied)  // Can be turned off.
1482
    removeSatisfied(clauses_persistent);
1483
16233
  checkGarbage();
1484
16233
  rebuildOrderHeap();
1485
1486
16233
  simpDB_assigns = nAssigns();
1487
16233
  simpDB_props =
1488
16233
      clauses_literals + learnts_literals;  // (shouldn't depend on stats
1489
                                            // really, but it will do for now)
1490
1491
16233
  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
13678
lbool Solver::search(int nof_conflicts)
1509
{
1510
13678
  Assert(ok);
1511
  int backtrack_level;
1512
13678
  int conflictC = 0;
1513
27356
  vec<Lit> learnt_clause;
1514
13678
  starts++;
1515
1516
13678
  TheoryCheckType check_type = CHECK_WITH_THEORY;
1517
  for (;;)
1518
  {
1519
    // Propagate and call the theory solvers
1520
2577582
    CRef confl = propagate(check_type);
1521
2577568
    Assert(lemmas.size() == 0);
1522
1523
2577568
    if (confl != CRef_Undef)
1524
    {
1525
295564
      conflicts++;
1526
295564
      conflictC++;
1527
1528
295564
      if (decisionLevel() == 0)
1529
      {
1530
3132
        if (needProof())
1531
        {
1532
830
          if (confl == CRef_Lazy)
1533
          {
1534
45
            d_pfManager->finalizeProof();
1535
          }
1536
          else
1537
          {
1538
785
            d_pfManager->finalizeProof(ca[confl]);
1539
          }
1540
        }
1541
3132
        return l_False;
1542
      }
1543
1544
      // Analyze the conflict
1545
292432
      learnt_clause.clear();
1546
292432
      int max_level = analyze(confl, learnt_clause, backtrack_level);
1547
292432
      cancelUntil(backtrack_level);
1548
1549
      // Assert the conflict clause and the asserting literal
1550
292432
      if (learnt_clause.size() == 1)
1551
      {
1552
5415
        uncheckedEnqueue(learnt_clause[0]);
1553
5415
        if (needProof())
1554
        {
1555
1326
          d_pfManager->endResChain(learnt_clause[0]);
1556
        }
1557
      }
1558
      else
1559
      {
1560
287017
        CRef cr = ca.alloc(assertionLevelOnly() ? assertionLevel : max_level,
1561
                           learnt_clause,
1562
287017
                           true);
1563
287017
        clauses_removable.push(cr);
1564
287017
        attachClause(cr);
1565
287017
        claBumpActivity(ca[cr]);
1566
287017
        uncheckedEnqueue(learnt_clause[0], cr);
1567
287017
        if (needProof())
1568
        {
1569
30622
          d_pfManager->endResChain(ca[cr]);
1570
        }
1571
      }
1572
1573
292432
      varDecayActivity();
1574
292432
      claDecayActivity();
1575
1576
292432
      if (--learntsize_adjust_cnt == 0)
1577
      {
1578
521
        learntsize_adjust_confl *= learntsize_adjust_inc;
1579
521
        learntsize_adjust_cnt = (int)learntsize_adjust_confl;
1580
521
        max_learnts *= learntsize_inc;
1581
1582
521
        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
343173
      if (theoryConflict && options::sat_refine_conflicts())
1596
      {
1597
        check_type = CHECK_FINAL_FAKE;
1598
      }
1599
      else
1600
      {
1601
292432
        check_type = CHECK_WITH_THEORY;
1602
      }
1603
    }
1604
    else
1605
    {
1606
      // If this was a final check, we are satisfiable
1607
2282004
      if (check_type == CHECK_FINAL)
1608
      {
1609
53928
        bool decisionEngineDone = d_proxy->isDecisionEngineDone();
1610
        // Unless a lemma has added more stuff to the queues
1611
151345
        if (!decisionEngineDone
1612
53928
            && (!order_heap.empty() || qhead < trail.size()))
1613
        {
1614
43489
          check_type = CHECK_WITH_THEORY;
1615
147216
          continue;
1616
        }
1617
10439
        else if (recheck)
1618
        {
1619
          // There some additional stuff added, so we go for another
1620
          // full-check
1621
4302
          continue;
1622
        }
1623
        else
1624
        {
1625
          // Yes, we're truly satisfiable
1626
6137
          return l_True;
1627
        }
1628
      }
1629
2228076
      else if (check_type == CHECK_FINAL_FAKE)
1630
      {
1631
        check_type = CHECK_WITH_THEORY;
1632
      }
1633
1634
4456152
      if ((nof_conflicts >= 0 && conflictC >= nof_conflicts)
1635
4453672
          || !withinBudget(Resource::SatConflictStep))
1636
      {
1637
        // Reached bound on number of conflicts:
1638
2480
        progress_estimate = progressEstimate();
1639
2480
        cancelUntil(0);
1640
        // [mdeters] notify theory engine of restarts for deferred
1641
        // theory processing
1642
2480
        d_proxy->notifyRestart();
1643
2480
        return l_Undef;
1644
      }
1645
1646
      // Simplify the set of problem clauses:
1647
2225596
      if (decisionLevel() == 0 && !simplify())
1648
      {
1649
        return l_False;
1650
      }
1651
1652
2225596
      if (clauses_removable.size() - nAssigns() >= max_learnts)
1653
      {
1654
        // Reduce the set of learnt clauses:
1655
2877
        reduceDB();
1656
      }
1657
1658
2225596
      Lit next = lit_Undef;
1659
2264068
      while (decisionLevel() < assumptions.size())
1660
      {
1661
        // Perform user provided assumption:
1662
264445
        Lit p = assumptions[decisionLevel()];
1663
264445
        if (value(p) == l_True)
1664
        {
1665
          // Dummy decision level:
1666
19236
          newDecisionLevel();
1667
        }
1668
245209
        else if (value(p) == l_False)
1669
        {
1670
1913
          analyzeFinal(~p, d_conflict);
1671
1913
          return l_False;
1672
        }
1673
        else
1674
        {
1675
243296
          next = p;
1676
243296
          break;
1677
        }
1678
      }
1679
1680
2223683
      if (next == lit_Undef)
1681
      {
1682
        // New variable decision:
1683
1980387
        next = pickBranchLit();
1684
1685
2036321
        if (next == lit_Undef)
1686
        {
1687
          // We need to do a full theory check to confirm
1688
111872
          Debug("minisat::search")
1689
55936
              << "Doing a full theory check..." << std::endl;
1690
55936
          check_type = CHECK_FINAL;
1691
55936
          continue;
1692
        }
1693
      }
1694
1695
      // Increase decision level and enqueue 'next'
1696
2167745
      newDecisionLevel();
1697
2167745
      uncheckedEnqueue(next);
1698
    }
1699
2563904
  }
1700
}
1701
1702
1703
2480
double Solver::progressEstimate() const
1704
{
1705
2480
    double  progress = 0;
1706
2480
    double  F = 1.0 / nVars();
1707
1708
181600
    for (int i = 0; i <= decisionLevel(); i++){
1709
179120
        int beg = i == 0 ? 0 : trail_lim[i - 1];
1710
179120
        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
1711
179120
        progress += pow(F, i) * (end - beg);
1712
    }
1713
1714
2480
    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
13678
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
13678
    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1);
1735
1736
24974
    while (size-1 != x){
1737
5648
        size = (size-1)>>1;
1738
5648
        seq--;
1739
5648
        x = x % size;
1740
    }
1741
1742
13678
    return pow(y, seq);
1743
}
1744
1745
// NOTE: assumptions passed in member-variable 'assumptions'.
1746
12514
lbool Solver::solve_()
1747
{
1748
12514
    Debug("minisat") << "nvars = " << nVars() << std::endl;
1749
1750
25028
    ScopedBool scoped_bool(minisat_busy, true);
1751
1752
12514
    Assert(decisionLevel() == 0);
1753
1754
12514
    model.clear();
1755
12514
    d_conflict.clear();
1756
12514
    if (!ok){
1757
1316
      minisat_busy = false;
1758
1316
      return l_False;
1759
    }
1760
1761
11198
    solves++;
1762
1763
11198
    max_learnts               = nClauses() * learntsize_factor;
1764
11198
    learntsize_adjust_confl   = learntsize_adjust_start_confl;
1765
11198
    learntsize_adjust_cnt     = (int)learntsize_adjust_confl;
1766
11198
    lbool   status            = l_Undef;
1767
1768
11198
    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
11198
    int curr_restarts = 0;
1777
38522
    while (status == l_Undef){
1778
13678
        double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts);
1779
13678
        status = search(rest_base * restart_first);
1780
13662
        if (!withinBudget(Resource::SatConflictStep))
1781
          break;  // FIXME add restart option?
1782
13662
        curr_restarts++;
1783
    }
1784
1785
11182
    if (!withinBudget(Resource::SatConflictStep))
1786
      status = l_Undef;
1787
1788
11182
    if (verbosity >= 1)
1789
1
        printf("===============================================================================\n");
1790
1791
1792
11182
    if (status == l_True){
1793
        // Extend & copy model:
1794
6137
        model.growTo(nVars());
1795
531974
        for (int i = 0; i < nVars(); i++) {
1796
525837
          model[i] = value(i);
1797
525837
          Debug("minisat") << i << " = " << model[i] << std::endl;
1798
        }
1799
    }
1800
5045
    else if (status == l_False && d_conflict.size() == 0)
1801
3132
      ok = false;
1802
1803
11182
    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
2512
void Solver::relocAll(ClauseAllocator& to)
1891
{
1892
    // All watchers:
1893
    //
1894
    // for (int i = 0; i < watches.size(); i++)
1895
2512
    watches.cleanAll();
1896
569111
    for (int v = 0; v < nVars(); v++)
1897
1699797
        for (int s = 0; s < 2; s++){
1898
1133198
            Lit p = mkLit(v, s);
1899
            // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
1900
1133198
            vec<Watcher>& ws = watches[p];
1901
2839954
            for (int j = 0; j < ws.size(); j++)
1902
            {
1903
1706756
              ca.reloc(ws[j].cref, to);
1904
            }
1905
        }
1906
1907
    // All reasons:
1908
    //
1909
170269
    for (int i = 0; i < trail.size(); i++){
1910
167757
        Var v = var(trail[i]);
1911
1912
335514
        if (hasReasonClause(v)
1913
167757
            && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
1914
        {
1915
36584
          ca.reloc(vardata[v].d_reason, to);
1916
        }
1917
    }
1918
    // All learnt:
1919
    //
1920
177524
    for (int i = 0; i < clauses_removable.size(); i++)
1921
    {
1922
175012
      ca.reloc(clauses_removable[i], to);
1923
    }
1924
    // All original:
1925
    //
1926
680878
    for (int i = 0; i < clauses_persistent.size(); i++)
1927
    {
1928
678366
      ca.reloc(clauses_persistent[i], to);
1929
    }
1930
2512
}
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
3596
void Solver::push()
1947
{
1948
3596
  Assert(d_enable_incremental);
1949
3596
  Assert(decisionLevel() == 0);
1950
1951
3596
  ++assertionLevel;
1952
3596
  Debug("minisat") << "in user push, increasing assertion level to " << assertionLevel << std::endl;
1953
3596
  trail_ok.push(ok);
1954
3596
  assigns_lim.push(assigns.size());
1955
1956
3596
  d_context->push();  // SAT context for cvc5
1957
1958
3596
  Debug("minisat") << "MINISAT PUSH assertionLevel is " << assertionLevel << ", trail.size is " << trail.size() << std::endl;
1959
3596
}
1960
1961
3596
void Solver::pop()
1962
{
1963
3596
  Assert(d_enable_incremental);
1964
1965
3596
  Assert(decisionLevel() == 0);
1966
1967
  // Pop the trail below the user level
1968
3596
  --assertionLevel;
1969
7192
  Debug("minisat") << "in user pop, decreasing assertion level to "
1970
3596
                   << assertionLevel << "\n"
1971
3596
                   << cvc5::push;
1972
  while (true) {
1973
55690
    Debug("minisat") << "== unassigning " << trail.last() << std::endl;
1974
55690
    Var      x  = var(trail.last());
1975
55690
    if (user_level(x) > assertionLevel) {
1976
52094
      assigns[x] = l_Undef;
1977
52094
      vardata[x] = VarData(CRef_Undef, -1, -1, intro_level(x), -1);
1978
52094
      if(phase_saving >= 1 && (polarity[x] & 0x2) == 0)
1979
51113
        polarity[x] = sign(trail.last());
1980
52094
      insertVarOrder(x);
1981
52094
      trail.pop();
1982
    } else {
1983
3596
      break;
1984
    }
1985
52094
  }
1986
1987
  // The head should be at the trail top
1988
3596
  qhead = trail.size();
1989
1990
  // Remove the clauses
1991
3596
  removeClausesAboveLevel(clauses_persistent, assertionLevel);
1992
3596
  removeClausesAboveLevel(clauses_removable, assertionLevel);
1993
3596
  Debug("minisat") << cvc5::pop;
1994
  // Pop the SAT context to notify everyone
1995
3596
  d_context->pop();  // SAT context for cvc5
1996
1997
7192
  Debug("minisat") << "MINISAT POP assertionLevel is " << assertionLevel
1998
3596
                   << ", trail.size is " << trail.size() << "\n";
1999
  // Pop the created variables
2000
3596
  resizeVars(assigns_lim.last());
2001
3596
  assigns_lim.pop();
2002
3596
  variables_to_register.clear();
2003
2004
  // Pop the OK
2005
3596
  ok = trail_ok.last();
2006
3596
  trail_ok.pop();
2007
3596
}
2008
2009
224393
CRef Solver::updateLemmas() {
2010
2011
224393
  Debug("minisat::lemmas") << "Solver::updateLemmas() begin" << std::endl;
2012
2013
  // Avoid adding lemmas indefinitely without resource-out
2014
224393
  d_proxy->spendResource(Resource::LemmaStep);
2015
2016
224393
  CRef conflict = CRef_Undef;
2017
2018
  // Decision level to backtrack to
2019
224393
  int backtrackLevel = decisionLevel();
2020
2021
  // We use this comparison operator
2022
224393
  lemma_lt lt(*this);
2023
2024
  // Check for propagation and level to backtrack to
2025
224393
  int i = 0;
2026
673295
  while (i < lemmas.size()) {
2027
    // We need this loop as when we backtrack, due to registration more lemmas could be added
2028
1654351
    for (; i < lemmas.size(); ++ i)
2029
    {
2030
      // The current lemma
2031
714950
      vec<Lit>& lemma = lemmas[i];
2032
2033
714950
      Trace("pf::sat") << "Solver::updateLemmas: working on lemma: ";
2034
3551912
      for (int k = 0; k < lemma.size(); ++k) {
2035
2836962
        Trace("pf::sat") << lemma[k] << " ";
2036
      }
2037
714950
      Trace("pf::sat") << std::endl;
2038
2039
      // If it's an empty lemma, we have a conflict at zero level
2040
716142
      if (lemma.size() == 0) {
2041
1192
        Assert(!options::unsatCores() && !needProof());
2042
1192
        conflict = CRef_Lazy;
2043
1192
        backtrackLevel = 0;
2044
1192
        Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
2045
1192
        continue;
2046
      }
2047
      // Sort the lemma to be able to attach
2048
713758
      sort(lemma, lt);
2049
      // See if the lemma propagates something
2050
713758
      if (lemma.size() == 1 || value(lemma[1]) == l_False) {
2051
374955
        Debug("minisat::lemmas") << "found unit " << lemma.size() << std::endl;
2052
        // This lemma propagates, see which level we need to backtrack to
2053
374955
        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
374955
        if (value(lemma[0]) != l_True || level(var(lemma[0])) > currentBacktrackLevel) {
2056
364992
          if (currentBacktrackLevel < backtrackLevel) {
2057
129300
            backtrackLevel = currentBacktrackLevel;
2058
          }
2059
        }
2060
      }
2061
    }
2062
2063
    // Pop so that propagation would be current
2064
224451
    Debug("minisat::lemmas") << "Solver::updateLemmas(): backtracking to " << backtrackLevel << " from " << decisionLevel() << std::endl;
2065
224451
    cancelUntil(backtrackLevel);
2066
  }
2067
2068
  // Last index in the trail
2069
224393
  int backtrack_index = trail.size();
2070
2071
  // Attach all the clauses and enqueue all the propagations
2072
939343
  for (int j = 0; j < lemmas.size(); ++j)
2073
  {
2074
    // The current lemma
2075
714950
    vec<Lit>& lemma = lemmas[j];
2076
714950
    bool removable = lemmas_removable[j];
2077
2078
    // Attach it if non-unit
2079
714950
    CRef lemma_ref = CRef_Undef;
2080
714950
    if (lemma.size() > 1) {
2081
      // If the lemmas is removable, we can compute its level by the level
2082
657402
      int clauseLevel = assertionLevel;
2083
657402
      if (removable && !assertionLevelOnly())
2084
      {
2085
168386
        clauseLevel = 0;
2086
1570032
        for (int k = 0; k < lemma.size(); ++k)
2087
        {
2088
1401646
          clauseLevel = std::max(clauseLevel, intro_level(var(lemma[k])));
2089
        }
2090
      }
2091
2092
657402
      lemma_ref = ca.alloc(clauseLevel, lemma, removable);
2093
657402
      if (removable) {
2094
172456
        clauses_removable.push(lemma_ref);
2095
      } else {
2096
484946
        clauses_persistent.push(lemma_ref);
2097
      }
2098
657402
      attachClause(lemma_ref);
2099
    }
2100
2101
    // If the lemma is propagating enqueue its literal (or set the conflict)
2102
714950
    if (conflict == CRef_Undef && value(lemma[0]) != l_True) {
2103
664642
      if (lemma.size() == 1 || (value(lemma[1]) == l_False && trail_index(var(lemma[1])) < backtrack_index)) {
2104
589506
        Trace("pf::sat") << "Solver::updateLemmas: unit theory lemma: "
2105
294753
                         << lemma[0] << std::endl;
2106
294753
        if (value(lemma[0]) == l_False) {
2107
          // We have a conflict
2108
52210
          if (lemma.size() > 1) {
2109
51816
            Debug("minisat::lemmas") << "Solver::updateLemmas(): conflict" << std::endl;
2110
51816
            conflict = lemma_ref;
2111
          } else {
2112
394
            Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
2113
394
            conflict = CRef_Lazy;
2114
394
            if (needProof())
2115
            {
2116
45
              d_pfManager->storeUnitConflict(lemma[0]);
2117
            }
2118
          }
2119
        } else {
2120
242543
          Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
2121
242543
          Debug("minisat::lemmas") << "lemma ref is " << lemma_ref << std::endl;
2122
242543
          uncheckedEnqueue(lemma[0], lemma_ref);
2123
        }
2124
      }
2125
    }
2126
  }
2127
2128
  // Clear the lemmas
2129
224393
  lemmas.clear();
2130
224393
  lemmas_removable.clear();
2131
2132
224393
  if (conflict != CRef_Undef) {
2133
53300
    theoryConflict = true;
2134
  }
2135
2136
224393
  Debug("minisat::lemmas") << "Solver::updateLemmas() end" << std::endl;
2137
2138
224393
  return conflict;
2139
}
2140
2141
3270075
void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to)
2142
{
2143
3270075
  Debug("minisat") << "ClauseAllocator::reloc: cr " << cr << std::endl;
2144
  // FIXME what is this CRef_lazy
2145
3270075
  if (cr == CRef_Lazy) return;
2146
2147
3270075
  Clause& c = operator[](cr);
2148
3270075
  if (c.reloced()) { cr = c.relocation(); return; }
2149
2150
854073
  cr = to.alloc(c.level(), c, c.removable());
2151
854073
  c.relocate(cr);
2152
  // Copy extra data-fields:
2153
  // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
2154
854073
  to[cr].mark(c.mark());
2155
854073
  if (to[cr].removable())         to[cr].activity() = c.activity();
2156
679061
  else if (to[cr].has_extra()) to[cr].calcAbstraction();
2157
}
2158
2159
2250440
inline bool Solver::withinBudget(Resource r) const
2160
{
2161
2250440
  Assert(d_proxy);
2162
  // spendResource sets async_interrupt or throws UnsafeInterruptException
2163
  // depending on whether hard-limit is enabled
2164
2250440
  d_proxy->spendResource(r);
2165
2166
2250440
  bool within_budget =
2167
4500880
      !asynch_interrupt && (conflict_budget < 0 || conflicts < conflict_budget)
2168
4500880
      && (propagation_budget < 0 || propagations < propagation_budget);
2169
2250440
  return within_budget;
2170
}
2171
2172
2438
SatProofManager* Solver::getProofManager()
2173
{
2174
2438
  return isProofEnabled() ? d_pfManager.get() : nullptr;
2175
}
2176
2177
2709
std::shared_ptr<ProofNode> Solver::getProof()
2178
{
2179
2709
  return isProofEnabled() ? d_pfManager->getProof() : nullptr;
2180
}
2181
2182
13673851
bool Solver::isProofEnabled() const { return d_pfManager != nullptr; }
2183
2184
13668704
bool Solver::needProof() const
2185
{
2186
13668704
  return isProofEnabled()
2187
15115121
         && options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS;
2188
}
2189
2190
}  // namespace Minisat
2191
30870242
}  // namespace cvc5