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

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Haniel Barbosa, Morgan Deters
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
 * Rewriter for the theory of inductive quantifiers.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
19
#define CVC5__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H
20
21
#include "proof/trust_node.h"
22
#include "theory/theory_rewriter.h"
23
24
namespace cvc5 {
25
namespace theory {
26
namespace quantifiers {
27
28
struct QAttributes;
29
30
/**
31
 * List of steps used by the quantifiers rewriter, details on these steps
32
 * can be found in the class below.
33
 */
34
enum RewriteStep
35
{
36
  /** Eliminate symbols (e.g. implies, xor) */
37
  COMPUTE_ELIM_SYMBOLS = 0,
38
  /** Miniscoping */
39
  COMPUTE_MINISCOPING,
40
  /** Aggressive miniscoping */
41
  COMPUTE_AGGRESSIVE_MINISCOPING,
42
  /** Apply the extended rewriter to quantified formula bodies */
43
  COMPUTE_EXT_REWRITE,
44
  /**
45
   * Term processing (e.g. simplifying terms based on ITE lifting,
46
   * eliminating extended arithmetic symbols).
47
   */
48
  COMPUTE_PROCESS_TERMS,
49
  /** Prenexing */
50
  COMPUTE_PRENEX,
51
  /** Variable elimination */
52
  COMPUTE_VAR_ELIMINATION,
53
  /** Conditional splitting */
54
  COMPUTE_COND_SPLIT,
55
  /** Placeholder for end of steps */
56
  COMPUTE_LAST
57
};
58
std::ostream& operator<<(std::ostream& out, RewriteStep s);
59
60
19849
class QuantifiersRewriter : public TheoryRewriter
61
{
62
 public:
63
  static bool isLiteral( Node n );
64
  //-------------------------------------variable elimination utilities
65
  /** is variable elimination
66
   *
67
   * Returns true if v is not a subterm of s, and the type of s is a subtype of
68
   * the type of v.
69
   */
70
  static bool isVarElim(Node v, Node s);
71
  /** get variable elimination literal
72
   *
73
   * If n asserted with polarity pol in body, and is equivalent to an equality
74
   * of the form v = s for some v in args, where isVariableElim( v, s ) holds,
75
   * then this method removes v from args, adds v to vars, adds s to subs, and
76
   * returns true. Otherwise, it returns false.
77
   */
78
  static bool getVarElimLit(Node body,
79
                            Node n,
80
                            bool pol,
81
                            std::vector<Node>& args,
82
                            std::vector<Node>& vars,
83
                            std::vector<Node>& subs);
84
  /**
85
   * Get variable eliminate for an equality based on theory-specific reasoning.
86
   */
87
  static Node getVarElimEq(Node lit, const std::vector<Node>& args, Node& var);
88
  /** variable eliminate for real equalities
89
   *
90
   * If this returns a non-null value ret, then var is updated to a member of
91
   * args, lit is equivalent to ( var = ret ).
92
   */
93
  static Node getVarElimEqReal(Node lit,
94
                               const std::vector<Node>& args,
95
                               Node& var);
96
  /** variable eliminate for bit-vector equalities
97
   *
98
   * If this returns a non-null value ret, then var is updated to a member of
99
   * args, lit is equivalent to ( var = ret ).
100
   */
101
  static Node getVarElimEqBv(Node lit,
102
                             const std::vector<Node>& args,
103
                             Node& var);
104
  /** variable eliminate for string equalities
105
   *
106
   * If this returns a non-null value ret, then var is updated to a member of
107
   * args, lit is equivalent to ( var = ret ).
108
   */
109
  static Node getVarElimEqString(Node lit,
110
                                 const std::vector<Node>& args,
111
                                 Node& var);
112
  /** get variable elimination
113
   *
114
   * If there exists an n with some polarity in body, and entails a literal that
115
   * corresponds to a variable elimination for some v via the above method
116
   * getVarElimLit, we return true. In this case, we update args/vars/subs
117
   * based on eliminating v.
118
   */
119
  static bool getVarElim(Node body,
120
                         std::vector<Node>& args,
121
                         std::vector<Node>& vars,
122
                         std::vector<Node>& subs);
123
  /** has variable elimination
124
   *
125
   * Returns true if n asserted with polarity pol entails a literal for
126
   * which variable elimination is possible.
127
   */
128
  static bool hasVarElim(Node n, bool pol, std::vector<Node>& args);
129
  /** compute variable elimination inequality
130
   *
131
   * This method eliminates variables from the body of quantified formula
132
   * "body" using (global) reasoning about inequalities. In particular, if there
133
   * exists a variable x that only occurs in body or annotation qa in literals
134
   * of the form x>=t with a fixed polarity P, then we may replace all such
135
   * literals with P. For example, note that:
136
   *   forall xy. x>y OR P(y) is equivalent to forall y. P(y).
137
   *
138
   * In the case that a variable x from args can be eliminated in this way,
139
   * we remove x from args, add x >= t1, ..., x >= tn to bounds, add false, ...,
140
   * false to subs, and return true.
141
   */
142
  static bool getVarElimIneq(Node body,
143
                             std::vector<Node>& args,
144
                             std::vector<Node>& bounds,
145
                             std::vector<Node>& subs,
146
                             QAttributes& qa);
147
  //-------------------------------------end variable elimination utilities
148
 private:
149
  /**
150
   * Helper method for getVarElim, called when n has polarity pol in body.
151
   */
152
  static bool getVarElimInternal(Node body,
153
                                 Node n,
154
                                 bool pol,
155
                                 std::vector<Node>& args,
156
                                 std::vector<Node>& vars,
157
                                 std::vector<Node>& subs);
158
  static int getPurifyIdLit2(Node n, std::map<Node, int>& visited);
159
  static bool addCheckElimChild(std::vector<Node>& children,
160
                                Node c,
161
                                Kind k,
162
                                std::map<Node, bool>& lit_pol,
163
                                bool& childrenChanged);
164
  static void addNodeToOrBuilder(Node n, NodeBuilder& t);
165
  static void computeArgs(const std::vector<Node>& args,
166
                          std::map<Node, bool>& activeMap,
167
                          Node n,
168
                          std::map<Node, bool>& visited);
169
  static void computeArgVec(const std::vector<Node>& args,
170
                            std::vector<Node>& activeArgs,
171
                            Node n);
172
  static void computeArgVec2(const std::vector<Node>& args,
173
                             std::vector<Node>& activeArgs,
174
                             Node n,
175
                             Node ipl);
176
  static Node computeProcessTerms2(Node body,
177
                                   std::map<Node, Node>& cache,
178
                                   std::vector<Node>& new_vars,
179
                                   std::vector<Node>& new_conds);
180
  static void computeDtTesterIteSplit(
181
      Node n,
182
      std::map<Node, Node>& pcons,
183
      std::map<Node, std::map<int, Node> >& ncons,
184
      std::vector<Node>& conj);
185
186
  //-------------------------------------variable elimination
187
  /** compute variable elimination
188
   *
189
   * This computes variable elimination rewrites for a body of a quantified
190
   * formula with bound variables args. This method updates args to args' and
191
   * returns a node body' such that (forall args. body) is equivalent to
192
   * (forall args'. body'). An example of a variable elimination rewrite is:
193
   *   forall xy. x != a V P( x,y ) ---> forall y. P( a, y )
194
   */
195
  static Node computeVarElimination(Node body,
196
                                    std::vector<Node>& args,
197
                                    QAttributes& qa);
198
  //-------------------------------------end variable elimination
199
  //-------------------------------------conditional splitting
200
  /** compute conditional splitting
201
   *
202
   * This computes conditional splitting rewrites for a body of a quantified
203
   * formula with bound variables args. It returns a body' that is equivalent
204
   * to body. We split body into a conjunction if variable elimination can
205
   * occur in one of the conjuncts. Examples of this are:
206
   *   ite( x=a, P(x), Q(x) ) ----> ( x!=a V P(x) ) ^ ( x=a V Q(x) )
207
   *   (x=a) = P(x) ----> ( x!=a V P(x) ) ^ ( x=a V ~P(x) )
208
   *   ( x!=a ^ P(x) ) V Q(x) ---> ( x!=a V Q(x) ) ^ ( P(x) V Q(x) )
209
   * where in each case, x can be eliminated in the first conjunct.
210
   */
211
  static Node computeCondSplit(Node body,
212
                               const std::vector<Node>& args,
213
                               QAttributes& qa);
214
  //-------------------------------------end conditional splitting
215
  //------------------------------------- process terms
216
  /** compute process terms
217
   *
218
   * This takes as input a quantified formula q with attributes qa whose
219
   * body is body.
220
   *
221
   * This rewrite eliminates problematic terms from the bodies of
222
   * quantified formulas, which includes performing:
223
   * - Certain cases of ITE lifting,
224
   * - Elimination of extended arithmetic functions like to_int/is_int/div/mod,
225
   * - Elimination of select over store.
226
   *
227
   * It may introduce new variables V into new_vars and new conditions C into
228
   * new_conds. It returns a node retBody such that q of the form
229
   *   forall X. body
230
   * is equivalent to:
231
   *   forall X, V. ( C => retBody )
232
   */
233
  static Node computeProcessTerms(Node body,
234
                                  std::vector<Node>& new_vars,
235
                                  std::vector<Node>& new_conds,
236
                                  Node q,
237
                                  QAttributes& qa);
238
  //------------------------------------- end process terms
239
  //------------------------------------- extended rewrite
240
  /** compute extended rewrite
241
   *
242
   * This returns the result of applying the extended rewriter on the body
243
   * of quantified formula q.
244
   */
245
  static Node computeExtendedRewrite(Node q);
246
  //------------------------------------- end extended rewrite
247
 public:
248
  static Node computeElimSymbols( Node body );
249
  /**
250
   * Compute miniscoping in quantified formula q with attributes in qa.
251
   */
252
  static Node computeMiniscoping(Node q, QAttributes& qa);
253
  static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
254
  /**
255
   * This function removes top-level quantifiers from subformulas of body
256
   * appearing with overall polarity pol. It adds quantified variables that
257
   * appear in positive polarity positions into args, and those at negative
258
   * polarity positions in nargs.
259
   *
260
   * If prenexAgg is true, we ensure that all top-level quantifiers are
261
   * eliminated from subformulas. This means that we must expand ITE and
262
   * Boolean equalities to ensure that quantifiers are at fixed polarities.
263
   *
264
   * For example, calling this function on:
265
   *   (or (forall ((x Int)) (P x z)) (not (forall ((y Int)) (Q y z))))
266
   * would return:
267
   *   (or (P x z) (not (Q y z)))
268
   * and add {x} to args, and {y} to nargs.
269
   */
270
  static Node computePrenex(Node q,
271
                            Node body,
272
                            std::unordered_set<Node>& args,
273
                            std::unordered_set<Node>& nargs,
274
                            bool pol,
275
                            bool prenexAgg);
276
  /**
277
   * Apply prenexing aggressively. Returns the prenex normal form of n.
278
   */
279
  static Node computePrenexAgg(Node n, std::map<Node, Node>& visited);
280
  static Node computeSplit( std::vector< Node >& args, Node body, QAttributes& qa );
281
private:
282
 static Node computeOperation(Node f,
283
                              RewriteStep computeOption,
284
                              QAttributes& qa);
285
286
public:
287
 RewriteResponse preRewrite(TNode in) override;
288
 RewriteResponse postRewrite(TNode in) override;
289
290
private:
291
  /** options */
292
 static bool doOperation(Node f, RewriteStep computeOption, QAttributes& qa);
293
294
private:
295
  static Node preSkolemizeQuantifiers(Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector<TNode>& fvs);
296
public:
297
  static bool isPrenexNormalForm( Node n );
298
  /** preprocess
299
   *
300
   * This returns the result of applying simple quantifiers-specific
301
   * preprocessing to n, including but not limited to:
302
   * - rewrite rule elimination,
303
   * - pre-skolemization,
304
   * - aggressive prenexing.
305
   * The argument isInst is set to true if n is an instance of a previously
306
   * registered quantified formula. If this flag is true, we do not apply
307
   * certain steps like pre-skolemization since we know they will have no
308
   * effect.
309
   *
310
   * The result is wrapped in a trust node of kind TrustNodeKind::REWRITE.
311
   */
312
  static TrustNode preprocess(Node n, bool isInst = false);
313
  static Node mkForAll(const std::vector<Node>& args,
314
                       Node body,
315
                       QAttributes& qa);
316
  static Node mkForall(const std::vector<Node>& args,
317
                       Node body,
318
                       bool marked = false);
319
  static Node mkForall(const std::vector<Node>& args,
320
                       Node body,
321
                       std::vector<Node>& iplc,
322
                       bool marked = false);
323
}; /* class QuantifiersRewriter */
324
325
}  // namespace quantifiers
326
}  // namespace theory
327
}  // namespace cvc5
328
329
#endif /* CVC5__THEORY__QUANTIFIERS__QUANTIFIERS_REWRITER_H */