GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/proof_manager.cpp Lines: 72 96 75.0 %
Date: 2021-09-07 Branches: 98 330 29.7 %

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