GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/dynamic_rewrite.cpp Lines: 76 89 85.4 %
Date: 2021-08-14 Branches: 162 356 45.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Andres Noetzli, Aina Niemetz
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 dynamic_rewriter.
14
 */
15
16
#include "theory/quantifiers/dynamic_rewrite.h"
17
18
#include "expr/skolem_manager.h"
19
#include "theory/rewriter.h"
20
21
using namespace std;
22
using namespace cvc5::kind;
23
24
namespace cvc5 {
25
namespace theory {
26
namespace quantifiers {
27
28
7
DynamicRewriter::DynamicRewriter(const std::string& name,
29
7
                                 context::UserContext* u)
30
7
    : d_equalityEngine(u, "DynamicRewriter::" + name, true), d_rewrites(u)
31
{
32
7
  d_equalityEngine.addFunctionKind(kind::APPLY_UF);
33
7
}
34
35
105
void DynamicRewriter::addRewrite(Node a, Node b)
36
{
37
105
  Trace("dyn-rewrite") << "Dyn-Rewriter : " << a << " == " << b << std::endl;
38
105
  if (a == b)
39
  {
40
    Trace("dyn-rewrite") << "...equal." << std::endl;
41
    return;
42
  }
43
44
  // add to the equality engine
45
210
  Node ai = toInternal(a);
46
210
  Node bi = toInternal(b);
47
105
  if (ai.isNull() || bi.isNull())
48
  {
49
    Trace("dyn-rewrite") << "...not internalizable." << std::endl;
50
    return;
51
  }
52
105
  Trace("dyn-rewrite-debug") << "Internal : " << ai << " " << bi << std::endl;
53
54
105
  Trace("dyn-rewrite-debug") << "assert eq..." << std::endl;
55
210
  Node eq = ai.eqNode(bi);
56
105
  d_rewrites.push_back(eq);
57
105
  d_equalityEngine.assertEquality(eq, true, eq);
58
105
  Assert(d_equalityEngine.consistent());
59
105
  Trace("dyn-rewrite-debug") << "Finished" << std::endl;
60
}
61
62
804
bool DynamicRewriter::areEqual(Node a, Node b)
63
{
64
804
  if (a == b)
65
  {
66
    return true;
67
  }
68
804
  Trace("dyn-rewrite-debug") << "areEqual? : " << a << " " << b << std::endl;
69
  // add to the equality engine
70
1608
  Node ai = toInternal(a);
71
1608
  Node bi = toInternal(b);
72
804
  if (ai.isNull() || bi.isNull())
73
  {
74
    Trace("dyn-rewrite") << "...not internalizable." << std::endl;
75
    return false;
76
  }
77
804
  Trace("dyn-rewrite-debug") << "internal : " << ai << " " << bi << std::endl;
78
804
  d_equalityEngine.addTerm(ai);
79
804
  d_equalityEngine.addTerm(bi);
80
804
  Trace("dyn-rewrite-debug") << "...added terms" << std::endl;
81
804
  return d_equalityEngine.areEqual(ai, bi);
82
}
83
84
3994
Node DynamicRewriter::toInternal(Node a)
85
{
86
3994
  std::map<Node, Node>::iterator it = d_term_to_internal.find(a);
87
3994
  if (it != d_term_to_internal.end())
88
  {
89
3018
    return it->second;
90
  }
91
1952
  Node ret = a;
92
93
976
  if (!a.isVar())
94
  {
95
1934
    std::vector<Node> children;
96
967
    if (a.hasOperator())
97
    {
98
1914
      Node op = a.getOperator();
99
957
      if (a.getKind() != APPLY_UF)
100
      {
101
957
        op = d_ois_trie[op].getSymbol(a);
102
        // if this term involves an argument that is not of first class type,
103
        // we cannot reason about it. This includes operators like str.in-re.
104
957
        if (op.isNull())
105
        {
106
          return Node::null();
107
        }
108
      }
109
957
      children.push_back(op);
110
    }
111
2874
    for (const Node& ca : a)
112
    {
113
3814
      Node cai = toInternal(ca);
114
1907
      if (cai.isNull())
115
      {
116
        return Node::null();
117
      }
118
1907
      children.push_back(cai);
119
    }
120
967
    if (!children.empty())
121
    {
122
957
      if (children.size() == 1)
123
      {
124
        ret = children[0];
125
      }
126
      else
127
      {
128
957
        ret = NodeManager::currentNM()->mkNode(APPLY_UF, children);
129
      }
130
    }
131
  }
132
976
  d_term_to_internal[a] = ret;
133
976
  d_internal_to_term[ret] = a;
134
976
  return ret;
135
}
136
137
244
Node DynamicRewriter::toExternal(Node ai)
138
{
139
244
  std::map<Node, Node>::iterator it = d_internal_to_term.find(ai);
140
244
  if (it != d_internal_to_term.end())
141
  {
142
244
    return it->second;
143
  }
144
  return Node::null();
145
}
146
147
957
Node DynamicRewriter::OpInternalSymTrie::getSymbol(Node n)
148
{
149
957
  NodeManager* nm = NodeManager::currentNM();
150
957
  SkolemManager* sm = nm->getSkolemManager();
151
1914
  std::vector<TypeNode> ctypes;
152
2864
  for (const Node& cn : n)
153
  {
154
1907
    ctypes.push_back(cn.getType());
155
  }
156
957
  ctypes.push_back(n.getType());
157
158
957
  OpInternalSymTrie* curr = this;
159
3821
  for (unsigned i = 0, size = ctypes.size(); i < size; i++)
160
  {
161
    // cannot handle certain types (e.g. regular expressions or functions)
162
2864
    if (!ctypes[i].isFirstClass())
163
    {
164
      return Node::null();
165
    }
166
2864
    curr = &(curr->d_children[ctypes[i]]);
167
  }
168
957
  if (!curr->d_sym.isNull())
169
  {
170
927
    return curr->d_sym;
171
  }
172
  // make UF operator
173
60
  TypeNode utype;
174
30
  if (ctypes.size() == 1)
175
  {
176
    utype = ctypes[0];
177
  }
178
  else
179
  {
180
30
    utype = nm->mkFunctionType(ctypes);
181
  }
182
60
  Node f = sm->mkDummySkolem("ufd", utype, "internal op for dynamic_rewriter");
183
30
  curr->d_sym = f;
184
30
  return f;
185
}
186
187
}  // namespace quantifiers
188
}  // namespace theory
189
29340
}  // namespace cvc5