GCC Code Coverage Report
Directory: . Exec Total Coverage
File: test/unit/theory/theory_bv_int_blaster_white.cpp Lines: 142 142 100.0 %
Date: 2021-11-07 Branches: 484 1202 40.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   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
 * Unit tests for bit-vector solving via integers.
14
 */
15
16
#include <iostream>
17
#include <memory>
18
#include <vector>
19
20
#include "context/context.h"
21
#include "options/options.h"
22
#include "test_smt.h"
23
#include "theory/bv/int_blaster.h"
24
#include "theory/bv/theory_bv_utils.h"
25
#include "util/bitvector.h"
26
#include "util/rational.h"
27
namespace cvc5 {
28
29
using namespace kind;
30
using namespace theory;
31
32
namespace test {
33
34
16
class TestTheoryWhiteBvIntblaster : public TestSmtNoFinishInit
35
{
36
 protected:
37
8
  void SetUp() override
38
  {
39
8
    TestSmtNoFinishInit::SetUp();
40
8
    d_slvEngine->setOption("produce-models", "true");
41
8
    d_slvEngine->finishInit();
42
8
    d_true = d_nodeManager->mkConst<bool>(true);
43
8
    d_one = d_nodeManager->mkConst<Rational>(Rational(1));
44
8
  }
45
  Node d_true;
46
  Node d_one;
47
};
48
49
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_constants)
50
{
51
  // place holders for lemmas and skolem
52
4
  std::vector<Node> lemmas;
53
4
  std::map<Node, Node> skolems;
54
55
  // bit-vector constant representing the integer 7, with 4 bits
56
4
  BitVector c1(4, Integer(7));
57
4
  Node bv7_4 = d_nodeManager->mkConst<BitVector>(c1);
58
59
  // translating it to integers should yield 7.
60
4
  Options opts;
61
4
  Env env(d_nodeManager, &opts);
62
2
  env.d_logic.setLogicString("QF_UFBV");
63
2
  env.d_logic.lock();
64
  IntBlaster intBlaster(
65
4
      env, options::SolveBVAsIntMode::SUM, 1, false);
66
4
  Node result = intBlaster.translateNoChildren(bv7_4, lemmas, skolems);
67
4
  Node seven = d_nodeManager->mkConst(Rational(7));
68
2
  ASSERT_EQ(seven, result);
69
70
  // translating integer constants should not change them
71
2
  result = intBlaster.translateNoChildren(seven, lemmas, skolems);
72
2
  ASSERT_EQ(seven, result);
73
}
74
75
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_symbolic_constant)
76
{
77
  // place holders for lemmas and skolem
78
4
  std::vector<Node> lemmas;
79
4
  std::map<Node, Node> skolems;
80
81
  // bit-vector variable
82
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
83
4
  Node bv = d_nodeManager->mkVar("bv1", bvType);
84
85
  // translating it to integers should yield an integer variable.
86
4
  Options opts;
87
4
  Env env(d_nodeManager, &opts);
88
2
  env.d_logic.setLogicString("QF_UFBV");
89
2
  env.d_logic.lock();
90
  IntBlaster intBlaster(
91
4
      env, options::SolveBVAsIntMode::SUM, 1, true);
92
4
  Node result = intBlaster.translateNoChildren(bv, lemmas, skolems);
93
2
  ASSERT_TRUE(result.isVar() && result.getType().isInteger());
94
95
  // translating integer variables should not change them
96
4
  Node resultSquared = intBlaster.translateNoChildren(result, lemmas, skolems);
97
2
  ASSERT_EQ(resultSquared, result);
98
}
99
100
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_uf)
101
{
102
  // place holders for lemmas and skolem
103
4
  std::vector<Node> lemmas;
104
4
  std::map<Node, Node> skolems;
105
106
  // uf from integers and bit-vectors to Bools
107
4
  std::vector<TypeNode> domain;
108
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
109
4
  TypeNode intType = d_nodeManager->integerType();
110
2
  domain.push_back(intType);
111
2
  domain.push_back(bvType);
112
4
  TypeNode range = d_nodeManager->booleanType();
113
4
  TypeNode funType = d_nodeManager->mkFunctionType(domain, range);
114
4
  Node f = d_nodeManager->mkVar("f", funType);
115
116
  // translating it to integers should yield an Int x Int -> Bool function
117
4
  Options opts;
118
4
  Env env(d_nodeManager, &opts);
119
2
  env.d_logic.setLogicString("QF_UFBV");
120
2
  env.d_logic.lock();
121
  IntBlaster intBlaster(
122
4
      env, options::SolveBVAsIntMode::SUM, 1, true);
123
4
  Node result = intBlaster.translateNoChildren(f, lemmas, skolems);
124
4
  TypeNode resultType = result.getType();
125
4
  std::vector<TypeNode> resultDomain = resultType.getArgTypes();
126
4
  TypeNode resultRange = resultType.getRangeType();
127
2
  ASSERT_TRUE(result.isVar());
128
2
  ASSERT_TRUE(resultType.isFunction());
129
2
  ASSERT_TRUE(resultDomain.size() == 2);
130
2
  ASSERT_TRUE(resultDomain[0].isInteger());
131
2
  ASSERT_TRUE(resultDomain[1].isInteger());
132
2
  ASSERT_TRUE(resultRange.isBoolean());
133
}
134
135
/** Check all cases of the translation.
136
 * This is a sanity check, that noly verifies
137
 * the expected type, and that there were no
138
 * failures.
139
 */
140
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_with_children)
141
{
142
  // place holders for lemmas and skolem
143
4
  std::vector<Node> lemmas;
144
4
  std::map<Node, Node> skolems;
145
4
  Options opts;
146
4
  Env env(d_nodeManager, &opts);
147
2
  env.d_logic.setLogicString("QF_UFBV");
148
2
  env.d_logic.lock();
149
  IntBlaster intBlaster(
150
4
      env, options::SolveBVAsIntMode::SUM, 1, true);
151
152
  // bit-vector variables
153
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
154
4
  Node v1 = d_nodeManager->mkVar("v1", bvType);
155
4
  Node v2 = d_nodeManager->mkVar("v2", bvType);
156
157
  // translated integer variables
158
4
  Node i1 = intBlaster.translateNoChildren(v1, lemmas, skolems);
159
4
  Node i2 = intBlaster.translateNoChildren(v2, lemmas, skolems);
160
161
  // if original is BV, result should be Int.
162
  // Otherwise, they should have the same type.
163
4
  Node original;
164
4
  Node result;
165
166
  // sum
167
2
  original = d_nodeManager->mkNode(BITVECTOR_ADD, v1, v2);
168
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
169
2
  ASSERT_TRUE(result.getType().isInteger());
170
171
  // multiplication
172
2
  original = d_nodeManager->mkNode(BITVECTOR_MULT, v1, v2);
173
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
174
2
  ASSERT_TRUE(result.getType().isInteger());
175
176
  // division 1
177
2
  original = d_nodeManager->mkNode(BITVECTOR_UDIV, v1, v2);
178
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
179
2
  ASSERT_TRUE(result.getType().isInteger());
180
181
  // division 2
182
2
  original = d_nodeManager->mkNode(BITVECTOR_UREM, v1, v2);
183
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
184
2
  ASSERT_TRUE(result.getType().isInteger());
185
186
  // bit-wise negation
187
2
  original = d_nodeManager->mkNode(BITVECTOR_NOT, v1);
188
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
189
2
  ASSERT_TRUE(result.getType().isInteger());
190
191
  // arithmetic negation
192
2
  original = d_nodeManager->mkNode(BITVECTOR_NEG, v1);
193
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
194
2
  ASSERT_TRUE(result.getType().isInteger());
195
196
  // bv2nat
197
2
  original = d_nodeManager->mkNode(BITVECTOR_TO_NAT, v1);
198
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
199
2
  ASSERT_TRUE(result.getType().isInteger());
200
201
  // int2bv
202
4
  Node intToBVOp = d_nodeManager->mkConst<IntToBitVector>(IntToBitVector(4));
203
2
  original = d_nodeManager->mkNode(intToBVOp, i1);
204
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
205
2
  ASSERT_TRUE(result.getType().isInteger());
206
207
  // zero extend
208
  Node zeroExtOp =
209
4
      d_nodeManager->mkConst<BitVectorZeroExtend>(BitVectorZeroExtend(4));
210
2
  original = d_nodeManager->mkNode(zeroExtOp, v1);
211
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
212
2
  ASSERT_TRUE(result.getType().isInteger());
213
214
  // extract + BV ITE
215
4
  Node extract = theory::bv::utils::mkExtract(v1, 0, 0);
216
2
  original = d_nodeManager->mkNode(BITVECTOR_ITE, extract, v2, v1);
217
4
  Node intExtract = intBlaster.translateWithChildren(extract, {i1}, lemmas);
218
2
  result =
219
4
      intBlaster.translateWithChildren(original, {intExtract, i1, i2}, lemmas);
220
2
  ASSERT_TRUE(result.getType().isInteger());
221
2
  ASSERT_TRUE(intExtract.getType().isInteger());
222
223
  // concat
224
2
  original = d_nodeManager->mkNode(BITVECTOR_CONCAT, v1, v2);
225
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
226
2
  ASSERT_TRUE(result.getType().isInteger());
227
228
  // predicates
229
2
  original = d_nodeManager->mkNode(EQUAL, v1, v2);
230
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
231
2
  ASSERT_TRUE(result.getType().isBoolean());
232
233
2
  original = d_nodeManager->mkNode(BITVECTOR_ULT, v1, v2);
234
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
235
2
  ASSERT_TRUE(result.getType().isBoolean());
236
237
2
  original = d_nodeManager->mkNode(BITVECTOR_ULE, v1, v2);
238
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
239
2
  ASSERT_TRUE(result.getType().isBoolean());
240
241
2
  original = d_nodeManager->mkNode(BITVECTOR_UGT, v1, v2);
242
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
243
2
  ASSERT_TRUE(result.getType().isBoolean());
244
245
2
  original = d_nodeManager->mkNode(BITVECTOR_UGE, v1, v2);
246
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
247
2
  ASSERT_TRUE(result.getType().isBoolean());
248
249
  // BVULT with a BV result
250
2
  original = d_nodeManager->mkNode(BITVECTOR_ULTBV, v1, v2);
251
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
252
2
  ASSERT_TRUE(result.getType().isInteger());
253
254
  // function application
255
4
  TypeNode funType = d_nodeManager->mkFunctionType({bvType}, bvType);
256
4
  Node f = d_nodeManager->mkVar("f", funType);
257
4
  Node g = intBlaster.translateNoChildren(f, lemmas, skolems);
258
2
  original = d_nodeManager->mkNode(APPLY_UF, f, v1);
259
2
  result = intBlaster.translateWithChildren(original, {g, i1}, lemmas);
260
2
  ASSERT_TRUE(result.getType().isInteger());
261
}
262
263
}  // namespace test
264
15
}  // namespace cvc5