1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, 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 |
|
* Inference to proof conversion. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__STRINGS__INFER_PROOF_CONS_H |
19 |
|
#define CVC5__THEORY__STRINGS__INFER_PROOF_CONS_H |
20 |
|
|
21 |
|
#include <vector> |
22 |
|
|
23 |
|
#include "expr/node.h" |
24 |
|
#include "proof/proof_checker.h" |
25 |
|
#include "proof/proof_rule.h" |
26 |
|
#include "proof/theory_proof_step_buffer.h" |
27 |
|
#include "theory/builtin/proof_checker.h" |
28 |
|
#include "theory/strings/infer_info.h" |
29 |
|
#include "theory/strings/sequences_stats.h" |
30 |
|
#include "theory/uf/proof_equality_engine.h" |
31 |
|
|
32 |
|
namespace cvc5 { |
33 |
|
namespace theory { |
34 |
|
namespace strings { |
35 |
|
|
36 |
|
/** |
37 |
|
* Converts between the strings-specific (untrustworthy) InferInfo class and |
38 |
|
* information about how to construct a trustworthy proof step |
39 |
|
* (PfRule, children, args). It acts as a (lazy) proof generator where the |
40 |
|
* former is registered via notifyFact and the latter is asked for in |
41 |
|
* getProofFor, typically by the proof equality engine. |
42 |
|
* |
43 |
|
* The main (private) method of this class is convert below, which is |
44 |
|
* called when we need to construct a proof node from an InferInfo. |
45 |
|
* |
46 |
|
* This class uses lazy proof reconstruction. Namely, the getProofFor method |
47 |
|
* returns applications of the rule STRING_INFERENCE, which store the arguments |
48 |
|
* to the proof conversion routine "convert" below. |
49 |
|
*/ |
50 |
|
class InferProofCons : public ProofGenerator |
51 |
|
{ |
52 |
|
typedef context::CDHashMap<Node, std::shared_ptr<InferInfo>> NodeInferInfoMap; |
53 |
|
|
54 |
|
public: |
55 |
|
InferProofCons(context::Context* c, |
56 |
|
ProofNodeManager* pnm, |
57 |
|
SequencesStatistics& statistics); |
58 |
2486 |
~InferProofCons() {} |
59 |
|
/** |
60 |
|
* This is called to notify that ii is an inference that may need a proof |
61 |
|
* in the future. |
62 |
|
* |
63 |
|
* In detail, this class should be prepared to respond to a call to: |
64 |
|
* getProofFor(ii.d_conc) |
65 |
|
* in the remainder of the SAT context. This method copies ii and stores it |
66 |
|
* in the context-dependent map d_lazyFactMap below. |
67 |
|
* |
68 |
|
* This is used for lazy proof construction, where proofs are constructed |
69 |
|
* only for facts that are explained. |
70 |
|
*/ |
71 |
|
void notifyFact(const InferInfo& ii); |
72 |
|
|
73 |
|
/** |
74 |
|
* This returns the proof for fact. This is required for using this class as |
75 |
|
* a lazy proof generator. |
76 |
|
* |
77 |
|
* It should be the case that a call was made to notifyFact(ii) where |
78 |
|
* ii.d_conc is fact in this SAT context. |
79 |
|
* |
80 |
|
* This returns the appropriate application of STRING_INFERENCE so that it |
81 |
|
* can be reconstructed if necessary during proof post-processing. |
82 |
|
*/ |
83 |
|
std::shared_ptr<ProofNode> getProofFor(Node fact) override; |
84 |
|
/** Identify this generator (for debugging, etc..) */ |
85 |
|
virtual std::string identify() const override; |
86 |
|
/** |
87 |
|
* Add proof of running convert on the given arguments to CDProof pf. This is |
88 |
|
* called lazily during proof post-processing. |
89 |
|
*/ |
90 |
|
static bool addProofTo(CDProof* pf, |
91 |
|
Node conc, |
92 |
|
InferenceId infer, |
93 |
|
bool isRev, |
94 |
|
const std::vector<Node>& exp); |
95 |
|
/** |
96 |
|
* Pack arguments of a STRING_INFERENCE rule application in args. This proof |
97 |
|
* rule stores the arguments to the convert method of this class below. |
98 |
|
*/ |
99 |
|
static void packArgs(Node conc, |
100 |
|
InferenceId infer, |
101 |
|
bool isRev, |
102 |
|
const std::vector<Node>& exp, |
103 |
|
std::vector<Node>& args); |
104 |
|
/** |
105 |
|
* Inverse of the above method, which recovers the arguments that were packed |
106 |
|
* into the vector args. |
107 |
|
*/ |
108 |
|
static bool unpackArgs(const std::vector<Node>& args, |
109 |
|
Node& conc, |
110 |
|
InferenceId& infer, |
111 |
|
bool& isRev, |
112 |
|
std::vector<Node>& exp); |
113 |
|
|
114 |
|
private: |
115 |
|
/** convert |
116 |
|
* |
117 |
|
* This method is called when the theory of strings makes an inference |
118 |
|
* described by an InferInfo, whose fields are given by the first four |
119 |
|
* arguments of this method. |
120 |
|
* |
121 |
|
* This method converts this call to instructions on what the proof rule |
122 |
|
* step(s) are for concluding the conclusion of the inference. This |
123 |
|
* information is either: |
124 |
|
* |
125 |
|
* (A) stored in the argument ps, which consists of: |
126 |
|
* - A proof rule identifier (ProofStep::d_rule). |
127 |
|
* - The premises of the proof step (ProofStep::d_children). |
128 |
|
* - Arguments to the proof step (ProofStep::d_args). |
129 |
|
* |
130 |
|
* (B) If the proof for the inference cannot be captured by a single |
131 |
|
* step, then the d_rule field of ps is not set, and useBuffer is set to |
132 |
|
* true. In this case, the argument psb is updated to contain (possibly |
133 |
|
* multiple) proof steps for how to construct a proof for the given inference. |
134 |
|
* In particular, psb will contain a set of steps that form a proof |
135 |
|
* whose conclusion is ii.d_conc and whose free assumptions are ii.d_ant. |
136 |
|
*/ |
137 |
|
static void convert(InferenceId infer, |
138 |
|
bool isRev, |
139 |
|
Node conc, |
140 |
|
const std::vector<Node>& exp, |
141 |
|
ProofStep& ps, |
142 |
|
TheoryProofStepBuffer& psb, |
143 |
|
bool& useBuffer); |
144 |
|
/** |
145 |
|
* Convert length proof. If this method returns true, it adds proof step(s) |
146 |
|
* to the buffer psb that conclude lenReq from premises lenExp. |
147 |
|
*/ |
148 |
|
static bool convertLengthPf(Node lenReq, |
149 |
|
const std::vector<Node>& lenExp, |
150 |
|
TheoryProofStepBuffer& psb); |
151 |
|
/** |
152 |
|
* Helper method, adds the proof of (TRANS eqa eqb) into the proof step |
153 |
|
* buffer psb, where eqa and eqb are flipped as needed. Returns the |
154 |
|
* conclusion, or null if we were not able to construct a TRANS step. |
155 |
|
*/ |
156 |
|
static Node convertTrans(Node eqa, Node eqb, TheoryProofStepBuffer& psb); |
157 |
|
/** |
158 |
|
* Purify core substitution. |
159 |
|
* |
160 |
|
* When reconstructing proofs for the core strings calculus, we rely on |
161 |
|
* sequential substitutions for constructing proofs involving recursive |
162 |
|
* computation of normal forms. However, this can be incorrect in cases where |
163 |
|
* a term like (str.replace x a b) is being treated as an atomic term, |
164 |
|
* and a substitution applied over (str.replace x a b) -> c, x -> d. |
165 |
|
* This can lead to the term (str.replace d a b) being generated instead of |
166 |
|
* c. |
167 |
|
* |
168 |
|
* As an example of this method, given input: |
169 |
|
* tgt = (= x (str.++ (f x) c)) |
170 |
|
* children = { (= (f x) a), (= x (str.++ b (f x))) } |
171 |
|
* concludeTgtNew = true |
172 |
|
* This method updates: |
173 |
|
* tgt = (= x (str.++ k c)) |
174 |
|
* children = { (= k a), (= x (str.++ b k)) } |
175 |
|
* where k is the purification skolem for (f x). Additionally, it ensures |
176 |
|
* that psb has a proof of: |
177 |
|
* (= x (str.++ k c)) from (= x (str.++ (f x) c)) |
178 |
|
* ...note the direction, since concludeTgtNew = true |
179 |
|
* (= k a) from (= (f x) a) |
180 |
|
* (= x (str.++ b k)) from (= x (str.++ b (f x))) |
181 |
|
* Notice that the resulting substitution can now be safely used as a |
182 |
|
* sequential substution, since (f x) has been purified with k. The proofs |
183 |
|
* in psb ensure that a proof step involving the purified substitution will |
184 |
|
* have the same net effect as a proof step using the original substitution. |
185 |
|
* |
186 |
|
* @param tgt The term we were originally going to apply the substitution to. |
187 |
|
* @param children The premises corresponding to the substitution. |
188 |
|
* @param psb The proof step buffer |
189 |
|
* @param concludeTgtNew Whether we require proving the purified form of |
190 |
|
* tgt from tgt or vice versa. |
191 |
|
* @return true if we successfully purified the substitution and the target |
192 |
|
* term. Additionally, if successful, we ensure psb contains proofs of |
193 |
|
* children'[i] from children[i] for all i, and tgt' from tgt (or vice versa |
194 |
|
* based on concludeTgtNew). |
195 |
|
*/ |
196 |
|
static bool purifyCoreSubstitution(Node& tgt, |
197 |
|
std::vector<Node>& children, |
198 |
|
TheoryProofStepBuffer& psb, |
199 |
|
bool concludeTgtNew = false); |
200 |
|
/** |
201 |
|
* Return the purified form of the predicate lit with respect to a set of |
202 |
|
* terms to purify, call the returned literal lit'. |
203 |
|
* If concludeNew is true, then we add a proof of lit' from lit in psb; |
204 |
|
* otherwise we add a proof of lit from lit'. |
205 |
|
* Note that string predicates that require purification are string |
206 |
|
* (dis)equalities only. |
207 |
|
*/ |
208 |
|
static Node purifyCorePredicate(Node lit, |
209 |
|
bool concludeNew, |
210 |
|
TheoryProofStepBuffer& psb, |
211 |
|
std::unordered_set<Node>& termsToPurify); |
212 |
|
/** |
213 |
|
* Purify term with respect to a set of terms to purify. This replaces |
214 |
|
* all terms to purify with their purification variables that occur in |
215 |
|
* positions that are relevant for the core calculus of strings (direct |
216 |
|
* children of concat or equal). |
217 |
|
*/ |
218 |
|
static Node purifyCoreTerm(Node n, std::unordered_set<Node>& termsToPurify); |
219 |
|
/** the proof node manager */ |
220 |
|
ProofNodeManager* d_pnm; |
221 |
|
/** The lazy fact map */ |
222 |
|
NodeInferInfoMap d_lazyFactMap; |
223 |
|
/** Reference to the statistics for the theory of strings/sequences. */ |
224 |
|
SequencesStatistics& d_statistics; |
225 |
|
}; |
226 |
|
|
227 |
|
} // namespace strings |
228 |
|
} // namespace theory |
229 |
|
} // namespace cvc5 |
230 |
|
|
231 |
|
#endif /* CVC5__THEORY__STRINGS__INFER_PROOF_CONS_H */ |