1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, 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 full model check class. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/fmf/full_model_check.h" |
17 |
|
|
18 |
|
#include "expr/skolem_manager.h" |
19 |
|
#include "options/quantifiers_options.h" |
20 |
|
#include "options/strings_options.h" |
21 |
|
#include "options/theory_options.h" |
22 |
|
#include "options/uf_options.h" |
23 |
|
#include "theory/quantifiers/first_order_model.h" |
24 |
|
#include "theory/quantifiers/fmf/bounded_integers.h" |
25 |
|
#include "theory/quantifiers/instantiate.h" |
26 |
|
#include "theory/quantifiers/quant_rep_bound_ext.h" |
27 |
|
#include "theory/quantifiers/quantifiers_inference_manager.h" |
28 |
|
#include "theory/quantifiers/quantifiers_registry.h" |
29 |
|
#include "theory/quantifiers/quantifiers_state.h" |
30 |
|
#include "theory/quantifiers/term_database.h" |
31 |
|
#include "theory/quantifiers/term_util.h" |
32 |
|
#include "theory/rewriter.h" |
33 |
|
|
34 |
|
using namespace cvc5::kind; |
35 |
|
using namespace cvc5::context; |
36 |
|
|
37 |
|
namespace cvc5 { |
38 |
|
namespace theory { |
39 |
|
namespace quantifiers { |
40 |
|
namespace fmcheck { |
41 |
|
|
42 |
185496 |
struct ModelBasisArgSort |
43 |
|
{ |
44 |
|
std::vector< Node > d_terms; |
45 |
|
// number of arguments that are model-basis terms |
46 |
|
std::unordered_map<Node, unsigned> d_mba_count; |
47 |
57185 |
bool operator() (int i,int j) { |
48 |
57185 |
return (d_mba_count[d_terms[i]] < d_mba_count[d_terms[j]]); |
49 |
|
} |
50 |
|
}; |
51 |
|
|
52 |
421758 |
bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) { |
53 |
421758 |
if (index==(int)c.getNumChildren()) { |
54 |
16404 |
return d_data!=-1; |
55 |
|
}else{ |
56 |
810708 |
TypeNode tn = c[index].getType(); |
57 |
810708 |
Node st = m->getStar(tn); |
58 |
405354 |
if(d_child.find(st)!=d_child.end()) { |
59 |
40498 |
if( d_child[st].hasGeneralization(m, c, index+1) ){ |
60 |
15196 |
return true; |
61 |
|
} |
62 |
|
} |
63 |
390158 |
if( c[index]!=st && d_child.find( c[index] )!=d_child.end() ){ |
64 |
56598 |
if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){ |
65 |
21642 |
return true; |
66 |
|
} |
67 |
|
} |
68 |
368516 |
if( c[index].getType().isSort() ){ |
69 |
|
//for star: check if all children are defined and have generalizations |
70 |
267760 |
if( c[index]==st ){ ///options::fmfFmcCoverSimplify() |
71 |
|
//check if all children exist and are complete |
72 |
|
unsigned num_child_def = |
73 |
154357 |
d_child.size() - (d_child.find(st) != d_child.end() ? 1 : 0); |
74 |
154357 |
if (num_child_def == m->getRepSet()->getNumRepresentatives(tn)) |
75 |
|
{ |
76 |
8587 |
bool complete = true; |
77 |
14791 |
for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
78 |
12538 |
if( !m->isStar(it->first) ){ |
79 |
12036 |
if( !it->second.hasGeneralization(m, c, index+1) ){ |
80 |
6334 |
complete = false; |
81 |
6334 |
break; |
82 |
|
} |
83 |
|
} |
84 |
|
} |
85 |
8587 |
if( complete ){ |
86 |
2253 |
return true; |
87 |
|
} |
88 |
|
} |
89 |
|
} |
90 |
|
} |
91 |
|
|
92 |
366263 |
return false; |
93 |
|
} |
94 |
|
} |
95 |
|
|
96 |
136475 |
int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index ) { |
97 |
136475 |
Debug("fmc-entry-trie") << "Get generalization index " << inst.size() << " " << index << std::endl; |
98 |
136475 |
if (index==(int)inst.size()) { |
99 |
40094 |
return d_data; |
100 |
|
}else{ |
101 |
96381 |
int minIndex = -1; |
102 |
192762 |
Node st = m->getStar(inst[index].getType()); |
103 |
96381 |
if (d_child.find(st) != d_child.end()) |
104 |
|
{ |
105 |
89911 |
minIndex = d_child[st].getGeneralizationIndex(m, inst, index + 1); |
106 |
|
} |
107 |
192762 |
Node cc = inst[index]; |
108 |
96381 |
if (cc != st && d_child.find(cc) != d_child.end()) |
109 |
|
{ |
110 |
12838 |
int gindex = d_child[cc].getGeneralizationIndex(m, inst, index + 1); |
111 |
12838 |
if (minIndex == -1 || (gindex != -1 && gindex < minIndex)) |
112 |
|
{ |
113 |
8811 |
minIndex = gindex; |
114 |
|
} |
115 |
|
} |
116 |
96381 |
return minIndex; |
117 |
|
} |
118 |
|
} |
119 |
|
|
120 |
781144 |
void EntryTrie::addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index ) { |
121 |
781144 |
if (index==(int)c.getNumChildren()) { |
122 |
299671 |
if(d_data==-1) { |
123 |
299671 |
d_data = data; |
124 |
|
} |
125 |
|
} |
126 |
|
else { |
127 |
481473 |
d_child[ c[index] ].addEntry(m,c,v,data,index+1); |
128 |
481473 |
if( d_complete==0 ){ |
129 |
|
d_complete = -1; |
130 |
|
} |
131 |
|
} |
132 |
781144 |
} |
133 |
|
|
134 |
336720 |
void EntryTrie::getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) { |
135 |
336720 |
if (index==(int)c.getNumChildren()) { |
136 |
70665 |
if( d_data!=-1) { |
137 |
70665 |
if( is_gen ){ |
138 |
64873 |
gen.push_back(d_data); |
139 |
|
} |
140 |
70665 |
compat.push_back(d_data); |
141 |
|
} |
142 |
|
}else{ |
143 |
266055 |
if (m->isStar(c[index])) { |
144 |
274011 |
for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
145 |
111730 |
it->second.getEntries(m, c, compat, gen, index+1, is_gen ); |
146 |
|
} |
147 |
|
}else{ |
148 |
207548 |
Node st = m->getStar(c[index].getType()); |
149 |
103774 |
if(d_child.find(st)!=d_child.end()) { |
150 |
7748 |
d_child[st].getEntries(m, c, compat, gen, index+1, false); |
151 |
|
} |
152 |
103774 |
if( d_child.find( c[index] )!=d_child.end() ){ |
153 |
30190 |
d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen); |
154 |
|
} |
155 |
|
} |
156 |
|
|
157 |
|
} |
158 |
336720 |
} |
159 |
|
|
160 |
312626 |
bool Def::addEntry( FirstOrderModelFmc * m, Node c, Node v) { |
161 |
312626 |
if (d_et.hasGeneralization(m, c)) { |
162 |
12955 |
Trace("fmc-debug") << "Already has generalization, skip." << std::endl; |
163 |
12955 |
return false; |
164 |
|
} |
165 |
299671 |
int newIndex = (int)d_cond.size(); |
166 |
299671 |
if (!d_has_simplified) { |
167 |
374104 |
std::vector<int> compat; |
168 |
374104 |
std::vector<int> gen; |
169 |
187052 |
d_et.getEntries(m, c, compat, gen); |
170 |
257717 |
for( unsigned i=0; i<compat.size(); i++) { |
171 |
70665 |
if( d_status[compat[i]]==status_unk ){ |
172 |
61753 |
if( d_value[compat[i]]!=v ){ |
173 |
38821 |
d_status[compat[i]] = status_non_redundant; |
174 |
|
} |
175 |
|
} |
176 |
|
} |
177 |
251925 |
for( unsigned i=0; i<gen.size(); i++) { |
178 |
64873 |
if( d_status[gen[i]]==status_unk ){ |
179 |
19268 |
if( d_value[gen[i]]==v ){ |
180 |
19268 |
d_status[gen[i]] = status_redundant; |
181 |
|
} |
182 |
|
} |
183 |
|
} |
184 |
187052 |
d_status.push_back( status_unk ); |
185 |
|
} |
186 |
299671 |
d_et.addEntry(m, c, v, newIndex); |
187 |
299671 |
d_cond.push_back(c); |
188 |
299671 |
d_value.push_back(v); |
189 |
299671 |
return true; |
190 |
|
} |
191 |
|
|
192 |
3259 |
Node Def::evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst ) { |
193 |
3259 |
int gindex = d_et.getGeneralizationIndex(m, inst); |
194 |
3259 |
if (gindex!=-1) { |
195 |
3255 |
return d_value[gindex]; |
196 |
|
}else{ |
197 |
4 |
Trace("fmc-warn") << "Warning : evaluation came up null!" << std::endl; |
198 |
4 |
return Node::null(); |
199 |
|
} |
200 |
|
} |
201 |
|
|
202 |
30467 |
int Def::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst ) { |
203 |
30467 |
return d_et.getGeneralizationIndex(m, inst); |
204 |
|
} |
205 |
|
|
206 |
68299 |
void Def::basic_simplify( FirstOrderModelFmc * m ) { |
207 |
68299 |
d_has_simplified = true; |
208 |
136598 |
std::vector< Node > cond; |
209 |
68299 |
cond.insert( cond.end(), d_cond.begin(), d_cond.end() ); |
210 |
68299 |
d_cond.clear(); |
211 |
136598 |
std::vector< Node > value; |
212 |
68299 |
value.insert( value.end(), d_value.begin(), d_value.end() ); |
213 |
68299 |
d_value.clear(); |
214 |
68299 |
d_et.reset(); |
215 |
200186 |
for (unsigned i=0; i<d_status.size(); i++) { |
216 |
131887 |
if( d_status[i]!=status_redundant ){ |
217 |
112619 |
addEntry(m, cond[i], value[i]); |
218 |
|
} |
219 |
|
} |
220 |
68299 |
d_status.clear(); |
221 |
68299 |
} |
222 |
|
|
223 |
62238 |
void Def::simplify(FullModelChecker * mc, FirstOrderModelFmc * m) { |
224 |
62238 |
Trace("fmc-simplify") << "Simplify definition, #cond = " << d_cond.size() << std::endl; |
225 |
62238 |
basic_simplify( m ); |
226 |
62238 |
Trace("fmc-simplify") << "post-basic simplify, #cond = " << d_cond.size() << std::endl; |
227 |
|
|
228 |
|
//check if the last entry is not all star, if so, we can make the last entry all stars |
229 |
62238 |
if( !d_cond.empty() ){ |
230 |
62238 |
bool last_all_stars = true; |
231 |
124476 |
Node cc = d_cond[d_cond.size()-1]; |
232 |
144793 |
for( unsigned i=0; i<cc.getNumChildren(); i++ ){ |
233 |
88616 |
if (!m->isStar(cc[i])) |
234 |
|
{ |
235 |
6061 |
last_all_stars = false; |
236 |
6061 |
break; |
237 |
|
} |
238 |
|
} |
239 |
62238 |
if( !last_all_stars ){ |
240 |
6061 |
Trace("fmc-cover-simplify") << "Need to modify last entry to be all stars." << std::endl; |
241 |
6061 |
Trace("fmc-cover-simplify") << "Before: " << std::endl; |
242 |
6061 |
debugPrint("fmc-cover-simplify",Node::null(), mc); |
243 |
6061 |
Trace("fmc-cover-simplify") << std::endl; |
244 |
12122 |
std::vector< Node > cond; |
245 |
6061 |
cond.insert( cond.end(), d_cond.begin(), d_cond.end() ); |
246 |
6061 |
d_cond.clear(); |
247 |
12122 |
std::vector< Node > value; |
248 |
6061 |
value.insert( value.end(), d_value.begin(), d_value.end() ); |
249 |
6061 |
d_value.clear(); |
250 |
6061 |
d_et.reset(); |
251 |
6061 |
d_has_simplified = false; |
252 |
|
//change the last to all star |
253 |
12122 |
std::vector< Node > nc; |
254 |
6061 |
nc.push_back( cc.getOperator() ); |
255 |
15732 |
for( unsigned j=0; j< cc.getNumChildren(); j++){ |
256 |
9671 |
nc.push_back(m->getStar(cc[j].getType())); |
257 |
|
} |
258 |
6061 |
cond[cond.size()-1] = NodeManager::currentNM()->mkNode( APPLY_UF, nc ); |
259 |
|
//re-add the entries |
260 |
17729 |
for (unsigned i=0; i<cond.size(); i++) { |
261 |
11668 |
addEntry(m, cond[i], value[i]); |
262 |
|
} |
263 |
6061 |
Trace("fmc-cover-simplify") << "Finished re-adding entries." << std::endl; |
264 |
6061 |
basic_simplify( m ); |
265 |
6061 |
Trace("fmc-cover-simplify") << "After: " << std::endl; |
266 |
6061 |
debugPrint("fmc-cover-simplify",Node::null(), mc); |
267 |
6061 |
Trace("fmc-cover-simplify") << std::endl; |
268 |
|
} |
269 |
|
} |
270 |
62238 |
Trace("fmc-simplify") << "finish simplify, #cond = " << d_cond.size() << std::endl; |
271 |
62238 |
} |
272 |
|
|
273 |
227601 |
void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) { |
274 |
227601 |
if (!op.isNull()) { |
275 |
38582 |
Trace(tr) << "Model for " << op << " : " << std::endl; |
276 |
|
} |
277 |
595690 |
for( unsigned i=0; i<d_cond.size(); i++) { |
278 |
|
//print the condition |
279 |
368089 |
if (!op.isNull()) { |
280 |
96312 |
Trace(tr) << op; |
281 |
|
} |
282 |
368089 |
m->debugPrintCond(tr, d_cond[i], true); |
283 |
368089 |
Trace(tr) << " -> "; |
284 |
368089 |
m->debugPrint(tr, d_value[i]); |
285 |
368089 |
Trace(tr) << std::endl; |
286 |
|
} |
287 |
227601 |
} |
288 |
|
|
289 |
1463 |
FullModelChecker::FullModelChecker(QuantifiersState& qs, |
290 |
|
QuantifiersInferenceManager& qim, |
291 |
|
QuantifiersRegistry& qr, |
292 |
1463 |
TermRegistry& tr) |
293 |
1463 |
: QModelBuilder(qs, qim, qr, tr), d_fm(new FirstOrderModelFmc(qs, qr, tr)) |
294 |
|
{ |
295 |
1463 |
d_true = NodeManager::currentNM()->mkConst(true); |
296 |
1463 |
d_false = NodeManager::currentNM()->mkConst(false); |
297 |
1463 |
} |
298 |
|
|
299 |
1463 |
void FullModelChecker::finishInit() { d_model = d_fm.get(); } |
300 |
|
|
301 |
2046 |
bool FullModelChecker::preProcessBuildModel(TheoryModel* m) { |
302 |
|
//standard pre-process |
303 |
2046 |
if( !preProcessBuildModelStd( m ) ){ |
304 |
|
return false; |
305 |
|
} |
306 |
|
|
307 |
2046 |
Trace("fmc") << "---Full Model Check preprocess() " << std::endl; |
308 |
2046 |
d_preinitialized_eqc.clear(); |
309 |
2046 |
d_preinitialized_types.clear(); |
310 |
|
//traverse equality engine |
311 |
2046 |
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(m->getEqualityEngine()); |
312 |
85596 |
while( !eqcs_i.isFinished() ){ |
313 |
83550 |
Node r = *eqcs_i; |
314 |
83550 |
TypeNode tr = r.getType(); |
315 |
41775 |
d_preinitialized_eqc[tr] = r; |
316 |
41775 |
++eqcs_i; |
317 |
|
} |
318 |
|
|
319 |
|
//must ensure model basis terms exists in model for each relevant type |
320 |
2046 |
Trace("fmc") << "preInitialize types..." << std::endl; |
321 |
2046 |
d_fm->initialize(); |
322 |
9267 |
for (std::pair<const Node, Def*>& mp : d_fm->d_models) |
323 |
|
{ |
324 |
14442 |
Node op = mp.first; |
325 |
7221 |
Trace("fmc") << "preInitialize types for " << op << std::endl; |
326 |
14442 |
TypeNode tno = op.getType(); |
327 |
26474 |
for( unsigned i=0; i<tno.getNumChildren(); i++) { |
328 |
19253 |
Trace("fmc") << "preInitializeType " << tno[i] << std::endl; |
329 |
19253 |
preInitializeType(m, tno[i]); |
330 |
19253 |
Trace("fmc") << "finished preInitializeType " << tno[i] << std::endl; |
331 |
|
} |
332 |
|
} |
333 |
2046 |
Trace("fmc") << "Finish preInitialize types" << std::endl; |
334 |
|
//do not have to introduce terms for sorts of domains of quantified formulas if we are allowed to assume empty sorts |
335 |
11211 |
for (unsigned i = 0, nquant = d_fm->getNumAssertedQuantifiers(); i < nquant; |
336 |
|
i++) |
337 |
|
{ |
338 |
18219 |
Node q = d_fm->getAssertedQuantifier(i); |
339 |
9165 |
registerQuantifiedFormula(q); |
340 |
9165 |
if (!isHandled(q)) |
341 |
|
{ |
342 |
111 |
continue; |
343 |
|
} |
344 |
|
// make sure all types are set |
345 |
22963 |
for (const Node& v : q[0]) |
346 |
|
{ |
347 |
13909 |
preInitializeType(m, v.getType()); |
348 |
|
} |
349 |
|
} |
350 |
2046 |
return true; |
351 |
|
} |
352 |
|
|
353 |
2046 |
bool FullModelChecker::processBuildModel(TheoryModel* m){ |
354 |
2046 |
if (!m->areFunctionValuesEnabled()) |
355 |
|
{ |
356 |
|
// nothing to do if no functions |
357 |
|
return true; |
358 |
|
} |
359 |
2046 |
FirstOrderModelFmc* fm = d_fm.get(); |
360 |
2046 |
Trace("fmc") << "---Full Model Check reset() " << std::endl; |
361 |
2046 |
d_quant_models.clear(); |
362 |
2046 |
d_rep_ids.clear(); |
363 |
2046 |
d_star_insts.clear(); |
364 |
|
//process representatives |
365 |
2046 |
RepSet* rs = m->getRepSetPtr(); |
366 |
8707 |
for (std::map<TypeNode, std::vector<Node> >::iterator it = |
367 |
2046 |
rs->d_type_reps.begin(); |
368 |
10753 |
it != rs->d_type_reps.end(); |
369 |
|
++it) |
370 |
|
{ |
371 |
8707 |
if( it->first.isSort() ){ |
372 |
1958 |
Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl; |
373 |
5649 |
for( size_t a=0; a<it->second.size(); a++ ){ |
374 |
7382 |
Node r = m->getRepresentative(it->second[a]); |
375 |
3691 |
if( Trace.isOn("fmc-model-debug") ){ |
376 |
|
std::vector< Node > eqc; |
377 |
|
d_qstate.getEquivalenceClass(r, eqc); |
378 |
|
Trace("fmc-model-debug") << " " << (it->second[a]==r); |
379 |
|
Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : "; |
380 |
|
//Trace("fmc-model-debug") << r2 << " : " << ir << " : "; |
381 |
|
Trace("fmc-model-debug") << " {"; |
382 |
|
for( size_t i=0; i<eqc.size(); i++ ){ |
383 |
|
Trace("fmc-model-debug") << eqc[i] << ", "; |
384 |
|
} |
385 |
|
Trace("fmc-model-debug") << "}" << std::endl; |
386 |
|
} |
387 |
3691 |
d_rep_ids[it->first][r] = (int)a; |
388 |
|
} |
389 |
1958 |
Trace("fmc-model-debug") << std::endl; |
390 |
|
} |
391 |
|
} |
392 |
|
|
393 |
|
//now, make models |
394 |
9267 |
for (std::pair<const Node, Def*>& fmm : d_fm->d_models) |
395 |
|
{ |
396 |
14442 |
Node op = fmm.first; |
397 |
|
//reset the model |
398 |
7221 |
d_fm->d_models[op]->reset(); |
399 |
|
|
400 |
14442 |
std::vector< Node > add_conds; |
401 |
14442 |
std::vector< Node > add_values; |
402 |
7221 |
bool needsDefault = true; |
403 |
7221 |
if (m->hasUfTerms(op)) |
404 |
|
{ |
405 |
5443 |
const std::vector<Node>& uft = m->getUfTerms(op); |
406 |
10886 |
Trace("fmc-model-debug") |
407 |
5443 |
<< uft.size() << " model values for " << op << " ... " << std::endl; |
408 |
36991 |
for (const Node& n : uft) |
409 |
|
{ |
410 |
|
// only consider unique up to congruence (in model equality engine)? |
411 |
31548 |
add_conds.push_back( n ); |
412 |
31548 |
add_values.push_back( n ); |
413 |
63096 |
Node r = m->getRepresentative(n); |
414 |
31548 |
Trace("fmc-model-debug") << n << " -> " << r << std::endl; |
415 |
|
} |
416 |
|
}else{ |
417 |
1778 |
Trace("fmc-model-debug") << "No model values for " << op << " ... " << std::endl; |
418 |
|
} |
419 |
7221 |
Trace("fmc-model-debug") << std::endl; |
420 |
|
//possibly get default |
421 |
7221 |
if( needsDefault ){ |
422 |
14442 |
Node nmb = d_fm->getModelBasisOpTerm(op); |
423 |
|
//add default value if necessary |
424 |
7221 |
if (m->hasTerm(nmb)) |
425 |
|
{ |
426 |
3879 |
Trace("fmc-model-debug") << "Add default " << nmb << std::endl; |
427 |
3879 |
add_conds.push_back( nmb ); |
428 |
3879 |
add_values.push_back( nmb ); |
429 |
|
}else{ |
430 |
6684 |
Node vmb = getSomeDomainElement(d_fm.get(), nmb.getType()); |
431 |
3342 |
Trace("fmc-model-debug") << "Add default to default representative " << nmb << " "; |
432 |
6684 |
Trace("fmc-model-debug") |
433 |
6684 |
<< m->getRepSet()->getNumRepresentatives(nmb.getType()) |
434 |
3342 |
<< std::endl; |
435 |
3342 |
add_conds.push_back( nmb ); |
436 |
3342 |
add_values.push_back( vmb ); |
437 |
|
} |
438 |
|
} |
439 |
|
|
440 |
14442 |
std::vector< Node > conds; |
441 |
14442 |
std::vector< Node > values; |
442 |
14442 |
std::vector< Node > entry_conds; |
443 |
|
//get the entries for the model |
444 |
45990 |
for( size_t i=0; i<add_conds.size(); i++ ){ |
445 |
77538 |
Node c = add_conds[i]; |
446 |
77538 |
Node v = add_values[i]; |
447 |
77538 |
Trace("fmc-model-debug") |
448 |
38769 |
<< "Add cond/value : " << c << " -> " << v << std::endl; |
449 |
77538 |
std::vector< Node > children; |
450 |
77538 |
std::vector< Node > entry_children; |
451 |
38769 |
children.push_back(op); |
452 |
38769 |
entry_children.push_back(op); |
453 |
38769 |
bool hasNonStar = false; |
454 |
113799 |
for (const Node& ci : c) |
455 |
|
{ |
456 |
150060 |
Node ri = fm->getRepresentative(ci); |
457 |
75030 |
children.push_back(ri); |
458 |
75030 |
bool isStar = false; |
459 |
75030 |
if (fm->isModelBasisTerm(ri)) |
460 |
|
{ |
461 |
21596 |
ri = fm->getStar(ri.getType()); |
462 |
21596 |
isStar = true; |
463 |
|
} |
464 |
|
else |
465 |
|
{ |
466 |
53434 |
hasNonStar = true; |
467 |
|
} |
468 |
75030 |
if( !isStar && !ri.isConst() ){ |
469 |
|
Trace("fmc-warn") << "Warning : model for " << op |
470 |
|
<< " has non-constant argument in model " << ri |
471 |
|
<< " (from " << ci << ")" << std::endl; |
472 |
|
Assert(false); |
473 |
|
} |
474 |
75030 |
entry_children.push_back(ri); |
475 |
|
} |
476 |
77538 |
Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children ); |
477 |
77538 |
Node nv = fm->getRepresentative( v ); |
478 |
77538 |
Trace("fmc-model-debug") |
479 |
38769 |
<< "Representative of " << v << " is " << nv << std::endl; |
480 |
38769 |
if( !nv.isConst() ){ |
481 |
|
Trace("fmc-warn") << "Warning : model for " << op << " has non-constant value in model " << nv << std::endl; |
482 |
|
Assert(false); |
483 |
|
} |
484 |
77538 |
Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children ); |
485 |
38769 |
if( std::find(conds.begin(), conds.end(), n )==conds.end() ){ |
486 |
24405 |
Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl; |
487 |
24405 |
conds.push_back(n); |
488 |
24405 |
values.push_back(nv); |
489 |
24405 |
entry_conds.push_back(en); |
490 |
|
} |
491 |
|
else { |
492 |
14364 |
Trace("fmc-model-debug") << "Already have entry for : " << n << " -> " << nv << " (entry is " << en << ")" << std::endl; |
493 |
|
} |
494 |
|
} |
495 |
|
|
496 |
|
|
497 |
|
//sort based on # default arguments |
498 |
14442 |
std::vector< int > indices; |
499 |
14442 |
ModelBasisArgSort mbas; |
500 |
31626 |
for (int i=0; i<(int)conds.size(); i++) { |
501 |
24405 |
mbas.d_terms.push_back(conds[i]); |
502 |
24405 |
mbas.d_mba_count[conds[i]] = fm->getModelBasisArg(conds[i]); |
503 |
24405 |
indices.push_back(i); |
504 |
|
} |
505 |
7221 |
std::sort( indices.begin(), indices.end(), mbas ); |
506 |
|
|
507 |
31626 |
for (int i=0; i<(int)indices.size(); i++) { |
508 |
24405 |
fm->d_models[op]->addEntry(fm, entry_conds[indices[i]], values[indices[i]]); |
509 |
|
} |
510 |
|
|
511 |
7221 |
Trace("fmc-model-simplify") << "Before simplification : " << std::endl; |
512 |
7221 |
fm->d_models[op]->debugPrint("fmc-model-simplify", op, this); |
513 |
7221 |
Trace("fmc-model-simplify") << std::endl; |
514 |
|
|
515 |
7221 |
Trace("fmc-model-simplify") << "Simplifying " << op << "..." << std::endl; |
516 |
7221 |
fm->d_models[op]->simplify( this, fm ); |
517 |
|
|
518 |
7221 |
fm->d_models[op]->debugPrint("fmc-model", op, this); |
519 |
7221 |
Trace("fmc-model") << std::endl; |
520 |
|
|
521 |
|
//for debugging |
522 |
|
/* |
523 |
|
for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){ |
524 |
|
std::vector< Node > inst; |
525 |
|
for( unsigned j=0; j<fm->d_uf_terms[op][i].getNumChildren(); j++ ){ |
526 |
|
Node r = fm->getRepresentative( fm->d_uf_terms[op][i][j] ); |
527 |
|
inst.push_back( r ); |
528 |
|
} |
529 |
|
Node ev = fm->d_models[op]->evaluate( fm, inst ); |
530 |
|
Trace("fmc-model-debug") << ".....Checking eval( " << |
531 |
|
fm->d_uf_terms[op][i] << " ) = " << ev << std::endl; AlwaysAssert( |
532 |
|
fm->areEqual( ev, fm->d_uf_terms[op][i] ) ); |
533 |
|
} |
534 |
|
*/ |
535 |
|
} |
536 |
2046 |
Assert(d_addedLemmas == 0); |
537 |
|
|
538 |
|
//make function values |
539 |
9267 |
for( std::map<Node, Def * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ){ |
540 |
14442 |
Node f_def = getFunctionValue( fm, it->first, "$x" ); |
541 |
7221 |
m->assignFunctionDefinition( it->first, f_def ); |
542 |
|
} |
543 |
2046 |
return TheoryEngineModelBuilder::processBuildModel( m ); |
544 |
|
} |
545 |
|
|
546 |
33162 |
void FullModelChecker::preInitializeType(TheoryModel* m, TypeNode tn) |
547 |
|
{ |
548 |
33162 |
if( d_preinitialized_types.find( tn )==d_preinitialized_types.end() ){ |
549 |
4871 |
d_preinitialized_types[tn] = true; |
550 |
4871 |
if (tn.isFirstClass()) |
551 |
|
{ |
552 |
4865 |
Trace("fmc") << "Get model basis term " << tn << "..." << std::endl; |
553 |
9730 |
Node mb = d_fm->getModelBasisTerm(tn); |
554 |
4865 |
Trace("fmc") << "...return " << mb << std::endl; |
555 |
|
// if the model basis term does not exist in the model, |
556 |
|
// either add it directly to the model's equality engine if no other terms |
557 |
|
// of this type exist, or otherwise assert that it is equal to the first |
558 |
|
// equivalence class of its type. |
559 |
4865 |
if (!m->hasTerm(mb) && !mb.isConst()) |
560 |
|
{ |
561 |
558 |
std::map<TypeNode, Node>::iterator itpe = d_preinitialized_eqc.find(tn); |
562 |
558 |
if (itpe == d_preinitialized_eqc.end()) |
563 |
|
{ |
564 |
528 |
Trace("fmc") << "...add model basis term to EE of model " << mb << " " |
565 |
264 |
<< tn << std::endl; |
566 |
264 |
m->getEqualityEngine()->addTerm(mb); |
567 |
|
} |
568 |
|
else |
569 |
|
{ |
570 |
588 |
Trace("fmc") << "...add model basis eqc equality to model " << mb |
571 |
294 |
<< " == " << itpe->second << " " << tn << std::endl; |
572 |
294 |
bool ret = m->assertEquality(mb, itpe->second, true); |
573 |
294 |
AlwaysAssert(ret); |
574 |
|
} |
575 |
|
} |
576 |
|
} |
577 |
|
} |
578 |
33162 |
} |
579 |
|
|
580 |
373302 |
void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) { |
581 |
373302 |
Trace(tr) << "("; |
582 |
960205 |
for( unsigned j=0; j<n.getNumChildren(); j++) { |
583 |
586903 |
if( j>0 ) Trace(tr) << ", "; |
584 |
586903 |
debugPrint(tr, n[j], dispStar); |
585 |
|
} |
586 |
373302 |
Trace(tr) << ")"; |
587 |
373302 |
} |
588 |
|
|
589 |
1473063 |
void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) { |
590 |
1473063 |
if( n.isNull() ){ |
591 |
32717 |
Trace(tr) << "null"; |
592 |
|
} |
593 |
1440346 |
else if (FirstOrderModelFmc::isStar(n) && dispStar) |
594 |
|
{ |
595 |
696384 |
Trace(tr) << "*"; |
596 |
|
} |
597 |
|
else |
598 |
|
{ |
599 |
1487924 |
TypeNode tn = n.getType(); |
600 |
743962 |
if( tn.isSort() && d_rep_ids.find(tn)!=d_rep_ids.end() ){ |
601 |
348651 |
if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) { |
602 |
326381 |
Trace(tr) << d_rep_ids[tn][n]; |
603 |
|
}else{ |
604 |
22270 |
Trace(tr) << n; |
605 |
|
} |
606 |
|
}else{ |
607 |
395311 |
Trace(tr) << n; |
608 |
|
} |
609 |
|
} |
610 |
1473063 |
} |
611 |
|
|
612 |
|
|
613 |
11605 |
int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { |
614 |
11605 |
Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl; |
615 |
|
// register the quantifier |
616 |
11605 |
registerQuantifiedFormula(f); |
617 |
11605 |
Assert(!d_qstate.isInConflict()); |
618 |
|
// we do not do model-based quantifier instantiation if the option |
619 |
|
// disables it, or if the quantified formula has an unhandled type. |
620 |
11605 |
if (!optUseModel() || !isHandled(f)) |
621 |
|
{ |
622 |
|
return 0; |
623 |
|
} |
624 |
11605 |
FirstOrderModelFmc* fmfmc = static_cast<FirstOrderModelFmc*>(fm); |
625 |
11605 |
if (effort == 0) |
626 |
|
{ |
627 |
8786 |
if (options::mbqiMode() == options::MbqiMode::NONE) |
628 |
|
{ |
629 |
|
// just exhaustive instantiate |
630 |
4332 |
Node c = mkCondDefault(fmfmc, f); |
631 |
2166 |
d_quant_models[f].addEntry(fmfmc, c, d_false); |
632 |
2166 |
if (!exhaustiveInstantiate(fmfmc, f, c)) |
633 |
|
{ |
634 |
20 |
return 0; |
635 |
|
} |
636 |
2146 |
return 1; |
637 |
|
} |
638 |
|
// model check the quantifier |
639 |
6620 |
doCheck(fmfmc, f, d_quant_models[f], f[1]); |
640 |
6620 |
std::vector<Node>& mcond = d_quant_models[f].d_cond; |
641 |
6620 |
Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl; |
642 |
6620 |
Assert(!mcond.empty()); |
643 |
6620 |
d_quant_models[f].debugPrint("fmc", Node::null(), this); |
644 |
6620 |
Trace("fmc") << std::endl; |
645 |
|
|
646 |
|
// consider all entries going to non-true |
647 |
6620 |
Instantiate* instq = d_qim.getInstantiate(); |
648 |
15237 |
for (unsigned i = 0, msize = mcond.size(); i < msize; i++) |
649 |
|
{ |
650 |
8617 |
if (d_quant_models[f].d_value[i] == d_true) |
651 |
|
{ |
652 |
|
// already satisfied |
653 |
11296 |
continue; |
654 |
|
} |
655 |
7290 |
Trace("fmc-inst") << "Instantiate based on " << mcond[i] << "..." |
656 |
3645 |
<< std::endl; |
657 |
3645 |
bool hasStar = false; |
658 |
5938 |
std::vector<Node> inst; |
659 |
9049 |
for (unsigned j = 0, nchild = mcond[i].getNumChildren(); j < nchild; j++) |
660 |
|
{ |
661 |
5404 |
if (fmfmc->isStar(mcond[i][j])) |
662 |
|
{ |
663 |
4405 |
hasStar = true; |
664 |
4405 |
inst.push_back(fmfmc->getModelBasisTerm(mcond[i][j].getType())); |
665 |
|
} |
666 |
|
else |
667 |
|
{ |
668 |
999 |
inst.push_back(mcond[i][j]); |
669 |
|
} |
670 |
|
} |
671 |
3645 |
bool addInst = true; |
672 |
3645 |
if (hasStar) |
673 |
|
{ |
674 |
|
// try obvious (specified by inst) |
675 |
6518 |
Node ev = d_quant_models[f].evaluate(fmfmc, inst); |
676 |
3259 |
if (ev == d_true) |
677 |
|
{ |
678 |
9 |
addInst = false; |
679 |
18 |
Trace("fmc-debug") |
680 |
9 |
<< "...do not instantiate, evaluation was " << ev << std::endl; |
681 |
|
} |
682 |
|
} |
683 |
|
else |
684 |
|
{ |
685 |
|
// for debugging |
686 |
386 |
if (Trace.isOn("fmc-test-inst")) |
687 |
|
{ |
688 |
|
Node ev = d_quant_models[f].evaluate(fmfmc, inst); |
689 |
|
if (ev == d_true) |
690 |
|
{ |
691 |
|
CVC5Message() << "WARNING: instantiation was true! " << f << " " |
692 |
|
<< mcond[i] << std::endl; |
693 |
|
AlwaysAssert(false); |
694 |
|
} |
695 |
|
else |
696 |
|
{ |
697 |
|
Trace("fmc-test-inst") |
698 |
|
<< "...instantiation evaluated to false." << std::endl; |
699 |
|
} |
700 |
|
} |
701 |
|
} |
702 |
3654 |
if (!addInst) |
703 |
|
{ |
704 |
18 |
Trace("fmc-debug-inst") |
705 |
9 |
<< "** Instantiation was already true." << std::endl; |
706 |
|
// might try it next effort level |
707 |
9 |
d_star_insts[f].push_back(i); |
708 |
9 |
continue; |
709 |
|
} |
710 |
3636 |
if (options::fmfBound() || options::stringExp()) |
711 |
|
{ |
712 |
2686 |
std::vector<Node> cond; |
713 |
1343 |
cond.push_back(d_quant_cond[f]); |
714 |
1343 |
cond.insert(cond.end(), inst.begin(), inst.end()); |
715 |
|
// need to do exhaustive instantiate algorithm to set things properly |
716 |
|
// (should only add one instance) |
717 |
2686 |
Node c = mkCond(cond); |
718 |
1343 |
unsigned prevInst = d_addedLemmas; |
719 |
1343 |
exhaustiveInstantiate(fmfmc, f, c); |
720 |
1343 |
if (d_addedLemmas == prevInst) |
721 |
|
{ |
722 |
1026 |
d_star_insts[f].push_back(i); |
723 |
|
} |
724 |
1343 |
continue; |
725 |
|
} |
726 |
|
// just add the instance |
727 |
2293 |
d_triedLemmas++; |
728 |
4586 |
if (instq->addInstantiation(f, |
729 |
|
inst, |
730 |
|
InferenceId::QUANTIFIERS_INST_FMF_FMC, |
731 |
4586 |
Node::null(), |
732 |
|
true)) |
733 |
|
{ |
734 |
758 |
Trace("fmc-debug-inst") << "** Added instantiation." << std::endl; |
735 |
758 |
d_addedLemmas++; |
736 |
758 |
if (d_qstate.isInConflict() || options::fmfOneInstPerRound()) |
737 |
|
{ |
738 |
|
break; |
739 |
|
} |
740 |
|
} |
741 |
|
else |
742 |
|
{ |
743 |
3070 |
Trace("fmc-debug-inst") |
744 |
1535 |
<< "** Instantiation was duplicate." << std::endl; |
745 |
|
// might try it next effort level |
746 |
1535 |
d_star_insts[f].push_back(i); |
747 |
|
} |
748 |
|
} |
749 |
6620 |
return 1; |
750 |
|
} |
751 |
|
// Get the list of instantiation regions (described by "star entries" in the |
752 |
|
// definition) that were not tried at the previous effort level. For each |
753 |
|
// of these, we add one instantiation. |
754 |
2819 |
std::vector<Node>& mcond = d_quant_models[f].d_cond; |
755 |
2819 |
if (!d_star_insts[f].empty()) |
756 |
|
{ |
757 |
1629 |
if (Trace.isOn("fmc-exh")) |
758 |
|
{ |
759 |
|
Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl; |
760 |
|
Trace("fmc-exh") << "Definition was : " << std::endl; |
761 |
|
d_quant_models[f].debugPrint("fmc-exh", Node::null(), this); |
762 |
|
Trace("fmc-exh") << std::endl; |
763 |
|
} |
764 |
3225 |
Def temp; |
765 |
|
// simplify the exceptions? |
766 |
3354 |
for (int i = (d_star_insts[f].size() - 1); i >= 0; i--) |
767 |
|
{ |
768 |
|
// get witness for d_star_insts[f][i] |
769 |
1758 |
int j = d_star_insts[f][i]; |
770 |
1758 |
if (temp.addEntry(fmfmc, mcond[j], d_quant_models[f].d_value[j])) |
771 |
|
{ |
772 |
1704 |
if (!exhaustiveInstantiate(fmfmc, f, mcond[j])) |
773 |
|
{ |
774 |
|
// something went wrong, resort to exhaustive instantiation |
775 |
33 |
return 0; |
776 |
|
} |
777 |
|
} |
778 |
|
} |
779 |
|
} |
780 |
2786 |
return 1; |
781 |
|
} |
782 |
|
|
783 |
|
/** Representative bound fmc entry |
784 |
|
* |
785 |
|
* This bound information corresponds to one |
786 |
|
* entry in a term definition (see terminology in |
787 |
|
* Chapter 5 of Finite Model Finding for |
788 |
|
* Satisfiability Modulo Theories thesis). |
789 |
|
* For example, a term definition for the body |
790 |
|
* of a quantified formula: |
791 |
|
* forall xyz. P( x, y, z ) |
792 |
|
* may be: |
793 |
|
* ( 0, 0, 0 ) -> false |
794 |
|
* ( *, 1, 2 ) -> false |
795 |
|
* ( *, *, * ) -> true |
796 |
|
* Indicating that the quantified formula evaluates |
797 |
|
* to false in the current model for x=0, y=0, z=0, |
798 |
|
* or y=1, z=2 for any x, and evaluates to true |
799 |
|
* otherwise. |
800 |
|
* This class is used if we wish |
801 |
|
* to iterate over all values corresponding to one |
802 |
|
* of these entries. For example, for the second entry: |
803 |
|
* (*, 1, 2 ) |
804 |
|
* we iterate over all values of x, but only {1} |
805 |
|
* for y and {2} for z. |
806 |
|
*/ |
807 |
|
class RepBoundFmcEntry : public QRepBoundExt |
808 |
|
{ |
809 |
|
public: |
810 |
5213 |
RepBoundFmcEntry(QuantifiersBoundInference& qbi, |
811 |
|
Node e, |
812 |
|
FirstOrderModelFmc* f) |
813 |
5213 |
: QRepBoundExt(qbi, f), d_entry(e), d_fm(f) |
814 |
|
{ |
815 |
5213 |
} |
816 |
5213 |
~RepBoundFmcEntry() {} |
817 |
|
/** set bound */ |
818 |
7082 |
virtual RsiEnumType setBound(Node owner, |
819 |
|
unsigned i, |
820 |
|
std::vector<Node>& elements) override |
821 |
|
{ |
822 |
7082 |
if (!d_fm->isStar(d_entry[i])) |
823 |
|
{ |
824 |
|
// only need to consider the single point |
825 |
1756 |
elements.push_back(d_entry[i]); |
826 |
1756 |
return ENUM_DEFAULT; |
827 |
|
} |
828 |
5326 |
return QRepBoundExt::setBound(owner, i, elements); |
829 |
|
} |
830 |
|
|
831 |
|
private: |
832 |
|
/** the entry for this bound */ |
833 |
|
Node d_entry; |
834 |
|
/** the model builder associated with this bound */ |
835 |
|
FirstOrderModelFmc* d_fm; |
836 |
|
}; |
837 |
|
|
838 |
5213 |
bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc* fm, |
839 |
|
Node f, |
840 |
|
Node c) |
841 |
|
{ |
842 |
5213 |
Trace("fmc-exh") << "----Exhaustive instantiate based on " << c << " "; |
843 |
5213 |
debugPrintCond("fmc-exh", c, true); |
844 |
5213 |
Trace("fmc-exh")<< std::endl; |
845 |
5213 |
QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference(); |
846 |
10426 |
RepBoundFmcEntry rbfe(qbi, c, fm); |
847 |
10426 |
RepSetIterator riter(fm->getRepSet(), &rbfe); |
848 |
5213 |
Trace("fmc-exh-debug") << "Set quantifier..." << std::endl; |
849 |
|
//initialize |
850 |
5213 |
if (riter.setQuantifier(f)) |
851 |
|
{ |
852 |
5213 |
Trace("fmc-exh-debug") << "Set element domains..." << std::endl; |
853 |
5213 |
int addedLemmas = 0; |
854 |
|
//now do full iteration |
855 |
5213 |
Instantiate* ie = d_qim.getInstantiate(); |
856 |
66147 |
while( !riter.isFinished() ){ |
857 |
30467 |
d_triedLemmas++; |
858 |
30467 |
Trace("fmc-exh-debug") << "Inst : "; |
859 |
60934 |
std::vector< Node > ev_inst; |
860 |
60934 |
std::vector< Node > inst; |
861 |
106104 |
for (unsigned i = 0; i < riter.getNumTerms(); i++) |
862 |
|
{ |
863 |
151274 |
TypeNode tn = riter.getTypeOf(i); |
864 |
|
// if the type is not closed enumerable (see |
865 |
|
// TypeNode::isClosedEnumerable), then we must ensure that we are |
866 |
|
// using a term and not a value. This ensures that e.g. uninterpreted |
867 |
|
// constants do not appear in instantiations. |
868 |
151274 |
Node rr = riter.getCurrentTerm(i, !tn.isClosedEnumerable()); |
869 |
151274 |
Node r = fm->getRepresentative(rr); |
870 |
75637 |
debugPrint("fmc-exh-debug", r); |
871 |
75637 |
Trace("fmc-exh-debug") << " (term : " << rr << ")"; |
872 |
75637 |
ev_inst.push_back( r ); |
873 |
75637 |
inst.push_back( rr ); |
874 |
|
} |
875 |
30467 |
int ev_index = d_quant_models[f].getGeneralizationIndex(fm, ev_inst); |
876 |
30467 |
Trace("fmc-exh-debug") << ", index = " << ev_index << " / " << d_quant_models[f].d_value.size(); |
877 |
60934 |
Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index]; |
878 |
30467 |
if (ev!=d_true) { |
879 |
27737 |
Trace("fmc-exh-debug") << ", add!"; |
880 |
|
//add as instantiation |
881 |
55474 |
if (ie->addInstantiation(f, |
882 |
|
inst, |
883 |
|
InferenceId::QUANTIFIERS_INST_FMF_FMC_EXH, |
884 |
55474 |
Node::null(), |
885 |
|
true)) |
886 |
|
{ |
887 |
5002 |
Trace("fmc-exh-debug") << " ...success."; |
888 |
5002 |
addedLemmas++; |
889 |
5002 |
if (d_qstate.isInConflict() || options::fmfOneInstPerRound()) |
890 |
|
{ |
891 |
|
break; |
892 |
|
} |
893 |
|
}else{ |
894 |
22735 |
Trace("fmc-exh-debug") << ", failed."; |
895 |
|
} |
896 |
|
}else{ |
897 |
2730 |
Trace("fmc-exh-debug") << ", already true"; |
898 |
|
} |
899 |
30467 |
Trace("fmc-exh-debug") << std::endl; |
900 |
30467 |
int index = riter.increment(); |
901 |
30467 |
Trace("fmc-exh-debug") << "Incremented index " << index << std::endl; |
902 |
30467 |
if( !riter.isFinished() ){ |
903 |
78657 |
if (index >= 0 && riter.d_index[index] > 0 && addedLemmas > 0 |
904 |
32772 |
&& riter.d_enum_type[index] == ENUM_CUSTOM) |
905 |
|
{ |
906 |
2794 |
Trace("fmc-exh-debug") |
907 |
1397 |
<< "Since this is a custom enumeration, skip to the next..." |
908 |
1397 |
<< std::endl; |
909 |
1397 |
riter.incrementAtIndex(index - 1); |
910 |
|
} |
911 |
|
} |
912 |
|
} |
913 |
5213 |
d_addedLemmas += addedLemmas; |
914 |
5213 |
Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.isIncomplete() << std::endl; |
915 |
5213 |
return addedLemmas>0 || !riter.isIncomplete(); |
916 |
|
}else{ |
917 |
|
Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl; |
918 |
|
return !riter.isIncomplete(); |
919 |
|
} |
920 |
|
} |
921 |
|
|
922 |
115260 |
void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n ) { |
923 |
115260 |
Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl; |
924 |
|
//first check if it is a bounding literal |
925 |
115260 |
if( n.hasAttribute(BoundIntLitAttribute()) ){ |
926 |
2812 |
Trace("fmc-debug") << "It is a bounding literal, polarity = " << n.getAttribute(BoundIntLitAttribute()) << std::endl; |
927 |
2812 |
d.addEntry(fm, mkCondDefault(fm, f), n.getAttribute(BoundIntLitAttribute())==1 ? d_false : d_true ); |
928 |
112448 |
}else if( n.getKind() == kind::BOUND_VARIABLE ){ |
929 |
25951 |
Trace("fmc-debug") << "Add default entry..." << std::endl; |
930 |
25951 |
d.addEntry(fm, mkCondDefault(fm, f), n); |
931 |
|
} |
932 |
86497 |
else if( n.getKind() == kind::NOT ){ |
933 |
|
//just do directly |
934 |
8948 |
doCheck( fm, f, d, n[0] ); |
935 |
8948 |
doNegate( d ); |
936 |
|
} |
937 |
77549 |
else if( n.getKind() == kind::FORALL ){ |
938 |
1998 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
939 |
|
} |
940 |
75551 |
else if( n.getType().isArray() ){ |
941 |
|
//Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl; |
942 |
|
//Trace("fmc-warn") << " Default value was : " << odefaultValue << std::endl; |
943 |
|
//Trace("fmc-debug") << "Can't process base array " << r << std::endl; |
944 |
|
//can't process this array |
945 |
452 |
d.reset(); |
946 |
452 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
947 |
|
} |
948 |
75099 |
else if( n.getNumChildren()==0 ){ |
949 |
40164 |
Node r = n; |
950 |
20082 |
if( !n.isConst() ){ |
951 |
17156 |
TypeNode tn = n.getType(); |
952 |
8578 |
if( !fm->hasTerm(n) && tn.isFirstClass() ){ |
953 |
185 |
r = getSomeDomainElement(fm, tn ); |
954 |
|
} |
955 |
8578 |
r = fm->getRepresentative( r ); |
956 |
|
} |
957 |
20082 |
Trace("fmc-debug") << "Add constant entry..." << std::endl; |
958 |
20082 |
d.addEntry(fm, mkCondDefault(fm, f), r); |
959 |
|
} |
960 |
|
else{ |
961 |
110034 |
std::vector< int > var_ch; |
962 |
110034 |
std::vector< Def > children; |
963 |
154709 |
for( int i=0; i<(int)n.getNumChildren(); i++) { |
964 |
199384 |
Def dc; |
965 |
99692 |
doCheck(fm, f, dc, n[i]); |
966 |
99692 |
children.push_back(dc); |
967 |
99692 |
if( n[i].getKind() == kind::BOUND_VARIABLE ){ |
968 |
25947 |
var_ch.push_back(i); |
969 |
|
} |
970 |
|
} |
971 |
|
|
972 |
55017 |
if( n.getKind()==APPLY_UF ){ |
973 |
24140 |
Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl; |
974 |
|
//uninterpreted compose |
975 |
24140 |
doUninterpretedCompose( fm, f, d, n.getOperator(), children ); |
976 |
|
/* |
977 |
|
} else if( n.getKind()==SELECT ){ |
978 |
|
Trace("fmc-debug") << "Do select compose " << n << std::endl; |
979 |
|
std::vector< Def > children2; |
980 |
|
children2.push_back( children[1] ); |
981 |
|
std::vector< Node > cond; |
982 |
|
mkCondDefaultVec(fm, f, cond); |
983 |
|
std::vector< Node > val; |
984 |
|
doUninterpretedCompose(fm, f, d, children[0], children2, 0, cond, val ); |
985 |
|
*/ |
986 |
|
} else { |
987 |
30877 |
if( !var_ch.empty() ){ |
988 |
4193 |
if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){ |
989 |
788 |
if( var_ch.size()==2 ){ |
990 |
302 |
Trace("fmc-debug") << "Do variable equality " << n << std::endl; |
991 |
302 |
doVariableEquality( fm, f, d, n ); |
992 |
|
}else{ |
993 |
486 |
Trace("fmc-debug") << "Do variable relation " << n << std::endl; |
994 |
486 |
doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] ); |
995 |
|
} |
996 |
|
}else{ |
997 |
3405 |
Trace("fmc-warn") << "Don't know how to check " << n << std::endl; |
998 |
3405 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
999 |
|
} |
1000 |
|
}else{ |
1001 |
26684 |
Trace("fmc-debug") << "Do interpreted compose " << n << std::endl; |
1002 |
53368 |
std::vector< Node > cond; |
1003 |
26684 |
mkCondDefaultVec(fm, f, cond); |
1004 |
53368 |
std::vector< Node > val; |
1005 |
|
//interpreted compose |
1006 |
26684 |
doInterpretedCompose( fm, f, d, n, children, 0, cond, val ); |
1007 |
|
} |
1008 |
|
} |
1009 |
55017 |
Trace("fmc-debug") << "Simplify the definition..." << std::endl; |
1010 |
55017 |
d.debugPrint("fmc-debug", Node::null(), this); |
1011 |
55017 |
d.simplify(this, fm); |
1012 |
55017 |
Trace("fmc-debug") << "Done simplifying" << std::endl; |
1013 |
|
} |
1014 |
115260 |
Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl; |
1015 |
115260 |
d.debugPrint("fmc-debug", Node::null(), this); |
1016 |
115260 |
Trace("fmc-debug") << std::endl; |
1017 |
115260 |
} |
1018 |
|
|
1019 |
8948 |
void FullModelChecker::doNegate( Def & dc ) { |
1020 |
20508 |
for (unsigned i=0; i<dc.d_cond.size(); i++) { |
1021 |
23120 |
Node v = dc.d_value[i]; |
1022 |
11560 |
if (!v.isNull()) |
1023 |
|
{ |
1024 |
|
// In the case that the value is not-constant, we cannot reason about |
1025 |
|
// its value (since the range of this must be a constant or variable). |
1026 |
|
// In particular, returning null here is important if we have (not x) |
1027 |
|
// where x is a bound variable. |
1028 |
8335 |
dc.d_value[i] = |
1029 |
16670 |
v == d_true ? d_false : (v == d_false ? d_true : Node::null()); |
1030 |
|
} |
1031 |
|
} |
1032 |
8948 |
} |
1033 |
|
|
1034 |
302 |
void FullModelChecker::doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq ) { |
1035 |
604 |
std::vector<Node> cond; |
1036 |
302 |
mkCondDefaultVec(fm, f, cond); |
1037 |
302 |
if (eq[0]==eq[1]){ |
1038 |
|
d.addEntry(fm, mkCond(cond), d_true); |
1039 |
|
}else{ |
1040 |
604 |
TypeNode tn = eq[0].getType(); |
1041 |
302 |
if( tn.isSort() ){ |
1042 |
302 |
int j = fm->getVariableId(f, eq[0]); |
1043 |
302 |
int k = fm->getVariableId(f, eq[1]); |
1044 |
302 |
const RepSet* rs = fm->getRepSet(); |
1045 |
302 |
if (!rs->hasType(tn)) |
1046 |
|
{ |
1047 |
|
getSomeDomainElement( fm, tn ); //to verify the type is initialized |
1048 |
|
} |
1049 |
302 |
unsigned nreps = rs->getNumRepresentatives(tn); |
1050 |
880 |
for (unsigned i = 0; i < nreps; i++) |
1051 |
|
{ |
1052 |
1156 |
Node r = fm->getRepresentative(rs->getRepresentative(tn, i)); |
1053 |
578 |
cond[j+1] = r; |
1054 |
578 |
cond[k+1] = r; |
1055 |
578 |
d.addEntry( fm, mkCond(cond), d_true); |
1056 |
|
} |
1057 |
302 |
d.addEntry( fm, mkCondDefault(fm, f), d_false); |
1058 |
|
}else{ |
1059 |
|
d.addEntry( fm, mkCondDefault(fm, f), Node::null()); |
1060 |
|
} |
1061 |
|
} |
1062 |
302 |
} |
1063 |
|
|
1064 |
486 |
void FullModelChecker::doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v) { |
1065 |
486 |
int j = fm->getVariableId(f, v); |
1066 |
1106 |
for (unsigned i=0; i<dc.d_cond.size(); i++) { |
1067 |
1240 |
Node val = dc.d_value[i]; |
1068 |
620 |
if( val.isNull() ){ |
1069 |
9 |
d.addEntry( fm, dc.d_cond[i], val); |
1070 |
|
}else{ |
1071 |
611 |
if( dc.d_cond[i][j]!=val ){ |
1072 |
489 |
if (fm->isStar(dc.d_cond[i][j])) { |
1073 |
954 |
std::vector<Node> cond; |
1074 |
477 |
mkCondVec(dc.d_cond[i],cond); |
1075 |
477 |
cond[j+1] = val; |
1076 |
477 |
d.addEntry(fm, mkCond(cond), d_true); |
1077 |
477 |
cond[j+1] = fm->getStar(val.getType()); |
1078 |
477 |
d.addEntry(fm, mkCond(cond), d_false); |
1079 |
|
}else{ |
1080 |
12 |
d.addEntry( fm, dc.d_cond[i], d_false); |
1081 |
|
} |
1082 |
|
}else{ |
1083 |
122 |
d.addEntry( fm, dc.d_cond[i], d_true); |
1084 |
|
} |
1085 |
|
} |
1086 |
|
} |
1087 |
486 |
} |
1088 |
|
|
1089 |
24140 |
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) { |
1090 |
24140 |
Trace("fmc-uf-debug") << "Definition : " << std::endl; |
1091 |
24140 |
fm->d_models[op]->debugPrint("fmc-uf-debug", op, this); |
1092 |
24140 |
Trace("fmc-uf-debug") << std::endl; |
1093 |
|
|
1094 |
48280 |
std::vector< Node > cond; |
1095 |
24140 |
mkCondDefaultVec(fm, f, cond); |
1096 |
48280 |
std::vector< Node > val; |
1097 |
24140 |
doUninterpretedCompose( fm, f, d, *fm->d_models[op], dc, 0, cond, val); |
1098 |
24140 |
} |
1099 |
|
|
1100 |
66714 |
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, |
1101 |
|
Def & df, std::vector< Def > & dc, int index, |
1102 |
|
std::vector< Node > & cond, std::vector<Node> & val ) { |
1103 |
66714 |
Trace("fmc-uf-process") << "process at " << index << std::endl; |
1104 |
181673 |
for( unsigned i=1; i<cond.size(); i++) { |
1105 |
114959 |
debugPrint("fmc-uf-process", cond[i], true); |
1106 |
114959 |
Trace("fmc-uf-process") << " "; |
1107 |
|
} |
1108 |
66714 |
Trace("fmc-uf-process") << std::endl; |
1109 |
66714 |
if (index==(int)dc.size()) { |
1110 |
|
//we have an entry, now do actual compose |
1111 |
60312 |
std::map< int, Node > entries; |
1112 |
30156 |
doUninterpretedCompose2( fm, f, entries, 0, cond, val, df.d_et); |
1113 |
30156 |
if( entries.empty() ){ |
1114 |
1061 |
d.addEntry(fm, mkCond(cond), Node::null()); |
1115 |
|
}else{ |
1116 |
|
//add them to the definition |
1117 |
96485 |
for( unsigned e=0; e<df.d_cond.size(); e++ ){ |
1118 |
67390 |
if ( entries.find(e)!=entries.end() ){ |
1119 |
48338 |
Trace("fmf-uf-process-debug") << "Add entry..." << std::endl; |
1120 |
48338 |
d.addEntry(fm, entries[e], df.d_value[e] ); |
1121 |
48338 |
Trace("fmf-uf-process-debug") << "Done add entry." << std::endl; |
1122 |
|
} |
1123 |
|
} |
1124 |
|
} |
1125 |
|
}else{ |
1126 |
85020 |
for (unsigned i=0; i<dc[index].d_cond.size(); i++) { |
1127 |
48462 |
if (isCompat(fm, cond, dc[index].d_cond[i])!=0) { |
1128 |
85148 |
std::vector< Node > new_cond; |
1129 |
42574 |
new_cond.insert(new_cond.end(), cond.begin(), cond.end()); |
1130 |
42574 |
if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){ |
1131 |
42574 |
Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl; |
1132 |
42574 |
val.push_back(dc[index].d_value[i]); |
1133 |
42574 |
doUninterpretedCompose(fm, f, d, df, dc, index+1, new_cond, val); |
1134 |
42574 |
val.pop_back(); |
1135 |
|
}else{ |
1136 |
|
Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl; |
1137 |
|
} |
1138 |
|
} |
1139 |
|
} |
1140 |
|
} |
1141 |
66714 |
} |
1142 |
|
|
1143 |
100625 |
void FullModelChecker::doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f, |
1144 |
|
std::map< int, Node > & entries, int index, |
1145 |
|
std::vector< Node > & cond, std::vector< Node > & val, |
1146 |
|
EntryTrie & curr ) { |
1147 |
100625 |
Trace("fmc-uf-process") << "compose " << index << " / " << val.size() << std::endl; |
1148 |
273828 |
for( unsigned i=1; i<cond.size(); i++) { |
1149 |
173203 |
debugPrint("fmc-uf-process", cond[i], true); |
1150 |
173203 |
Trace("fmc-uf-process") << " "; |
1151 |
|
} |
1152 |
100625 |
Trace("fmc-uf-process") << std::endl; |
1153 |
100625 |
if (index==(int)val.size()) { |
1154 |
96676 |
Node c = mkCond(cond); |
1155 |
48338 |
Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl; |
1156 |
48338 |
entries[curr.d_data] = c; |
1157 |
|
}else{ |
1158 |
104574 |
Node v = val[index]; |
1159 |
52287 |
Trace("fmc-uf-process") << "Process " << v << std::endl; |
1160 |
52287 |
bool bind_var = false; |
1161 |
52287 |
if( !v.isNull() && v.getKind()==kind::BOUND_VARIABLE ){ |
1162 |
24535 |
int j = fm->getVariableId(f, v); |
1163 |
24535 |
Trace("fmc-uf-process") << v << " is variable #" << j << std::endl; |
1164 |
24535 |
if (!fm->isStar(cond[j + 1])) |
1165 |
|
{ |
1166 |
38 |
v = cond[j+1]; |
1167 |
|
}else{ |
1168 |
24497 |
bind_var = true; |
1169 |
|
} |
1170 |
|
} |
1171 |
52287 |
if (bind_var) { |
1172 |
24497 |
Trace("fmc-uf-process") << "bind variable..." << std::endl; |
1173 |
24497 |
int j = fm->getVariableId(f, v); |
1174 |
24497 |
Assert(fm->isStar(cond[j + 1])); |
1175 |
64442 |
for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin(); |
1176 |
64442 |
it != curr.d_child.end(); |
1177 |
|
++it) |
1178 |
|
{ |
1179 |
39945 |
cond[j + 1] = it->first; |
1180 |
39945 |
doUninterpretedCompose2( |
1181 |
39945 |
fm, f, entries, index + 1, cond, val, it->second); |
1182 |
|
} |
1183 |
24497 |
cond[j + 1] = fm->getStar(v.getType()); |
1184 |
|
}else{ |
1185 |
27790 |
if( !v.isNull() ){ |
1186 |
26720 |
if (curr.d_child.find(v) != curr.d_child.end()) |
1187 |
|
{ |
1188 |
7892 |
Trace("fmc-uf-process") << "follow value..." << std::endl; |
1189 |
7892 |
doUninterpretedCompose2( |
1190 |
7892 |
fm, f, entries, index + 1, cond, val, curr.d_child[v]); |
1191 |
|
} |
1192 |
53440 |
Node st = fm->getStar(v.getType()); |
1193 |
26720 |
if (curr.d_child.find(st) != curr.d_child.end()) |
1194 |
|
{ |
1195 |
22632 |
Trace("fmc-uf-process") << "follow star..." << std::endl; |
1196 |
22632 |
doUninterpretedCompose2( |
1197 |
22632 |
fm, f, entries, index + 1, cond, val, curr.d_child[st]); |
1198 |
|
} |
1199 |
|
} |
1200 |
|
} |
1201 |
|
} |
1202 |
100625 |
} |
1203 |
|
|
1204 |
109731 |
void FullModelChecker::doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n, |
1205 |
|
std::vector< Def > & dc, int index, |
1206 |
|
std::vector< Node > & cond, std::vector<Node> & val ) { |
1207 |
109731 |
Trace("fmc-if-process") << "int compose " << index << " / " << dc.size() << std::endl; |
1208 |
264003 |
for( unsigned i=1; i<cond.size(); i++) { |
1209 |
154272 |
debugPrint("fmc-if-process", cond[i], true); |
1210 |
154272 |
Trace("fmc-if-process") << " "; |
1211 |
|
} |
1212 |
109731 |
Trace("fmc-if-process") << std::endl; |
1213 |
109731 |
if ( index==(int)dc.size() ){ |
1214 |
92684 |
Node c = mkCond(cond); |
1215 |
92684 |
Node v = evaluateInterpreted(n, val); |
1216 |
46342 |
d.addEntry(fm, c, v); |
1217 |
|
} |
1218 |
|
else { |
1219 |
126778 |
TypeNode vtn = n.getType(); |
1220 |
165504 |
for (unsigned i=0; i<dc[index].d_cond.size(); i++) { |
1221 |
102115 |
if (isCompat(fm, cond, dc[index].d_cond[i])!=0) { |
1222 |
181278 |
std::vector< Node > new_cond; |
1223 |
90639 |
new_cond.insert(new_cond.end(), cond.begin(), cond.end()); |
1224 |
90639 |
if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){ |
1225 |
90639 |
bool process = true; |
1226 |
90639 |
if (vtn.isBoolean()) { |
1227 |
|
//short circuit |
1228 |
116533 |
if( (n.getKind()==OR && dc[index].d_value[i]==d_true) || |
1229 |
54859 |
(n.getKind()==AND && dc[index].d_value[i]==d_false) ){ |
1230 |
15184 |
Node c = mkCond(new_cond); |
1231 |
7592 |
d.addEntry(fm, c, dc[index].d_value[i]); |
1232 |
7592 |
process = false; |
1233 |
|
} |
1234 |
|
} |
1235 |
90639 |
if (process) { |
1236 |
83047 |
val.push_back(dc[index].d_value[i]); |
1237 |
83047 |
doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val); |
1238 |
83047 |
val.pop_back(); |
1239 |
|
} |
1240 |
|
} |
1241 |
|
} |
1242 |
|
} |
1243 |
|
} |
1244 |
109731 |
} |
1245 |
|
|
1246 |
150577 |
int FullModelChecker::isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) { |
1247 |
150577 |
Trace("fmc-debug3") << "isCompat " << c << std::endl; |
1248 |
150577 |
Assert(cond.size() == c.getNumChildren() + 1); |
1249 |
383874 |
for (unsigned i=1; i<cond.size(); i++) { |
1250 |
250661 |
if (cond[i] != c[i - 1] && !fm->isStar(cond[i]) && !fm->isStar(c[i - 1])) |
1251 |
|
{ |
1252 |
17364 |
return 0; |
1253 |
|
} |
1254 |
|
} |
1255 |
133213 |
return 1; |
1256 |
|
} |
1257 |
|
|
1258 |
133213 |
bool FullModelChecker::doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) { |
1259 |
133213 |
Trace("fmc-debug3") << "doMeet " << c << std::endl; |
1260 |
133213 |
Assert(cond.size() == c.getNumChildren() + 1); |
1261 |
351178 |
for (unsigned i=1; i<cond.size(); i++) { |
1262 |
217965 |
if( cond[i]!=c[i-1] ) { |
1263 |
64858 |
if (fm->isStar(cond[i])) |
1264 |
|
{ |
1265 |
36659 |
cond[i] = c[i - 1]; |
1266 |
|
} |
1267 |
28199 |
else if (!fm->isStar(c[i - 1])) |
1268 |
|
{ |
1269 |
|
return false; |
1270 |
|
} |
1271 |
|
} |
1272 |
|
} |
1273 |
133213 |
return true; |
1274 |
|
} |
1275 |
|
|
1276 |
163376 |
Node FullModelChecker::mkCond( std::vector< Node > & cond ) { |
1277 |
163376 |
return NodeManager::currentNM()->mkNode(APPLY_UF, cond); |
1278 |
|
} |
1279 |
|
|
1280 |
57168 |
Node FullModelChecker::mkCondDefault( FirstOrderModelFmc * fm, Node f) { |
1281 |
114336 |
std::vector< Node > cond; |
1282 |
57168 |
mkCondDefaultVec(fm, f, cond); |
1283 |
114336 |
return mkCond(cond); |
1284 |
|
} |
1285 |
|
|
1286 |
108294 |
void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond ) { |
1287 |
108294 |
Trace("fmc-debug") << "Make default vec" << std::endl; |
1288 |
|
//get function symbol for f |
1289 |
108294 |
cond.push_back(d_quant_cond[f]); |
1290 |
271482 |
for (unsigned i=0; i<f[0].getNumChildren(); i++) { |
1291 |
326376 |
Node ts = fm->getStar(f[0][i].getType()); |
1292 |
163188 |
Assert(ts.getType() == f[0][i].getType()); |
1293 |
163188 |
cond.push_back(ts); |
1294 |
|
} |
1295 |
108294 |
} |
1296 |
|
|
1297 |
477 |
void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) { |
1298 |
477 |
cond.push_back(n.getOperator()); |
1299 |
1074 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1300 |
597 |
cond.push_back( n[i] ); |
1301 |
|
} |
1302 |
477 |
} |
1303 |
|
|
1304 |
46342 |
Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) { |
1305 |
46342 |
if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){ |
1306 |
11481 |
if (!vals[0].isNull() && !vals[1].isNull()) { |
1307 |
9708 |
return vals[0]==vals[1] ? d_true : d_false; |
1308 |
|
}else{ |
1309 |
1773 |
return Node::null(); |
1310 |
|
} |
1311 |
34861 |
}else if( n.getKind()==ITE ){ |
1312 |
3835 |
if( vals[0]==d_true ){ |
1313 |
1702 |
return vals[1]; |
1314 |
2133 |
}else if( vals[0]==d_false ){ |
1315 |
2049 |
return vals[2]; |
1316 |
|
}else{ |
1317 |
84 |
return vals[1]==vals[2] ? vals[1] : Node::null(); |
1318 |
|
} |
1319 |
31026 |
}else if( n.getKind()==AND || n.getKind()==OR ){ |
1320 |
5836 |
bool isNull = false; |
1321 |
22466 |
for (unsigned i=0; i<vals.size(); i++) { |
1322 |
16630 |
if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) { |
1323 |
|
return vals[i]; |
1324 |
16630 |
}else if( vals[i].isNull() ){ |
1325 |
4122 |
isNull = true; |
1326 |
|
} |
1327 |
|
} |
1328 |
5836 |
return isNull ? Node::null() : vals[0]; |
1329 |
|
}else{ |
1330 |
50380 |
std::vector<Node> children; |
1331 |
25190 |
if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){ |
1332 |
7925 |
children.push_back( n.getOperator() ); |
1333 |
|
} |
1334 |
64001 |
for (unsigned i=0; i<vals.size(); i++) { |
1335 |
42308 |
if( vals[i].isNull() ){ |
1336 |
3497 |
return Node::null(); |
1337 |
|
}else{ |
1338 |
38811 |
children.push_back( vals[i] ); |
1339 |
|
} |
1340 |
|
} |
1341 |
43386 |
Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children); |
1342 |
21693 |
Trace("fmc-eval") << "Evaluate " << nc << " to "; |
1343 |
21693 |
nc = Rewriter::rewrite(nc); |
1344 |
21693 |
Trace("fmc-eval") << nc << std::endl; |
1345 |
21693 |
return nc; |
1346 |
|
} |
1347 |
|
} |
1348 |
|
|
1349 |
3527 |
Node FullModelChecker::getSomeDomainElement( FirstOrderModelFmc * fm, TypeNode tn ) { |
1350 |
3527 |
bool addRepId = !fm->getRepSet()->hasType(tn); |
1351 |
3527 |
Node de = fm->getSomeDomainElement(tn); |
1352 |
3527 |
if( addRepId ){ |
1353 |
116 |
d_rep_ids[tn][de] = 0; |
1354 |
|
} |
1355 |
3527 |
return de; |
1356 |
|
} |
1357 |
|
|
1358 |
7221 |
Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix ) { |
1359 |
7221 |
return fm->getFunctionValue(op, argPrefix); |
1360 |
|
} |
1361 |
|
|
1362 |
|
|
1363 |
38769 |
bool FullModelChecker::useSimpleModels() { |
1364 |
38769 |
return options::fmfFmcSimple(); |
1365 |
|
} |
1366 |
20770 |
void FullModelChecker::registerQuantifiedFormula(Node q) |
1367 |
|
{ |
1368 |
20770 |
if (d_quant_cond.find(q) != d_quant_cond.end()) |
1369 |
|
{ |
1370 |
19270 |
return; |
1371 |
|
} |
1372 |
1500 |
NodeManager* nm = NodeManager::currentNM(); |
1373 |
1500 |
SkolemManager* sm = nm->getSkolemManager(); |
1374 |
3000 |
std::vector<TypeNode> types; |
1375 |
3705 |
for (const Node& v : q[0]) |
1376 |
|
{ |
1377 |
4410 |
TypeNode tn = v.getType(); |
1378 |
2205 |
if (tn.isFunction()) |
1379 |
|
{ |
1380 |
|
// we will not use model-based quantifier instantiation for q, since |
1381 |
|
// the model-based instantiation algorithm does not handle (universally |
1382 |
|
// quantified) functions |
1383 |
24 |
d_unhandledQuant.insert(q); |
1384 |
|
} |
1385 |
2205 |
types.push_back(tn); |
1386 |
|
} |
1387 |
3000 |
TypeNode typ = nm->mkFunctionType(types, nm->booleanType()); |
1388 |
3000 |
Node op = sm->mkDummySkolem("qfmc", typ, "op for full-model checking"); |
1389 |
1500 |
d_quant_cond[q] = op; |
1390 |
|
} |
1391 |
|
|
1392 |
20770 |
bool FullModelChecker::isHandled(Node q) const |
1393 |
|
{ |
1394 |
20770 |
return d_unhandledQuant.find(q) == d_unhandledQuant.end(); |
1395 |
|
} |
1396 |
|
|
1397 |
|
} // namespace fmcheck |
1398 |
|
} // namespace quantifiers |
1399 |
|
} // namespace theory |
1400 |
29505 |
} // namespace cvc5 |