GCC Code Coverage Report
Directory: . Exec Total Coverage
File: test/unit/theory/theory_bv_int_blaster_white.cpp Lines: 126 126 100.0 %
Date: 2021-09-15 Branches: 464 1162 39.9 %

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_smtEngine->setOption("produce-models", "true");
41
8
    d_smtEngine->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
  IntBlaster intBlaster(
61
4
      d_smtEngine->getContext(), options::SolveBVAsIntMode::SUM, 1, false);
62
4
  Node result = intBlaster.translateNoChildren(bv7_4, lemmas, skolems);
63
4
  Node seven = d_nodeManager->mkConst(Rational(7));
64
2
  ASSERT_EQ(seven, result);
65
66
  // translating integer constants should not change them
67
2
  result = intBlaster.translateNoChildren(seven, lemmas, skolems);
68
2
  ASSERT_EQ(seven, result);
69
}
70
71
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_symbolic_constant)
72
{
73
  // place holders for lemmas and skolem
74
4
  std::vector<Node> lemmas;
75
4
  std::map<Node, Node> skolems;
76
77
  // bit-vector variable
78
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
79
4
  Node bv = d_nodeManager->mkVar("bv1", bvType);
80
81
  // translating it to integers should yield an integer variable.
82
  IntBlaster intBlaster(
83
4
      d_smtEngine->getContext(), options::SolveBVAsIntMode::SUM, 1, true);
84
4
  Node result = intBlaster.translateNoChildren(bv, lemmas, skolems);
85
2
  ASSERT_TRUE(result.isVar() && result.getType().isInteger());
86
87
  // translating integer variables should not change them
88
4
  Node resultSquared = intBlaster.translateNoChildren(result, lemmas, skolems);
89
2
  ASSERT_EQ(resultSquared, result);
90
}
91
92
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_uf)
93
{
94
  // place holders for lemmas and skolem
95
4
  std::vector<Node> lemmas;
96
4
  std::map<Node, Node> skolems;
97
98
  // uf from integers and bit-vectors to Bools
99
4
  std::vector<TypeNode> domain;
100
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
101
4
  TypeNode intType = d_nodeManager->integerType();
102
2
  domain.push_back(intType);
103
2
  domain.push_back(bvType);
104
4
  TypeNode range = d_nodeManager->booleanType();
105
4
  TypeNode funType = d_nodeManager->mkFunctionType(domain, range);
106
4
  Node f = d_nodeManager->mkVar("f", funType);
107
108
  // translating it to integers should yield an Int x Int -> Bool function
109
  IntBlaster intBlaster(
110
4
      d_smtEngine->getContext(), options::SolveBVAsIntMode::SUM, 1, true);
111
4
  Node result = intBlaster.translateNoChildren(f, lemmas, skolems);
112
4
  TypeNode resultType = result.getType();
113
4
  std::vector<TypeNode> resultDomain = resultType.getArgTypes();
114
4
  TypeNode resultRange = resultType.getRangeType();
115
2
  ASSERT_TRUE(result.isVar());
116
2
  ASSERT_TRUE(resultType.isFunction());
117
2
  ASSERT_TRUE(resultDomain.size() == 2);
118
2
  ASSERT_TRUE(resultDomain[0].isInteger());
119
2
  ASSERT_TRUE(resultDomain[1].isInteger());
120
2
  ASSERT_TRUE(resultRange.isBoolean());
121
}
122
123
/** Check all cases of the translation.
124
 * This is a sanity check, that noly verifies
125
 * the expected type, and that there were no
126
 * failures.
127
 */
128
13
TEST_F(TestTheoryWhiteBvIntblaster, intblaster_with_children)
129
{
130
  // place holders for lemmas and skolem
131
4
  std::vector<Node> lemmas;
132
4
  std::map<Node, Node> skolems;
133
  IntBlaster intBlaster(
134
4
      d_smtEngine->getContext(), options::SolveBVAsIntMode::SUM, 1, true);
135
136
  // bit-vector variables
137
4
  TypeNode bvType = d_nodeManager->mkBitVectorType(4);
138
4
  Node v1 = d_nodeManager->mkVar("v1", bvType);
139
4
  Node v2 = d_nodeManager->mkVar("v2", bvType);
140
141
  // translated integer variables
142
4
  Node i1 = intBlaster.translateNoChildren(v1, lemmas, skolems);
143
4
  Node i2 = intBlaster.translateNoChildren(v2, lemmas, skolems);
144
145
  // if original is BV, result should be Int.
146
  // Otherwise, they should have the same type.
147
4
  Node original;
148
4
  Node result;
149
150
  // sum
151
2
  original = d_nodeManager->mkNode(BITVECTOR_ADD, v1, v2);
152
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
153
2
  ASSERT_TRUE(result.getType().isInteger());
154
155
  // multiplication
156
2
  original = d_nodeManager->mkNode(BITVECTOR_MULT, v1, v2);
157
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
158
2
  ASSERT_TRUE(result.getType().isInteger());
159
160
  // division 1
161
2
  original = d_nodeManager->mkNode(BITVECTOR_UDIV, v1, v2);
162
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
163
2
  ASSERT_TRUE(result.getType().isInteger());
164
165
  // division 2
166
2
  original = d_nodeManager->mkNode(BITVECTOR_UREM, v1, v2);
167
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
168
2
  ASSERT_TRUE(result.getType().isInteger());
169
170
  // bit-wise negation
171
2
  original = d_nodeManager->mkNode(BITVECTOR_NOT, v1);
172
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
173
2
  ASSERT_TRUE(result.getType().isInteger());
174
175
  // arithmetic negation
176
2
  original = d_nodeManager->mkNode(BITVECTOR_NEG, v1);
177
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
178
2
  ASSERT_TRUE(result.getType().isInteger());
179
180
  // bv2nat
181
2
  original = d_nodeManager->mkNode(BITVECTOR_TO_NAT, v1);
182
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
183
2
  ASSERT_TRUE(result.getType().isInteger());
184
185
  // int2bv
186
4
  Node intToBVOp = d_nodeManager->mkConst<IntToBitVector>(IntToBitVector(4));
187
2
  original = d_nodeManager->mkNode(intToBVOp, i1);
188
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
189
2
  ASSERT_TRUE(result.getType().isInteger());
190
191
  // zero extend
192
  Node zeroExtOp =
193
4
      d_nodeManager->mkConst<BitVectorZeroExtend>(BitVectorZeroExtend(4));
194
2
  original = d_nodeManager->mkNode(zeroExtOp, v1);
195
2
  result = intBlaster.translateWithChildren(original, {i1}, lemmas);
196
2
  ASSERT_TRUE(result.getType().isInteger());
197
198
  // extract + BV ITE
199
4
  Node extract = theory::bv::utils::mkExtract(v1, 0, 0);
200
2
  original = d_nodeManager->mkNode(BITVECTOR_ITE, extract, v2, v1);
201
4
  Node intExtract = intBlaster.translateWithChildren(extract, {i1}, lemmas);
202
2
  result =
203
4
      intBlaster.translateWithChildren(original, {intExtract, i1, i2}, lemmas);
204
2
  ASSERT_TRUE(result.getType().isInteger());
205
2
  ASSERT_TRUE(intExtract.getType().isInteger());
206
207
  // concat
208
2
  original = d_nodeManager->mkNode(BITVECTOR_CONCAT, v1, v2);
209
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
210
2
  ASSERT_TRUE(result.getType().isInteger());
211
212
  // predicates
213
2
  original = d_nodeManager->mkNode(EQUAL, v1, v2);
214
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
215
2
  ASSERT_TRUE(result.getType().isBoolean());
216
217
2
  original = d_nodeManager->mkNode(BITVECTOR_ULT, v1, v2);
218
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
219
2
  ASSERT_TRUE(result.getType().isBoolean());
220
221
2
  original = d_nodeManager->mkNode(BITVECTOR_ULE, v1, v2);
222
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
223
2
  ASSERT_TRUE(result.getType().isBoolean());
224
225
2
  original = d_nodeManager->mkNode(BITVECTOR_UGT, v1, v2);
226
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
227
2
  ASSERT_TRUE(result.getType().isBoolean());
228
229
2
  original = d_nodeManager->mkNode(BITVECTOR_UGE, v1, v2);
230
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
231
2
  ASSERT_TRUE(result.getType().isBoolean());
232
233
  // BVULT with a BV result
234
2
  original = d_nodeManager->mkNode(BITVECTOR_ULTBV, v1, v2);
235
2
  result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
236
2
  ASSERT_TRUE(result.getType().isInteger());
237
238
  // function application
239
4
  TypeNode funType = d_nodeManager->mkFunctionType({bvType}, bvType);
240
4
  Node f = d_nodeManager->mkVar("f", funType);
241
4
  Node g = intBlaster.translateNoChildren(f, lemmas, skolems);
242
2
  original = d_nodeManager->mkNode(APPLY_UF, f, v1);
243
2
  result = intBlaster.translateWithChildren(original, {g, i1}, lemmas);
244
2
  ASSERT_TRUE(result.getType().isInteger());
245
}
246
247
}  // namespace test
248
64889
}  // namespace cvc5