GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/theory_strings.h Lines: 32 32 100.0 %
Date: 2021-08-06 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(context::Context* c,
68
                context::UserContext* u,
69
                OutputChannel& out,
70
                Valuation valuation,
71
                const LogicInfo& logicInfo,
72
                ProofNodeManager* pnm);
73
  ~TheoryStrings();
74
  //--------------------------------- initialization
75
  /** get the official theory rewriter of this theory */
76
  TheoryRewriter* getTheoryRewriter() override;
77
  /** get the proof checker of this theory */
78
  ProofRuleChecker* getProofChecker() override;
79
  /**
80
   * Returns true if we need an equality engine. If so, we initialize the
81
   * information regarding how it should be setup. For details, see the
82
   * documentation in Theory::needsEqualityEngine.
83
   */
84
  bool needsEqualityEngine(EeSetupInfo& esi) override;
85
  /** finish initialization */
86
  void finishInit() override;
87
  //--------------------------------- end initialization
88
  /** Identify this theory */
89
  std::string identify() const override;
90
  /** Explain */
91
  TrustNode explain(TNode literal) override;
92
  /** presolve */
93
  void presolve() override;
94
  /** shutdown */
95
9847
  void shutdown() override {}
96
  /** preregister term */
97
  void preRegisterTerm(TNode n) override;
98
  //--------------------------------- standard check
99
  /** Do we need a check call at last call effort? */
100
  bool needsCheckLastEffort() override;
101
  bool preNotifyFact(TNode atom,
102
                     bool pol,
103
                     TNode fact,
104
                     bool isPrereg,
105
                     bool isInternal) override;
106
  void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
107
  /** Post-check, called after the fact queue of the theory is processed. */
108
  void postCheck(Effort level) override;
109
  //--------------------------------- end standard check
110
  /** propagate method */
111
  bool propagateLit(TNode literal);
112
  /** Conflict when merging two constants */
113
  void conflict(TNode a, TNode b);
114
  /** called when a new equivalence class is created */
115
  void eqNotifyNewClass(TNode t);
116
  /** preprocess rewrite */
117
  TrustNode ppRewrite(TNode atom, std::vector<SkolemLemma>& lems) override;
118
  /** Collect model values in m based on the relevant terms given by termSet */
119
  bool collectModelValues(TheoryModel* m,
120
                          const std::set<Node>& termSet) override;
121
122
 private:
123
  /** NotifyClass for equality engine */
124
9853
  class NotifyClass : public eq::EqualityEngineNotify {
125
  public:
126
9853
   NotifyClass(TheoryStrings& ts) : d_str(ts), d_eagerSolver(ts.d_eagerSolver)
127
   {
128
9853
   }
129
463488
   bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
130
   {
131
926976
     Debug("strings") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate
132
463488
                      << ", " << (value ? "true" : "false") << ")" << std::endl;
133
463488
     if (value)
134
     {
135
250472
       return d_str.propagateLit(predicate);
136
     }
137
213016
     return d_str.propagateLit(predicate.notNode());
138
    }
139
482840
    bool eqNotifyTriggerTermEquality(TheoryId tag,
140
                                     TNode t1,
141
                                     TNode t2,
142
                                     bool value) override
143
    {
144
482840
      Debug("strings") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
145
482840
      if (value) {
146
373997
        return d_str.propagateLit(t1.eqNode(t2));
147
      }
148
108843
      return d_str.propagateLit(t1.eqNode(t2).notNode());
149
    }
150
1032
    void eqNotifyConstantTermMerge(TNode t1, TNode t2) override
151
    {
152
1032
      Debug("strings") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
153
1032
      d_str.conflict(t1, t2);
154
1032
    }
155
119502
    void eqNotifyNewClass(TNode t) override
156
    {
157
119502
      Debug("strings") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
158
119502
      d_str.eqNotifyNewClass(t);
159
119502
    }
160
1283956
    void eqNotifyMerge(TNode t1, TNode t2) override
161
    {
162
2567912
      Debug("strings") << "NotifyClass::eqNotifyMerge(" << t1 << ", " << t2
163
1283956
                       << std::endl;
164
1283956
      d_eagerSolver.eqNotifyMerge(t1, t2);
165
1283956
    }
166
181108
    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) override
167
    {
168
181108
      Debug("strings") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
169
181108
      d_eagerSolver.eqNotifyDisequal(t1, t2, reason);
170
181108
    }
171
172
   private:
173
    /** The theory of strings object to notify */
174
    TheoryStrings& d_str;
175
    /** The eager solver of the theory of strings */
176
    EagerSolver& d_eagerSolver;
177
  };/* class TheoryStrings::NotifyClass */
178
  /** compute care graph */
179
  void computeCareGraph() override;
180
  /**
181
   * Are x and y shared terms that are not equal? This is used for constructing
182
   * the care graph in the above function.
183
   */
184
  bool areCareDisequal(TNode x, TNode y);
185
  /** Add care pairs */
186
  void addCarePairs(TNodeTrie* t1,
187
                    TNodeTrie* t2,
188
                    unsigned arity,
189
                    unsigned depth);
190
  /** Collect model info for type tn
191
   *
192
   * Assigns model values (in m) to all relevant terms of the string-like type
193
   * tn in the current context, which are stored in repSet[tn].
194
   *
195
   * @param tn The type to compute model values for
196
   * @param toProcess Remaining types to compute model values for
197
   * @param repSet A map of types to the representatives of the equivalence
198
   *               classes of the given type
199
   * @return false if a conflict is discovered while doing this assignment.
200
   */
201
  bool collectModelInfoType(
202
      TypeNode tn,
203
      std::unordered_set<TypeNode>& toProcess,
204
      const std::map<TypeNode, std::unordered_set<Node>>& repSet,
205
      TheoryModel* m);
206
207
  /** assert pending fact
208
   *
209
   * This asserts atom with polarity to the equality engine of this class,
210
   * where exp is the explanation of why (~) atom holds.
211
   *
212
   * This call may trigger further initialization steps involving the terms
213
   * of atom, including calls to registerTerm.
214
   */
215
  void assertPendingFact(Node atom, bool polarity, Node exp);
216
  //-----------------------inference steps
217
  /** check register terms pre-normal forms
218
   *
219
   * This calls registerTerm(n,2) on all non-congruent strings in the
220
   * equality engine of this class.
221
   */
222
  void checkRegisterTermsPreNormalForm();
223
  /** check codes
224
   *
225
   * This inference schema ensures that constraints between str.code terms
226
   * are satisfied by models that correspond to extensions of the current
227
   * assignment. In particular, this method ensures that str.code can be
228
   * given an interpretation that is injective for string arguments with length
229
   * one. It may add lemmas of the form:
230
   *   str.code(x) == -1 V str.code(x) != str.code(y) V x == y
231
   */
232
  void checkCodes();
233
  /** check register terms for normal forms
234
   *
235
   * This calls registerTerm(str.++(t1, ..., tn ), 3) on the normal forms
236
   * (t1, ..., tn) of all string equivalence classes { s1, ..., sm } such that
237
   * there does not exist a term of the form str.len(si) in the current context.
238
   */
239
  void checkRegisterTermsNormalForms();
240
  //-----------------------end inference steps
241
  /** run the given inference step */
242
  void runInferStep(InferStep s, int effort);
243
  /** run strategy for effort e */
244
  void runStrategy(Theory::Effort e);
245
  /** print strings equivalence classes for debugging */
246
  std::string debugPrintStringsEqc();
247
  /** Commonly used constants */
248
  Node d_true;
249
  Node d_false;
250
  Node d_zero;
251
  Node d_one;
252
  Node d_neg_one;
253
  /** the cardinality of the alphabet */
254
  uint32_t d_cardSize;
255
  /** The notify class */
256
  NotifyClass d_notify;
257
  /**
258
   * Statistics for the theory of strings/sequences. All statistics for these
259
   * theories is collected in this object.
260
   */
261
  SequencesStatistics d_statistics;
262
  /** The solver state object */
263
  SolverState d_state;
264
  /** The eager solver */
265
  EagerSolver d_eagerSolver;
266
  /** The term registry for this theory */
267
  TermRegistry d_termReg;
268
  /** The extended theory callback */
269
  StringsExtfCallback d_extTheoryCb;
270
  /** Extended theory, responsible for context-dependent simplification. */
271
  ExtTheory d_extTheory;
272
  /** The (custom) output channel of the theory of strings */
273
  InferenceManager d_im;
274
  /** The theory rewriter for this theory. */
275
  StringsRewriter d_rewriter;
276
  /** The proof rule checker */
277
  StringProofRuleChecker d_checker;
278
  /**
279
   * The base solver, responsible for reasoning about congruent terms and
280
   * inferring constants for equivalence classes.
281
   */
282
  BaseSolver d_bsolver;
283
  /**
284
   * The core solver, responsible for reasoning about string concatenation
285
   * with length constraints.
286
   */
287
  CoreSolver d_csolver;
288
  /**
289
   * Extended function solver, responsible for reductions and simplifications
290
   * involving extended string functions.
291
   */
292
  ExtfSolver d_esolver;
293
  /** regular expression solver module */
294
  RegExpSolver d_rsolver;
295
  /** regular expression elimination module */
296
  RegExpElimination d_regexp_elim;
297
  /** Strings finite model finding decision strategy */
298
  StringsFmf d_stringsFmf;
299
  /** The representation of the strategy */
300
  Strategy d_strat;
301
};/* class TheoryStrings */
302
303
}  // namespace strings
304
}  // namespace theory
305
}  // namespace cvc5
306
307
#endif /* CVC5__THEORY__STRINGS__THEORY_STRINGS_H */