1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Andres Noetzli, Tim King |
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 |
|
* Solver for extended functions of theory of strings. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__STRINGS__EXTF_SOLVER_H |
19 |
|
#define CVC5__THEORY__STRINGS__EXTF_SOLVER_H |
20 |
|
|
21 |
|
#include <map> |
22 |
|
#include <vector> |
23 |
|
|
24 |
|
#include "context/cdo.h" |
25 |
|
#include "expr/node.h" |
26 |
|
#include "smt/env_obj.h" |
27 |
|
#include "theory/ext_theory.h" |
28 |
|
#include "theory/strings/base_solver.h" |
29 |
|
#include "theory/strings/core_solver.h" |
30 |
|
#include "theory/strings/inference_manager.h" |
31 |
|
#include "theory/strings/sequences_stats.h" |
32 |
|
#include "theory/strings/skolem_cache.h" |
33 |
|
#include "theory/strings/solver_state.h" |
34 |
|
#include "theory/strings/strings_rewriter.h" |
35 |
|
#include "theory/strings/theory_strings_preprocess.h" |
36 |
|
|
37 |
|
namespace cvc5 { |
38 |
|
namespace theory { |
39 |
|
namespace strings { |
40 |
|
|
41 |
|
/** |
42 |
|
* Non-static information about an extended function t. This information is |
43 |
|
* constructed and used during the check extended function evaluation |
44 |
|
* inference schema. |
45 |
|
* |
46 |
|
* In the following, we refer to the "context-dependent simplified form" |
47 |
|
* of a term t to be the result of rewriting t * sigma, where sigma is a |
48 |
|
* derivable substitution in the current context. For example, the |
49 |
|
* context-depdendent simplified form of contains( x++y, "a" ) given |
50 |
|
* sigma = { x -> "" } is contains(y,"a"). |
51 |
|
*/ |
52 |
547816 |
class ExtfInfoTmp |
53 |
|
{ |
54 |
|
public: |
55 |
547816 |
ExtfInfoTmp() : d_modelActive(true) {} |
56 |
|
/** |
57 |
|
* If s is in d_ctn[true] (resp. d_ctn[false]), then contains( t, s ) |
58 |
|
* (resp. ~contains( t, s )) holds in the current context. The vector |
59 |
|
* d_ctnFrom is the explanation for why this holds. For example, |
60 |
|
* if d_ctn[false][i] is "A", then d_ctnFrom[false][i] might be |
61 |
|
* t = x ++ y AND x = "" AND y = "B". |
62 |
|
*/ |
63 |
|
std::map<bool, std::vector<Node> > d_ctn; |
64 |
|
std::map<bool, std::vector<Node> > d_ctnFrom; |
65 |
|
/** |
66 |
|
* The constant that t is entailed to be equal to, or null if none exist. |
67 |
|
*/ |
68 |
|
Node d_const; |
69 |
|
/** |
70 |
|
* The explanation for why t is equal to its context-dependent simplified |
71 |
|
* form. |
72 |
|
*/ |
73 |
|
std::vector<Node> d_exp; |
74 |
|
/** This flag is false if t is reduced in the model. */ |
75 |
|
bool d_modelActive; |
76 |
|
}; |
77 |
|
|
78 |
|
/** |
79 |
|
* Extended function solver for the theory of strings. This manages extended |
80 |
|
* functions for the theory of strings using a combination of context-dependent |
81 |
|
* simplification (Reynolds et al CAV 2017) and lazy reductions. |
82 |
|
*/ |
83 |
|
class ExtfSolver : protected EnvObj |
84 |
|
{ |
85 |
|
typedef context::CDHashSet<Node> NodeSet; |
86 |
|
|
87 |
|
public: |
88 |
|
ExtfSolver(Env& env, |
89 |
|
SolverState& s, |
90 |
|
InferenceManager& im, |
91 |
|
TermRegistry& tr, |
92 |
|
StringsRewriter& rewriter, |
93 |
|
BaseSolver& bs, |
94 |
|
CoreSolver& cs, |
95 |
|
ExtTheory& et, |
96 |
|
SequencesStatistics& statistics); |
97 |
|
~ExtfSolver(); |
98 |
|
/** check extended functions evaluation |
99 |
|
* |
100 |
|
* This applies "context-dependent simplification" for all active extended |
101 |
|
* function terms in this SAT context. This infers facts of the form: |
102 |
|
* x = c => f( t1 ... tn ) = c' |
103 |
|
* where the rewritten form of f( t1...tn ) { x |-> c } is c', and x = c |
104 |
|
* is a (tuple of) equalities that are asserted in this SAT context, and |
105 |
|
* f( t1 ... tn ) is a term from this SAT context. |
106 |
|
* |
107 |
|
* For more details, this is steps 4 when effort=0 and step 6 when |
108 |
|
* effort=1 from Strategy 1 in Reynolds et al, "Scaling up DPLL(T) String |
109 |
|
* Solvers using Context-Dependent Simplification", CAV 2017. When called with |
110 |
|
* effort=3, we apply context-dependent simplification based on model values. |
111 |
|
*/ |
112 |
|
void checkExtfEval(int effort); |
113 |
|
/** check extended function reductions |
114 |
|
* |
115 |
|
* This adds "reduction" lemmas for each active extended function in this SAT |
116 |
|
* context. These are generally lemmas of the form: |
117 |
|
* F[t1...tn,k] ^ f( t1 ... tn ) = k |
118 |
|
* where f( t1 ... tn ) is an active extended function, k is a fresh constant |
119 |
|
* and F is a formula that constrains k based on the definition of f. |
120 |
|
* |
121 |
|
* For more details, this is step 7 from Strategy 1 in Reynolds et al, |
122 |
|
* CAV 2017. We stratify this in practice, where calling this with effort=1 |
123 |
|
* reduces some of the "easier" extended functions, and effort=2 reduces |
124 |
|
* the rest. |
125 |
|
*/ |
126 |
|
void checkExtfReductions(int effort); |
127 |
|
/** get preprocess module */ |
128 |
|
StringsPreprocess* getPreprocess() { return &d_preproc; } |
129 |
|
|
130 |
|
/** |
131 |
|
* Get the current substitution for term n. |
132 |
|
* |
133 |
|
* This method returns a term that n is currently equal to in the current |
134 |
|
* context. It updates exp to contain an explanation of why it is currently |
135 |
|
* equal to that term. |
136 |
|
* |
137 |
|
* The argument effort determines what kind of term to return, either |
138 |
|
* a constant in the equivalence class of n (effort=0), the normal form of |
139 |
|
* n (effort=1,2) or the model value of n (effort>=3). The latter is only |
140 |
|
* valid at LAST_CALL effort. If a term of the above form cannot be returned, |
141 |
|
* then n itself is returned. |
142 |
|
*/ |
143 |
|
Node getCurrentSubstitutionFor(int effort, Node n, std::vector<Node>& exp); |
144 |
|
/** get mapping from extended functions to their information |
145 |
|
* |
146 |
|
* This information is valid during a full effort check after a call to |
147 |
|
* checkExtfEval. |
148 |
|
*/ |
149 |
|
const std::map<Node, ExtfInfoTmp>& getInfo() const; |
150 |
|
//---------------------------------- information about ExtTheory |
151 |
|
/** Are there any active extended functions? */ |
152 |
|
bool hasExtendedFunctions() const; |
153 |
|
/** |
154 |
|
* Get the function applications of kind k that are active in the current |
155 |
|
* context (see ExtTheory::getActive). |
156 |
|
*/ |
157 |
|
std::vector<Node> getActive(Kind k) const; |
158 |
|
//---------------------------------- end information about ExtTheory |
159 |
|
/** |
160 |
|
* Print the relevant information regarding why we have a model, return as a |
161 |
|
* string. |
162 |
|
*/ |
163 |
|
std::string debugPrintModel(); |
164 |
|
|
165 |
|
private: |
166 |
|
/** do reduction |
167 |
|
* |
168 |
|
* This is called when an extended function application n is not able to be |
169 |
|
* simplified by context-depdendent simplification, and we are resorting to |
170 |
|
* expanding n to its full semantics via a reduction. This method returns |
171 |
|
* true if it successfully reduced n by some reduction. If so, it either |
172 |
|
* caches that the reduction lemma was sent, or marks n as reduced in this |
173 |
|
* SAT-context. The argument effort has the same meaning as in |
174 |
|
* checkExtfReductions. |
175 |
|
*/ |
176 |
|
bool doReduction(int effort, Node n); |
177 |
|
/** check extended function inferences |
178 |
|
* |
179 |
|
* This function makes additional inferences for n that do not contribute |
180 |
|
* to its reduction, but may help show a refutation. |
181 |
|
* |
182 |
|
* This function is called when the context-depdendent simplified form of |
183 |
|
* n is nr. The argument "in" is the information object for n. The argument |
184 |
|
* "effort" has the same meaning as the effort argument of checkExtfEval. |
185 |
|
*/ |
186 |
|
void checkExtfInference(Node n, Node nr, ExtfInfoTmp& in, int effort); |
187 |
|
/** The solver state object */ |
188 |
|
SolverState& d_state; |
189 |
|
/** The (custom) output channel of the theory of strings */ |
190 |
|
InferenceManager& d_im; |
191 |
|
/** Reference to the term registry of theory of strings */ |
192 |
|
TermRegistry& d_termReg; |
193 |
|
/** The theory rewriter for this theory. */ |
194 |
|
StringsRewriter& d_rewriter; |
195 |
|
/** reference to the base solver, used for certain queries */ |
196 |
|
BaseSolver& d_bsolver; |
197 |
|
/** reference to the core solver, used for certain queries */ |
198 |
|
CoreSolver& d_csolver; |
199 |
|
/** the extended theory object for the theory of strings */ |
200 |
|
ExtTheory& d_extt; |
201 |
|
/** Reference to the statistics for the theory of strings/sequences. */ |
202 |
|
SequencesStatistics& d_statistics; |
203 |
|
/** preprocessing utility, for performing strings reductions */ |
204 |
|
StringsPreprocess d_preproc; |
205 |
|
/** Common constants */ |
206 |
|
Node d_true; |
207 |
|
Node d_false; |
208 |
|
/** Empty vector */ |
209 |
|
std::vector<Node> d_emptyVec; |
210 |
|
/** map extended functions to the above information */ |
211 |
|
std::map<Node, ExtfInfoTmp> d_extfInfoTmp; |
212 |
|
/** any non-reduced extended functions exist? */ |
213 |
|
context::CDO<bool> d_hasExtf; |
214 |
|
/** extended functions inferences cache */ |
215 |
|
NodeSet d_extfInferCache; |
216 |
|
/** The set of extended functions we have sent reduction lemmas for */ |
217 |
|
NodeSet d_reduced; |
218 |
|
}; |
219 |
|
|
220 |
|
/** An extended theory callback */ |
221 |
9939 |
class StringsExtfCallback : public ExtTheoryCallback |
222 |
|
{ |
223 |
|
public: |
224 |
9942 |
StringsExtfCallback() : d_esolver(nullptr) {} |
225 |
|
/** |
226 |
|
* Get current substitution based on the underlying extended function |
227 |
|
* solver. |
228 |
|
*/ |
229 |
|
bool getCurrentSubstitution(int effort, |
230 |
|
const std::vector<Node>& vars, |
231 |
|
std::vector<Node>& subs, |
232 |
|
std::map<Node, std::vector<Node> >& exp) override; |
233 |
|
/** The extended function solver */ |
234 |
|
ExtfSolver* d_esolver; |
235 |
|
}; |
236 |
|
|
237 |
|
} // namespace strings |
238 |
|
} // namespace theory |
239 |
|
} // namespace cvc5 |
240 |
|
|
241 |
|
#endif /* CVC5__THEORY__STRINGS__EXTF_SOLVER_H */ |