1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Gereon Kremer, 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 |
|
* Datatypes inference manager. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/datatypes/inference_manager.h" |
17 |
|
|
18 |
|
#include "expr/dtype.h" |
19 |
|
#include "options/datatypes_options.h" |
20 |
|
#include "proof/eager_proof_generator.h" |
21 |
|
#include "smt/smt_statistics_registry.h" |
22 |
|
#include "theory/rewriter.h" |
23 |
|
#include "theory/theory.h" |
24 |
|
#include "theory/theory_state.h" |
25 |
|
#include "theory/trust_substitutions.h" |
26 |
|
|
27 |
|
using namespace cvc5::kind; |
28 |
|
|
29 |
|
namespace cvc5 { |
30 |
|
namespace theory { |
31 |
|
namespace datatypes { |
32 |
|
|
33 |
9924 |
InferenceManager::InferenceManager(Env& env, |
34 |
|
Theory& t, |
35 |
|
TheoryState& state, |
36 |
9924 |
ProofNodeManager* pnm) |
37 |
|
: InferenceManagerBuffered(env, t, state, pnm, "theory::datatypes::"), |
38 |
|
d_pnm(pnm), |
39 |
|
d_ipc(pnm == nullptr ? nullptr |
40 |
1243 |
: new InferProofCons(state.getSatContext(), pnm)), |
41 |
|
d_lemPg(pnm == nullptr |
42 |
|
? nullptr |
43 |
|
: new EagerProofGenerator( |
44 |
11167 |
pnm, state.getUserContext(), "datatypes::lemPg")) |
45 |
|
{ |
46 |
9924 |
d_false = NodeManager::currentNM()->mkConst(false); |
47 |
9924 |
} |
48 |
|
|
49 |
9921 |
InferenceManager::~InferenceManager() |
50 |
|
{ |
51 |
9921 |
} |
52 |
|
|
53 |
303194 |
void InferenceManager::addPendingInference(Node conc, |
54 |
|
InferenceId id, |
55 |
|
Node exp, |
56 |
|
bool forceLemma) |
57 |
|
{ |
58 |
|
// if we are forcing the inference to be processed as a lemma, or if the |
59 |
|
// inference must be sent as a lemma based on the policy in |
60 |
|
// mustCommunicateFact. |
61 |
303194 |
if (forceLemma || DatatypesInference::mustCommunicateFact(conc, exp)) |
62 |
|
{ |
63 |
22520 |
d_pendingLem.emplace_back(new DatatypesInference(this, conc, exp, id)); |
64 |
|
} |
65 |
|
else |
66 |
|
{ |
67 |
280674 |
d_pendingFact.emplace_back(new DatatypesInference(this, conc, exp, id)); |
68 |
|
} |
69 |
303194 |
} |
70 |
|
|
71 |
2605161 |
void InferenceManager::process() |
72 |
|
{ |
73 |
|
// if we are in conflict, immediately reset and clear pending |
74 |
2605161 |
if (d_theoryState.isInConflict()) |
75 |
|
{ |
76 |
11401 |
reset(); |
77 |
11401 |
clearPending(); |
78 |
11401 |
return; |
79 |
|
} |
80 |
|
// process pending lemmas, used infrequently, only for definitional lemmas |
81 |
2593760 |
doPendingLemmas(); |
82 |
|
// now process the pending facts |
83 |
2593760 |
doPendingFacts(); |
84 |
|
} |
85 |
|
|
86 |
1281 |
void InferenceManager::sendDtLemma(Node lem, InferenceId id, LemmaProperty p) |
87 |
|
{ |
88 |
1281 |
if (isProofEnabled()) |
89 |
|
{ |
90 |
182 |
TrustNode trn = processDtLemma(lem, Node::null(), id); |
91 |
91 |
trustedLemma(trn, id); |
92 |
91 |
return; |
93 |
|
} |
94 |
|
// otherwise send as a normal lemma directly |
95 |
1190 |
lemma(lem, id, p); |
96 |
|
} |
97 |
|
|
98 |
2470 |
void InferenceManager::sendDtConflict(const std::vector<Node>& conf, InferenceId id) |
99 |
|
{ |
100 |
2470 |
if (isProofEnabled()) |
101 |
|
{ |
102 |
372 |
Node exp = NodeManager::currentNM()->mkAnd(conf); |
103 |
186 |
prepareDtInference(d_false, exp, id, d_ipc.get()); |
104 |
|
} |
105 |
2470 |
conflictExp(id, conf, d_ipc.get()); |
106 |
2470 |
} |
107 |
|
|
108 |
348763 |
bool InferenceManager::isProofEnabled() const { return d_ipc != nullptr; } |
109 |
|
|
110 |
22456 |
TrustNode InferenceManager::processDtLemma(Node conc, Node exp, InferenceId id) |
111 |
|
{ |
112 |
|
// set up a proof constructor |
113 |
44912 |
std::shared_ptr<InferProofCons> ipcl; |
114 |
22456 |
if (isProofEnabled()) |
115 |
|
{ |
116 |
981 |
ipcl = std::make_shared<InferProofCons>(nullptr, d_pnm); |
117 |
|
} |
118 |
22456 |
conc = prepareDtInference(conc, exp, id, ipcl.get()); |
119 |
|
// send it as a lemma |
120 |
44912 |
Node lem; |
121 |
22456 |
if (!exp.isNull() && !exp.isConst()) |
122 |
|
{ |
123 |
21698 |
lem = NodeManager::currentNM()->mkNode(kind::IMPLIES, exp, conc); |
124 |
|
} |
125 |
|
else |
126 |
|
{ |
127 |
758 |
lem = conc; |
128 |
|
} |
129 |
22456 |
if (isProofEnabled()) |
130 |
|
{ |
131 |
|
// store its proof |
132 |
1962 |
std::shared_ptr<ProofNode> pbody = ipcl->getProofFor(conc); |
133 |
1962 |
std::shared_ptr<ProofNode> pn = pbody; |
134 |
981 |
if (!exp.isNull() && !exp.isConst()) |
135 |
|
{ |
136 |
1546 |
std::vector<Node> expv; |
137 |
773 |
expv.push_back(exp); |
138 |
773 |
pn = d_pnm->mkScope(pbody, expv); |
139 |
|
} |
140 |
981 |
d_lemPg->setProofFor(lem, pn); |
141 |
|
} |
142 |
44912 |
return TrustNode::mkTrustLemma(lem, d_lemPg.get()); |
143 |
|
} |
144 |
|
|
145 |
277458 |
Node InferenceManager::processDtFact(Node conc, |
146 |
|
Node exp, |
147 |
|
InferenceId id, |
148 |
|
ProofGenerator*& pg) |
149 |
|
{ |
150 |
277458 |
pg = d_ipc.get(); |
151 |
277458 |
return prepareDtInference(conc, exp, id, d_ipc.get()); |
152 |
|
} |
153 |
|
|
154 |
300100 |
Node InferenceManager::prepareDtInference(Node conc, |
155 |
|
Node exp, |
156 |
|
InferenceId id, |
157 |
|
InferProofCons* ipc) |
158 |
|
{ |
159 |
600200 |
Trace("dt-lemma-debug") << "prepareDtInference : " << conc << " via " << exp |
160 |
300100 |
<< " by " << id << std::endl; |
161 |
300100 |
if (conc.getKind() == EQUAL && conc[0].getType().isBoolean()) |
162 |
|
{ |
163 |
|
// must turn (= conc false) into (not conc) |
164 |
508 |
conc = Rewriter::rewrite(conc); |
165 |
|
} |
166 |
300100 |
if (isProofEnabled()) |
167 |
|
{ |
168 |
11381 |
Assert(ipc != nullptr); |
169 |
|
// If proofs are enabled, notify the proof constructor. |
170 |
|
// Notice that we have to reconstruct a datatypes inference here. This is |
171 |
|
// because the inference in the pending vector may be destroyed as we are |
172 |
|
// processing this inference, if we triggered to backtrack based on the |
173 |
|
// call below, since it is a unique pointer. |
174 |
|
std::shared_ptr<DatatypesInference> di = |
175 |
22762 |
std::make_shared<DatatypesInference>(this, conc, exp, id); |
176 |
11381 |
ipc->notifyFact(di); |
177 |
|
} |
178 |
300100 |
return conc; |
179 |
|
} |
180 |
|
|
181 |
|
} // namespace datatypes |
182 |
|
} // namespace theory |
183 |
29499 |
} // namespace cvc5 |