GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/theory_strings.h Lines: 32 32 100.0 %
Date: 2021-09-17 Branches: 69 132 52.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tianyi Liang, Mathias Preiner
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
 * Theory of strings.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__STRINGS__THEORY_STRINGS_H
19
#define CVC5__THEORY__STRINGS__THEORY_STRINGS_H
20
21
#include <climits>
22
#include <deque>
23
24
#include "context/cdhashset.h"
25
#include "context/cdlist.h"
26
#include "expr/node_trie.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/eager_solver.h"
31
#include "theory/strings/extf_solver.h"
32
#include "theory/strings/infer_info.h"
33
#include "theory/strings/inference_manager.h"
34
#include "theory/strings/normal_form.h"
35
#include "theory/strings/proof_checker.h"
36
#include "theory/strings/regexp_elim.h"
37
#include "theory/strings/regexp_operation.h"
38
#include "theory/strings/regexp_solver.h"
39
#include "theory/strings/sequences_stats.h"
40
#include "theory/strings/solver_state.h"
41
#include "theory/strings/strategy.h"
42
#include "theory/strings/strings_fmf.h"
43
#include "theory/strings/strings_rewriter.h"
44
#include "theory/strings/term_registry.h"
45
#include "theory/theory.h"
46
#include "theory/uf/equality_engine.h"
47
48
namespace cvc5 {
49
namespace theory {
50
namespace strings {
51
52
/**
53
 * A theory solver for strings. At a high level, the solver implements
54
 * techniques described in:
55
 * - Liang et al, CAV 2014,
56
 * - Reynolds et al, CAV 2017,
57
 * - Reynolds et al, IJCAR 2020.
58
 * Its rewriter is described in:
59
 * - Reynolds et al, CAV 2019.
60
 */
61
class TheoryStrings : public Theory {
62
  friend class InferenceManager;
63
  typedef context::CDHashSet<Node> NodeSet;
64
  typedef context::CDHashSet<TypeNode, std::hash<TypeNode>> TypeNodeSet;
65
66
 public:
67
  TheoryStrings(Env& env, OutputChannel& out, Valuation valuation);
68
  ~TheoryStrings();
69
  //--------------------------------- initialization
70
  /** get the official theory rewriter of this theory */
71
  TheoryRewriter* getTheoryRewriter() override;
72
  /** get the proof checker of this theory */
73
  ProofRuleChecker* getProofChecker() override;
74
  /**
75
   * Returns true if we need an equality engine. If so, we initialize the
76
   * information regarding how it should be setup. For details, see the
77
   * documentation in Theory::needsEqualityEngine.
78
   */
79
  bool needsEqualityEngine(EeSetupInfo& esi) override;
80
  /** finish initialization */
81
  void finishInit() override;
82
  //--------------------------------- end initialization
83
  /** Identify this theory */
84
  std::string identify() const override;
85
  /** Explain */
86
  TrustNode explain(TNode literal) override;
87
  /** presolve */
88
  void presolve() override;
89
  /** shutdown */
90
9933
  void shutdown() override {}
91
  /** preregister term */
92
  void preRegisterTerm(TNode n) override;
93
  //--------------------------------- standard check
94
  /** Do we need a check call at last call effort? */
95
  bool needsCheckLastEffort() override;
96
  bool preNotifyFact(TNode atom,
97
                     bool pol,
98
                     TNode fact,
99
                     bool isPrereg,
100
                     bool isInternal) override;
101
  void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
102
  /** Post-check, called after the fact queue of the theory is processed. */
103
  void postCheck(Effort level) override;
104
  //--------------------------------- end standard check
105
  /** propagate method */
106
  bool propagateLit(TNode literal);
107
  /** Conflict when merging two constants */
108
  void conflict(TNode a, TNode b);
109
  /** called when a new equivalence class is created */
110
  void eqNotifyNewClass(TNode t);
111
  /** preprocess rewrite */
112
  TrustNode ppRewrite(TNode atom, std::vector<SkolemLemma>& lems) override;
113
  /** Collect model values in m based on the relevant terms given by termSet */
114
  bool collectModelValues(TheoryModel* m,
115
                          const std::set<Node>& termSet) override;
116
117
 private:
118
  /** NotifyClass for equality engine */
119
9939
  class NotifyClass : public eq::EqualityEngineNotify {
120
  public:
121
9942
   NotifyClass(TheoryStrings& ts) : d_str(ts), d_eagerSolver(ts.d_eagerSolver)
122
   {
123
9942
   }
124
526294
   bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
125
   {
126
1052588
     Debug("strings") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate
127
526294
                      << ", " << (value ? "true" : "false") << ")" << std::endl;
128
526294
     if (value)
129
     {
130
283161
       return d_str.propagateLit(predicate);
131
     }
132
243133
     return d_str.propagateLit(predicate.notNode());
133
    }
134
547428
    bool eqNotifyTriggerTermEquality(TheoryId tag,
135
                                     TNode t1,
136
                                     TNode t2,
137
                                     bool value) override
138
    {
139
547428
      Debug("strings") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
140
547428
      if (value) {
141
424911
        return d_str.propagateLit(t1.eqNode(t2));
142
      }
143
122517
      return d_str.propagateLit(t1.eqNode(t2).notNode());
144
    }
145
1135
    void eqNotifyConstantTermMerge(TNode t1, TNode t2) override
146
    {
147
1135
      Debug("strings") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
148
1135
      d_str.conflict(t1, t2);
149
1135
    }
150
124678
    void eqNotifyNewClass(TNode t) override
151
    {
152
124678
      Debug("strings") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
153
124678
      d_str.eqNotifyNewClass(t);
154
124678
    }
155
1420018
    void eqNotifyMerge(TNode t1, TNode t2) override
156
    {
157
2840036
      Debug("strings") << "NotifyClass::eqNotifyMerge(" << t1 << ", " << t2
158
1420018
                       << std::endl;
159
1420018
      d_eagerSolver.eqNotifyMerge(t1, t2);
160
1420018
    }
161
204238
    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) override
162
    {
163
204238
      Debug("strings") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
164
204238
      d_eagerSolver.eqNotifyDisequal(t1, t2, reason);
165
204238
    }
166
167
   private:
168
    /** The theory of strings object to notify */
169
    TheoryStrings& d_str;
170
    /** The eager solver of the theory of strings */
171
    EagerSolver& d_eagerSolver;
172
  };/* class TheoryStrings::NotifyClass */
173
  /** compute care graph */
174
  void computeCareGraph() override;
175
  /**
176
   * Are x and y shared terms that are not equal? This is used for constructing
177
   * the care graph in the above function.
178
   */
179
  bool areCareDisequal(TNode x, TNode y);
180
  /** Add care pairs */
181
  void addCarePairs(TNodeTrie* t1,
182
                    TNodeTrie* t2,
183
                    unsigned arity,
184
                    unsigned depth);
185
  /** Collect model info for type tn
186
   *
187
   * Assigns model values (in m) to all relevant terms of the string-like type
188
   * tn in the current context, which are stored in repSet[tn].
189
   *
190
   * @param tn The type to compute model values for
191
   * @param toProcess Remaining types to compute model values for
192
   * @param repSet A map of types to the representatives of the equivalence
193
   *               classes of the given type
194
   * @return false if a conflict is discovered while doing this assignment.
195
   */
196
  bool collectModelInfoType(
197
      TypeNode tn,
198
      std::unordered_set<TypeNode>& toProcess,
199
      const std::map<TypeNode, std::unordered_set<Node>>& repSet,
200
      TheoryModel* m);
201
202
  /** assert pending fact
203
   *
204
   * This asserts atom with polarity to the equality engine of this class,
205
   * where exp is the explanation of why (~) atom holds.
206
   *
207
   * This call may trigger further initialization steps involving the terms
208
   * of atom, including calls to registerTerm.
209
   */
210
  void assertPendingFact(Node atom, bool polarity, Node exp);
211
  //-----------------------inference steps
212
  /** check register terms pre-normal forms
213
   *
214
   * This calls registerTerm(n,2) on all non-congruent strings in the
215
   * equality engine of this class.
216
   */
217
  void checkRegisterTermsPreNormalForm();
218
  /** check codes
219
   *
220
   * This inference schema ensures that constraints between str.code terms
221
   * are satisfied by models that correspond to extensions of the current
222
   * assignment. In particular, this method ensures that str.code can be
223
   * given an interpretation that is injective for string arguments with length
224
   * one. It may add lemmas of the form:
225
   *   str.code(x) == -1 V str.code(x) != str.code(y) V x == y
226
   */
227
  void checkCodes();
228
  /** check register terms for normal forms
229
   *
230
   * This calls registerTerm(str.++(t1, ..., tn ), 3) on the normal forms
231
   * (t1, ..., tn) of all string equivalence classes { s1, ..., sm } such that
232
   * there does not exist a term of the form str.len(si) in the current context.
233
   */
234
  void checkRegisterTermsNormalForms();
235
  //-----------------------end inference steps
236
  /** run the given inference step */
237
  void runInferStep(InferStep s, int effort);
238
  /** run strategy for effort e */
239
  void runStrategy(Theory::Effort e);
240
  /** print strings equivalence classes for debugging */
241
  std::string debugPrintStringsEqc();
242
  /** Commonly used constants */
243
  Node d_true;
244
  Node d_false;
245
  Node d_zero;
246
  Node d_one;
247
  Node d_neg_one;
248
  /** the cardinality of the alphabet */
249
  uint32_t d_cardSize;
250
  /** The notify class */
251
  NotifyClass d_notify;
252
  /**
253
   * Statistics for the theory of strings/sequences. All statistics for these
254
   * theories is collected in this object.
255
   */
256
  SequencesStatistics d_statistics;
257
  /** The solver state object */
258
  SolverState d_state;
259
  /** The eager solver */
260
  EagerSolver d_eagerSolver;
261
  /** The term registry for this theory */
262
  TermRegistry d_termReg;
263
  /** The extended theory callback */
264
  StringsExtfCallback d_extTheoryCb;
265
  /** The (custom) output channel of the theory of strings */
266
  InferenceManager d_im;
267
  /** Extended theory, responsible for context-dependent simplification. */
268
  ExtTheory d_extTheory;
269
  /** The theory rewriter for this theory. */
270
  StringsRewriter d_rewriter;
271
  /** The proof rule checker */
272
  StringProofRuleChecker d_checker;
273
  /**
274
   * The base solver, responsible for reasoning about congruent terms and
275
   * inferring constants for equivalence classes.
276
   */
277
  BaseSolver d_bsolver;
278
  /**
279
   * The core solver, responsible for reasoning about string concatenation
280
   * with length constraints.
281
   */
282
  CoreSolver d_csolver;
283
  /**
284
   * Extended function solver, responsible for reductions and simplifications
285
   * involving extended string functions.
286
   */
287
  ExtfSolver d_esolver;
288
  /** regular expression solver module */
289
  RegExpSolver d_rsolver;
290
  /** regular expression elimination module */
291
  RegExpElimination d_regexp_elim;
292
  /** Strings finite model finding decision strategy */
293
  StringsFmf d_stringsFmf;
294
  /** The representation of the strategy */
295
  Strategy d_strat;
296
};/* class TheoryStrings */
297
298
}  // namespace strings
299
}  // namespace theory
300
}  // namespace cvc5
301
302
#endif /* CVC5__THEORY__STRINGS__THEORY_STRINGS_H */