GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/skolem_cache.h Lines: 1 1 100.0 %
Date: 2021-11-07 Branches: 0 0 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Andres Noetzli, Yoni Zohar
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
 * A cache of skolems for theory of strings.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__STRINGS__SKOLEM_CACHE_H
19
#define CVC5__THEORY__STRINGS__SKOLEM_CACHE_H
20
21
#include <map>
22
#include <tuple>
23
#include <unordered_set>
24
25
#include "expr/node.h"
26
#include "expr/skolem_manager.h"
27
28
namespace cvc5 {
29
namespace theory {
30
31
class Rewriter;
32
33
namespace strings {
34
35
/**
36
 * A cache of all string skolems generated by the TheoryStrings class. This
37
 * cache is used to ensure that duplicate skolems are not generated when
38
 * possible, and helps identify what skolems were allocated in the current run.
39
 */
40
16422
class SkolemCache
41
{
42
 public:
43
  /**
44
   * Constructor.
45
   *
46
   * @param rr determines if we aggressively share Skolems based on rewriting or
47
   * return the constants they are entailed to be equal to. This argument is
48
   * optional.
49
   */
50
  SkolemCache(Rewriter* rr);
51
  /** Identifiers for skolem types
52
   *
53
   * The comments below document the properties of each skolem introduced by
54
   * inference in the strings solver, where by skolem we mean the fresh
55
   * string variable that witnesses each of "exists k".
56
   *
57
   * The skolems with _REV suffixes are used for the reverse version of the
58
   * preconditions below, e.g. where we are considering a' ++ a = b' ++ b.
59
   *
60
   * All skolems assume a and b are strings unless otherwise stated.
61
   *
62
   * Notice that these identifiers are each syntax sugar for constructing a
63
   * purification skolem. It is required for the purposes of proof checking
64
   * that this only results in calls to SkolemManager::mkPurifySkolem.
65
   */
66
  enum SkolemId
67
  {
68
    // exists k. k = a
69
    SK_PURIFY,
70
    // a != "" ^ b = "ccccd" ^ a ++ "d" ++ a' = b ++ b' =>
71
    //    exists k. a = "cccc" ++ k
72
    SK_ID_C_SPT,
73
    SK_ID_C_SPT_REV,
74
    // a != "" ^ b = "c" ^ len(a)!=len(b) ^ a ++ a' = b ++ b' =>
75
    //    exists k. a = "c" ++ k
76
    SK_ID_VC_SPT,
77
    SK_ID_VC_SPT_REV,
78
    // a != "" ^ b != "" ^ len(a)!=len(b) ^ a ++ a' = b ++ b' =>
79
    //    exists k1 k2. len( k1 )>0 ^ len( k2 )>0 ^
80
    //                  ( a ++ k1 = b OR a = b ++ k2 )
81
    // k1 is the variable for (a,b) and k2 is the skolem for (b,a).
82
    SK_ID_V_SPT,
83
    SK_ID_V_SPT_REV,
84
    // a != "" ^ b != "" ^ len(a)!=len(b) ^ a ++ a' = b ++ b' =>
85
    //    exists k. len( k )>0 ^ ( a ++ k = b OR a = b ++ k )
86
    SK_ID_V_UNIFIED_SPT,
87
    SK_ID_V_UNIFIED_SPT_REV,
88
    // a != ""  ^ b = "c" ^ a ++ a' != b ++ b' =>
89
    //    exists k, k_rem.
90
    //         len( k ) = 1 ^
91
    //         ( ( a = k ++ k_rem ^ k != "c" ) OR ( a = "c" ++ k_rem ) )
92
    SK_ID_DC_SPT,
93
    SK_ID_DC_SPT_REM,
94
    // a != ""  ^ b != "" ^ len( a ) != len( b ) ^ a ++ a' != b ++ b' =>
95
    //    exists k_x k_y k_z.
96
    //         ( len( k_y ) = len( a ) ^ len( k_x ) = len( b ) ^ len( k_z) > 0
97
    //           ( a = k_x ++ k_z OR b = k_y ++ k_z ) )
98
    SK_ID_DEQ_X,
99
    SK_ID_DEQ_Y,
100
    // contains( a, b ) =>
101
    //    exists k_pre, k_post. a = k_pre ++ b ++ k_post ^
102
    //                          ~contains(k_pre ++ substr( b, 0, len(b)-1 ), b)
103
    //
104
    // As an optimization, these skolems are reused for positive occurrences of
105
    // contains, where they have the semantics:
106
    //
107
    //   contains( a, b ) =>
108
    //      exists k_pre, k_post. a = k_pre ++ b ++ k_post
109
    //
110
    // We reuse them since it is sound to consider w.l.o.g. the first occurrence
111
    // of b in a as the witness for contains( a, b ).
112
    SK_FIRST_CTN_PRE,
113
    SK_FIRST_CTN_POST,
114
    // For integer b,
115
    // len( a ) > b =>
116
    //    exists k. a = k ++ a' ^ len( k ) = b
117
    SK_PREFIX,
118
    // For integer b,
119
    // b > 0 =>
120
    //    exists k. a = a' ++ k ^ len( k ) = ite( len(a)>b, len(a)-b, 0 )
121
    SK_SUFFIX_REM
122
  };
123
  /**
124
   * Returns a skolem of type string that is cached for (a,b,id) and has
125
   * name c.
126
   */
127
  Node mkSkolemCached(Node a, Node b, SkolemId id, const char* c);
128
  /**
129
   * Returns a skolem of type string that is cached for (a,[null],id) and has
130
   * name c.
131
   */
132
  Node mkSkolemCached(Node a, SkolemId id, const char* c);
133
  /** Same as above, but the skolem to construct has a custom type tn */
134
  Node mkTypedSkolemCached(
135
      TypeNode tn, Node a, Node b, SkolemId id, const char* c);
136
  /** Same as mkTypedSkolemCached above for (a,[null],id) */
137
  Node mkTypedSkolemCached(TypeNode tn, Node a, SkolemId id, const char* c);
138
  /**
139
   * Specific version for seq.nth, used for cases where the index is out of
140
   * range for sequence type seqType.
141
   */
142
  static Node mkSkolemSeqNth(TypeNode seqType, const char* c);
143
  /** Returns a (uncached) skolem of type string with name c */
144
  Node mkSkolem(const char* c);
145
  /** Returns true if n is a skolem allocated by this class */
146
  bool isSkolem(Node n) const;
147
  /** Make index variable
148
   *
149
   * This returns an integer variable of kind BOUND_VARIABLE that is used
150
   * for axiomatizing the behavior of a term or predicate t. Notice that this
151
   * index variable does *not* necessarily refer to indices in the term t
152
   * itself. Instead, it refers to indices in the relevant string in the
153
   * reduction of t. For example, the index variable for the term str.to_int(s)
154
   * is used to quantify over the positions in string term s.
155
   */
156
  static Node mkIndexVar(Node t);
157
158
  /** Make length variable
159
   *
160
   * This returns an integer variable of kind BOUND_VARIABLE that is used for
161
   * axiomatizing the behavior of a term or predicate t. It refers to lengths
162
   * of strings in the reduction of t. For example, the length variable for the
163
   * term str.indexof(s, r, n) is used to quantify over the lengths of strings
164
   * that could be matched by r.
165
   */
166
  static Node mkLengthVar(Node t);
167
  /**
168
   * Make skolem function, possibly normalizing based on the rewriter of this
169
   * class. This method should be used whenever it is not possible to define
170
   * a Skolem identifier that amounts to purification of a term.
171
   *
172
   * Notice that this method is not static or constant since it tracks the
173
   * Skolem we construct (in d_allSkolems), which is used for finite model
174
   * finding.
175
   */
176
  Node mkSkolemFun(SkolemFunId id,
177
                   TypeNode tn,
178
                   Node a = Node::null(),
179
                   Node b = Node::null());
180
181
 private:
182
  /**
183
   * Simplifies the arguments for a string skolem used for indexing into the
184
   * cache. In certain cases, we can share skolems with similar arguments e.g.
185
   * SK_FIRST_CTN(a, c) can be used instead of SK_FIRST_CTN((str.substr a 0 n),
186
   * c) because the first occurrence of "c" in "(str.substr a 0 n)" is also the
187
   * first occurrence of "c" in "a" (assuming that "c" appears in both and
188
   * otherwise the value of SK_FIRST_CTN does not matter).
189
   *
190
   * @param id The type of skolem
191
   * @param a The first argument used for indexing
192
   * @param b The second argument used for indexing
193
   * @return A tuple with the new skolem id, the new first, and the new second
194
   * argument
195
   */
196
  std::tuple<SkolemId, Node, Node> normalizeStringSkolem(SkolemId id,
197
                                                         Node a,
198
                                                         Node b);
199
  /** the optional rewriter */
200
  Rewriter* d_rr;
201
  /** string type */
202
  TypeNode d_strType;
203
  /** Constant node zero */
204
  Node d_zero;
205
  /** map from node pairs and identifiers to skolems */
206
  std::map<Node, std::map<Node, std::map<SkolemId, Node> > > d_skolemCache;
207
  /** the set of all skolems we have generated */
208
  std::unordered_set<Node> d_allSkolems;
209
};
210
211
}  // namespace strings
212
}  // namespace theory
213
}  // namespace cvc5
214
215
#endif /* CVC5__THEORY__STRINGS__SKOLEM_CACHE_H */