GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/prop_engine.cpp Lines: 260 346 75.1 %
Date: 2021-09-29 Branches: 377 1194 31.6 %

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_old.h"
25
#include "decision/justification_strategy.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
9354
  ScopedBool(bool& reference) :
59
9354
    d_reference(reference) {
60
9354
    d_original = reference;
61
9354
  }
62
63
18708
  ~ScopedBool() {
64
9354
    d_reference = d_original;
65
9354
  }
66
};
67
68
6328
PropEngine::PropEngine(TheoryEngine* te, Env& env)
69
    : d_inCheckSat(false),
70
      d_theoryEngine(te),
71
      d_env(env),
72
6328
      d_skdm(new SkolemDefManager(d_env.getContext(), d_env.getUserContext())),
73
      d_theoryProxy(nullptr),
74
      d_satSolver(nullptr),
75
      d_cnfStream(nullptr),
76
      d_pfCnfStream(nullptr),
77
      d_ppm(nullptr),
78
      d_interrupted(false),
79
12656
      d_assumptions(d_env.getUserContext())
80
{
81
6328
  Debug("prop") << "Constructing the PropEngine" << std::endl;
82
6328
  context::Context* satContext = d_env.getContext();
83
6328
  context::UserContext* userContext = d_env.getUserContext();
84
6328
  ProofNodeManager* pnm = d_env.getProofNodeManager();
85
6328
  ResourceManager* rm = d_env.getResourceManager();
86
87
6328
  options::DecisionMode dmode = options::decisionMode();
88
6328
  if (dmode == options::DecisionMode::JUSTIFICATION
89
1608
      || dmode == options::DecisionMode::STOPONLY)
90
  {
91
9924
    d_decisionEngine.reset(new decision::JustificationStrategy(
92
4962
        satContext, userContext, d_skdm.get(), rm));
93
  }
94
1366
  else if (dmode == options::DecisionMode::JUSTIFICATION_OLD
95
1364
           || dmode == options::DecisionMode::STOPONLY_OLD)
96
  {
97
2
    d_decisionEngine.reset(new DecisionEngineOld(satContext, userContext, rm));
98
  }
99
  else
100
  {
101
1364
    d_decisionEngine.reset(new decision::DecisionEngineEmpty(satContext, rm));
102
  }
103
104
6328
  d_satSolver = SatSolverFactory::createCDCLTMinisat(smtStatisticsRegistry());
105
106
  // CNF stream and theory proxy required pointers to each other, make the
107
  // theory proxy first
108
6328
  d_theoryProxy = new TheoryProxy(
109
6328
      this, d_theoryEngine, d_decisionEngine.get(), d_skdm.get(), d_env);
110
18984
  d_cnfStream = new CnfStream(d_satSolver,
111
6328
                              d_theoryProxy,
112
                              userContext,
113
6328
                              &d_env,
114
                              rm,
115
                              FormulaLitPolicy::TRACK,
116
12656
                              "prop");
117
118
  // connect theory proxy
119
6328
  d_theoryProxy->finishInit(d_cnfStream);
120
6328
  bool satProofs = d_env.isSatProofProducing();
121
  // connect SAT solver
122
18984
  d_satSolver->initialize(d_env.getContext(),
123
                          d_theoryProxy,
124
6328
                          d_env.getUserContext(),
125
6328
                          satProofs ? pnm : nullptr);
126
127
6328
  d_decisionEngine->finishInit(d_satSolver, d_cnfStream);
128
6328
  if (satProofs)
129
  {
130
128
    d_pfCnfStream.reset(new ProofCnfStream(
131
        userContext,
132
64
        *d_cnfStream,
133
64
        static_cast<MinisatSatSolver*>(d_satSolver)->getProofManager(),
134
128
        pnm));
135
128
    d_ppm.reset(
136
64
        new PropPfManager(userContext, pnm, d_satSolver, d_pfCnfStream.get()));
137
  }
138
6328
}
139
140
6328
void PropEngine::finishInit()
141
{
142
6328
  NodeManager* nm = NodeManager::currentNM();
143
6328
  d_cnfStream->convertAndAssert(nm->mkConst(true), false, false);
144
  // this is necessary because if True is later asserted to the prop engine the
145
  // CNF stream will ignore it since the SAT solver already had it registered,
146
  // thus not having True as an assumption for the SAT proof. To solve this
147
  // issue we track it directly here
148
6328
  if (isProofEnabled())
149
  {
150
64
    static_cast<MinisatSatSolver*>(d_satSolver)
151
        ->getProofManager()
152
64
        ->registerSatAssumptions({nm->mkConst(true)});
153
  }
154
6328
  d_cnfStream->convertAndAssert(nm->mkConst(false).notNode(), false, false);
155
6328
}
156
157
12650
PropEngine::~PropEngine() {
158
6325
  Debug("prop") << "Destructing the PropEngine" << std::endl;
159
6325
  d_decisionEngine.reset(nullptr);
160
6325
  delete d_cnfStream;
161
6325
  delete d_satSolver;
162
6325
  delete d_theoryProxy;
163
6325
}
164
165
63836
TrustNode PropEngine::preprocess(TNode node,
166
                                 std::vector<TrustNode>& newLemmas,
167
                                 std::vector<Node>& newSkolems)
168
{
169
63836
  return d_theoryProxy->preprocess(node, newLemmas, newSkolems);
170
}
171
172
2
TrustNode PropEngine::removeItes(TNode node,
173
                                 std::vector<TrustNode>& newLemmas,
174
                                 std::vector<Node>& newSkolems)
175
{
176
2
  return d_theoryProxy->removeItes(node, newLemmas, newSkolems);
177
}
178
179
8532
void PropEngine::assertInputFormulas(
180
    const std::vector<Node>& assertions,
181
    std::unordered_map<size_t, Node>& skolemMap)
182
{
183
8532
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
184
  // notify the theory engine of preprocessed assertions
185
8532
  d_theoryEngine->notifyPreprocessedAssertions(assertions);
186
  // Now, notify the theory proxy of the assertions and skolem definitions.
187
  // Notice we do this before asserting the formulas to the CNF stream below,
188
  // since (preregistration) lemmas may occur during calls to assertInternal.
189
  // These lemmas we want to be notified about after the theory proxy has
190
  // been notified about all input assertions.
191
8532
  std::unordered_map<size_t, Node>::iterator it;
192
81045
  for (size_t i = 0, asize = assertions.size(); i < asize; i++)
193
  {
194
    // is the assertion a skolem definition?
195
72513
    it = skolemMap.find(i);
196
145026
    Node skolem;
197
72513
    if (it != skolemMap.end())
198
    {
199
9014
      skolem = it->second;
200
    }
201
72513
    d_theoryProxy->notifyAssertion(assertions[i], skolem);
202
  }
203
81035
  for (const Node& node : assertions)
204
  {
205
72507
    Debug("prop") << "assertFormula(" << node << ")" << std::endl;
206
72511
    assertInternal(node, false, false, true);
207
  }
208
8528
}
209
210
248867
void PropEngine::assertLemma(TrustNode tlemma, theory::LemmaProperty p)
211
{
212
248867
  bool removable = isLemmaPropertyRemovable(p);
213
214
  // call preprocessor
215
497734
  std::vector<TrustNode> ppLemmas;
216
497734
  std::vector<Node> ppSkolems;
217
  TrustNode tplemma =
218
497734
      d_theoryProxy->preprocessLemma(tlemma, ppLemmas, ppSkolems);
219
220
248865
  Assert(ppSkolems.size() == ppLemmas.size());
221
222
  // do final checks on the lemmas we are about to send
223
497730
  if (isProofEnabled()
224
248865
      && options::proofCheck() == options::ProofCheckMode::EAGER)
225
  {
226
    Assert(tplemma.getGenerator() != nullptr);
227
    // ensure closed, make the proof node eagerly here to debug
228
    tplemma.debugCheckClosed("te-proof-debug", "TheoryEngine::lemma");
229
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
230
    {
231
      Assert(ppLemmas[i].getGenerator() != nullptr);
232
      ppLemmas[i].debugCheckClosed("te-proof-debug", "TheoryEngine::lemma_new");
233
    }
234
  }
235
236
248865
  if (Trace.isOn("te-lemma"))
237
  {
238
    Trace("te-lemma") << "Lemma, output: " << tplemma.getProven() << std::endl;
239
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
240
    {
241
      Trace("te-lemma") << "Lemma, new lemma: " << ppLemmas[i].getProven()
242
                        << " (skolem is " << ppSkolems[i] << ")" << std::endl;
243
    }
244
  }
245
246
  // now, assert the lemmas
247
248865
  assertLemmasInternal(tplemma, ppLemmas, ppSkolems, removable);
248
248865
}
249
250
254656
void PropEngine::assertTrustedLemmaInternal(TrustNode trn, bool removable)
251
{
252
509312
  Node node = trn.getNode();
253
254656
  Debug("prop::lemmas") << "assertLemma(" << node << ")" << std::endl;
254
254656
  bool negated = trn.getKind() == TrustNodeKind::CONFLICT;
255
254656
  Assert(
256
      !isProofEnabled() || trn.getGenerator() != nullptr
257
      || options::unsatCores()
258
      || (options::unsatCores()
259
          && options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF));
260
254656
  assertInternal(trn.getNode(), negated, removable, false, trn.getGenerator());
261
254656
}
262
263
327163
void PropEngine::assertInternal(
264
    TNode node, bool negated, bool removable, bool input, ProofGenerator* pg)
265
{
266
  // Assert as (possibly) removable
267
327163
  if (options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS)
268
  {
269
3061
    if (input)
270
    {
271
1741
      d_cnfStream->ensureLiteral(node);
272
1741
      if (negated)
273
      {
274
        d_assumptions.push_back(node.notNode());
275
      }
276
      else
277
      {
278
1741
        d_assumptions.push_back(node);
279
      }
280
    }
281
    else
282
    {
283
1320
      d_cnfStream->convertAndAssert(node, removable, negated, input);
284
    }
285
  }
286
324102
  else if (isProofEnabled())
287
  {
288
3937
    d_pfCnfStream->convertAndAssert(node, negated, removable, pg);
289
    // if input, register the assertion in the proof manager
290
3937
    if (input)
291
    {
292
246
      d_ppm->registerAssertion(node);
293
    }
294
  }
295
  else
296
  {
297
320169
    d_cnfStream->convertAndAssert(node, removable, negated, input);
298
  }
299
327159
}
300
301
375460
void PropEngine::assertLemmasInternal(TrustNode trn,
302
                                      const std::vector<TrustNode>& ppLemmas,
303
                                      const std::vector<Node>& ppSkolems,
304
                                      bool removable)
305
{
306
375460
  if (!trn.isNull())
307
  {
308
248865
    assertTrustedLemmaInternal(trn, removable);
309
  }
310
381251
  for (const TrustNode& tnl : ppLemmas)
311
  {
312
5791
    assertTrustedLemmaInternal(tnl, removable);
313
  }
314
  // assert to decision engine
315
375460
  if (!removable)
316
  {
317
    // also add to the decision engine, where notice we don't need proofs
318
293608
    if (!trn.isNull())
319
    {
320
      // notify the theory proxy of the lemma
321
167013
      d_theoryProxy->notifyAssertion(trn.getProven());
322
    }
323
293608
    Assert(ppSkolems.size() == ppLemmas.size());
324
299399
    for (size_t i = 0, lsize = ppLemmas.size(); i < lsize; ++i)
325
    {
326
11582
      Node lem = ppLemmas[i].getProven();
327
5791
      d_theoryProxy->notifyAssertion(ppLemmas[i].getProven(), ppSkolems[i]);
328
    }
329
  }
330
375460
}
331
332
42570
void PropEngine::requirePhase(TNode n, bool phase) {
333
42570
  Debug("prop") << "requirePhase(" << n << ", " << phase << ")" << std::endl;
334
335
42570
  Assert(n.getType().isBoolean());
336
42570
  SatLiteral lit = d_cnfStream->getLiteral(n);
337
42570
  d_satSolver->requirePhase(phase ? lit : ~lit);
338
42570
}
339
340
127641
bool PropEngine::isDecision(Node lit) const {
341
127641
  Assert(isSatLiteral(lit));
342
127641
  return d_satSolver->isDecision(d_cnfStream->getLiteral(lit).getSatVariable());
343
}
344
345
16
int32_t PropEngine::getDecisionLevel(Node lit) const
346
{
347
16
  Assert(isSatLiteral(lit));
348
32
  return d_satSolver->getDecisionLevel(
349
32
      d_cnfStream->getLiteral(lit).getSatVariable());
350
}
351
352
8
int32_t PropEngine::getIntroLevel(Node lit) const
353
{
354
8
  Assert(isSatLiteral(lit));
355
16
  return d_satSolver->getIntroLevel(
356
16
      d_cnfStream->getLiteral(lit).getSatVariable());
357
}
358
359
void PropEngine::printSatisfyingAssignment(){
360
  const CnfStream::NodeToLiteralMap& transCache =
361
    d_cnfStream->getTranslationCache();
362
  Debug("prop-value") << "Literal | Value | Expr" << std::endl
363
                      << "----------------------------------------"
364
                      << "-----------------" << std::endl;
365
  for(CnfStream::NodeToLiteralMap::const_iterator i = transCache.begin(),
366
      end = transCache.end();
367
      i != end;
368
      ++i) {
369
    std::pair<Node, SatLiteral> curr = *i;
370
    SatLiteral l = curr.second;
371
    if(!l.isNegated()) {
372
      Node n = curr.first;
373
      SatValue value = d_satSolver->modelValue(l);
374
      Debug("prop-value") << "'" << l << "' " << value << " " << n << std::endl;
375
    }
376
  }
377
}
378
379
9354
Result PropEngine::checkSat() {
380
9354
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
381
9354
  Debug("prop") << "PropEngine::checkSat()" << std::endl;
382
383
  // Mark that we are in the checkSat
384
18708
  ScopedBool scopedBool(d_inCheckSat);
385
9354
  d_inCheckSat = true;
386
387
  // TODO This currently ignores conflicts (a dangerous practice).
388
9354
  d_decisionEngine->presolve();
389
9354
  d_theoryEngine->presolve();
390
391
9354
  if(options::preprocessOnly()) {
392
3
    return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK);
393
  }
394
395
  // Reset the interrupted flag
396
9351
  d_interrupted = false;
397
398
  // Check the problem
399
  SatValue result;
400
9351
  if (d_assumptions.size() == 0)
401
  {
402
9206
    result = d_satSolver->solve();
403
  }
404
  else
405
  {
406
290
    std::vector<SatLiteral> assumptions;
407
8875
    for (const Node& node : d_assumptions)
408
    {
409
8730
      assumptions.push_back(d_cnfStream->getLiteral(node));
410
    }
411
145
    result = d_satSolver->solve(assumptions);
412
  }
413
414
9335
  if( result == SAT_VALUE_UNKNOWN ) {
415
    ResourceManager* rm = d_env.getResourceManager();
416
    Result::UnknownExplanation why = Result::INTERRUPTED;
417
    if (rm->outOfTime())
418
    {
419
      why = Result::TIMEOUT;
420
    }
421
    if (rm->outOfResources())
422
    {
423
      why = Result::RESOURCEOUT;
424
    }
425
    return Result(Result::SAT_UNKNOWN, why);
426
  }
427
428
9335
  if( result == SAT_VALUE_TRUE && Debug.isOn("prop") ) {
429
    printSatisfyingAssignment();
430
  }
431
432
9335
  Debug("prop") << "PropEngine::checkSat() => " << result << std::endl;
433
9335
  if(result == SAT_VALUE_TRUE && d_theoryEngine->isIncomplete()) {
434
94
    return Result(Result::SAT_UNKNOWN, Result::INCOMPLETE);
435
  }
436
9241
  return Result(result == SAT_VALUE_TRUE ? Result::SAT : Result::UNSAT);
437
}
438
439
35117
Node PropEngine::getValue(TNode node) const
440
{
441
35117
  Assert(node.getType().isBoolean());
442
35117
  Assert(d_cnfStream->hasLiteral(node));
443
444
35117
  SatLiteral lit = d_cnfStream->getLiteral(node);
445
446
35117
  SatValue v = d_satSolver->value(lit);
447
35117
  if (v == SAT_VALUE_TRUE)
448
  {
449
35101
    return NodeManager::currentNM()->mkConst(true);
450
  }
451
16
  else if (v == SAT_VALUE_FALSE)
452
  {
453
16
    return NodeManager::currentNM()->mkConst(false);
454
  }
455
  else
456
  {
457
    Assert(v == SAT_VALUE_UNKNOWN);
458
    return Node::null();
459
  }
460
}
461
462
17614617
bool PropEngine::isSatLiteral(TNode node) const
463
{
464
17614617
  return d_cnfStream->hasLiteral(node);
465
}
466
467
6614535
bool PropEngine::hasValue(TNode node, bool& value) const
468
{
469
6614535
  Assert(node.getType().isBoolean());
470
6614535
  Assert(d_cnfStream->hasLiteral(node)) << node;
471
472
6614535
  SatLiteral lit = d_cnfStream->getLiteral(node);
473
474
6614535
  SatValue v = d_satSolver->value(lit);
475
6614535
  if (v == SAT_VALUE_TRUE)
476
  {
477
3933368
    value = true;
478
3933368
    return true;
479
  }
480
2681167
  else if (v == SAT_VALUE_FALSE)
481
  {
482
104396
    value = false;
483
104396
    return true;
484
  }
485
  else
486
  {
487
2576771
    Assert(v == SAT_VALUE_UNKNOWN);
488
2576771
    return false;
489
  }
490
}
491
492
12845
void PropEngine::getBooleanVariables(std::vector<TNode>& outputVariables) const
493
{
494
12845
  d_cnfStream->getBooleanVariables(outputVariables);
495
12845
}
496
497
124061
Node PropEngine::ensureLiteral(TNode n)
498
{
499
  // must preprocess
500
124061
  Node preprocessed = getPreprocessedTerm(n);
501
248122
  Trace("ensureLiteral") << "ensureLiteral preprocessed: " << preprocessed
502
124061
                         << std::endl;
503
124061
  if (isProofEnabled())
504
  {
505
2540
    d_pfCnfStream->ensureLiteral(preprocessed);
506
  }
507
  else
508
  {
509
121521
    d_cnfStream->ensureLiteral(preprocessed);
510
  }
511
124061
  return preprocessed;
512
}
513
514
126595
Node PropEngine::getPreprocessedTerm(TNode n)
515
{
516
  // must preprocess
517
253190
  std::vector<TrustNode> newLemmas;
518
253190
  std::vector<Node> newSkolems;
519
253190
  TrustNode tpn = d_theoryProxy->preprocess(n, newLemmas, newSkolems);
520
  // send lemmas corresponding to the skolems introduced by preprocessing n
521
253190
  TrustNode trnNull;
522
126595
  assertLemmasInternal(trnNull, newLemmas, newSkolems, false);
523
253190
  return tpn.isNull() ? Node(n) : tpn.getNode();
524
}
525
526
1263
Node PropEngine::getPreprocessedTerm(TNode n,
527
                                     std::vector<Node>& skAsserts,
528
                                     std::vector<Node>& sks)
529
{
530
  // get the preprocessed form of the term
531
1263
  Node pn = getPreprocessedTerm(n);
532
  // initialize the set of skolems and assertions to process
533
2526
  std::vector<Node> toProcessAsserts;
534
2526
  std::vector<Node> toProcess;
535
1263
  d_theoryProxy->getSkolems(pn, toProcessAsserts, toProcess);
536
1263
  size_t index = 0;
537
  // until fixed point is reached
538
4131
  while (index < toProcess.size())
539
  {
540
2099
    Node ka = toProcessAsserts[index];
541
2099
    Node k = toProcess[index];
542
1434
    index++;
543
1434
    if (std::find(sks.begin(), sks.end(), k) != sks.end())
544
    {
545
      // already added the skolem to the list
546
769
      continue;
547
    }
548
    // must preprocess lemmas as well
549
1330
    Node kap = getPreprocessedTerm(ka);
550
665
    skAsserts.push_back(kap);
551
665
    sks.push_back(k);
552
    // get the skolems in the preprocessed form of the lemma ka
553
665
    d_theoryProxy->getSkolems(kap, toProcessAsserts, toProcess);
554
  }
555
  // return the preprocessed term
556
2526
  return pn;
557
}
558
559
3245
void PropEngine::push()
560
{
561
3245
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
562
3245
  d_satSolver->push();
563
3245
  Debug("prop") << "push()" << std::endl;
564
3245
}
565
566
3245
void PropEngine::pop()
567
{
568
3245
  Assert(!d_inCheckSat) << "Sat solver in solve()!";
569
3245
  d_satSolver->pop();
570
3245
  Debug("prop") << "pop()" << std::endl;
571
3245
}
572
573
9338
void PropEngine::resetTrail()
574
{
575
9338
  d_satSolver->resetTrail();
576
9338
  Debug("prop") << "resetTrail()" << std::endl;
577
9338
}
578
579
11649
unsigned PropEngine::getAssertionLevel() const
580
{
581
11649
  return d_satSolver->getAssertionLevel();
582
}
583
584
bool PropEngine::isRunning() const { return d_inCheckSat; }
585
void PropEngine::interrupt()
586
{
587
  if (!d_inCheckSat)
588
  {
589
    return;
590
  }
591
592
  d_interrupted = true;
593
  d_satSolver->interrupt();
594
  Debug("prop") << "interrupt()" << std::endl;
595
}
596
597
1312
void PropEngine::spendResource(Resource r)
598
{
599
1312
  d_env.getResourceManager()->spendResource(r);
600
1312
}
601
602
bool PropEngine::properExplanation(TNode node, TNode expl) const
603
{
604
  if (!d_cnfStream->hasLiteral(node))
605
  {
606
    Trace("properExplanation")
607
        << "properExplanation(): Failing because node "
608
        << "being explained doesn't have a SAT literal ?!" << std::endl
609
        << "properExplanation(): The node is: " << node << std::endl;
610
    return false;
611
  }
612
613
  SatLiteral nodeLit = d_cnfStream->getLiteral(node);
614
615
  for (TNode::kinded_iterator i = expl.begin(kind::AND),
616
                              i_end = expl.end(kind::AND);
617
       i != i_end;
618
       ++i)
619
  {
620
    if (!d_cnfStream->hasLiteral(*i))
621
    {
622
      Trace("properExplanation")
623
          << "properExplanation(): Failing because one of explanation "
624
          << "nodes doesn't have a SAT literal" << std::endl
625
          << "properExplanation(): The explanation node is: " << *i
626
          << std::endl;
627
      return false;
628
    }
629
630
    SatLiteral iLit = d_cnfStream->getLiteral(*i);
631
632
    if (iLit == nodeLit)
633
    {
634
      Trace("properExplanation")
635
          << "properExplanation(): Failing because the node" << std::endl
636
          << "properExplanation(): " << node << std::endl
637
          << "properExplanation(): cannot be made to explain itself!"
638
          << std::endl;
639
      return false;
640
    }
641
642
    if (!d_satSolver->properExplanation(nodeLit, iLit))
643
    {
644
      Trace("properExplanation")
645
          << "properExplanation(): SAT solver told us that node" << std::endl
646
          << "properExplanation(): " << *i << std::endl
647
          << "properExplanation(): is not part of a proper explanation node for"
648
          << std::endl
649
          << "properExplanation(): " << node << std::endl
650
          << "properExplanation(): Perhaps it one of the two isn't assigned or "
651
             "the explanation"
652
          << std::endl
653
          << "properExplanation(): node wasn't propagated before the node "
654
             "being explained"
655
          << std::endl;
656
      return false;
657
    }
658
  }
659
660
  return true;
661
}
662
663
void PropEngine::checkProof(context::CDList<Node>* assertions)
664
{
665
  if (!d_env.isSatProofProducing())
666
  {
667
    return;
668
  }
669
  return d_ppm->checkProof(assertions);
670
}
671
672
229
ProofCnfStream* PropEngine::getProofCnfStream() { return d_pfCnfStream.get(); }
673
674
43
std::shared_ptr<ProofNode> PropEngine::getProof()
675
{
676
43
  if (!d_env.isSatProofProducing())
677
  {
678
    return nullptr;
679
  }
680
43
  return d_ppm->getProof();
681
}
682
683
958012
bool PropEngine::isProofEnabled() const { return d_pfCnfStream != nullptr; }
684
685
32
void PropEngine::getUnsatCore(std::vector<Node>& core)
686
{
687
32
  Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
688
64
  std::vector<SatLiteral> unsat_assumptions;
689
32
  d_satSolver->getUnsatAssumptions(unsat_assumptions);
690
335
  for (const SatLiteral& lit : unsat_assumptions)
691
  {
692
303
    core.push_back(d_cnfStream->getNode(lit));
693
  }
694
32
}
695
696
32
std::shared_ptr<ProofNode> PropEngine::getRefutation()
697
{
698
32
  Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
699
64
  std::vector<Node> core;
700
32
  getUnsatCore(core);
701
64
  CDProof cdp(d_env.getProofNodeManager());
702
64
  Node fnode = NodeManager::currentNM()->mkConst(false);
703
32
  cdp.addStep(fnode, PfRule::SAT_REFUTATION, core, {});
704
64
  return cdp.getProofFor(fnode);
705
}
706
707
}  // namespace prop
708
22746
}  // namespace cvc5