GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/theory_strings.h Lines: 32 32 100.0 %
Date: 2021-05-22 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
9454
  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
9460
  class NotifyClass : public eq::EqualityEngineNotify {
125
  public:
126
9460
   NotifyClass(TheoryStrings& ts) : d_str(ts), d_eagerSolver(ts.d_eagerSolver)
127
   {
128
9460
   }
129
259969
   bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
130
   {
131
519938
     Debug("strings") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate
132
259969
                      << ", " << (value ? "true" : "false") << ")" << std::endl;
133
259969
     if (value)
134
     {
135
142897
       return d_str.propagateLit(predicate);
136
     }
137
117072
     return d_str.propagateLit(predicate.notNode());
138
    }
139
277902
    bool eqNotifyTriggerTermEquality(TheoryId tag,
140
                                     TNode t1,
141
                                     TNode t2,
142
                                     bool value) override
143
    {
144
277902
      Debug("strings") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
145
277902
      if (value) {
146
206590
        return d_str.propagateLit(t1.eqNode(t2));
147
      }
148
71312
      return d_str.propagateLit(t1.eqNode(t2).notNode());
149
    }
150
693
    void eqNotifyConstantTermMerge(TNode t1, TNode t2) override
151
    {
152
693
      Debug("strings") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
153
693
      d_str.conflict(t1, t2);
154
693
    }
155
84119
    void eqNotifyNewClass(TNode t) override
156
    {
157
84119
      Debug("strings") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
158
84119
      d_str.eqNotifyNewClass(t);
159
84119
    }
160
699447
    void eqNotifyMerge(TNode t1, TNode t2) override
161
    {
162
1398894
      Debug("strings") << "NotifyClass::eqNotifyMerge(" << t1 << ", " << t2
163
699447
                       << std::endl;
164
699447
      d_eagerSolver.eqNotifyMerge(t1, t2);
165
699447
    }
166
116493
    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) override
167
    {
168
116493
      Debug("strings") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
169
116493
      d_eagerSolver.eqNotifyDisequal(t1, t2, reason);
170
116493
    }
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. Furthermore,
194
   * col is a partition of repSet where equivalence classes are grouped into
195
   * sets having equal length, where these lengths are stored in lts.
196
   *
197
   * Returns false if a conflict is discovered while doing this assignment.
198
   */
199
  bool collectModelInfoType(TypeNode tn,
200
                            const std::unordered_set<Node>& repSet,
201
                            std::vector<std::vector<Node>>& col,
202
                            std::vector<Node>& lts,
203
                            TheoryModel* m);
204
205
  /** assert pending fact
206
   *
207
   * This asserts atom with polarity to the equality engine of this class,
208
   * where exp is the explanation of why (~) atom holds.
209
   *
210
   * This call may trigger further initialization steps involving the terms
211
   * of atom, including calls to registerTerm.
212
   */
213
  void assertPendingFact(Node atom, bool polarity, Node exp);
214
  //-----------------------inference steps
215
  /** check register terms pre-normal forms
216
   *
217
   * This calls registerTerm(n,2) on all non-congruent strings in the
218
   * equality engine of this class.
219
   */
220
  void checkRegisterTermsPreNormalForm();
221
  /** check codes
222
   *
223
   * This inference schema ensures that constraints between str.code terms
224
   * are satisfied by models that correspond to extensions of the current
225
   * assignment. In particular, this method ensures that str.code can be
226
   * given an interpretation that is injective for string arguments with length
227
   * one. It may add lemmas of the form:
228
   *   str.code(x) == -1 V str.code(x) != str.code(y) V x == y
229
   */
230
  void checkCodes();
231
  /** check register terms for normal forms
232
   *
233
   * This calls registerTerm(str.++(t1, ..., tn ), 3) on the normal forms
234
   * (t1, ..., tn) of all string equivalence classes { s1, ..., sm } such that
235
   * there does not exist a term of the form str.len(si) in the current context.
236
   */
237
  void checkRegisterTermsNormalForms();
238
  //-----------------------end inference steps
239
  /** run the given inference step */
240
  void runInferStep(InferStep s, int effort);
241
  /** run strategy for effort e */
242
  void runStrategy(Theory::Effort e);
243
  /** print strings equivalence classes for debugging */
244
  std::string debugPrintStringsEqc();
245
  /** Commonly used constants */
246
  Node d_true;
247
  Node d_false;
248
  Node d_zero;
249
  Node d_one;
250
  Node d_neg_one;
251
  /** the cardinality of the alphabet */
252
  uint32_t d_cardSize;
253
  /** The notify class */
254
  NotifyClass d_notify;
255
  /**
256
   * Statistics for the theory of strings/sequences. All statistics for these
257
   * theories is collected in this object.
258
   */
259
  SequencesStatistics d_statistics;
260
  /** The solver state object */
261
  SolverState d_state;
262
  /** The eager solver */
263
  EagerSolver d_eagerSolver;
264
  /** The term registry for this theory */
265
  TermRegistry d_termReg;
266
  /** The extended theory callback */
267
  StringsExtfCallback d_extTheoryCb;
268
  /** Extended theory, responsible for context-dependent simplification. */
269
  ExtTheory d_extTheory;
270
  /** The (custom) output channel of the theory of strings */
271
  InferenceManager d_im;
272
  /** The theory rewriter for this theory. */
273
  StringsRewriter d_rewriter;
274
  /** The proof rule checker */
275
  StringProofRuleChecker d_checker;
276
  /**
277
   * The base solver, responsible for reasoning about congruent terms and
278
   * inferring constants for equivalence classes.
279
   */
280
  BaseSolver d_bsolver;
281
  /**
282
   * The core solver, responsible for reasoning about string concatenation
283
   * with length constraints.
284
   */
285
  CoreSolver d_csolver;
286
  /**
287
   * Extended function solver, responsible for reductions and simplifications
288
   * involving extended string functions.
289
   */
290
  ExtfSolver d_esolver;
291
  /** regular expression solver module */
292
  RegExpSolver d_rsolver;
293
  /** regular expression elimination module */
294
  RegExpElimination d_regexp_elim;
295
  /** Strings finite model finding decision strategy */
296
  StringsFmf d_stringsFmf;
297
  /** The representation of the strategy */
298
  Strategy d_strat;
299
};/* class TheoryStrings */
300
301
}  // namespace strings
302
}  // namespace theory
303
}  // namespace cvc5
304
305
#endif /* CVC5__THEORY__STRINGS__THEORY_STRINGS_H */