GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.cpp Lines: 171 171 100.0 %
Date: 2021-05-22 Branches: 445 1064 41.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Mathias Preiner, Aina Niemetz, 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
 * Implementation of ceg_bv_instantiator.
14
 */
15
16
#include "theory/quantifiers/cegqi/ceg_bv_instantiator_utils.h"
17
18
#include "theory/bv/theory_bv_utils.h"
19
#include "theory/rewriter.h"
20
21
using namespace cvc5::kind;
22
23
namespace cvc5 {
24
namespace theory {
25
namespace quantifiers {
26
namespace utils {
27
28
470
Node getPvCoeff(TNode pv, TNode n)
29
{
30
470
  bool neg = false;
31
940
  Node coeff;
32
33
470
  if (n.getKind() == BITVECTOR_NEG)
34
  {
35
2
    neg = true;
36
2
    n = n[0];
37
  }
38
39
470
  if (n == pv)
40
  {
41
312
    coeff = bv::utils::mkOne(bv::utils::getSize(pv));
42
  }
43
  /* All multiplications are normalized to pv * (t1 * t2). */
44
158
  else if (n.getKind() == BITVECTOR_MULT && n.getAttribute(BvLinearAttribute()))
45
  {
46
156
    Assert(n.getNumChildren() == 2);
47
156
    Assert(n[0] == pv);
48
156
    coeff = n[1];
49
  }
50
  else /* n is in no form to extract the coefficient for pv */
51
  {
52
4
    Trace("cegqi-bv-nl") << "Cannot extract coefficient for " << pv << " in "
53
2
                         << n << std::endl;
54
2
    return Node::null();
55
  }
56
468
  Assert(!coeff.isNull());
57
58
468
  if (neg) return NodeManager::currentNM()->mkNode(BITVECTOR_NEG, coeff);
59
466
  return coeff;
60
}
61
62
632
Node normalizePvMult(TNode pv,
63
                     const std::vector<Node>& children,
64
                     std::unordered_map<Node, bool>& contains_pv)
65
{
66
632
  bool neg, neg_coeff = false;
67
632
  bool found_pv = false;
68
  NodeManager* nm;
69
1264
  NodeBuilder nb(BITVECTOR_MULT);
70
  BvLinearAttribute is_linear;
71
72
632
  nm = NodeManager::currentNM();
73
1862
  for (TNode nc : children)
74
  {
75
1900
    if (!contains_pv[nc])
76
    {
77
628
      nb << nc;
78
628
      continue;
79
    }
80
81
644
    neg = false;
82
644
    if (nc.getKind() == BITVECTOR_NEG)
83
    {
84
8
      neg = true;
85
8
      nc = nc[0];
86
    }
87
88
1242
    if (!found_pv && nc == pv)
89
    {
90
598
      found_pv = true;
91
598
      neg_coeff = neg;
92
598
      continue;
93
    }
94
128
    else if (!found_pv && nc.getKind() == BITVECTOR_MULT
95
50
             && nc.getAttribute(is_linear))
96
    {
97
4
      Assert(nc.getNumChildren() == 2);
98
4
      Assert(nc[0] == pv);
99
4
      Assert(!contains_pv[nc[1]]);
100
4
      found_pv = true;
101
4
      neg_coeff = neg;
102
4
      nb << nc[1];
103
4
      continue;
104
    }
105
42
    return Node::null(); /* non-linear */
106
  }
107
590
  Assert(nb.getNumChildren() > 0);
108
109
1180
  Node coeff = (nb.getNumChildren() == 1) ? nb[0] : nb.constructNode();
110
590
  if (neg_coeff)
111
  {
112
6
    coeff = nm->mkNode(BITVECTOR_NEG, coeff);
113
  }
114
590
  coeff = Rewriter::rewrite(coeff);
115
590
  unsigned size_coeff = bv::utils::getSize(coeff);
116
1180
  Node zero = bv::utils::mkZero(size_coeff);
117
590
  if (coeff == zero)
118
  {
119
8
    return zero;
120
  }
121
1164
  Node result;
122
582
  if (found_pv)
123
  {
124
580
    if (coeff == bv::utils::mkOne(size_coeff))
125
    {
126
220
      return pv;
127
    }
128
360
    result = nm->mkNode(BITVECTOR_MULT, pv, coeff);
129
360
    contains_pv[result] = true;
130
360
    result.setAttribute(is_linear, true);
131
  }
132
  else
133
  {
134
2
    result = coeff;
135
  }
136
362
  return result;
137
}
138
139
#ifdef CVC5_ASSERTIONS
140
namespace {
141
58
bool isLinearPlus(TNode n,
142
                  TNode pv,
143
                  std::unordered_map<Node, bool>& contains_pv)
144
{
145
116
  Node coeff;
146
58
  Assert(n.getAttribute(BvLinearAttribute()));
147
58
  Assert(n.getNumChildren() == 2);
148
58
  if (n[0] != pv)
149
  {
150
32
    Assert(n[0].getKind() == BITVECTOR_MULT);
151
32
    Assert(n[0].getNumChildren() == 2);
152
32
    Assert(n[0][0] == pv);
153
32
    Assert(!contains_pv[n[0][1]]);
154
  }
155
58
  Assert(!contains_pv[n[1]]);
156
58
  coeff = utils::getPvCoeff(pv, n[0]);
157
58
  Assert(!coeff.isNull());
158
58
  Assert(!contains_pv[coeff]);
159
116
  return true;
160
}
161
}  // namespace
162
#endif
163
164
990
Node normalizePvPlus(Node pv,
165
                     const std::vector<Node>& children,
166
                     std::unordered_map<Node, bool>& contains_pv)
167
{
168
  NodeManager* nm;
169
1980
  NodeBuilder nb_c(BITVECTOR_ADD);
170
1980
  NodeBuilder nb_l(BITVECTOR_ADD);
171
  BvLinearAttribute is_linear;
172
  bool neg;
173
174
990
  nm = NodeManager::currentNM();
175
1726
  for (TNode nc : children)
176
  {
177
1828
    if (!contains_pv[nc])
178
    {
179
418
      nb_l << nc;
180
418
      continue;
181
    }
182
183
992
    neg = false;
184
992
    if (nc.getKind() == BITVECTOR_NEG)
185
    {
186
32
      neg = true;
187
32
      nc = nc[0];
188
    }
189
190
1984
    if (nc == pv
191
992
        || (nc.getKind() == BITVECTOR_MULT && nc.getAttribute(is_linear)))
192
    {
193
604
      Node coeff = utils::getPvCoeff(pv, nc);
194
302
      Assert(!coeff.isNull());
195
302
      if (neg)
196
      {
197
28
        coeff = nm->mkNode(BITVECTOR_NEG, coeff);
198
      }
199
302
      nb_c << coeff;
200
302
      continue;
201
    }
202
690
    else if (nc.getKind() == BITVECTOR_ADD && nc.getAttribute(is_linear))
203
    {
204
16
      Assert(isLinearPlus(nc, pv, contains_pv));
205
32
      Node coeff = utils::getPvCoeff(pv, nc[0]);
206
16
      Assert(!coeff.isNull());
207
32
      Node leaf = nc[1];
208
16
      if (neg)
209
      {
210
2
        coeff = nm->mkNode(BITVECTOR_NEG, coeff);
211
2
        leaf = nm->mkNode(BITVECTOR_NEG, leaf);
212
      }
213
16
      nb_c << coeff;
214
16
      nb_l << leaf;
215
16
      continue;
216
    }
217
    /* can't collect coefficients of 'pv' in 'cur' -> non-linear */
218
674
    return Node::null();
219
  }
220
316
  Assert(nb_c.getNumChildren() > 0 || nb_l.getNumChildren() > 0);
221
222
632
  Node pv_mult_coeffs, result;
223
316
  if (nb_c.getNumChildren() > 0)
224
  {
225
628
    Node coeffs = (nb_c.getNumChildren() == 1) ? nb_c[0] : nb_c.constructNode();
226
314
    coeffs = Rewriter::rewrite(coeffs);
227
314
    result = pv_mult_coeffs =
228
628
        utils::normalizePvMult(pv, {pv, coeffs}, contains_pv);
229
  }
230
231
316
  if (nb_l.getNumChildren() > 0)
232
  {
233
628
    Node leafs = (nb_l.getNumChildren() == 1) ? nb_l[0] : nb_l.constructNode();
234
314
    leafs = Rewriter::rewrite(leafs);
235
628
    Node zero = bv::utils::mkZero(bv::utils::getSize(pv));
236
    /* pv * 0 + t --> t */
237
314
    if (pv_mult_coeffs.isNull() || pv_mult_coeffs == zero)
238
    {
239
4
      result = leafs;
240
    }
241
    else
242
    {
243
310
      result = nm->mkNode(BITVECTOR_ADD, pv_mult_coeffs, leafs);
244
310
      contains_pv[result] = true;
245
310
      result.setAttribute(is_linear, true);
246
    }
247
  }
248
316
  Assert(!result.isNull());
249
316
  return result;
250
}
251
252
188
Node normalizePvEqual(Node pv,
253
                      const std::vector<Node>& children,
254
                      std::unordered_map<Node, bool>& contains_pv)
255
{
256
188
  Assert(children.size() == 2);
257
258
188
  NodeManager* nm = NodeManager::currentNM();
259
  BvLinearAttribute is_linear;
260
376
  Node coeffs[2], leafs[2];
261
  bool neg;
262
376
  TNode child;
263
264
564
  for (unsigned i = 0; i < 2; ++i)
265
  {
266
376
    child = children[i];
267
376
    neg = false;
268
376
    if (child.getKind() == BITVECTOR_NEG)
269
    {
270
4
      neg = true;
271
4
      child = child[0];
272
    }
273
376
    if (child.getAttribute(is_linear) || child == pv)
274
    {
275
84
      if (child.getKind() == BITVECTOR_ADD)
276
      {
277
42
        Assert(isLinearPlus(child, pv, contains_pv));
278
42
        coeffs[i] = utils::getPvCoeff(pv, child[0]);
279
42
        leafs[i] = child[1];
280
      }
281
      else
282
      {
283
42
        Assert(child.getKind() == BITVECTOR_MULT || child == pv);
284
42
        coeffs[i] = utils::getPvCoeff(pv, child);
285
      }
286
    }
287
376
    if (neg)
288
    {
289
4
      if (!coeffs[i].isNull())
290
      {
291
4
        coeffs[i] = nm->mkNode(BITVECTOR_NEG, coeffs[i]);
292
      }
293
4
      if (!leafs[i].isNull())
294
      {
295
2
        leafs[i] = nm->mkNode(BITVECTOR_NEG, leafs[i]);
296
      }
297
    }
298
  }
299
300
188
  if (coeffs[0].isNull() || coeffs[1].isNull())
301
  {
302
166
    return Node::null();
303
  }
304
305
44
  Node coeff = nm->mkNode(BITVECTOR_SUB, coeffs[0], coeffs[1]);
306
22
  coeff = Rewriter::rewrite(coeff);
307
44
  std::vector<Node> mult_children = {pv, coeff};
308
44
  Node lhs = utils::normalizePvMult(pv, mult_children, contains_pv);
309
310
44
  Node rhs;
311
22
  if (!leafs[0].isNull() && !leafs[1].isNull())
312
  {
313
2
    rhs = nm->mkNode(BITVECTOR_SUB, leafs[1], leafs[0]);
314
  }
315
20
  else if (!leafs[0].isNull())
316
  {
317
8
    rhs = nm->mkNode(BITVECTOR_NEG, leafs[0]);
318
  }
319
12
  else if (!leafs[1].isNull())
320
  {
321
2
    rhs = leafs[1];
322
  }
323
  else
324
  {
325
10
    rhs = bv::utils::mkZero(bv::utils::getSize(pv));
326
  }
327
22
  rhs = Rewriter::rewrite(rhs);
328
329
22
  if (lhs == rhs)
330
  {
331
2
    return bv::utils::mkTrue();
332
  }
333
334
40
  Node result = lhs.eqNode(rhs);
335
20
  contains_pv[result] = true;
336
20
  return result;
337
}
338
339
}  // namespace utils
340
}  // namespace quantifiers
341
}  // namespace theory
342
28194
}  // namespace cvc5