GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/expand_definitions.cpp Lines: 69 70 98.6 %
Date: 2021-05-22 Branches: 126 274 46.0 %

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 expand definitions for an SMT engine.
14
 */
15
16
#include "smt/expand_definitions.h"
17
18
#include <stack>
19
#include <utility>
20
21
#include "expr/node_manager_attributes.h"
22
#include "expr/term_conversion_proof_generator.h"
23
#include "preprocessing/assertion_pipeline.h"
24
#include "smt/env.h"
25
#include "smt/smt_engine.h"
26
#include "smt/smt_engine_stats.h"
27
#include "theory/rewriter.h"
28
#include "theory/theory.h"
29
#include "util/resource_manager.h"
30
31
using namespace cvc5::preprocessing;
32
using namespace cvc5::theory;
33
using namespace cvc5::kind;
34
35
namespace cvc5 {
36
namespace smt {
37
38
10092
ExpandDefs::ExpandDefs(Env& env, SmtEngineStatistics& stats)
39
10092
    : d_env(env), d_smtStats(stats), d_tpg(nullptr)
40
{
41
10092
}
42
43
10092
ExpandDefs::~ExpandDefs() {}
44
45
4621
Node ExpandDefs::expandDefinitions(TNode n,
46
                                   std::unordered_map<Node, Node>& cache)
47
{
48
9242
  TrustNode trn = expandDefinitions(n, cache, nullptr);
49
9242
  return trn.isNull() ? Node(n) : trn.getNode();
50
}
51
52
4621
TrustNode ExpandDefs::expandDefinitions(TNode n,
53
                                        std::unordered_map<Node, Node>& cache,
54
                                        TConvProofGenerator* tpg)
55
{
56
9242
  const TNode orig = n;
57
9242
  std::stack<std::tuple<Node, Node, bool>> worklist;
58
9242
  std::stack<Node> result;
59
4621
  worklist.push(std::make_tuple(Node(n), Node(n), false));
60
  // The worklist is made of triples, each is input / original node then the
61
  // output / rewritten node and finally a flag tracking whether the children
62
  // have been explored (i.e. if this is a downward or upward pass).
63
64
4621
  ResourceManager* rm = d_env.getResourceManager();
65
4621
  Rewriter* rr = d_env.getRewriter();
66
34546
  do
67
  {
68
39167
    rm->spendResource(Resource::PreprocessStep);
69
70
    // n is the input / original
71
    // node is the output / result
72
63833
    Node node;
73
    bool childrenPushed;
74
39167
    std::tie(n, node, childrenPushed) = worklist.top();
75
39167
    worklist.pop();
76
77
    // Working downwards
78
39167
    if (!childrenPushed)
79
    {
80
      // we can short circuit (variable) leaves
81
38073
      if (n.isVar())
82
      {
83
        // don't bother putting in the cache
84
11239
        result.push(n);
85
25740
        continue;
86
      }
87
88
      // maybe it's in the cache
89
15595
      std::unordered_map<Node, Node>::iterator cacheHit = cache.find(n);
90
15595
      if (cacheHit != cache.end())
91
      {
92
6524
        TNode ret = (*cacheHit).second;
93
3262
        result.push(ret.isNull() ? n : ret);
94
3262
        continue;
95
      }
96
12333
      theory::TheoryId tid = theory::Theory::theoryOf(node);
97
12333
      theory::TheoryRewriter* tr = rr->getTheoryRewriter(tid);
98
99
12333
      Assert(tr != NULL);
100
24666
      TrustNode trn = tr->expandDefinition(n);
101
12333
      if (!trn.isNull())
102
      {
103
295
        node = trn.getNode();
104
295
        if (tpg != nullptr)
105
        {
106
          tpg->addRewriteStep(
107
              n, node, trn.getGenerator(), true, PfRule::THEORY_EXPAND_DEF);
108
        }
109
      }
110
      else
111
      {
112
12038
        node = n;
113
      }
114
      // the partial functions can fall through, in which case we still
115
      // consider their children
116
36999
      worklist.push(std::make_tuple(
117
24666
          Node(n), node, true));  // Original and rewritten result
118
119
34546
      for (size_t i = 0; i < node.getNumChildren(); ++i)
120
      {
121
22213
        worklist.push(
122
44426
            std::make_tuple(node[i],
123
                            node[i],
124
                            false));  // Rewrite the children of the result only
125
      }
126
    }
127
    else
128
    {
129
      // Working upwards
130
      // Reconstruct the node from it's (now rewritten) children on the stack
131
132
12333
      Debug("expand") << "cons : " << node << std::endl;
133
12333
      if (node.getNumChildren() > 0)
134
      {
135
        // cout << "cons : " << node << std::endl;
136
21542
        NodeBuilder nb(node.getKind());
137
10771
        if (node.getMetaKind() == metakind::PARAMETERIZED)
138
        {
139
1911
          Debug("expand") << "op   : " << node.getOperator() << std::endl;
140
          // cout << "op   : " << node.getOperator() << std::endl;
141
1911
          nb << node.getOperator();
142
        }
143
32984
        for (size_t i = 0, nchild = node.getNumChildren(); i < nchild; ++i)
144
        {
145
22213
          Assert(!result.empty());
146
44426
          Node expanded = result.top();
147
22213
          result.pop();
148
          // cout << "exchld : " << expanded << std::endl;
149
22213
          Debug("expand") << "exchld : " << expanded << std::endl;
150
22213
          nb << expanded;
151
        }
152
10771
        node = nb;
153
      }
154
      // Only cache once all subterms are expanded
155
12333
      cache[n] = n == node ? Node::null() : node;
156
12333
      result.push(node);
157
    }
158
39167
  } while (!worklist.empty());
159
160
4621
  AlwaysAssert(result.size() == 1);
161
162
9242
  Node res = result.top();
163
164
4621
  if (res == orig)
165
  {
166
4368
    return TrustNode::null();
167
  }
168
253
  return TrustNode::mkTrustRewrite(orig, res, tpg);
169
}
170
171
3600
void ExpandDefs::setProofNodeManager(ProofNodeManager* pnm)
172
{
173
3600
  if (d_tpg == nullptr)
174
  {
175
10800
    d_tpg.reset(new TConvProofGenerator(pnm,
176
3600
                                        d_env.getUserContext(),
177
                                        TConvPolicy::FIXPOINT,
178
                                        TConvCachePolicy::NEVER,
179
                                        "ExpandDefs::TConvProofGenerator",
180
                                        nullptr,
181
3600
                                        true));
182
  }
183
3600
}
184
185
}  // namespace smt
186
28191
}  // namespace cvc5