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