GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/proof_post_processor.h Lines: 1 1 100.0 %
Date: 2021-09-16 Branches: 0 0 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Haniel Barbosa, Gereon Kremer
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 module for processing proof nodes.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__SMT__PROOF_POST_PROCESSOR_H
19
#define CVC5__SMT__PROOF_POST_PROCESSOR_H
20
21
#include <map>
22
#include <sstream>
23
#include <unordered_set>
24
25
#include "proof/proof_node_updater.h"
26
#include "smt/proof_final_callback.h"
27
#include "smt/witness_form.h"
28
#include "theory/inference_id.h"
29
#include "util/statistics_stats.h"
30
31
namespace cvc5 {
32
33
class Env;
34
35
namespace rewriter {
36
class RewriteDb;
37
}
38
39
namespace smt {
40
41
/**
42
 * A callback class used by SmtEngine for post-processing proof nodes by
43
 * connecting proofs of preprocessing, and expanding macro PfRule applications.
44
 */
45
class ProofPostprocessCallback : public ProofNodeUpdaterCallback
46
{
47
 public:
48
  ProofPostprocessCallback(Env& env,
49
                           ProofGenerator* pppg,
50
                           rewriter::RewriteDb* rdb,
51
                           bool updateScopedAssumptions);
52
3796
  ~ProofPostprocessCallback() {}
53
  /**
54
   * Initialize, called once for each new ProofNode to process. This initializes
55
   * static information to be used by successive calls to update.
56
   */
57
  void initializeUpdate();
58
  /**
59
   * Set eliminate rule, which adds rule to the list of rules we will eliminate
60
   * during update. This adds rule to d_elimRules. Supported rules for
61
   * elimination include MACRO_*, SUBS and REWRITE. Otherwise, this method
62
   * has no effect.
63
   */
64
  void setEliminateRule(PfRule rule);
65
  /** Should proof pn be updated? */
66
  bool shouldUpdate(std::shared_ptr<ProofNode> pn,
67
                    const std::vector<Node>& fa,
68
                    bool& continueUpdate) override;
69
  /** Update the proof rule application. */
70
  bool update(Node res,
71
              PfRule id,
72
              const std::vector<Node>& children,
73
              const std::vector<Node>& args,
74
              CDProof* cdp,
75
              bool& continueUpdate) override;
76
77
 private:
78
  /** Common constants */
79
  Node d_true;
80
  /** Reference to the env */
81
  Env& d_env;
82
  /** Pointer to the proof node manager */
83
  ProofNodeManager* d_pnm;
84
  /** The preprocessing proof generator */
85
  ProofGenerator* d_pppg;
86
  /** The witness form proof generator */
87
  WitnessFormGenerator d_wfpm;
88
  /** The witness form assumptions used in the proof */
89
  std::vector<Node> d_wfAssumptions;
90
  /** Kinds of proof rules we are eliminating */
91
  std::unordered_set<PfRule, PfRuleHashFunction> d_elimRules;
92
  /** Whether we post-process assumptions in scope. */
93
  bool d_updateScopedAssumptions;
94
  //---------------------------------reset at the begining of each update
95
  /** Mapping assumptions to their proof from preprocessing */
96
  std::map<Node, std::shared_ptr<ProofNode> > d_assumpToProof;
97
  //---------------------------------end reset at the begining of each update
98
  /**
99
   * Expand rules in the given application, add the expanded proof to cdp.
100
   * The set of rules we expand is configured by calls to setEliminateRule
101
   * above. This method calls update to perform possible post-processing in the
102
   * rules it introduces as a result of the expansion.
103
   *
104
   * @param id The rule of the application
105
   * @param children The children of the application
106
   * @param args The arguments of the application
107
   * @param cdp The proof to add to
108
   * @return The conclusion of the rule, or null if this rule is not eliminated.
109
   */
110
  Node expandMacros(PfRule id,
111
                    const std::vector<Node>& children,
112
                    const std::vector<Node>& args,
113
                    CDProof* cdp);
114
  /**
115
   * Update the proof rule application, called during expand macros when
116
   * we wish to apply the update method. This method has the same behavior
117
   * as update apart from ignoring the continueUpdate flag.
118
   */
119
  bool updateInternal(Node res,
120
                      PfRule id,
121
                      const std::vector<Node>& children,
122
                      const std::vector<Node>& args,
123
                      CDProof* cdp);
124
  /**
125
   * Add proof for witness form. This returns the equality t = toWitness(t)
126
   * and ensures that the proof of this equality has been added to cdp.
127
   * Notice the proof of this fact may have open assumptions of the form:
128
   *   k = toWitness(k)
129
   * where k is a skolem. Furthermore, note that all open assumptions of this
130
   * form are available via d_wfpm.getWitnessFormEqs() in the remainder of
131
   * the lifetime of this class.
132
   */
133
  Node addProofForWitnessForm(Node t, CDProof* cdp);
134
  /**
135
   * Apply transivity if necessary for the arguments. The nodes in
136
   * tchildren have been ordered such that they are legal arguments to TRANS.
137
   *
138
   * Returns the conclusion of the transitivity step, which is null if
139
   * tchildren is empty. Also note if tchildren contains a single element,
140
   * then no TRANS step is necessary to add to cdp.
141
   *
142
   * @param tchildren The children of a TRANS step
143
   * @param cdp The proof to add the TRANS step to
144
   * @return The conclusion of the TRANS step.
145
   */
146
  Node addProofForTrans(const std::vector<Node>& tchildren, CDProof* cdp);
147
  /**
148
   * Add proof for substitution step. Some substitutions are derived based
149
   * on viewing a formula as a Boolean assignment (see MethodId::SB_LITERAL for
150
   * example). This method ensures that the proof of var == subs exists
151
   * in cdp, where var, subs were derived from BuiltinProofRuleChecker's
152
   * getSubstitution method.
153
   *
154
   * @param var The variable of the substitution
155
   * @param subs The substituted term
156
   * @param assump The formula the substitution was derived from
157
   * @param cdp The proof to add to
158
   * @return var == subs, the conclusion of the substitution step.
159
   */
160
  Node addProofForSubsStep(Node var, Node subs, Node assump, CDProof* cdp);
161
  /** Add eq (or its symmetry) to transivity children, if not reflexive */
162
  bool addToTransChildren(Node eq,
163
                          std::vector<Node>& tchildren,
164
                          bool isSymm = false);
165
166
  /**
167
   * When given children and args lead to different sets of literals in a
168
   * conclusion depending on whether macro resolution or chain resolution is
169
   * applied, the literals that appear in the chain resolution result, but not
170
   * in the macro resolution result, from now on "crowding literals", are
171
   * literals removed implicitly by macro resolution. For example
172
   *
173
   *      l0 v l0 v l0 v l1 v l2    ~l0 v l1   ~l1
174
   * (1)  ----------------------------------------- MACRO_RES
175
   *                 l2
176
   *
177
   * but
178
   *
179
   *      l0 v l0 v l0 v l1 v l2    ~l0 v l1   ~l1
180
   * (2)  ---------------------------------------- CHAIN_RES
181
   *                l0 v l0 v l1 v l2
182
   *
183
   * where l0 and l1 are crowding literals in the second proof.
184
   *
185
   * There are two views for how MACRO_RES implicitly removes the crowding
186
   * literal, i.e., how MACRO_RES can be expanded into CHAIN_RES so that
187
   * crowding literals are removed. The first is that (1) becomes
188
   *
189
   *  l0 v l0 v l0 v l1 v l2  ~l0 v l1  ~l0 v l1  ~l0 v l1  ~l1  ~l1  ~l1  ~l1
190
   *  ---------------------------------------------------------------- CHAIN_RES
191
   *                                 l2
192
   *
193
   * via the repetition of the premise responsible for removing more than one
194
   * occurrence of the crowding literal. The issue however is that this
195
   * expansion is exponential. Note that (2) has two occurrences of l0 and one
196
   * of l1 as crowding literals. However, by repeating ~l0 v l1 two times to
197
   * remove l0, the clause ~l1, which would originally need to be repeated only
198
   * one time, now has to be repeated two extra times on top of that one. With
199
   * multiple crowding literals and their elimination depending on premises that
200
   * themselves add crowding literals one can easily end up with resolution
201
   * chains going from dozens to thousands of premises. Such examples do occur
202
   * in practice, even in our regressions.
203
   *
204
   * The second way of expanding MACRO_RES, which avoids this exponential
205
   * behavior, is so that (1) becomes
206
   *
207
   *      l0 v l0 v l0 v l1 v l2
208
   * (4)  ---------------------- FACTORING
209
   *      l0 v l1 v l2                       ~l0 v l1
210
   *      ------------------------------------------- CHAIN_RES
211
   *                   l1 v l1 v l2
212
   *                  ------------- FACTORING
213
   *                     l1 v l2                   ~l1
214
   *                    ------------------------------ CHAIN_RES
215
   *                                 l2
216
   *
217
   * This method first determines what are the crowding literals by checking
218
   * what literals occur in clauseLits that do not occur in targetClauseLits
219
   * (the latter contains the literals from the original MACRO_RES conclusion
220
   * while the former the literals from a direct application of CHAIN_RES). Then
221
   * it builds a proof such as (4) and adds the steps to cdp. The final
222
   * conclusion is returned.
223
   *
224
   * Note that in the example the CHAIN_RES steps introduced had only two
225
   * premises, and could thus be replaced by a RESOLUTION step, but since we
226
   * general there can be more than two premises we always use CHAIN_RES.
227
   *
228
   * @param clauseLits literals in the conclusion of a CHAIN_RESOLUTION step
229
   * with children and args[1:]
230
   * @param clauseLits literals in the conclusion of a MACRO_RESOLUTION step
231
   * with children and args
232
   * @param children a list of clauses
233
   * @param args a list of arguments to a MACRO_RESOLUTION step
234
   * @param cdp a CDProof
235
   * @return The resulting node of transforming MACRO_RESOLUTION into
236
   * CHAIN_RESOLUTION according to the above idea.
237
   */
238
  Node eliminateCrowdingLits(const std::vector<Node>& clauseLits,
239
                             const std::vector<Node>& targetClauseLits,
240
                             const std::vector<Node>& children,
241
                             const std::vector<Node>& args,
242
                             CDProof* cdp);
243
};
244
245
/**
246
 * The proof postprocessor module. This postprocesses the final proof
247
 * produced by an SmtEngine. Its main two tasks are to:
248
 * (1) Connect proofs of preprocessing,
249
 * (2) Expand macro PfRule applications.
250
 */
251
class ProofPostproccess
252
{
253
 public:
254
  /**
255
   * @param env The environment we are using
256
   * @param pppg The proof generator for pre-processing proofs
257
   * @param updateScopedAssumptions Whether we post-process assumptions in
258
   * scope. Since doing so is sound and only problematic depending on who is
259
   * consuming the proof, it's true by default.
260
   */
261
  ProofPostproccess(Env& env,
262
                    ProofGenerator* pppg,
263
                    rewriter::RewriteDb* rdb,
264
                    bool updateScopedAssumptions = true);
265
  ~ProofPostproccess();
266
  /** post-process */
267
  void process(std::shared_ptr<ProofNode> pf);
268
  /** set eliminate rule */
269
  void setEliminateRule(PfRule rule);
270
271
 private:
272
  /** The post process callback */
273
  ProofPostprocessCallback d_cb;
274
  /**
275
   * The updater, which is responsible for expanding macros in the final proof
276
   * and connecting preprocessed assumptions to input assumptions.
277
   */
278
  ProofNodeUpdater d_updater;
279
  /** The post process callback for finalization */
280
  ProofFinalCallback d_finalCb;
281
  /**
282
   * The finalizer, which is responsible for taking stats and checking for
283
   * (lazy) pedantic failures.
284
   */
285
  ProofNodeUpdater d_finalizer;
286
};
287
288
}  // namespace smt
289
}  // namespace cvc5
290
291
#endif