GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/proof_manager.cpp Lines: 70 94 74.5 %
Date: 2021-08-20 Branches: 96 324 29.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Haniel Barbosa, Diego Della Rocca de Camargos
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
 * The proof manager of the SMT engine.
14
 */
15
16
#include "smt/proof_manager.h"
17
18
#include "options/base_options.h"
19
#include "options/proof_options.h"
20
#include "options/smt_options.h"
21
#include "proof/dot/dot_printer.h"
22
#include "proof/proof_checker.h"
23
#include "proof/proof_node_algorithm.h"
24
#include "proof/proof_node_manager.h"
25
#include "smt/assertions.h"
26
#include "smt/env.h"
27
#include "smt/preprocess_proof_generator.h"
28
#include "smt/proof_post_processor.h"
29
30
namespace cvc5 {
31
namespace smt {
32
33
3771
PfManager::PfManager(Env& env, SmtEngine* smte)
34
    : d_env(env),
35
7542
      d_pchecker(new ProofChecker(options::proofPedantic())),
36
3771
      d_pnm(new ProofNodeManager(d_pchecker.get())),
37
      d_pppg(new PreprocessProofGenerator(
38
7542
          d_pnm.get(), env.getUserContext(), "smt::PreprocessProofGenerator")),
39
      d_pfpp(new ProofPostproccess(
40
3771
          d_pnm.get(),
41
          smte,
42
3771
          d_pppg.get(),
43
          // by default the post-processor will update all assumptions, which
44
          // can lead to SCOPE subproofs of the form
45
          //   A
46
          //  ...
47
          //   B1    B2
48
          //  ...   ...
49
          // ------------
50
          //      C
51
          // ------------- SCOPE [B1, B2]
52
          // B1 ^ B2 => C
53
          //
54
          // where A is an available assumption from outside the scope (note
55
          // that B1 was an assumption of this SCOPE subproof but since it could
56
          // be inferred from A, it was updated). This shape is problematic for
57
          // the veriT reconstruction, so we disable the update of scoped
58
          // assumptions (which would disable the update of B1 in this case).
59
3771
          options::proofFormatMode() != options::ProofFormatMode::VERIT)),
60
26397
      d_finalProof(nullptr)
61
{
62
  // add rules to eliminate here
63
3771
  if (options::proofGranularityMode() != options::ProofGranularityMode::OFF)
64
  {
65
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_SR_EQ_INTRO);
66
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_SR_PRED_INTRO);
67
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_SR_PRED_ELIM);
68
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_SR_PRED_TRANSFORM);
69
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_RESOLUTION_TRUST);
70
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_RESOLUTION);
71
1178
    d_pfpp->setEliminateRule(PfRule::MACRO_ARITH_SCALE_SUM_UB);
72
2356
    if (options::proofGranularityMode()
73
1178
        != options::ProofGranularityMode::REWRITE)
74
    {
75
1178
      d_pfpp->setEliminateRule(PfRule::SUBS);
76
1178
      d_pfpp->setEliminateRule(PfRule::REWRITE);
77
2356
      if (options::proofGranularityMode()
78
1178
          != options::ProofGranularityMode::THEORY_REWRITE)
79
      {
80
        // this eliminates theory rewriting steps with finer-grained DSL rules
81
        d_pfpp->setEliminateRule(PfRule::THEORY_REWRITE);
82
      }
83
    }
84
1178
    d_pfpp->setEliminateRule(PfRule::BV_BITBLAST);
85
  }
86
3771
  d_false = NodeManager::currentNM()->mkConst(false);
87
3771
}
88
89
3771
PfManager::~PfManager() {}
90
91
2805
void PfManager::setFinalProof(std::shared_ptr<ProofNode> pfn, Assertions& as)
92
{
93
  // Note this assumes that setFinalProof is only called once per unsat
94
  // response. This method would need to cache its result otherwise.
95
2805
  Trace("smt-proof") << "SmtEngine::setFinalProof(): get proof body...\n";
96
97
2805
  if (Trace.isOn("smt-proof-debug"))
98
  {
99
    Trace("smt-proof-debug")
100
        << "SmtEngine::setFinalProof(): Proof node for false:\n";
101
    Trace("smt-proof-debug") << *pfn.get() << std::endl;
102
    Trace("smt-proof-debug") << "=====" << std::endl;
103
  }
104
105
5610
  std::vector<Node> assertions;
106
2805
  getAssertions(as, assertions);
107
108
2805
  if (Trace.isOn("smt-proof"))
109
  {
110
    Trace("smt-proof") << "SmtEngine::setFinalProof(): get free assumptions..."
111
                       << std::endl;
112
    std::vector<Node> fassumps;
113
    expr::getFreeAssumptions(pfn.get(), fassumps);
114
    Trace("smt-proof")
115
        << "SmtEngine::setFinalProof(): initial free assumptions are:\n";
116
    for (const Node& a : fassumps)
117
    {
118
      Trace("smt-proof") << "- " << a << std::endl;
119
    }
120
121
    Trace("smt-proof") << "SmtEngine::setFinalProof(): assertions are:\n";
122
    for (const Node& n : assertions)
123
    {
124
      Trace("smt-proof") << "- " << n << std::endl;
125
    }
126
    Trace("smt-proof") << "=====" << std::endl;
127
  }
128
129
2805
  Trace("smt-proof") << "SmtEngine::setFinalProof(): postprocess...\n";
130
2805
  Assert(d_pfpp != nullptr);
131
2805
  d_pfpp->process(pfn);
132
133
2805
  Trace("smt-proof") << "SmtEngine::setFinalProof(): make scope...\n";
134
135
  // Now make the final scope, which ensures that the only open leaves of the
136
  // proof are the assertions.
137
2805
  d_finalProof = d_pnm->mkScope(pfn, assertions);
138
2805
  Trace("smt-proof") << "SmtEngine::setFinalProof(): finished.\n";
139
2805
}
140
141
5
void PfManager::printProof(std::ostream& out,
142
                           std::shared_ptr<ProofNode> pfn,
143
                           Assertions& as)
144
{
145
5
  Trace("smt-proof") << "PfManager::printProof: start" << std::endl;
146
10
  std::shared_ptr<ProofNode> fp = getFinalProof(pfn, as);
147
  // if we are in incremental mode, we don't want to invalidate the proof
148
  // nodes in fp, since these may be reused in further check-sat calls
149
10
  if (options::incrementalSolving()
150
5
      && options::proofFormatMode() != options::ProofFormatMode::NONE)
151
  {
152
    fp = d_pnm->clone(fp);
153
  }
154
  // TODO (proj #37) according to the proof format, post process the proof node
155
  // TODO (proj #37) according to the proof format, print the proof node
156
157
5
  if (options::proofFormatMode() == options::ProofFormatMode::DOT)
158
  {
159
    proof::DotPrinter dotPrinter;
160
    dotPrinter.print(out, fp.get());
161
  }
162
5
  else if (options::proofFormatMode() == options::ProofFormatMode::TPTP)
163
  {
164
    out << "% SZS output start Proof for " << d_env.getFilename() << std::endl;
165
    // TODO (proj #37) print in TPTP compliant format
166
    out << *fp;
167
    out << "% SZS output end Proof for " << d_env.getFilename() << std::endl;
168
  }
169
  else
170
  {
171
5
    out << "(proof\n";
172
5
    out << *fp;
173
5
    out << "\n)\n";
174
  }
175
5
}
176
1368
void PfManager::checkProof(std::shared_ptr<ProofNode> pfn, Assertions& as)
177
{
178
1368
  Trace("smt-proof") << "PfManager::checkProof: start" << std::endl;
179
2736
  std::shared_ptr<ProofNode> fp = getFinalProof(pfn, as);
180
2736
  Trace("smt-proof-debug") << "PfManager::checkProof: returned " << *fp.get()
181
1368
                           << std::endl;
182
1368
}
183
184
ProofChecker* PfManager::getProofChecker() const { return d_pchecker.get(); }
185
186
3771
ProofNodeManager* PfManager::getProofNodeManager() const { return d_pnm.get(); }
187
188
3771
smt::PreprocessProofGenerator* PfManager::getPreprocessProofGenerator() const
189
{
190
3771
  return d_pppg.get();
191
}
192
193
2805
std::shared_ptr<ProofNode> PfManager::getFinalProof(
194
    std::shared_ptr<ProofNode> pfn, Assertions& as)
195
{
196
2805
  setFinalProof(pfn, as);
197
2805
  Assert(d_finalProof);
198
2805
  return d_finalProof;
199
}
200
201
2805
void PfManager::getAssertions(Assertions& as,
202
                              std::vector<Node>& assertions)
203
{
204
2805
  context::CDList<Node>* al = as.getAssertionList();
205
2805
  Assert(al != nullptr);
206
37232
  for (context::CDList<Node>::const_iterator i = al->begin(); i != al->end();
207
       ++i)
208
  {
209
34427
    assertions.push_back(*i);
210
  }
211
2805
}
212
213
}  // namespace smt
214
29358
}  // namespace cvc5