GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/prop_engine.cpp Lines: 247 341 72.4 %
Date: 2021-05-22 Branches: 361 1202 30.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Haniel Barbosa, Morgan Deters
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implementation of the propositional engine of cvc5.
14
 */
15
16
#include "prop/prop_engine.h"
17
18
#include <iomanip>
19
#include <map>
20
#include <utility>
21
22
#include "base/check.h"
23
#include "base/output.h"
24
#include "decision/decision_engine.h"
25
#include "decision/decision_engine_old.h"
26
#include "options/base_options.h"
27
#include "options/decision_options.h"
28
#include "options/main_options.h"
29
#include "options/options.h"
30
#include "options/proof_options.h"
31
#include "options/smt_options.h"
32
#include "prop/cnf_stream.h"
33
#include "prop/minisat/minisat.h"
34
#include "prop/prop_proof_manager.h"
35
#include "prop/sat_solver.h"
36
#include "prop/sat_solver_factory.h"
37
#include "prop/theory_proxy.h"
38
#include "smt/env.h"
39
#include "smt/smt_statistics_registry.h"
40
#include "theory/output_channel.h"
41
#include "theory/theory_engine.h"
42
#include "util/resource_manager.h"
43
#include "util/result.h"
44
45
namespace cvc5 {
46
namespace prop {
47
48
/** Keeps a boolean flag scoped */
49
class ScopedBool {
50
51
private:
52
53
  bool d_original;
54
  bool& d_reference;
55
56
public:
57
58
14310
  ScopedBool(bool& reference) :
59
14310
    d_reference(reference) {
60
14310
    d_original = reference;
61
14310
  }
62
63
28620
  ~ScopedBool() {
64
14310
    d_reference = d_original;
65
14310
  }
66
};
67
68
9494
PropEngine::PropEngine(TheoryEngine* te,
69
                       Env& env,
70
                       OutputManager& outMgr,
71
9494
                       ProofNodeManager* pnm)
72
    : d_inCheckSat(false),
73
      d_theoryEngine(te),
74
      d_env(env),
75
9494
      d_skdm(new SkolemDefManager(d_env.getContext(), d_env.getUserContext())),
76
      d_theoryProxy(nullptr),
77
      d_satSolver(nullptr),
78
      d_pnm(pnm),
79
      d_cnfStream(nullptr),
80
      d_pfCnfStream(nullptr),
81
      d_ppm(nullptr),
82
      d_interrupted(false),
83
      d_outMgr(outMgr),
84
18988
      d_assumptions(d_env.getUserContext())
85
{
86
9494
  Debug("prop") << "Constructing the PropEngine" << std::endl;
87
9494
  context::Context* satContext = d_env.getContext();
88
9494
  context::UserContext* userContext = d_env.getUserContext();
89
9494
  ResourceManager* rm = d_env.getResourceManager();
90
91
18988
  d_decisionEngine.reset(
92
9494
      new decision::DecisionEngine(satContext, userContext, d_skdm.get(), rm));
93
94
9494
  d_satSolver = SatSolverFactory::createCDCLTMinisat(smtStatisticsRegistry());
95
96
  // CNF stream and theory proxy required pointers to each other, make the
97
  // theory proxy first
98
9494
  d_theoryProxy = new TheoryProxy(this,
99
                                  d_theoryEngine,
100
9494
                                  d_decisionEngine.get(),
101
9494
                                  d_skdm.get(),
102
                                  satContext,
103
                                  userContext,
104
9494
                                  pnm);
105
28482
  d_cnfStream = new CnfStream(d_satSolver,
106
9494
                              d_theoryProxy,
107
                              userContext,
108
9494
                              &d_outMgr,
109
                              rm,
110
18988
                              FormulaLitPolicy::TRACK);
111
112
  // connect theory proxy
113
9494
  d_theoryProxy->finishInit(d_cnfStream);
114
  // connect SAT solver
115
37976
  d_satSolver->initialize(
116
9494
      d_env.getContext(),
117
      d_theoryProxy,
118
9494
      d_env.getUserContext(),
119
9494
      options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS
120
          ? pnm
121
9494
          : nullptr);
122
123
9494
  d_decisionEngine->finishInit(d_satSolver, d_cnfStream);
124
9494
  if (pnm && options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS)
125
  {
126
2394
    d_pfCnfStream.reset(new ProofCnfStream(
127
        userContext,
128
1197
        *d_cnfStream,
129
1197
        static_cast<MinisatSatSolver*>(d_satSolver)->getProofManager(),
130
2394
        pnm));
131
2394
    d_ppm.reset(
132
1197
        new PropPfManager(userContext, pnm, d_satSolver, d_pfCnfStream.get()));
133
  }
134
9494
}
135
136
9494
void PropEngine::finishInit()
137
{
138
9494
  NodeManager* nm = NodeManager::currentNM();
139
9494
  d_cnfStream->convertAndAssert(nm->mkConst(true), false, false);
140
  // this is necessary because if True is later asserted to the prop engine the
141
  // CNF stream will ignore it since the SAT solver already had it registered,
142
  // thus not having True as an assumption for the SAT proof. To solve this
143
  // issue we track it directly here
144
9494
  if (isProofEnabled())
145
  {
146
1197
    static_cast<MinisatSatSolver*>(d_satSolver)
147
        ->getProofManager()
148
1197
        ->registerSatAssumptions({nm->mkConst(true)});
149
  }
150
9494
  d_cnfStream->convertAndAssert(nm->mkConst(false).notNode(), false, false);
151
9494
}
152
153
18988
PropEngine::~PropEngine() {
154
9494
  Debug("prop") << "Destructing the PropEngine" << std::endl;
155
9494
  d_decisionEngine.reset(nullptr);
156
9494
  delete d_cnfStream;
157
9494
  delete d_satSolver;
158
9494
  delete d_theoryProxy;
159
9494
}
160
161
104712
theory::TrustNode PropEngine::preprocess(
162
    TNode node,
163
    std::vector<theory::TrustNode>& newLemmas,
164
    std::vector<Node>& newSkolems)
165
{
166
104712
  return d_theoryProxy->preprocess(node, newLemmas, newSkolems);
167
}
168
169
4
theory::TrustNode PropEngine::removeItes(
170
    TNode node,
171
    std::vector<theory::TrustNode>& newLemmas,
172
    std::vector<Node>& newSkolems)
173
{
174
4
  return d_theoryProxy->removeItes(node, newLemmas, newSkolems);
175
}
176
177
12874
void PropEngine::assertInputFormulas(
178
    const std::vector<Node>& assertions,
179
    std::unordered_map<size_t, Node>& skolemMap)
180
{
181
12874
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
182
  // notify the theory engine of preprocessed assertions
183
12874
  d_theoryEngine->notifyPreprocessedAssertions(assertions);
184
  // Now, notify the theory proxy of the assertions and skolem definitions.
185
  // Notice we do this before asserting the formulas to the CNF stream below,
186
  // since (preregistration) lemmas may occur during calls to assertInternal.
187
  // These lemmas we want to be notified about after the theory proxy has
188
  // been notified about all input assertions.
189
12874
  std::unordered_map<size_t, Node>::iterator it;
190
136144
  for (size_t i = 0, asize = assertions.size(); i < asize; i++)
191
  {
192
    // is the assertion a skolem definition?
193
123270
    it = skolemMap.find(i);
194
246540
    Node skolem;
195
123270
    if (it != skolemMap.end())
196
    {
197
19220
      skolem = it->second;
198
    }
199
123270
    d_theoryProxy->notifyAssertion(assertions[i], skolem);
200
  }
201
136134
  for (const Node& node : assertions)
202
  {
203
123264
    Debug("prop") << "assertFormula(" << node << ")" << std::endl;
204
123268
    assertInternal(node, false, false, true);
205
  }
206
12870
}
207
208
414663
void PropEngine::assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p)
209
{
210
414663
  bool removable = isLemmaPropertyRemovable(p);
211
212
  // call preprocessor
213
829326
  std::vector<theory::TrustNode> ppLemmas;
214
829326
  std::vector<Node> ppSkolems;
215
  theory::TrustNode tplemma =
216
829326
      d_theoryProxy->preprocessLemma(tlemma, ppLemmas, ppSkolems);
217
218
414661
  Assert(ppSkolems.size() == ppLemmas.size());
219
220
  // do final checks on the lemmas we are about to send
221
14429519
  if (isProofEnabled() && options::proofEagerChecking())
222
  {
223
    Assert(tplemma.getGenerator() != nullptr);
224
    // ensure closed, make the proof node eagerly here to debug
225
    tplemma.debugCheckClosed("te-proof-debug", "TheoryEngine::lemma");
226
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
227
    {
228
      Assert(ppLemmas[i].getGenerator() != nullptr);
229
      ppLemmas[i].debugCheckClosed("te-proof-debug", "TheoryEngine::lemma_new");
230
    }
231
  }
232
233
414661
  if (Trace.isOn("te-lemma"))
234
  {
235
    Trace("te-lemma") << "Lemma, output: " << tplemma.getProven() << std::endl;
236
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
237
    {
238
      Trace("te-lemma") << "Lemma, new lemma: " << ppLemmas[i].getProven()
239
                        << " (skolem is " << ppSkolems[i] << ")" << std::endl;
240
    }
241
  }
242
243
  // now, assert the lemmas
244
414661
  assertLemmasInternal(tplemma, ppLemmas, ppSkolems, removable);
245
414661
}
246
247
426311
void PropEngine::assertTrustedLemmaInternal(theory::TrustNode trn,
248
                                            bool removable)
249
{
250
852622
  Node node = trn.getNode();
251
426311
  Debug("prop::lemmas") << "assertLemma(" << node << ")" << std::endl;
252
426311
  bool negated = trn.getKind() == theory::TrustNodeKind::CONFLICT;
253
426311
  Assert(
254
      !isProofEnabled() || trn.getGenerator() != nullptr
255
      || options::unsatCores()
256
      || (options::unsatCores()
257
          && options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF));
258
426311
  assertInternal(trn.getNode(), negated, removable, false, trn.getGenerator());
259
426311
}
260
261
549575
void PropEngine::assertInternal(
262
    TNode node, bool negated, bool removable, bool input, ProofGenerator* pg)
263
{
264
  // Assert as (possibly) removable
265
549575
  if (options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS)
266
  {
267
163762
    if (input)
268
    {
269
33139
      d_cnfStream->ensureLiteral(node);
270
33139
      if (negated)
271
      {
272
        d_assumptions.push_back(node.notNode());
273
      }
274
      else
275
      {
276
33139
        d_assumptions.push_back(node);
277
      }
278
    }
279
    else
280
    {
281
130623
      d_cnfStream->convertAndAssert(node, removable, negated, input);
282
    }
283
  }
284
385813
  else if (isProofEnabled())
285
  {
286
90682
    d_pfCnfStream->convertAndAssert(node, negated, removable, pg);
287
    // if input, register the assertion in the proof manager
288
90682
    if (input)
289
    {
290
20959
      d_ppm->registerAssertion(node);
291
    }
292
  }
293
  else
294
  {
295
295135
    d_cnfStream->convertAndAssert(node, removable, negated, input);
296
  }
297
549571
}
298
299
572681
void PropEngine::assertLemmasInternal(
300
    theory::TrustNode trn,
301
    const std::vector<theory::TrustNode>& ppLemmas,
302
    const std::vector<Node>& ppSkolems,
303
    bool removable)
304
{
305
572681
  if (!trn.isNull())
306
  {
307
414661
    assertTrustedLemmaInternal(trn, removable);
308
  }
309
584331
  for (const theory::TrustNode& tnl : ppLemmas)
310
  {
311
11650
    assertTrustedLemmaInternal(tnl, removable);
312
  }
313
  // assert to decision engine
314
572681
  if (!removable)
315
  {
316
    // also add to the decision engine, where notice we don't need proofs
317
457529
    if (!trn.isNull())
318
    {
319
      // notify the theory proxy of the lemma
320
299509
      d_theoryProxy->notifyAssertion(trn.getProven());
321
    }
322
457529
    Assert(ppSkolems.size() == ppLemmas.size());
323
469179
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
324
    {
325
23300
      Node lem = ppLemmas[i].getProven();
326
11650
      d_theoryProxy->notifyAssertion(ppLemmas[i].getProven(), ppSkolems[i]);
327
    }
328
  }
329
572681
}
330
331
59362
void PropEngine::requirePhase(TNode n, bool phase) {
332
59362
  Debug("prop") << "requirePhase(" << n << ", " << phase << ")" << std::endl;
333
334
59362
  Assert(n.getType().isBoolean());
335
59362
  SatLiteral lit = d_cnfStream->getLiteral(n);
336
59362
  d_satSolver->requirePhase(phase ? lit : ~lit);
337
59362
}
338
339
226480
bool PropEngine::isDecision(Node lit) const {
340
226480
  Assert(isSatLiteral(lit));
341
226480
  return d_satSolver->isDecision(d_cnfStream->getLiteral(lit).getSatVariable());
342
}
343
344
int32_t PropEngine::getDecisionLevel(Node lit) const
345
{
346
  Assert(isSatLiteral(lit));
347
  return d_satSolver->getDecisionLevel(
348
      d_cnfStream->getLiteral(lit).getSatVariable());
349
}
350
351
int32_t PropEngine::getIntroLevel(Node lit) const
352
{
353
  Assert(isSatLiteral(lit));
354
  return d_satSolver->getIntroLevel(
355
      d_cnfStream->getLiteral(lit).getSatVariable());
356
}
357
358
void PropEngine::printSatisfyingAssignment(){
359
  const CnfStream::NodeToLiteralMap& transCache =
360
    d_cnfStream->getTranslationCache();
361
  Debug("prop-value") << "Literal | Value | Expr" << std::endl
362
                      << "----------------------------------------"
363
                      << "-----------------" << std::endl;
364
  for(CnfStream::NodeToLiteralMap::const_iterator i = transCache.begin(),
365
      end = transCache.end();
366
      i != end;
367
      ++i) {
368
    std::pair<Node, SatLiteral> curr = *i;
369
    SatLiteral l = curr.second;
370
    if(!l.isNegated()) {
371
      Node n = curr.first;
372
      SatValue value = d_satSolver->modelValue(l);
373
      Debug("prop-value") << "'" << l << "' " << value << " " << n << std::endl;
374
    }
375
  }
376
}
377
378
14310
Result PropEngine::checkSat() {
379
14310
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
380
14310
  Debug("prop") << "PropEngine::checkSat()" << std::endl;
381
382
  // Mark that we are in the checkSat
383
28620
  ScopedBool scopedBool(d_inCheckSat);
384
14310
  d_inCheckSat = true;
385
386
  // TODO This currently ignores conflicts (a dangerous practice).
387
14310
  d_decisionEngine->presolve();
388
14310
  d_theoryEngine->presolve();
389
390
28623
  if(options::preprocessOnly()) {
391
3
    return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK);
392
  }
393
394
  // Reset the interrupted flag
395
14307
  d_interrupted = false;
396
397
  // Check the problem
398
  SatValue result;
399
14307
  if (d_assumptions.size() == 0)
400
  {
401
10806
    result = d_satSolver->solve();
402
  }
403
  else
404
  {
405
7002
    std::vector<SatLiteral> assumptions;
406
51354
    for (const Node& node : d_assumptions)
407
    {
408
47853
      assumptions.push_back(d_cnfStream->getLiteral(node));
409
    }
410
3501
    result = d_satSolver->solve(assumptions);
411
  }
412
413
14291
  if( result == SAT_VALUE_UNKNOWN ) {
414
    ResourceManager* rm = d_env.getResourceManager();
415
    Result::UnknownExplanation why = Result::INTERRUPTED;
416
    if (rm->outOfTime())
417
    {
418
      why = Result::TIMEOUT;
419
    }
420
    if (rm->outOfResources())
421
    {
422
      why = Result::RESOURCEOUT;
423
    }
424
    return Result(Result::SAT_UNKNOWN, why);
425
  }
426
427
14291
  if( result == SAT_VALUE_TRUE && Debug.isOn("prop") ) {
428
    printSatisfyingAssignment();
429
  }
430
431
14291
  Debug("prop") << "PropEngine::checkSat() => " << result << std::endl;
432
14291
  if(result == SAT_VALUE_TRUE && d_theoryEngine->isIncomplete()) {
433
88
    return Result(Result::SAT_UNKNOWN, Result::INCOMPLETE);
434
  }
435
14203
  return Result(result == SAT_VALUE_TRUE ? Result::SAT : Result::UNSAT);
436
}
437
438
35074
Node PropEngine::getValue(TNode node) const
439
{
440
35074
  Assert(node.getType().isBoolean());
441
35074
  Assert(d_cnfStream->hasLiteral(node));
442
443
35074
  SatLiteral lit = d_cnfStream->getLiteral(node);
444
445
35074
  SatValue v = d_satSolver->value(lit);
446
35074
  if (v == SAT_VALUE_TRUE)
447
  {
448
35058
    return NodeManager::currentNM()->mkConst(true);
449
  }
450
16
  else if (v == SAT_VALUE_FALSE)
451
  {
452
16
    return NodeManager::currentNM()->mkConst(false);
453
  }
454
  else
455
  {
456
    Assert(v == SAT_VALUE_UNKNOWN);
457
    return Node::null();
458
  }
459
}
460
461
22374860
bool PropEngine::isSatLiteral(TNode node) const
462
{
463
22374860
  return d_cnfStream->hasLiteral(node);
464
}
465
466
8886252
bool PropEngine::hasValue(TNode node, bool& value) const
467
{
468
8886252
  Assert(node.getType().isBoolean());
469
8886252
  Assert(d_cnfStream->hasLiteral(node)) << node;
470
471
8886252
  SatLiteral lit = d_cnfStream->getLiteral(node);
472
473
8886252
  SatValue v = d_satSolver->value(lit);
474
8886252
  if (v == SAT_VALUE_TRUE)
475
  {
476
5348426
    value = true;
477
5348426
    return true;
478
  }
479
3537826
  else if (v == SAT_VALUE_FALSE)
480
  {
481
139873
    value = false;
482
139873
    return true;
483
  }
484
  else
485
  {
486
3397953
    Assert(v == SAT_VALUE_UNKNOWN);
487
3397953
    return false;
488
  }
489
}
490
491
15238
void PropEngine::getBooleanVariables(std::vector<TNode>& outputVariables) const
492
{
493
15238
  d_cnfStream->getBooleanVariables(outputVariables);
494
15238
}
495
496
153965
Node PropEngine::ensureLiteral(TNode n)
497
{
498
  // must preprocess
499
153965
  Node preprocessed = getPreprocessedTerm(n);
500
307930
  Trace("ensureLiteral") << "ensureLiteral preprocessed: " << preprocessed
501
153965
                         << std::endl;
502
153965
  if (isProofEnabled())
503
  {
504
18920
    d_pfCnfStream->ensureLiteral(preprocessed);
505
  }
506
  else
507
  {
508
135045
    d_cnfStream->ensureLiteral(preprocessed);
509
  }
510
153965
  return preprocessed;
511
}
512
513
158020
Node PropEngine::getPreprocessedTerm(TNode n)
514
{
515
  // must preprocess
516
316040
  std::vector<theory::TrustNode> newLemmas;
517
316040
  std::vector<Node> newSkolems;
518
316040
  theory::TrustNode tpn = d_theoryProxy->preprocess(n, newLemmas, newSkolems);
519
  // send lemmas corresponding to the skolems introduced by preprocessing n
520
316040
  theory::TrustNode trnNull;
521
158020
  assertLemmasInternal(trnNull, newLemmas, newSkolems, false);
522
316040
  return tpn.isNull() ? Node(n) : tpn.getNode();
523
}
524
525
1582
Node PropEngine::getPreprocessedTerm(TNode n,
526
                                     std::vector<Node>& skAsserts,
527
                                     std::vector<Node>& sks)
528
{
529
  // get the preprocessed form of the term
530
1582
  Node pn = getPreprocessedTerm(n);
531
  // initialize the set of skolems and assertions to process
532
3164
  std::vector<Node> toProcessAsserts;
533
3164
  std::vector<Node> toProcess;
534
1582
  d_theoryProxy->getSkolems(pn, toProcessAsserts, toProcess);
535
1582
  size_t index = 0;
536
  // until fixed point is reached
537
5952
  while (index < toProcess.size())
538
  {
539
3222
    Node ka = toProcessAsserts[index];
540
3222
    Node k = toProcess[index];
541
2185
    index++;
542
2185
    if (std::find(sks.begin(), sks.end(), k) != sks.end())
543
    {
544
      // already added the skolem to the list
545
1148
      continue;
546
    }
547
    // must preprocess lemmas as well
548
2074
    Node kap = getPreprocessedTerm(ka);
549
1037
    skAsserts.push_back(kap);
550
1037
    sks.push_back(k);
551
    // get the skolems in the preprocessed form of the lemma ka
552
1037
    d_theoryProxy->getSkolems(kap, toProcessAsserts, toProcess);
553
  }
554
  // return the preprocessed term
555
3164
  return pn;
556
}
557
558
4361
void PropEngine::push()
559
{
560
4361
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
561
4361
  d_satSolver->push();
562
4361
  Debug("prop") << "push()" << std::endl;
563
4361
}
564
565
4361
void PropEngine::pop()
566
{
567
4361
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
568
4361
  d_satSolver->pop();
569
4361
  Debug("prop") << "pop()" << std::endl;
570
4361
}
571
572
14294
void PropEngine::resetTrail()
573
{
574
14294
  d_satSolver->resetTrail();
575
14294
  Debug("prop") << "resetTrail()" << std::endl;
576
14294
}
577
578
18701
unsigned PropEngine::getAssertionLevel() const
579
{
580
18701
  return d_satSolver->getAssertionLevel();
581
}
582
583
bool PropEngine::isRunning() const { return d_inCheckSat; }
584
void PropEngine::interrupt()
585
{
586
  if (!d_inCheckSat)
587
  {
588
    return;
589
  }
590
591
  d_interrupted = true;
592
  d_satSolver->interrupt();
593
  Debug("prop") << "interrupt()" << std::endl;
594
}
595
596
2527
void PropEngine::spendResource(Resource r)
597
{
598
2527
  d_env.getResourceManager()->spendResource(r);
599
2527
}
600
601
bool PropEngine::properExplanation(TNode node, TNode expl) const
602
{
603
  if (!d_cnfStream->hasLiteral(node))
604
  {
605
    Trace("properExplanation")
606
        << "properExplanation(): Failing because node "
607
        << "being explained doesn't have a SAT literal ?!" << std::endl
608
        << "properExplanation(): The node is: " << node << std::endl;
609
    return false;
610
  }
611
612
  SatLiteral nodeLit = d_cnfStream->getLiteral(node);
613
614
  for (TNode::kinded_iterator i = expl.begin(kind::AND),
615
                              i_end = expl.end(kind::AND);
616
       i != i_end;
617
       ++i)
618
  {
619
    if (!d_cnfStream->hasLiteral(*i))
620
    {
621
      Trace("properExplanation")
622
          << "properExplanation(): Failing because one of explanation "
623
          << "nodes doesn't have a SAT literal" << std::endl
624
          << "properExplanation(): The explanation node is: " << *i
625
          << std::endl;
626
      return false;
627
    }
628
629
    SatLiteral iLit = d_cnfStream->getLiteral(*i);
630
631
    if (iLit == nodeLit)
632
    {
633
      Trace("properExplanation")
634
          << "properExplanation(): Failing because the node" << std::endl
635
          << "properExplanation(): " << node << std::endl
636
          << "properExplanation(): cannot be made to explain itself!"
637
          << std::endl;
638
      return false;
639
    }
640
641
    if (!d_satSolver->properExplanation(nodeLit, iLit))
642
    {
643
      Trace("properExplanation")
644
          << "properExplanation(): SAT solver told us that node" << std::endl
645
          << "properExplanation(): " << *i << std::endl
646
          << "properExplanation(): is not part of a proper explanation node for"
647
          << std::endl
648
          << "properExplanation(): " << node << std::endl
649
          << "properExplanation(): Perhaps it one of the two isn't assigned or "
650
             "the explanation"
651
          << std::endl
652
          << "properExplanation(): node wasn't propagated before the node "
653
             "being explained"
654
          << std::endl;
655
      return false;
656
    }
657
  }
658
659
  return true;
660
}
661
662
void PropEngine::checkProof(context::CDList<Node>* assertions)
663
{
664
  if (!d_pnm)
665
  {
666
    return;
667
  }
668
  return d_ppm->checkProof(assertions);
669
}
670
671
21449
ProofCnfStream* PropEngine::getProofCnfStream() { return d_pfCnfStream.get(); }
672
673
2698
std::shared_ptr<ProofNode> PropEngine::getProof()
674
{
675
2698
  if (!d_pnm)
676
  {
677
    return nullptr;
678
  }
679
2698
  return d_ppm->getProof();
680
}
681
682
1390244
bool PropEngine::isProofEnabled() const { return d_pfCnfStream != nullptr; }
683
684
1318
void PropEngine::getUnsatCore(std::vector<Node>& core)
685
{
686
1318
  Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
687
2636
  std::vector<SatLiteral> unsat_assumptions;
688
1318
  d_satSolver->getUnsatAssumptions(unsat_assumptions);
689
7964
  for (const SatLiteral& lit : unsat_assumptions)
690
  {
691
6646
    core.push_back(d_cnfStream->getNode(lit));
692
  }
693
1318
}
694
695
1318
std::shared_ptr<ProofNode> PropEngine::getRefutation()
696
{
697
1318
  Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
698
2636
  std::vector<Node> core;
699
1318
  getUnsatCore(core);
700
2636
  CDProof cdp(d_pnm);
701
2636
  Node fnode = NodeManager::currentNM()->mkConst(false);
702
1318
  cdp.addStep(fnode, PfRule::SAT_REFUTATION, core, {});
703
2636
  return cdp.getProofFor(fnode);
704
}
705
706
}  // namespace prop
707
28191
}  // namespace cvc5