GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/sygus/sygus_reconstruct.h Lines: 1 1 100.0 %
Date: 2021-05-22 Branches: 0 0 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Abdalrhman Mohamed, Andrew Reynolds
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
 * Utility for reconstructing terms to match a grammar.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__QUANTIFIERS__SYGUS_RECONSTRUCT_H
19
#define CVC5__THEORY__QUANTIFIERS__SYGUS_RECONSTRUCT_H
20
21
#include <map>
22
#include <vector>
23
24
#include "theory/quantifiers/sygus/rcons_obligation.h"
25
#include "theory/quantifiers/sygus/rcons_type_info.h"
26
27
namespace cvc5 {
28
namespace theory {
29
namespace quantifiers {
30
31
using BuiltinSet = std::unordered_set<Node>;
32
using TypeBuiltinSetMap = std::unordered_map<TypeNode, BuiltinSet>;
33
34
/** SygusReconstruct
35
 *
36
 * This class implements an algorithm for reconstructing a given term such that
37
 * the reconstructed term is equivalent to the original term and its syntax
38
 * matches a specified grammar.
39
 *
40
 * Goal: find a term g in sygus type T0 that is equivalent to builtin term t0.
41
 *
42
 * rcons(t0, T0) returns g
43
 * {
44
 *   Obs: A set of pairs to reconstruct into T, where each pair is of the form
45
 *        (k, ts), where k is a skolem of a sygus type T and ts is a set of
46
 *        builtin terms of the type encoded by T.
47
 *
48
 *   Terms: A map from skolems k to a set of builtin terms in the pairs (k, ts).
49
 *          That is, Terms[k] = ts.
50
 *
51
 *   Sol: A map from skolems k to (possibly null) sygus terms of type T
52
 *        representing solutions to the obligations.
53
 *
54
 *   CandSols : A map from a skolem k to a set of possible solutions for its
55
 *              corresponding obligation. Whenever there is a successful match,
56
 *              it is added to this set.
57
 *
58
 *   Pool : A map from a sygus type T to a set of enumerated terms in T.
59
 *          The terms in this pool are patterns whose builtin analogs are used
60
 *          for matching against the terms to reconstruct ts in (k, ts).
61
 *
62
 *   let k0 be a fresh skolem of sygus type T0
63
 *   Obs[T0] += (k0, {t0})
64
 *
65
 *   TermsToRecons[T0] = {t0}
66
 *
67
 *   while Sol[k0] == null
68
 *     // map from T to terms pending addition to TermsToRecons
69
 *     TermsToRecons' = {}
70
 *     // enumeration phase
71
 *     for each subfield type T of T0
72
 *       // enumerated terms may contain variables zs ranging over all terms of
73
 *       // their type (subfield types of T0)
74
 *       s[zs] = nextEnum(T)
75
 *       if (s[zs] is ground)
76
 *         builtin = rewrite(toBuiltIn(s[zs]))
77
 *         // let X be the theory the solver is invoked with
78
 *         find (k, ts) in Obs s.t. |=_X ts[0] = builtin
79
 *         if no such pair exists
80
 *           k = newVar(T)
81
 *           ts = {builtin}
82
 *           Obs += (k, ts)
83
 *         markSolved((k, ts), s[zs])
84
 *       else if no s' in Pool[T] and matcher sigma s.t.
85
 *             rewrite(toBuiltIn(s')) * sigma = rewrite(toBuiltIn(s[zs]))
86
 *         Pool[T] += s[zs]
87
 *         for each t in TermsToRecons[T]
88
 *           TermsToRecons' += matchNewObs(t, s[zs])
89
 *     // match phase
90
 *     while TermsToRecons' != {}
91
 *       TermsToRecons'' = {}
92
 *       for each subfield type T of T0
93
 *         for each t in TermsToRecons'[T]
94
 *           TermsToRecons'[T] += t
95
 *           for each s[zs] in Pool[T]
96
 *             TermsToRecons'' += matchNewObs(t, s[zs])
97
 *         TermsToRecons' = TermsToRecons''
98
 *   g = Sol[k0]
99
 *   instantiate free variables of g with arbitrary sygus datatype values
100
 * }
101
 *
102
 * matchNewObs(t, s[zs]) returns TermsToRecons'
103
 * {
104
 *   u = rewrite(toBuiltIn(s[zs]))
105
 *   if match(u, t) == {toBuiltin(zs) -> sts}
106
 *     Sub = {} // substitution map from zs to corresponding new vars ks
107
 *     for each (z, st) in {zs -> sts}
108
 *       // let X be the theory the solver is invoked with
109
 *       if exists (k, ts) in Obs s.t. !=_X ts[0] = st
110
 *         ts += st
111
 *         Sub[z] = k
112
 *       else
113
 *         sk = newVar(typeOf(z))
114
 *         Sub[z] = sk
115
 *         TermsToRecons'[typeOf(z)] += st
116
 *     if Sol[sk] != null forall (z, sk) in Sub
117
 *       markSolved(k, s{Sub})
118
 *     else
119
 *       CandSol[k] += s{Sub}
120
 * }
121
 *
122
 * markSolved((k, ts), s)
123
 * {
124
 *   if Sol[k] != null
125
 *     return
126
 *   Sol[k] = s
127
 *   CandSols[k] += s
128
 *   Stack = {k}
129
 *   while Stack != {}
130
 *     k' = pop(Stack)
131
 *     for all k'' in CandSols keys
132
 *       for all s'[k'] in CandSols[k'']
133
 *         s'{k' -> Sol[k']}
134
 *         if s' does not contain free variables in Obs
135
 *           Sol[k''] = s'
136
 *           push(Stack, k'')
137
 * }
138
 */
139
3058
class SygusReconstruct : public expr::NotifyMatch
140
{
141
 public:
142
  /**
143
   * Constructor.
144
   *
145
   * @param tds database for sygus terms
146
   * @param s statistics managed for the synth engine
147
   */
148
  SygusReconstruct(TermDbSygus* tds, SygusStatistics& s);
149
150
  /** Reconstruct solution.
151
   *
152
   * Return (if possible) a sygus encoding of a node that is equivalent to sol
153
   * and whose syntax matches the grammar corresponding to sygus datatype stn.
154
   *
155
   * For example, given:
156
   *   sol = (* 2 x)
157
   *   stn = A sygus datatype encoding the grammar
158
   *           Start -> (c_PLUS Start Start) | c_x | c_0 | c_1
159
   * This method may return (c_PLUS c_x c_x) and set reconstructed to 1.
160
   *
161
   * @param sol the target term
162
   * @param stn the sygus datatype type encoding the syntax restrictions
163
   * @param reconstructed the flag to update, set to 1 if we successfully return
164
   *                      a node, otherwise it is set to -1
165
   * @param enumLimit a value to limit the effort spent by this class (roughly
166
   *                  equal to the number of intermediate terms to try)
167
   * @return the reconstructed sygus term
168
   */
169
  Node reconstructSolution(Node sol,
170
                           TypeNode stn,
171
                           int8_t& reconstructed,
172
                           uint64_t enumLimit);
173
174
 private:
175
  /** Match builtin term `t` with pattern `sz`.
176
   *
177
   * This function matches the builtin term to reconstruct `t` with the builtin
178
   * analog of the pattern `sz`. If the match succeeds, `sz` is added to the set
179
   * of candidate solutions for the obligation `ob` corresponding to the builtin
180
   * term `t` and a set of new sub-terms to reconstruct is returned. If there
181
   * are no new sub-terms to reconstruct, then `sz` is considered a solution to
182
   * obligation `ob` and `markSolved(ob, sz)` is called. For example, given:
183
   *
184
   * Obs = [(k0, {(+ 1 1)})]
185
   * Pool[T0] = {(c_+ z1 z2)}
186
   * CandSols = {}
187
   *
188
   * Then calling `matchNewObs((+ 1 1), (c_+ z1 z2))` will result in:
189
   *
190
   * Obs = [(k0, {(+ 1 1)}), (k1, {1})]
191
   * Pool[T0] = {(c_+ z1 z2)}
192
   * CandSols = {k0 -> {(c_+ k1 k1)}}
193
   *
194
   * and will return `{T0 -> {1}}`.
195
   *
196
   * Notice that the patterns/shapes in pool are generic, and thus, contain vars
197
   * `z` as opposed to skolems `k`. Also, notice that `(c_+ z1 z2)` is
198
   * instantiated with only one skolem `k1`, which is then added to the set of
199
   * obligations. That's because the builtin analogs of `z1` and `z2` match with
200
   * the same builtin term `1`.
201
   *
202
   * @param t builtin term we need to reconstruct
203
   * @param sz a pattern to match against `t`
204
   * @return a set of new builtin terms to reconstruct if the match succeeds
205
   */
206
  TypeBuiltinSetMap matchNewObs(Node t, Node sz);
207
208
  /** mark obligation `ob` as solved.
209
   *
210
   * This function first marks `s` as the complete/constant solution for
211
   * `ob`. Then it substitutes all instances of `ob` in partial solutions to
212
   * other obligations with `s`. The function repeats those two steps for each
213
   * partial solution that gets completed because of the second step. For
214
   * example, given:
215
   *
216
   * CandSols = {
217
   *   k0 -> {(c_+ k1 c_1)},
218
   *   k1 -> {(c_* k2 c_x)},
219
   *   k2 -> {c_2}
220
   * }
221
   * Sol = {}
222
   *
223
   * Then calling `markSolved(k2, c_2)` will result in:
224
   *
225
   * CandSols = {
226
   *   k0 -> {(c_+ k1 c_1), (c_+ (c_* c_2 c_x) c_1)},
227
   *   k1 -> {(c_* k2 c_x), (c_* c_2 c_x)},
228
   *   k2 -> {c_2}
229
   * }
230
   * Sol = {
231
   *   k0 -> (c_+ (c_* c_2 c_x) c_1),
232
   *   k1 -> (c_* c_2 c_x),
233
   *   k2 -> c_2
234
   * }
235
   *
236
   * @param ob free var to mark as solved and substitute
237
   * @param sol solution to `ob`
238
   */
239
  void markSolved(RConsObligation* ob, Node s);
240
241
  /**
242
   * Initialize a sygus enumerator and a candidate rewrite database for each
243
   * sygus datatype type.
244
   *
245
   * @param stn The sygus datatype type encoding the syntax restrictions
246
   */
247
  void initialize(TypeNode stn);
248
249
  /**
250
   * Remove reconstructed terms from the given set of terms to reconstruct.
251
   *
252
   * @param termsToRecons a set of terms to reconstruct possibly containing
253
   *                      already reconstructed ones
254
   */
255
  void removeReconstructedTerms(TypeBuiltinSetMap& termsToRecons);
256
257
  /**
258
   * Replace all variables in `n` with ground values. Before, calling `match`,
259
   * `matchNewObs` rewrites the builtin analog of `n` which contains variables.
260
   * The rewritten term, however, may contain fewer variables:
261
   *
262
   * rewrite((ite true z1 z2)) = z1 // n = (c_ite c_true z1 z2)
263
   *
264
   * In such cases, `matchNewObs` replaces the remaining variables (`z1`) with
265
   * obligations and ignores the eliminated ones (`z2`). Since the values of the
266
   * eliminated variables do not matter, they are replaced with some ground
267
   * values by calling this method.
268
   *
269
   * @param n a term containing variables
270
   * @return `n` with all vars in `n` replaced with ground values
271
   */
272
  Node mkGround(Node n) const;
273
274
  /**
275
   * A notification that s is equal to n * { vars -> subs }. This function
276
   * should return false if we do not wish to be notified of further matches.
277
   */
278
  bool notify(Node s,
279
              Node n,
280
              std::vector<Node>& vars,
281
              std::vector<Node>& subs) override;
282
283
  /**
284
   * Reset the state of this SygusReconstruct object.
285
   */
286
  void clear();
287
288
  /**
289
   * Print the pool of patterns/shape used in the matching phase.
290
   *
291
   * \note requires enabling "sygus-rcons" trace
292
   *
293
   * @param pool a pool of patterns/shapes to print
294
   */
295
  void printPool(
296
      const std::unordered_map<TypeNode, std::vector<Node>>& pool) const;
297
298
  /** pointer to the sygus term database */
299
  TermDbSygus* d_tds;
300
  /** reference to the statistics of parent */
301
  SygusStatistics& d_stats;
302
303
  /** a list of obligations to solve */
304
  std::vector<std::unique_ptr<RConsObligation>> d_obs;
305
  /** a map from a sygus datatype type to its reconstruction info */
306
  std::unordered_map<TypeNode, RConsTypeInfo> d_stnInfo;
307
308
  /** a map from an obligation's skolem to its sygus solution (if it exists) */
309
  std::unordered_map<TNode, TNode> d_sol;
310
311
  /** a map from a candidate solution to its sub-obligations */
312
  std::unordered_map<Node, std::vector<RConsObligation*>> d_subObs;
313
  /** a map from a candidate solution to its parent obligation */
314
  std::unordered_map<Node, RConsObligation*> d_parentOb;
315
316
  /** a cache of sygus variables treated as ground terms by matching */
317
  std::unordered_map<Node, Node> d_sygusVars;
318
319
  /** A trie for filtering out redundant terms from the paterns pool */
320
  expr::MatchTrie d_poolTrie;
321
};
322
323
}  // namespace quantifiers
324
}  // namespace theory
325
}  // namespace cvc5
326
327
#endif  // CVC5__THEORY__QUANTIFIERS__SYGUS_RECONSTRUCT_H