GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/proof_manager.cpp Lines: 72 100 72.0 %
Date: 2021-09-10 Branches: 100 334 29.9 %

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