GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/proof/dot/dot_printer.cpp Lines: 1 88 1.1 %
Date: 2021-05-22 Branches: 2 203 1.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Diego Della Rocca de Camargos
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
 * Implemantation of the module for printing dot proofs.
14
 */
15
16
#include "proof/dot/dot_printer.h"
17
18
#include <sstream>
19
20
#include "expr/proof_checker.h"
21
#include "expr/proof_node_manager.h"
22
#include "printer/smt2/smt2_printer.h"
23
#include "theory/builtin/proof_checker.h"
24
25
namespace cvc5 {
26
namespace proof {
27
28
std::string DotPrinter::sanitizeString(const std::string& s)
29
{
30
  std::string newS;
31
  newS.reserve(s.size());
32
  for (const char c : s)
33
  {
34
    switch (c)
35
    {
36
      case '\"': newS += "\\\""; break;
37
      case '>': newS += "\\>"; break;
38
      case '<': newS += "\\<"; break;
39
      case '{': newS += "\\{"; break;
40
      case '}': newS += "\\}"; break;
41
      case '|': newS += "\\|"; break;
42
      default: newS += c; break;
43
    }
44
  }
45
46
  return newS;
47
}
48
49
void DotPrinter::print(std::ostream& out, const ProofNode* pn)
50
{
51
  uint64_t ruleID = 0;
52
53
  // The dot attribute rankdir="BT" sets the direction of the graph layout,
54
  // placing the root node at the top. The "node [shape..." attribute sets the
55
  // shape of all nodes to record.
56
  out << "digraph proof {\n\trankdir=\"BT\";\n\tnode [shape=record];\n";
57
  DotPrinter::printInternal(out, pn, ruleID, 0, false);
58
  out << "}\n";
59
}
60
61
void DotPrinter::printInternal(std::ostream& out,
62
                               const ProofNode* pn,
63
                               uint64_t& ruleID,
64
                               uint64_t scopeCounter,
65
                               bool inPropositionalView)
66
{
67
  uint64_t currentRuleID = ruleID;
68
  const std::vector<std::shared_ptr<ProofNode>>& children = pn->getChildren();
69
  std::ostringstream currentArguments, resultStr, classes, colors;
70
71
  out << "\t" << currentRuleID << " [ label = \"{";
72
73
  resultStr << pn->getResult();
74
  std::string astring = resultStr.str();
75
  out << sanitizeString(astring);
76
77
  PfRule r = pn->getRule();
78
  DotPrinter::ruleArguments(currentArguments, pn);
79
  astring = currentArguments.str();
80
  out << "|" << r << sanitizeString(astring) << "}\"";
81
  classes << ", class = \"";
82
  colors << "";
83
84
  // set classes and colors, based on the view that the rule belongs
85
  switch (r)
86
  {
87
    case PfRule::SCOPE:
88
      if (scopeCounter < 1)
89
      {
90
        classes << " basic";
91
        colors << ", color = blue ";
92
        inPropositionalView = true;
93
      }
94
      scopeCounter++;
95
      break;
96
    case PfRule::ASSUME:
97
      // a node can belong to more than one view, so these if's must not be
98
      // exclusive
99
      if (scopeCounter < 2)
100
      {
101
        classes << " basic";
102
        colors << ", color = blue ";
103
      }
104
      if (inPropositionalView)
105
      {
106
        classes << " propositional";
107
        colors << ", fillcolor = aquamarine4, style = filled ";
108
      }
109
      break;
110
    case PfRule::CHAIN_RESOLUTION:
111
    case PfRule::FACTORING:
112
    case PfRule::REORDERING:
113
      if (inPropositionalView)
114
      {
115
        classes << " propositional";
116
        colors << ", fillcolor = aquamarine4, style = filled ";
117
      }
118
      break;
119
    default: inPropositionalView = false;
120
  }
121
  classes << " \"";
122
  out << classes.str() << colors.str();
123
  out << " ];\n";
124
125
  for (const std::shared_ptr<ProofNode>& c : children)
126
  {
127
    ++ruleID;
128
    out << "\t" << ruleID << " -> " << currentRuleID << ";\n";
129
    printInternal(out, c.get(), ruleID, scopeCounter, inPropositionalView);
130
  }
131
}
132
133
void DotPrinter::ruleArguments(std::ostringstream& currentArguments,
134
                               const ProofNode* pn)
135
{
136
  const std::vector<Node>& args = pn->getArguments();
137
  PfRule r = pn->getRule();
138
  // don't process arguments of rules whose conclusion is in the arguments
139
  if (!args.size() || r == PfRule::ASSUME || r == PfRule::REORDERING
140
      || r == PfRule::REFL)
141
  {
142
    return;
143
  }
144
  currentArguments << " :args [ ";
145
146
  // if cong, special process
147
  if (r == PfRule::CONG)
148
  {
149
    AlwaysAssert(args.size() == 1 || args.size() == 2);
150
    // if two arguments, ignore first and print second
151
    if (args.size() == 2)
152
    {
153
      currentArguments << args[1];
154
    }
155
    else
156
    {
157
      Kind k;
158
      ProofRuleChecker::getKind(args[0], k);
159
      currentArguments << printer::smt2::Smt2Printer::smtKindString(k);
160
    }
161
  }
162
  // if th_rw, likewise
163
  else if (r == PfRule::THEORY_REWRITE)
164
  {
165
    // print the second argument
166
    theory::TheoryId id;
167
    theory::builtin::BuiltinProofRuleChecker::getTheoryId(args[1], id);
168
    std::ostringstream ss;
169
    ss << id;
170
    std::string s = ss.str();
171
    // delete "THEORY_" prefix
172
    s.erase(0, 7);
173
    currentArguments << s;
174
  }
175
  else
176
  {
177
    currentArguments << args[0];
178
    for (size_t i = 1, size = args.size(); i < size; i++)
179
    {
180
      currentArguments << ", " << args[i];
181
    }
182
  }
183
  currentArguments << " ]";
184
}
185
186
}  // namespace proof
187
28191
}  // namespace cvc5