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 "expr/tconv_seq_proof_generator.h" |
17 |
|
|
18 |
|
#include <sstream> |
19 |
|
|
20 |
|
#include "expr/proof_node_manager.h" |
21 |
|
|
22 |
|
namespace cvc5 { |
23 |
|
|
24 |
3130 |
TConvSeqProofGenerator::TConvSeqProofGenerator( |
25 |
|
ProofNodeManager* pnm, |
26 |
|
const std::vector<ProofGenerator*>& ts, |
27 |
|
context::Context* c, |
28 |
3130 |
std::string name) |
29 |
3130 |
: d_pnm(pnm), d_converted(c), d_name(name) |
30 |
|
{ |
31 |
3130 |
d_tconvs.insert(d_tconvs.end(), ts.begin(), ts.end()); |
32 |
3130 |
AlwaysAssert(!d_tconvs.empty()) |
33 |
|
<< "TConvSeqProofGenerator::TConvSeqProofGenerator: expecting non-empty " |
34 |
|
"sequence"; |
35 |
3130 |
} |
36 |
|
|
37 |
6260 |
TConvSeqProofGenerator::~TConvSeqProofGenerator() {} |
38 |
|
|
39 |
4418 |
void TConvSeqProofGenerator::registerConvertedTerm(Node t, Node s, size_t index) |
40 |
|
{ |
41 |
4418 |
if (t == s) |
42 |
|
{ |
43 |
|
// no need |
44 |
|
return; |
45 |
|
} |
46 |
8836 |
std::pair<Node, size_t> key = std::pair<Node, size_t>(t, index); |
47 |
4418 |
d_converted[key] = s; |
48 |
|
} |
49 |
|
|
50 |
370 |
std::shared_ptr<ProofNode> TConvSeqProofGenerator::getProofFor(Node f) |
51 |
|
{ |
52 |
740 |
Trace("tconv-seq-pf-gen") |
53 |
740 |
<< "TConvSeqProofGenerator::getProofFor: " << identify() << ": " << f |
54 |
370 |
<< std::endl; |
55 |
370 |
return getSubsequenceProofFor(f, 0, d_tconvs.size() - 1); |
56 |
|
} |
57 |
|
|
58 |
370 |
std::shared_ptr<ProofNode> TConvSeqProofGenerator::getSubsequenceProofFor( |
59 |
|
Node f, size_t start, size_t end) |
60 |
|
{ |
61 |
370 |
Assert(end < d_tconvs.size()); |
62 |
370 |
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 |
740 |
Node curr = f[0]; |
73 |
|
// proofs forming transitivity chain |
74 |
740 |
std::vector<std::shared_ptr<ProofNode>> transChildren; |
75 |
740 |
std::pair<Node, size_t> currKey; |
76 |
370 |
NodeIndexNodeMap::iterator itc; |
77 |
|
// convert the term in sequence |
78 |
1110 |
for (size_t i = start; i <= end; i++) |
79 |
|
{ |
80 |
740 |
currKey = std::pair<Node, size_t>(curr, i); |
81 |
740 |
itc = d_converted.find(currKey); |
82 |
|
// if we provided a conversion at this index via registerConvertedTerm |
83 |
740 |
if (itc != d_converted.end()) |
84 |
|
{ |
85 |
1480 |
Node next = (*itc).second; |
86 |
740 |
Trace("tconv-seq-pf-gen") << "...convert to " << next << std::endl; |
87 |
1480 |
Node eq = curr.eqNode(next); |
88 |
1480 |
std::shared_ptr<ProofNode> pf = d_tconvs[i]->getProofFor(eq); |
89 |
740 |
transChildren.push_back(pf); |
90 |
740 |
curr = next; |
91 |
|
} |
92 |
|
} |
93 |
|
// should end up with the right hand side of the equality |
94 |
370 |
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 |
370 |
return d_pnm->mkTrans(transChildren, f); |
123 |
|
} |
124 |
|
|
125 |
71677 |
theory::TrustNode TConvSeqProofGenerator::mkTrustRewriteSequence( |
126 |
|
const std::vector<Node>& cterms) |
127 |
|
{ |
128 |
71677 |
Assert(cterms.size() == d_tconvs.size() + 1); |
129 |
71677 |
if (cterms[0] == cterms[cterms.size() - 1]) |
130 |
|
{ |
131 |
|
return theory::TrustNode::null(); |
132 |
|
} |
133 |
71677 |
bool useThis = false; |
134 |
71677 |
ProofGenerator* pg = nullptr; |
135 |
212822 |
for (size_t i = 0, nconvs = d_tconvs.size(); i < nconvs; i++) |
136 |
|
{ |
137 |
143354 |
if (cterms[i] == cterms[i + 1]) |
138 |
|
{ |
139 |
69468 |
continue; |
140 |
|
} |
141 |
73886 |
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 |
71677 |
pg = d_tconvs[i]; |
148 |
|
} |
149 |
|
else |
150 |
|
{ |
151 |
|
// need more than a single generator, use this class |
152 |
2209 |
useThis = true; |
153 |
2209 |
break; |
154 |
|
} |
155 |
|
} |
156 |
71677 |
if (useThis) |
157 |
|
{ |
158 |
2209 |
pg = this; |
159 |
|
// if more than two steps, we must register each conversion step |
160 |
6627 |
for (size_t i = 0, nconvs = d_tconvs.size(); i < nconvs; i++) |
161 |
|
{ |
162 |
4418 |
registerConvertedTerm(cterms[i], cterms[i + 1], i); |
163 |
|
} |
164 |
|
} |
165 |
71677 |
Assert(pg != nullptr); |
166 |
|
return theory::TrustNode::mkTrustRewrite( |
167 |
71677 |
cterms[0], cterms[cterms.size() - 1], pg); |
168 |
|
} |
169 |
|
|
170 |
2787 |
std::string TConvSeqProofGenerator::identify() const { return d_name; } |
171 |
|
|
172 |
27735 |
} // namespace cvc5 |