Merging bv parts of ajr/bvExt branch, minor additions to ExtTheory.
[cvc5.git] / src / theory / strings / theory_strings.h
1 /********************* */
2 /*! \file theory_strings.h
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Tianyi Liang, Andrew Reynolds, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2016 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.\endverbatim
11 **
12 ** \brief Theory of strings
13 **
14 ** Theory of strings.
15 **/
16
17 #include "cvc4_private.h"
18
19 #ifndef __CVC4__THEORY__STRINGS__THEORY_STRINGS_H
20 #define __CVC4__THEORY__STRINGS__THEORY_STRINGS_H
21
22 #include "theory/theory.h"
23 #include "theory/uf/equality_engine.h"
24 #include "theory/strings/theory_strings_preprocess.h"
25 #include "theory/strings/regexp_operation.h"
26
27 #include "context/cdchunk_list.h"
28 #include "context/cdhashset.h"
29 #include "expr/attribute.h"
30
31 #include <climits>
32 #include <deque>
33
34 namespace CVC4 {
35 namespace theory {
36
37 namespace quantifiers{
38 class TermArgTrie;
39 }
40
41 namespace strings {
42
43 /**
44 * Decision procedure for strings.
45 *
46 */
47
48 struct StringsProxyVarAttributeId {};
49 typedef expr::Attribute< StringsProxyVarAttributeId, bool > StringsProxyVarAttribute;
50
51 class TheoryStrings : public Theory {
52 typedef context::CDChunkList<Node> NodeList;
53 typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
54 typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
55 typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
56 typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
57
58 public:
59 TheoryStrings(context::Context* c, context::UserContext* u,
60 OutputChannel& out, Valuation valuation,
61 const LogicInfo& logicInfo);
62 ~TheoryStrings();
63
64 void setMasterEqualityEngine(eq::EqualityEngine* eq);
65
66 std::string identify() const { return std::string("TheoryStrings"); }
67
68 public:
69 void propagate(Effort e);
70 bool propagate(TNode literal);
71 void explain( TNode literal, std::vector<TNode>& assumptions );
72 Node explain( TNode literal );
73 eq::EqualityEngine * getEqualityEngine() { return &d_equalityEngine; }
74 bool getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp );
75 int getReduction( int effort, Node n, Node& nr );
76
77 // NotifyClass for equality engine
78 class NotifyClass : public eq::EqualityEngineNotify {
79 TheoryStrings& d_str;
80 public:
81 NotifyClass(TheoryStrings& t_str): d_str(t_str) {}
82 bool eqNotifyTriggerEquality(TNode equality, bool value) {
83 Debug("strings") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
84 if (value) {
85 return d_str.propagate(equality);
86 } else {
87 // We use only literal triggers so taking not is safe
88 return d_str.propagate(equality.notNode());
89 }
90 }
91 bool eqNotifyTriggerPredicate(TNode predicate, bool value) {
92 Debug("strings") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false") << ")" << std::endl;
93 if (value) {
94 return d_str.propagate(predicate);
95 } else {
96 return d_str.propagate(predicate.notNode());
97 }
98 }
99 bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
100 Debug("strings") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
101 if (value) {
102 return d_str.propagate(t1.eqNode(t2));
103 } else {
104 return d_str.propagate(t1.eqNode(t2).notNode());
105 }
106 }
107 void eqNotifyConstantTermMerge(TNode t1, TNode t2) {
108 Debug("strings") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
109 d_str.conflict(t1, t2);
110 }
111 void eqNotifyNewClass(TNode t) {
112 Debug("strings") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
113 d_str.eqNotifyNewClass(t);
114 }
115 void eqNotifyPreMerge(TNode t1, TNode t2) {
116 Debug("strings") << "NotifyClass::eqNotifyPreMerge(" << t1 << ", " << t2 << std::endl;
117 d_str.eqNotifyPreMerge(t1, t2);
118 }
119 void eqNotifyPostMerge(TNode t1, TNode t2) {
120 Debug("strings") << "NotifyClass::eqNotifyPostMerge(" << t1 << ", " << t2 << std::endl;
121 d_str.eqNotifyPostMerge(t1, t2);
122 }
123 void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
124 Debug("strings") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
125 d_str.eqNotifyDisequal(t1, t2, reason);
126 }
127 };/* class TheoryStrings::NotifyClass */
128
129 private:
130 // Constants
131 Node d_emptyString;
132 Node d_emptyRegexp;
133 Node d_true;
134 Node d_false;
135 Node d_zero;
136 Node d_one;
137 CVC4::Rational RMAXINT;
138 unsigned d_card_size;
139 // Helper functions
140 Node getRepresentative( Node t );
141 bool hasTerm( Node a );
142 bool areEqual( Node a, Node b );
143 bool areDisequal( Node a, Node b );
144 // t is representative, te = t, add lt = te to explanation exp
145 Node getLengthExp( Node t, std::vector< Node >& exp, Node te );
146 Node getLength( Node t, std::vector< Node >& exp );
147
148 private:
149 /** The notify class */
150 NotifyClass d_notify;
151 /** Equaltity engine */
152 eq::EqualityEngine d_equalityEngine;
153 /** Are we in conflict */
154 context::CDO<bool> d_conflict;
155 //list of pairs of nodes to merge
156 std::map< Node, Node > d_pending_exp;
157 std::vector< Node > d_pending;
158 std::vector< Node > d_lemma_cache;
159 std::map< Node, bool > d_pending_req_phase;
160 /** inferences: maintained to ensure ref count for internally introduced nodes */
161 NodeList d_infer;
162 NodeList d_infer_exp;
163 /** normal forms */
164 std::map< Node, Node > d_normal_forms_base;
165 std::map< Node, std::vector< Node > > d_normal_forms;
166 std::map< Node, std::vector< Node > > d_normal_forms_exp;
167 std::map< Node, std::map< Node, std::map< bool, int > > > d_normal_forms_exp_depend;
168 //map of pairs of terms that have the same normal form
169 NodeIntMap d_nf_pairs;
170 std::map< Node, std::vector< Node > > d_nf_pairs_data;
171 void addNormalFormPair( Node n1, Node n2 );
172 bool isNormalFormPair( Node n1, Node n2 );
173 bool isNormalFormPair2( Node n1, Node n2 );
174 // loop ant
175 NodeSet d_loop_antec;
176 // preReg cache
177 NodeSet d_pregistered_terms_cache;
178 NodeSet d_registered_terms_cache;
179 NodeSet d_length_lemma_terms_cache;
180 NodeSet d_skolem_ne_reg_cache;
181 // preprocess cache
182 StringsPreprocess d_preproc;
183 NodeBoolMap d_preproc_cache;
184 // extended functions inferences cache
185 NodeSet d_extf_infer_cache;
186 NodeSet d_extf_infer_cache_u;
187 std::vector< Node > d_empty_vec;
188 //
189 NodeList d_ee_disequalities;
190 private:
191 NodeSet d_congruent;
192 std::map< Node, Node > d_eqc_to_const;
193 std::map< Node, Node > d_eqc_to_const_base;
194 std::map< Node, Node > d_eqc_to_const_exp;
195 Node getConstantEqc( Node eqc );
196
197 std::map< Node, Node > d_eqc_to_len_term;
198 std::vector< Node > d_strings_eqc;
199 Node d_emptyString_r;
200 class TermIndex {
201 public:
202 Node d_data;
203 std::map< TNode, TermIndex > d_children;
204 Node add( TNode n, unsigned index, TheoryStrings* t, Node er, std::vector< Node >& c );
205 void clear(){ d_children.clear(); }
206 };
207 std::map< Kind, TermIndex > d_term_index;
208 //list of non-congruent concat terms in each eqc
209 std::map< Node, std::vector< Node > > d_eqc;
210 std::map< Node, std::vector< Node > > d_flat_form;
211 std::map< Node, std::vector< int > > d_flat_form_index;
212
213 void debugPrintFlatForms( const char * tc );
214 void debugPrintNormalForms( const char * tc );
215 /////////////////////////////////////////////////////////////////////////////
216 // MODEL GENERATION
217 /////////////////////////////////////////////////////////////////////////////
218 public:
219 void collectModelInfo(TheoryModel* m, bool fullModel);
220
221 /////////////////////////////////////////////////////////////////////////////
222 // NOTIFICATIONS
223 /////////////////////////////////////////////////////////////////////////////
224 public:
225 void presolve();
226 void shutdown() { }
227
228 /////////////////////////////////////////////////////////////////////////////
229 // MAIN SOLVER
230 /////////////////////////////////////////////////////////////////////////////
231 private:
232 void addSharedTerm(TNode n);
233 EqualityStatus getEqualityStatus(TNode a, TNode b);
234
235 private:
236 class EqcInfo {
237 public:
238 EqcInfo( context::Context* c );
239 ~EqcInfo(){}
240 //constant in this eqc
241 context::CDO< Node > d_length_term;
242 context::CDO< unsigned > d_cardinality_lem_k;
243 // 1 = added length lemma
244 context::CDO< Node > d_normalized_length;
245 };
246 /** map from representatives to information necessary for equivalence classes */
247 std::map< Node, EqcInfo* > d_eqc_info;
248 EqcInfo * getOrMakeEqcInfo( Node eqc, bool doMake = true );
249 //maintain which concat terms have the length lemma instantiated
250 NodeNodeMap d_proxy_var;
251 NodeNodeMap d_proxy_var_to_length;
252 /** All the function terms that the theory has seen */
253 context::CDList<TNode> d_functionsTerms;
254 private:
255 //any non-reduced extended functions exist
256 context::CDO< bool > d_has_extf;
257 // static information about extf
258 class ExtfInfo {
259 public:
260 //all variables in this term
261 std::vector< Node > d_vars;
262 };
263 // non-static information about extf
264 class ExtfInfoTmp {
265 public:
266 void init(){
267 d_pol = 0;
268 d_model_active = true;
269 }
270 // list of terms that something (does not) contain and their explanation
271 std::map< bool, std::vector< Node > > d_ctn;
272 std::map< bool, std::vector< Node > > d_ctn_from;
273 //polarity
274 int d_pol;
275 //explanation
276 std::vector< Node > d_exp;
277 //false if it is reduced in the model
278 bool d_model_active;
279 };
280 std::map< Node, ExtfInfoTmp > d_extf_info_tmp;
281 private:
282 class InferInfo {
283 public:
284 unsigned d_i;
285 unsigned d_j;
286 bool d_rev;
287 std::vector< Node > d_ant;
288 std::vector< Node > d_antn;
289 std::map< int, std::vector< Node > > d_new_skolem;
290 Node d_conc;
291 unsigned d_id;
292 std::map< Node, bool > d_pending_phase;
293 unsigned d_index;
294 const char * getId() {
295 switch( d_id ){
296 case 1:return "S-Split(CST-P)-prop";break;
297 case 2:return "S-Split(VAR)-prop";break;
298 case 3:return "Len-Split(Len)";break;
299 case 4:return "Len-Split(Emp)";break;
300 case 5:return "S-Split(CST-P)-binary";break;
301 case 6:return "S-Split(CST-P)";break;
302 case 7:return "S-Split(VAR)";break;
303 case 8:return "F-Loop";break;
304 default:break;
305 }
306 return "";
307 }
308 bool sendAsLemma();
309 };
310 //initial check
311 void checkInit();
312 void checkConstantEquivalenceClasses( TermIndex* ti, std::vector< Node >& vecc );
313 //extended functions evaluation check
314 void checkExtfEval( int effort = 0 );
315 void checkExtfInference( Node n, Node nr, ExtfInfoTmp& in, int effort );
316 void collectVars( Node n, std::vector< Node >& vars, std::map< Node, bool >& visited );
317 Node getSymbolicDefinition( Node n, std::vector< Node >& exp );
318 //check extf reduction
319 void checkExtfReductions( int effort );
320 //flat forms check
321 void checkFlatForms();
322 Node checkCycles( Node eqc, std::vector< Node >& curr, std::vector< Node >& exp );
323 //normal forms check
324 void checkNormalForms();
325 void normalizeEquivalenceClass( Node n );
326 void getNormalForms( Node &eqc, std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
327 std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend );
328 bool detectLoop( std::vector< std::vector< Node > > &normal_forms, int i, int j, int index, int &loop_in_i, int &loop_in_j, unsigned rproc );
329 bool processLoop( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
330 int i, int j, int loop_n_index, int other_n_index,int loop_index, int index, InferInfo& info );
331 void processNEqc( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
332 std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend );
333 void processReverseNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
334 std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
335 unsigned i, unsigned j, unsigned& index, unsigned rproc, std::vector< InferInfo >& pinfer );
336 void processSimpleNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
337 std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
338 unsigned i, unsigned j, unsigned& index, bool isRev, unsigned rproc, std::vector< InferInfo >& pinfer );
339 void processDeq( Node n1, Node n2 );
340 int processReverseDeq( std::vector< Node >& nfi, std::vector< Node >& nfj, Node ni, Node nj );
341 int processSimpleDeq( std::vector< Node >& nfi, std::vector< Node >& nfj, Node ni, Node nj, unsigned& index, bool isRev );
342 void checkDeqNF();
343 void getExplanationVectorForPrefix( std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
344 unsigned i, int index, bool isRev, std::vector< Node >& curr_exp );
345 void getExplanationVectorForPrefixEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
346 std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
347 unsigned i, unsigned j, int index_i, int index_j, bool isRev, std::vector< Node >& curr_exp );
348
349 Node collectConstantStringAt( std::vector< Node >& vec, int& index, bool isRev );
350
351 //check membership constraints
352 Node mkRegExpAntec(Node atom, Node ant);
353 Node normalizeRegexp(Node r);
354 bool normalizePosMemberships( std::map< Node, std::vector< Node > > &memb_with_exps );
355 bool applyRConsume( CVC4::String &s, Node &r );
356 Node applyRSplit( Node s1, Node s2, Node r );
357 bool applyRLen( std::map< Node, std::vector< Node > > &XinR_with_exps );
358 bool checkMembershipsWithoutLength( std::map< Node, std::vector< Node > > &memb_with_exps,
359 std::map< Node, std::vector< Node > > &XinR_with_exps);
360 void checkMemberships();
361 bool checkMemberships2();
362 bool checkPDerivative( Node x, Node r, Node atom, bool &addedLemma,
363 std::vector< Node > &processed, std::vector< Node > &cprocessed,
364 std::vector< Node > &nf_exp);
365 //check contains
366 void checkPosContains( std::vector< Node >& posContains );
367 void checkNegContains( std::vector< Node >& negContains );
368 //lengths normalize check
369 void checkLengthsEqc();
370 //cardinality check
371 void checkCardinality();
372
373 private:
374 void addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth );
375 public:
376 /** preregister term */
377 void preRegisterTerm(TNode n);
378 /** Expand definition */
379 Node expandDefinition(LogicRequest &logicRequest, Node n);
380 /** Check at effort e */
381 void check(Effort e);
382 /** needs check last effort */
383 bool needsCheckLastEffort();
384 /** Conflict when merging two constants */
385 void conflict(TNode a, TNode b);
386 /** called when a new equivalence class is created */
387 void eqNotifyNewClass(TNode t);
388 /** called when two equivalence classes will merge */
389 void eqNotifyPreMerge(TNode t1, TNode t2);
390 /** called when two equivalence classes have merged */
391 void eqNotifyPostMerge(TNode t1, TNode t2);
392 /** called when two equivalence classes are made disequal */
393 void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
394 /** get preprocess */
395 StringsPreprocess * getPreprocess() { return &d_preproc; }
396 protected:
397 /** compute care graph */
398 void computeCareGraph();
399
400 //do pending merges
401 void assertPendingFact(Node atom, bool polarity, Node exp);
402 void doPendingFacts();
403 void doPendingLemmas();
404 bool hasProcessed();
405 void addToExplanation( Node a, Node b, std::vector< Node >& exp );
406 void addToExplanation( Node lit, std::vector< Node >& exp );
407
408 //register term
409 void registerTerm( Node n, int effort );
410 //send lemma
411 void sendInference( std::vector< Node >& exp, std::vector< Node >& exp_n, Node eq, const char * c, bool asLemma = false );
412 void sendInference( std::vector< Node >& exp, Node eq, const char * c, bool asLemma = false );
413 void sendLemma( Node ant, Node conc, const char * c );
414 void sendInfer( Node eq_exp, Node eq, const char * c );
415 void sendSplit( Node a, Node b, const char * c, bool preq = true );
416 void sendLengthLemma( Node n );
417 /** mkConcat **/
418 inline Node mkConcat( Node n1, Node n2 );
419 inline Node mkConcat( Node n1, Node n2, Node n3 );
420 inline Node mkConcat( const std::vector< Node >& c );
421 inline Node mkLength( Node n );
422 //mkSkolem
423 enum {
424 sk_id_c_spt,
425 sk_id_vc_spt,
426 sk_id_vc_bin_spt,
427 sk_id_v_spt,
428 sk_id_c_spt_rev,
429 sk_id_vc_spt_rev,
430 sk_id_vc_bin_spt_rev,
431 sk_id_v_spt_rev,
432 sk_id_ctn_pre,
433 sk_id_ctn_post,
434 sk_id_dc_spt,
435 sk_id_dc_spt_rem,
436 sk_id_deq_x,
437 sk_id_deq_y,
438 sk_id_deq_z,
439 };
440 std::map< Node, std::map< Node, std::map< int, Node > > > d_skolem_cache;
441 Node mkSkolemCached( Node a, Node b, int id, const char * c, int isLenSplit = 0 );
442 inline Node mkSkolemS(const char * c, int isLenSplit = 0);
443 void registerNonEmptySkolem( Node sk );
444 //inline Node mkSkolemI(const char * c);
445 /** mkExplain **/
446 Node mkExplain( std::vector< Node >& a );
447 Node mkExplain( std::vector< Node >& a, std::vector< Node >& an );
448 /** mkAnd **/
449 Node mkAnd( std::vector< Node >& a );
450 /** get concat vector */
451 void getConcatVec( Node n, std::vector< Node >& c );
452
453 //get equivalence classes
454 void getEquivalenceClasses( std::vector< Node >& eqcs );
455
456 //separate into collections with equal length
457 void separateByLength( std::vector< Node >& n, std::vector< std::vector< Node > >& col, std::vector< Node >& lts );
458 void printConcat( std::vector< Node >& n, const char * c );
459
460 void inferSubstitutionProxyVars( Node n, std::vector< Node >& vars, std::vector< Node >& subs, std::vector< Node >& unproc );
461
462 // Symbolic Regular Expression
463 private:
464 // regular expression memberships
465 NodeList d_regexp_memberships;
466 NodeSet d_regexp_ucached;
467 NodeSet d_regexp_ccached;
468 // stored assertions
469 NodeIntMap d_pos_memberships;
470 std::map< Node, std::vector< Node > > d_pos_memberships_data;
471 NodeIntMap d_neg_memberships;
472 std::map< Node, std::vector< Node > > d_neg_memberships_data;
473 unsigned getNumMemberships( Node n, bool isPos );
474 Node getMembership( Node n, bool isPos, unsigned i );
475 // semi normal forms for symbolic expression
476 std::map< Node, Node > d_nf_regexps;
477 std::map< Node, std::vector< Node > > d_nf_regexps_exp;
478 // intersection
479 NodeNodeMap d_inter_cache;
480 NodeIntMap d_inter_index;
481 // processed memberships
482 NodeSet d_processed_memberships;
483 // antecedant for why regexp membership must be true
484 NodeNodeMap d_regexp_ant;
485 // membership length
486 //std::map< Node, bool > d_membership_length;
487 // regular expression operations
488 RegExpOpr d_regexp_opr;
489
490 CVC4::String getHeadConst( Node x );
491 bool deriveRegExp( Node x, Node r, Node ant );
492 void addMembership(Node assertion);
493 Node getNormalString(Node x, std::vector<Node> &nf_exp);
494 Node getNormalSymRegExp(Node r, std::vector<Node> &nf_exp);
495
496
497 // Finite Model Finding
498 private:
499 NodeSet d_input_vars;
500 context::CDO< Node > d_input_var_lsum;
501 context::CDHashMap< int, Node > d_cardinality_lits;
502 context::CDO< int > d_curr_cardinality;
503 public:
504 //for finite model finding
505 Node getNextDecisionRequest();
506 //ppRewrite
507 Node ppRewrite(TNode atom);
508 public:
509 /** statistics class */
510 class Statistics {
511 public:
512 IntStat d_splits;
513 IntStat d_eq_splits;
514 IntStat d_deq_splits;
515 IntStat d_loop_lemmas;
516 IntStat d_new_skolems;
517 Statistics();
518 ~Statistics();
519 };/* class TheoryStrings::Statistics */
520 Statistics d_statistics;
521
522 };/* class TheoryStrings */
523
524 }/* CVC4::theory::strings namespace */
525 }/* CVC4::theory namespace */
526 }/* CVC4 namespace */
527
528 #endif /* __CVC4__THEORY__STRINGS__THEORY_STRINGS_H */