GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/proof/conv_seq_proof_generator.cpp Lines: 55 78 70.5 %
Date: 2021-08-06 Branches: 70 304 23.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds
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
 * Term conversion sequence proof generator utility.
14
 */
15
16
#include "proof/conv_seq_proof_generator.h"
17
18
#include <sstream>
19
20
#include "proof/proof_node_manager.h"
21
22
namespace cvc5 {
23
24
3784
TConvSeqProofGenerator::TConvSeqProofGenerator(
25
    ProofNodeManager* pnm,
26
    const std::vector<ProofGenerator*>& ts,
27
    context::Context* c,
28
3784
    std::string name)
29
3784
    : d_pnm(pnm), d_converted(c), d_name(name)
30
{
31
3784
  d_tconvs.insert(d_tconvs.end(), ts.begin(), ts.end());
32
3784
  AlwaysAssert(!d_tconvs.empty())
33
      << "TConvSeqProofGenerator::TConvSeqProofGenerator: expecting non-empty "
34
         "sequence";
35
3784
}
36
37
7568
TConvSeqProofGenerator::~TConvSeqProofGenerator() {}
38
39
5826
void TConvSeqProofGenerator::registerConvertedTerm(Node t, Node s, size_t index)
40
{
41
5826
  if (t == s)
42
  {
43
    // no need
44
    return;
45
  }
46
11652
  std::pair<Node, size_t> key = std::pair<Node, size_t>(t, index);
47
5826
  d_converted[key] = s;
48
}
49
50
365
std::shared_ptr<ProofNode> TConvSeqProofGenerator::getProofFor(Node f)
51
{
52
730
  Trace("tconv-seq-pf-gen")
53
730
      << "TConvSeqProofGenerator::getProofFor: " << identify() << ": " << f
54
365
      << std::endl;
55
365
  return getSubsequenceProofFor(f, 0, d_tconvs.size() - 1);
56
}
57
58
365
std::shared_ptr<ProofNode> TConvSeqProofGenerator::getSubsequenceProofFor(
59
    Node f, size_t start, size_t end)
60
{
61
365
  Assert(end < d_tconvs.size());
62
365
  if (f.getKind() != kind::EQUAL)
63
  {
64
    std::stringstream serr;
65
    serr << "TConvSeqProofGenerator::getProofFor: " << identify()
66
         << ": fail, non-equality " << f;
67
    Unhandled() << serr.str();
68
    Trace("tconv-seq-pf-gen") << serr.str() << std::endl;
69
    return nullptr;
70
  }
71
  // start with the left hand side of the equality
72
730
  Node curr = f[0];
73
  // proofs forming transitivity chain
74
730
  std::vector<std::shared_ptr<ProofNode>> transChildren;
75
730
  std::pair<Node, size_t> currKey;
76
365
  NodeIndexNodeMap::iterator itc;
77
  // convert the term in sequence
78
1095
  for (size_t i = start; i <= end; i++)
79
  {
80
730
    currKey = std::pair<Node, size_t>(curr, i);
81
730
    itc = d_converted.find(currKey);
82
    // if we provided a conversion at this index via registerConvertedTerm
83
730
    if (itc != d_converted.end())
84
    {
85
1460
      Node next = (*itc).second;
86
730
      Trace("tconv-seq-pf-gen") << "...convert to " << next << std::endl;
87
1460
      Node eq = curr.eqNode(next);
88
1460
      std::shared_ptr<ProofNode> pf = d_tconvs[i]->getProofFor(eq);
89
730
      transChildren.push_back(pf);
90
730
      curr = next;
91
    }
92
  }
93
  // should end up with the right hand side of the equality
94
365
  if (curr != f[1])
95
  {
96
    // unexpected
97
    std::stringstream serr;
98
    serr << "TConvSeqProofGenerator::getProofFor: " << identify()
99
         << ": failed, mismatch (see -t tconv-seq-pf-gen-debug for details)"
100
         << std::endl;
101
    serr << "                    source: " << f[0] << std::endl;
102
    serr << "expected after conversions: " << f[1] << std::endl;
103
    serr << "  actual after conversions: " << curr << std::endl;
104
105
    if (Trace.isOn("tconv-seq-pf-gen-debug"))
106
    {
107
      Trace("tconv-pf-gen-debug")
108
          << "Printing conversion steps..." << std::endl;
109
      serr << "Conversions: " << std::endl;
110
      for (NodeIndexNodeMap::const_iterator it = d_converted.begin();
111
           it != d_converted.end();
112
           ++it)
113
      {
114
        serr << "(" << (*it).first.first << ", " << (*it).first.second
115
             << ") -> " << (*it).second << std::endl;
116
      }
117
    }
118
    Unhandled() << serr.str();
119
    return nullptr;
120
  }
121
  // otherwise, make transitivity
122
365
  return d_pnm->mkTrans(transChildren, f);
123
}
124
125
80847
TrustNode TConvSeqProofGenerator::mkTrustRewriteSequence(
126
    const std::vector<Node>& cterms)
127
{
128
80847
  Assert(cterms.size() == d_tconvs.size() + 1);
129
80847
  if (cterms[0] == cterms[cterms.size() - 1])
130
  {
131
    return TrustNode::null();
132
  }
133
80847
  bool useThis = false;
134
80847
  ProofGenerator* pg = nullptr;
135
239628
  for (size_t i = 0, nconvs = d_tconvs.size(); i < nconvs; i++)
136
  {
137
161694
    if (cterms[i] == cterms[i + 1])
138
    {
139
77934
      continue;
140
    }
141
83760
    else if (pg == nullptr)
142
    {
143
      // Maybe the i^th generator can explain it alone, which must be the case
144
      // if there is only one position in the sequence where the term changes.
145
      // We may overwrite pg with this class if another step is encountered in
146
      // this loop.
147
80847
      pg = d_tconvs[i];
148
    }
149
    else
150
    {
151
      // need more than a single generator, use this class
152
2913
      useThis = true;
153
2913
      break;
154
    }
155
  }
156
80847
  if (useThis)
157
  {
158
2913
    pg = this;
159
    // if more than two steps, we must register each conversion step
160
8739
    for (size_t i = 0, nconvs = d_tconvs.size(); i < nconvs; i++)
161
    {
162
5826
      registerConvertedTerm(cterms[i], cterms[i + 1], i);
163
    }
164
  }
165
80847
  Assert(pg != nullptr);
166
80847
  return TrustNode::mkTrustRewrite(cterms[0], cterms[cterms.size() - 1], pg);
167
}
168
169
3579
std::string TConvSeqProofGenerator::identify() const { return d_name; }
170
171
29322
}  // namespace cvc5