GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/minisat/core/Solver.cc Lines: 856 1027 83.3 %
Date: 2021-11-07 Branches: 1178 2784 42.3 %

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