GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/arith_entail.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
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
 * Arithmetic entailment computation for string terms.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__STRINGS__ARITH_ENTAIL_H
19
#define CVC5__THEORY__STRINGS__ARITH_ENTAIL_H
20
21
#include <vector>
22
23
#include "expr/node.h"
24
25
namespace cvc5 {
26
namespace theory {
27
28
class Rewriter;
29
30
namespace strings {
31
32
/**
33
 * Techniques for computing arithmetic entailment for string terms. This
34
 * is an implementation of the techniques from Reynolds et al, "High Level
35
 * Abstractions for Simplifying Extended String Constraints in SMT", CAV 2019.
36
 */
37
33181
class ArithEntail
38
{
39
 public:
40
  ArithEntail(Rewriter* r);
41
  /**
42
   * Returns the rewritten form a term, intended (although not enforced) to be
43
   * an arithmetic term.
44
   */
45
  Node rewrite(Node a);
46
  /** check arithmetic entailment equal
47
   * Returns true if it is always the case that a = b.
48
   */
49
  bool checkEq(Node a, Node b);
50
  /** check arithmetic entailment
51
   * Returns true if it is always the case that a >= b,
52
   * and a>b if strict is true.
53
   */
54
  bool check(Node a, Node b, bool strict = false);
55
  /** check arithmetic entailment
56
   * Returns true if it is always the case that a >= 0.
57
   */
58
  bool check(Node a, bool strict = false);
59
  /** check arithmetic entailment with approximations
60
   *
61
   * Returns true if it is always the case that a >= 0. We expect that a is in
62
   * rewritten form.
63
   *
64
   * This function uses "approximation" techniques that under-approximate
65
   * the value of a for the purposes of showing the entailment holds. For
66
   * example, given:
67
   *   len( x ) - len( substr( y, 0, len( x ) ) )
68
   * Since we know that len( substr( y, 0, len( x ) ) ) <= len( x ), the above
69
   * term can be under-approximated as len( x ) - len( x ) = 0, which is >= 0,
70
   * and thus the entailment len( x ) - len( substr( y, 0, len( x ) ) ) >= 0
71
   * holds.
72
   */
73
  bool checkApprox(Node a);
74
75
  /**
76
   * Checks whether assumption |= a >= 0 (if strict is false) or
77
   * assumption |= a > 0 (if strict is true), where assumption is an equality
78
   * assumption. The assumption must be in rewritten form.
79
   *
80
   * Example:
81
   *
82
   * checkWithEqAssumption(x + (str.len y) = 0, -x, false) = true
83
   *
84
   * Because: x = -(str.len y), so -x >= 0 --> (str.len y) >= 0 --> true
85
   */
86
  bool checkWithEqAssumption(Node assumption, Node a, bool strict = false);
87
88
  /**
89
   * Checks whether assumption |= a >= b (if strict is false) or
90
   * assumption |= a > b (if strict is true). The function returns true if it
91
   * can be shown that the entailment holds and false otherwise. Assumption
92
   * must be in rewritten form. Assumption may be an equality or an inequality.
93
   *
94
   * Example:
95
   *
96
   * checkWithAssumption(x + (str.len y) = 0, 0, x, false) = true
97
   *
98
   * Because: x = -(str.len y), so 0 >= x --> 0 >= -(str.len y) --> true
99
   *
100
   * Since this method rewrites on rewriting and may introduce new variables
101
   * (slack variables for inequalities), it should *not* be called from the
102
   * main rewriter of strings, or non-termination can occur.
103
   */
104
  bool checkWithAssumption(Node assumption,
105
                           Node a,
106
                           Node b,
107
                           bool strict = false);
108
109
  /**
110
   * Checks whether assumptions |= a >= b (if strict is false) or
111
   * assumptions |= a > b (if strict is true). The function returns true if it
112
   * can be shown that the entailment holds and false otherwise. Assumptions
113
   * must be in rewritten form. Assumptions may be an equalities or an
114
   * inequalities.
115
   *
116
   * Example:
117
   *
118
   * checkWithAssumptions([x + (str.len y) = 0], 0, x, false) = true
119
   *
120
   * Because: x = -(str.len y), so 0 >= x --> 0 >= -(str.len y) --> true
121
   *
122
   * Since this method rewrites on rewriting and may introduce new variables
123
   * (slack variables for inequalities), it should *not* be called from the
124
   * main rewriter of strings, or non-termination can occur.
125
   */
126
  bool checkWithAssumptions(std::vector<Node> assumptions,
127
                            Node a,
128
                            Node b,
129
                            bool strict = false);
130
131
  /** get arithmetic lower bound
132
   * If this function returns a non-null Node ret,
133
   * then ret is a rational constant and
134
   * we know that n >= ret always if isLower is true,
135
   * or n <= ret if isLower is false.
136
   *
137
   * Notice the following invariant.
138
   * If getConstantArithBound(a, true) = ret where ret is non-null, then for
139
   * strict = { true, false } :
140
   *   ret >= strict ? 1 : 0
141
   *     if and only if
142
   *   check( a, strict ) = true.
143
   */
144
  Node getConstantBound(Node a, bool isLower = true);
145
146
  /**
147
   * get constant bound on the length of s.
148
   */
149
  Node getConstantBoundLength(Node s, bool isLower = true);
150
  /**
151
   * Given an inequality y1 + ... + yn >= x, removes operands yi s.t. the
152
   * original inequality still holds. Returns true if the original inequality
153
   * holds and false otherwise. The list of ys is modified to contain a subset
154
   * of the original ys.
155
   *
156
   * Example:
157
   *
158
   * inferZerosInSumGeq( (str.len x), [ (str.len x), (str.len y), 1 ], [] )
159
   * --> returns true with ys = [ (str.len x) ] and zeroYs = [ (str.len y), 1 ]
160
   *     (can be used to rewrite the inequality to false)
161
   *
162
   * inferZerosInSumGeq( (str.len x), [ (str.len y) ], [] )
163
   * --> returns false because it is not possible to show
164
   *     str.len(y) >= str.len(x)
165
   */
166
  bool inferZerosInSumGeq(Node x,
167
                          std::vector<Node>& ys,
168
                          std::vector<Node>& zeroYs);
169
170
 private:
171
  /** check entail arithmetic internal
172
   * Returns true if we can show a >= 0 always.
173
   * a is in rewritten form.
174
   */
175
  bool checkInternal(Node a);
176
  /** Get arithmetic approximations
177
   *
178
   * This gets the (set of) arithmetic approximations for term a and stores
179
   * them in approx. If isOverApprox is true, these are over-approximations
180
   * for the value of a, otherwise, they are underapproximations. For example,
181
   * an over-approximation for len( substr( y, n, m ) ) is m; an
182
   * under-approximation for indexof( x, y, n ) is -1.
183
   *
184
   * Notice that this function is not generally recursive (although it may make
185
   * a small bounded of recursive calls). Instead, it returns the shape
186
   * of the approximations for a. For example, an under-approximation
187
   * for the term len( replace( substr( x, 0, n ), y, z ) ) returned by this
188
   * function might be len( substr( x, 0, n ) ) - len( y ), where we don't
189
   * consider (recursively) the approximations for len( substr( x, 0, n ) ).
190
   */
191
  void getArithApproximations(Node a,
192
                              std::vector<Node>& approx,
193
                              bool isOverApprox = false);
194
  /** Set bound cache */
195
  void setConstantBoundCache(Node n, Node ret, bool isLower);
196
  /** Get bound cache */
197
  Node getConstantBoundCache(Node n, bool isLower);
198
  /** The underlying rewriter */
199
  Rewriter* d_rr;
200
  /** Constant zero */
201
  Node d_zero;
202
};
203
204
}  // namespace strings
205
}  // namespace theory
206
}  // namespace cvc5
207
208
#endif