GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/proof/proof_node_to_sexpr.cpp Lines: 119 172 69.2 %
Date: 2021-08-06 Branches: 156 606 25.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Haniel Barbosa, 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 proof node to s-expression.
14
 */
15
16
#include "proof/proof_node_to_sexpr.h"
17
18
#include <iostream>
19
#include <sstream>
20
21
#include "options/proof_options.h"
22
#include "proof/proof_checker.h"
23
#include "proof/proof_node.h"
24
#include "theory/builtin/proof_checker.h"
25
26
using namespace cvc5::kind;
27
28
namespace cvc5 {
29
30
37859
ProofNodeToSExpr::ProofNodeToSExpr()
31
{
32
37859
  NodeManager* nm = NodeManager::currentNM();
33
37859
  d_conclusionMarker = nm->mkBoundVar(":conclusion", nm->sExprType());
34
37859
  d_argsMarker = nm->mkBoundVar(":args", nm->sExprType());
35
37859
}
36
37
37859
Node ProofNodeToSExpr::convertToSExpr(const ProofNode* pn)
38
{
39
37859
  NodeManager* nm = NodeManager::currentNM();
40
37859
  std::map<const ProofNode*, Node>::iterator it;
41
75718
  std::vector<const ProofNode*> visit;
42
75718
  std::vector<const ProofNode*> traversing;
43
  const ProofNode* cur;
44
37859
  visit.push_back(pn);
45
445887
  do
46
  {
47
483746
    cur = visit.back();
48
483746
    visit.pop_back();
49
483746
    it = d_pnMap.find(cur);
50
51
483746
    if (it == d_pnMap.end())
52
    {
53
241849
      d_pnMap[cur] = Node::null();
54
241849
      traversing.push_back(cur);
55
241849
      visit.push_back(cur);
56
241849
      const std::vector<std::shared_ptr<ProofNode>>& pc = cur->getChildren();
57
445887
      for (const std::shared_ptr<ProofNode>& cp : pc)
58
      {
59
612114
        if (std::find(traversing.begin(), traversing.end(), cp.get())
60
612114
            != traversing.end())
61
        {
62
          Unhandled() << "ProofNodeToSExpr::convertToSExpr: cyclic proof! (use "
63
                         "--proof-eager-checking)"
64
                      << std::endl;
65
          return Node::null();
66
        }
67
204038
        visit.push_back(cp.get());
68
      }
69
    }
70
241897
    else if (it->second.isNull())
71
    {
72
241849
      Assert(!traversing.empty());
73
241849
      traversing.pop_back();
74
483698
      std::vector<Node> children;
75
      // add proof rule
76
241849
      PfRule r = cur->getRule();
77
241849
      children.push_back(getOrMkPfRuleVariable(r));
78
483698
      if (options::proofPrintConclusion())
79
      {
80
        children.push_back(d_conclusionMarker);
81
        children.push_back(cur->getResult());
82
      }
83
241849
      const std::vector<std::shared_ptr<ProofNode>>& pc = cur->getChildren();
84
445887
      for (const std::shared_ptr<ProofNode>& cp : pc)
85
      {
86
204038
        it = d_pnMap.find(cp.get());
87
204038
        Assert(it != d_pnMap.end());
88
204038
        Assert(!it->second.isNull());
89
204038
        children.push_back(it->second);
90
      }
91
      // add arguments
92
241849
      const std::vector<Node>& args = cur->getArguments();
93
241849
      if (!args.empty())
94
      {
95
222439
        children.push_back(d_argsMarker);
96
        // needed to ensure builtin operators are not treated as operators
97
        // this can be the case for CONG where d_args may contain a builtin
98
        // operator
99
444878
        std::vector<Node> argsPrint;
100
483060
        for (size_t i = 0, nargs = args.size(); i < nargs; i++)
101
        {
102
260621
          ArgFormat f = getArgumentFormat(cur, i);
103
521242
          Node av = getArgument(args[i], f);
104
260621
          argsPrint.push_back(av);
105
        }
106
444878
        Node argsC = nm->mkNode(SEXPR, argsPrint);
107
222439
        children.push_back(argsC);
108
      }
109
241849
      d_pnMap[cur] = nm->mkNode(SEXPR, children);
110
    }
111
483746
  } while (!visit.empty());
112
37859
  Assert(d_pnMap.find(pn) != d_pnMap.end());
113
37859
  Assert(!d_pnMap.find(pn)->second.isNull());
114
37859
  return d_pnMap[pn];
115
}
116
117
241849
Node ProofNodeToSExpr::getOrMkPfRuleVariable(PfRule r)
118
{
119
241849
  std::map<PfRule, Node>::iterator it = d_pfrMap.find(r);
120
241849
  if (it != d_pfrMap.end())
121
  {
122
70783
    return it->second;
123
  }
124
342132
  std::stringstream ss;
125
171066
  ss << r;
126
171066
  NodeManager* nm = NodeManager::currentNM();
127
342132
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
128
171066
  d_pfrMap[r] = var;
129
171066
  return var;
130
}
131
61
Node ProofNodeToSExpr::getOrMkKindVariable(TNode n)
132
{
133
  Kind k;
134
61
  if (!ProofRuleChecker::getKind(n, k))
135
  {
136
    // just use self if we failed to get the node, throw a debug failure
137
    Assert(false) << "Expected kind node, got " << n;
138
    return n;
139
  }
140
61
  std::map<Kind, Node>::iterator it = d_kindMap.find(k);
141
61
  if (it != d_kindMap.end())
142
  {
143
20
    return it->second;
144
  }
145
82
  std::stringstream ss;
146
41
  ss << k;
147
41
  NodeManager* nm = NodeManager::currentNM();
148
82
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
149
41
  d_kindMap[k] = var;
150
41
  return var;
151
}
152
153
109
Node ProofNodeToSExpr::getOrMkTheoryIdVariable(TNode n)
154
{
155
  theory::TheoryId tid;
156
109
  if (!theory::builtin::BuiltinProofRuleChecker::getTheoryId(n, tid))
157
  {
158
    // just use self if we failed to get the node, throw a debug failure
159
    Assert(false) << "Expected theory id node, got " << n;
160
    return n;
161
  }
162
109
  std::map<theory::TheoryId, Node>::iterator it = d_tidMap.find(tid);
163
109
  if (it != d_tidMap.end())
164
  {
165
100
    return it->second;
166
  }
167
18
  std::stringstream ss;
168
9
  ss << tid;
169
9
  NodeManager* nm = NodeManager::currentNM();
170
18
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
171
9
  d_tidMap[tid] = var;
172
9
  return var;
173
}
174
175
109
Node ProofNodeToSExpr::getOrMkMethodIdVariable(TNode n)
176
{
177
  MethodId mid;
178
109
  if (!getMethodId(n, mid))
179
  {
180
    // just use self if we failed to get the node, throw a debug failure
181
    Assert(false) << "Expected method id node, got " << n;
182
    return n;
183
  }
184
109
  std::map<MethodId, Node>::iterator it = d_midMap.find(mid);
185
109
  if (it != d_midMap.end())
186
  {
187
99
    return it->second;
188
  }
189
20
  std::stringstream ss;
190
10
  ss << mid;
191
10
  NodeManager* nm = NodeManager::currentNM();
192
20
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
193
10
  d_midMap[mid] = var;
194
10
  return var;
195
}
196
Node ProofNodeToSExpr::getOrMkInferenceIdVariable(TNode n)
197
{
198
  theory::InferenceId iid;
199
  if (!theory::getInferenceId(n, iid))
200
  {
201
    // just use self if we failed to get the node, throw a debug failure
202
    Assert(false) << "Expected inference id node, got " << n;
203
    return n;
204
  }
205
  std::map<theory::InferenceId, Node>::iterator it = d_iidMap.find(iid);
206
  if (it != d_iidMap.end())
207
  {
208
    return it->second;
209
  }
210
  std::stringstream ss;
211
  ss << iid;
212
  NodeManager* nm = NodeManager::currentNM();
213
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
214
  d_iidMap[iid] = var;
215
  return var;
216
}
217
218
Node ProofNodeToSExpr::getOrMkNodeVariable(TNode n)
219
{
220
  std::map<TNode, Node>::iterator it = d_nodeMap.find(n);
221
  if (it != d_nodeMap.end())
222
  {
223
    return it->second;
224
  }
225
  std::stringstream ss;
226
  ss << n;
227
  NodeManager* nm = NodeManager::currentNM();
228
  Node var = nm->mkBoundVar(ss.str(), nm->sExprType());
229
  d_nodeMap[n] = var;
230
  return var;
231
}
232
233
260621
Node ProofNodeToSExpr::getArgument(Node arg, ArgFormat f)
234
{
235
260621
  switch (f)
236
  {
237
61
    case ArgFormat::KIND: return getOrMkKindVariable(arg);
238
109
    case ArgFormat::THEORY_ID: return getOrMkTheoryIdVariable(arg);
239
109
    case ArgFormat::METHOD_ID: return getOrMkMethodIdVariable(arg);
240
    case ArgFormat::INFERENCE_ID: return getOrMkInferenceIdVariable(arg);
241
    case ArgFormat::NODE_VAR: return getOrMkNodeVariable(arg);
242
260342
    default: return arg;
243
  }
244
}
245
246
260621
ProofNodeToSExpr::ArgFormat ProofNodeToSExpr::getArgumentFormat(
247
    const ProofNode* pn, size_t i)
248
{
249
260621
  PfRule r = pn->getRule();
250
260621
  switch (r)
251
  {
252
61
    case PfRule::CONG:
253
    {
254
61
      if (i == 0)
255
      {
256
61
        return ArgFormat::KIND;
257
      }
258
      const std::vector<Node>& args = pn->getArguments();
259
      Assert(i < args.size());
260
      if (args[i].getNumChildren() == 0
261
          && NodeManager::operatorToKind(args[i]) != UNDEFINED_KIND)
262
      {
263
        return ArgFormat::NODE_VAR;
264
      }
265
    }
266
    break;
267
65628
    case PfRule::SUBS:
268
    case PfRule::REWRITE:
269
    case PfRule::MACRO_SR_EQ_INTRO:
270
    case PfRule::MACRO_SR_PRED_INTRO:
271
    case PfRule::MACRO_SR_PRED_TRANSFORM:
272
65628
      if (i > 0)
273
      {
274
        return ArgFormat::METHOD_ID;
275
      }
276
65628
      break;
277
    case PfRule::MACRO_SR_PRED_ELIM: return ArgFormat::METHOD_ID; break;
278
327
    case PfRule::THEORY_LEMMA:
279
    case PfRule::THEORY_REWRITE:
280
327
      if (i == 1)
281
      {
282
109
        return ArgFormat::THEORY_ID;
283
      }
284
218
      else if (r == PfRule::THEORY_REWRITE && i == 2)
285
      {
286
109
        return ArgFormat::METHOD_ID;
287
      }
288
109
      break;
289
    case PfRule::INSTANTIATE:
290
    {
291
      Assert(!pn->getChildren().empty());
292
      Node q = pn->getChildren()[0]->getResult();
293
      Assert(q.getKind() == kind::FORALL);
294
      if (i == q[0].getNumChildren())
295
      {
296
        return ArgFormat::INFERENCE_ID;
297
      }
298
    }
299
    break;
300
194605
    default: break;
301
  }
302
260342
  return ArgFormat::DEFAULT;
303
}
304
305
271171
}  // namespace cvc5