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/theory_options.h" |
21 |
|
#include "options/uf_options.h" |
22 |
|
#include "theory/quantifiers/first_order_model.h" |
23 |
|
#include "theory/quantifiers/fmf/bounded_integers.h" |
24 |
|
#include "theory/quantifiers/instantiate.h" |
25 |
|
#include "theory/quantifiers/quant_rep_bound_ext.h" |
26 |
|
#include "theory/quantifiers/quantifiers_inference_manager.h" |
27 |
|
#include "theory/quantifiers/quantifiers_registry.h" |
28 |
|
#include "theory/quantifiers/quantifiers_state.h" |
29 |
|
#include "theory/quantifiers/term_database.h" |
30 |
|
#include "theory/quantifiers/term_util.h" |
31 |
|
#include "theory/rewriter.h" |
32 |
|
|
33 |
|
using namespace cvc5::kind; |
34 |
|
using namespace cvc5::context; |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
namespace theory { |
38 |
|
namespace quantifiers { |
39 |
|
namespace fmcheck { |
40 |
|
|
41 |
201550 |
struct ModelBasisArgSort |
42 |
|
{ |
43 |
|
std::vector< Node > d_terms; |
44 |
|
// number of arguments that are model-basis terms |
45 |
|
std::unordered_map<Node, unsigned> d_mba_count; |
46 |
63081 |
bool operator() (int i,int j) { |
47 |
63081 |
return (d_mba_count[d_terms[i]] < d_mba_count[d_terms[j]]); |
48 |
|
} |
49 |
|
}; |
50 |
|
|
51 |
434435 |
bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) { |
52 |
434435 |
if (index==(int)c.getNumChildren()) { |
53 |
19136 |
return d_data!=-1; |
54 |
|
}else{ |
55 |
830598 |
TypeNode tn = c[index].getType(); |
56 |
830598 |
Node st = m->getStar(tn); |
57 |
415299 |
if(d_child.find(st)!=d_child.end()) { |
58 |
42057 |
if( d_child[st].hasGeneralization(m, c, index+1) ){ |
59 |
17215 |
return true; |
60 |
|
} |
61 |
|
} |
62 |
398084 |
if( c[index]!=st && d_child.find( c[index] )!=d_child.end() ){ |
63 |
57753 |
if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){ |
64 |
22940 |
return true; |
65 |
|
} |
66 |
|
} |
67 |
375144 |
if( c[index].getType().isSort() ){ |
68 |
|
//for star: check if all children are defined and have generalizations |
69 |
322836 |
if( c[index]==st ){ ///options::fmfFmcCoverSimplify() |
70 |
|
//check if all children exist and are complete |
71 |
|
unsigned num_child_def = |
72 |
184460 |
d_child.size() - (d_child.find(st) != d_child.end() ? 1 : 0); |
73 |
184460 |
if (num_child_def == m->getRepSet()->getNumRepresentatives(tn)) |
74 |
|
{ |
75 |
8939 |
bool complete = true; |
76 |
15425 |
for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
77 |
12896 |
if( !m->isStar(it->first) ){ |
78 |
12408 |
if( !it->second.hasGeneralization(m, c, index+1) ){ |
79 |
6410 |
complete = false; |
80 |
6410 |
break; |
81 |
|
} |
82 |
|
} |
83 |
|
} |
84 |
8939 |
if( complete ){ |
85 |
2529 |
return true; |
86 |
|
} |
87 |
|
} |
88 |
|
} |
89 |
|
} |
90 |
|
|
91 |
372615 |
return false; |
92 |
|
} |
93 |
|
} |
94 |
|
|
95 |
132048 |
int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index ) { |
96 |
132048 |
Debug("fmc-entry-trie") << "Get generalization index " << inst.size() << " " << index << std::endl; |
97 |
132048 |
if (index==(int)inst.size()) { |
98 |
37982 |
return d_data; |
99 |
|
}else{ |
100 |
94066 |
int minIndex = -1; |
101 |
188132 |
Node st = m->getStar(inst[index].getType()); |
102 |
94066 |
if (d_child.find(st) != d_child.end()) |
103 |
|
{ |
104 |
87490 |
minIndex = d_child[st].getGeneralizationIndex(m, inst, index + 1); |
105 |
|
} |
106 |
188132 |
Node cc = inst[index]; |
107 |
94066 |
if (cc != st && d_child.find(cc) != d_child.end()) |
108 |
|
{ |
109 |
12984 |
int gindex = d_child[cc].getGeneralizationIndex(m, inst, index + 1); |
110 |
12984 |
if (minIndex == -1 || (gindex != -1 && gindex < minIndex)) |
111 |
|
{ |
112 |
8937 |
minIndex = gindex; |
113 |
|
} |
114 |
|
} |
115 |
94066 |
return minIndex; |
116 |
|
} |
117 |
|
} |
118 |
|
|
119 |
800702 |
void EntryTrie::addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index ) { |
120 |
800702 |
if (index==(int)c.getNumChildren()) { |
121 |
306550 |
if(d_data==-1) { |
122 |
306550 |
d_data = data; |
123 |
|
} |
124 |
|
} |
125 |
|
else { |
126 |
494152 |
d_child[ c[index] ].addEntry(m,c,v,data,index+1); |
127 |
494152 |
if( d_complete==0 ){ |
128 |
|
d_complete = -1; |
129 |
|
} |
130 |
|
} |
131 |
800702 |
} |
132 |
|
|
133 |
349428 |
void EntryTrie::getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) { |
134 |
349428 |
if (index==(int)c.getNumChildren()) { |
135 |
83986 |
if( d_data!=-1) { |
136 |
83986 |
if( is_gen ){ |
137 |
78240 |
gen.push_back(d_data); |
138 |
|
} |
139 |
83986 |
compat.push_back(d_data); |
140 |
|
} |
141 |
|
}else{ |
142 |
265442 |
if (m->isStar(c[index])) { |
143 |
273460 |
for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
144 |
125565 |
it->second.getEntries(m, c, compat, gen, index+1, is_gen ); |
145 |
|
} |
146 |
|
}else{ |
147 |
235094 |
Node st = m->getStar(c[index].getType()); |
148 |
117547 |
if(d_child.find(st)!=d_child.end()) { |
149 |
7464 |
d_child[st].getEntries(m, c, compat, gen, index+1, false); |
150 |
|
} |
151 |
117547 |
if( d_child.find( c[index] )!=d_child.end() ){ |
152 |
29749 |
d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen); |
153 |
|
} |
154 |
|
} |
155 |
|
|
156 |
|
} |
157 |
349428 |
} |
158 |
|
|
159 |
322217 |
bool Def::addEntry( FirstOrderModelFmc * m, Node c, Node v) { |
160 |
322217 |
if (d_et.hasGeneralization(m, c)) { |
161 |
15667 |
Trace("fmc-debug") << "Already has generalization, skip." << std::endl; |
162 |
15667 |
return false; |
163 |
|
} |
164 |
306550 |
int newIndex = (int)d_cond.size(); |
165 |
306550 |
if (!d_has_simplified) { |
166 |
373300 |
std::vector<int> compat; |
167 |
373300 |
std::vector<int> gen; |
168 |
186650 |
d_et.getEntries(m, c, compat, gen); |
169 |
270636 |
for( unsigned i=0; i<compat.size(); i++) { |
170 |
83986 |
if( d_status[compat[i]]==status_unk ){ |
171 |
75286 |
if( d_value[compat[i]]!=v ){ |
172 |
47796 |
d_status[compat[i]] = status_non_redundant; |
173 |
|
} |
174 |
|
} |
175 |
|
} |
176 |
264890 |
for( unsigned i=0; i<gen.size(); i++) { |
177 |
78240 |
if( d_status[gen[i]]==status_unk ){ |
178 |
23840 |
if( d_value[gen[i]]==v ){ |
179 |
23840 |
d_status[gen[i]] = status_redundant; |
180 |
|
} |
181 |
|
} |
182 |
|
} |
183 |
186650 |
d_status.push_back( status_unk ); |
184 |
|
} |
185 |
306550 |
d_et.addEntry(m, c, v, newIndex); |
186 |
306550 |
d_cond.push_back(c); |
187 |
306550 |
d_value.push_back(v); |
188 |
306550 |
return true; |
189 |
|
} |
190 |
|
|
191 |
2147 |
Node Def::evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst ) { |
192 |
2147 |
int gindex = d_et.getGeneralizationIndex(m, inst); |
193 |
2147 |
if (gindex!=-1) { |
194 |
2143 |
return d_value[gindex]; |
195 |
|
}else{ |
196 |
4 |
Trace("fmc-warn") << "Warning : evaluation came up null!" << std::endl; |
197 |
4 |
return Node::null(); |
198 |
|
} |
199 |
|
} |
200 |
|
|
201 |
29427 |
int Def::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst ) { |
202 |
29427 |
return d_et.getGeneralizationIndex(m, inst); |
203 |
|
} |
204 |
|
|
205 |
66131 |
void Def::basic_simplify( FirstOrderModelFmc * m ) { |
206 |
66131 |
d_has_simplified = true; |
207 |
132262 |
std::vector< Node > cond; |
208 |
66131 |
cond.insert( cond.end(), d_cond.begin(), d_cond.end() ); |
209 |
66131 |
d_cond.clear(); |
210 |
132262 |
std::vector< Node > value; |
211 |
66131 |
value.insert( value.end(), d_value.begin(), d_value.end() ); |
212 |
66131 |
d_value.clear(); |
213 |
66131 |
d_et.reset(); |
214 |
209871 |
for (unsigned i=0; i<d_status.size(); i++) { |
215 |
143740 |
if( d_status[i]!=status_redundant ){ |
216 |
119900 |
addEntry(m, cond[i], value[i]); |
217 |
|
} |
218 |
|
} |
219 |
66131 |
d_status.clear(); |
220 |
66131 |
} |
221 |
|
|
222 |
59483 |
void Def::simplify(FullModelChecker * mc, FirstOrderModelFmc * m) { |
223 |
59483 |
Trace("fmc-simplify") << "Simplify definition, #cond = " << d_cond.size() << std::endl; |
224 |
59483 |
basic_simplify( m ); |
225 |
59483 |
Trace("fmc-simplify") << "post-basic simplify, #cond = " << d_cond.size() << std::endl; |
226 |
|
|
227 |
|
//check if the last entry is not all star, if so, we can make the last entry all stars |
228 |
59483 |
if( !d_cond.empty() ){ |
229 |
59483 |
bool last_all_stars = true; |
230 |
118966 |
Node cc = d_cond[d_cond.size()-1]; |
231 |
139343 |
for( unsigned i=0; i<cc.getNumChildren(); i++ ){ |
232 |
86508 |
if (!m->isStar(cc[i])) |
233 |
|
{ |
234 |
6648 |
last_all_stars = false; |
235 |
6648 |
break; |
236 |
|
} |
237 |
|
} |
238 |
59483 |
if( !last_all_stars ){ |
239 |
6648 |
Trace("fmc-cover-simplify") << "Need to modify last entry to be all stars." << std::endl; |
240 |
6648 |
Trace("fmc-cover-simplify") << "Before: " << std::endl; |
241 |
6648 |
debugPrint("fmc-cover-simplify",Node::null(), mc); |
242 |
6648 |
Trace("fmc-cover-simplify") << std::endl; |
243 |
13296 |
std::vector< Node > cond; |
244 |
6648 |
cond.insert( cond.end(), d_cond.begin(), d_cond.end() ); |
245 |
6648 |
d_cond.clear(); |
246 |
13296 |
std::vector< Node > value; |
247 |
6648 |
value.insert( value.end(), d_value.begin(), d_value.end() ); |
248 |
6648 |
d_value.clear(); |
249 |
6648 |
d_et.reset(); |
250 |
6648 |
d_has_simplified = false; |
251 |
|
//change the last to all star |
252 |
13296 |
std::vector< Node > nc; |
253 |
6648 |
nc.push_back( cc.getOperator() ); |
254 |
17756 |
for( unsigned j=0; j< cc.getNumChildren(); j++){ |
255 |
11108 |
nc.push_back(m->getStar(cc[j].getType())); |
256 |
|
} |
257 |
6648 |
cond[cond.size()-1] = NodeManager::currentNM()->mkNode( APPLY_UF, nc ); |
258 |
|
//re-add the entries |
259 |
19401 |
for (unsigned i=0; i<cond.size(); i++) { |
260 |
12753 |
addEntry(m, cond[i], value[i]); |
261 |
|
} |
262 |
6648 |
Trace("fmc-cover-simplify") << "Finished re-adding entries." << std::endl; |
263 |
6648 |
basic_simplify( m ); |
264 |
6648 |
Trace("fmc-cover-simplify") << "After: " << std::endl; |
265 |
6648 |
debugPrint("fmc-cover-simplify",Node::null(), mc); |
266 |
6648 |
Trace("fmc-cover-simplify") << std::endl; |
267 |
|
} |
268 |
|
} |
269 |
59483 |
Trace("fmc-simplify") << "finish simplify, #cond = " << d_cond.size() << std::endl; |
270 |
59483 |
} |
271 |
|
|
272 |
212988 |
void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) { |
273 |
212988 |
if (!op.isNull()) { |
274 |
42577 |
Trace(tr) << "Model for " << op << " : " << std::endl; |
275 |
|
} |
276 |
608896 |
for( unsigned i=0; i<d_cond.size(); i++) { |
277 |
|
//print the condition |
278 |
395908 |
if (!op.isNull()) { |
279 |
123355 |
Trace(tr) << op; |
280 |
|
} |
281 |
395908 |
m->debugPrintCond(tr, d_cond[i], true); |
282 |
395908 |
Trace(tr) << " -> "; |
283 |
395908 |
m->debugPrint(tr, d_value[i]); |
284 |
395908 |
Trace(tr) << std::endl; |
285 |
|
} |
286 |
212988 |
} |
287 |
|
|
288 |
1340 |
FullModelChecker::FullModelChecker(QuantifiersState& qs, |
289 |
|
QuantifiersInferenceManager& qim, |
290 |
|
QuantifiersRegistry& qr, |
291 |
1340 |
TermRegistry& tr) |
292 |
1340 |
: QModelBuilder(qs, qim, qr, tr), d_fm(new FirstOrderModelFmc(qs, qr, tr)) |
293 |
|
{ |
294 |
1340 |
d_true = NodeManager::currentNM()->mkConst(true); |
295 |
1340 |
d_false = NodeManager::currentNM()->mkConst(false); |
296 |
1340 |
} |
297 |
|
|
298 |
1340 |
void FullModelChecker::finishInit() { d_model = d_fm.get(); } |
299 |
|
|
300 |
1934 |
bool FullModelChecker::preProcessBuildModel(TheoryModel* m) { |
301 |
|
//standard pre-process |
302 |
1934 |
if( !preProcessBuildModelStd( m ) ){ |
303 |
|
return false; |
304 |
|
} |
305 |
|
|
306 |
1934 |
Trace("fmc") << "---Full Model Check preprocess() " << std::endl; |
307 |
1934 |
d_preinitialized_eqc.clear(); |
308 |
1934 |
d_preinitialized_types.clear(); |
309 |
|
//traverse equality engine |
310 |
1934 |
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(m->getEqualityEngine()); |
311 |
101854 |
while( !eqcs_i.isFinished() ){ |
312 |
99920 |
Node r = *eqcs_i; |
313 |
99920 |
TypeNode tr = r.getType(); |
314 |
49960 |
d_preinitialized_eqc[tr] = r; |
315 |
49960 |
++eqcs_i; |
316 |
|
} |
317 |
|
|
318 |
|
//must ensure model basis terms exists in model for each relevant type |
319 |
1934 |
Trace("fmc") << "preInitialize types..." << std::endl; |
320 |
1934 |
d_fm->initialize(); |
321 |
9579 |
for (std::pair<const Node, Def*>& mp : d_fm->d_models) |
322 |
|
{ |
323 |
15290 |
Node op = mp.first; |
324 |
7645 |
Trace("fmc") << "preInitialize types for " << op << std::endl; |
325 |
15290 |
TypeNode tno = op.getType(); |
326 |
27821 |
for( unsigned i=0; i<tno.getNumChildren(); i++) { |
327 |
20176 |
Trace("fmc") << "preInitializeType " << tno[i] << std::endl; |
328 |
20176 |
preInitializeType(m, tno[i]); |
329 |
20176 |
Trace("fmc") << "finished preInitializeType " << tno[i] << std::endl; |
330 |
|
} |
331 |
|
} |
332 |
1934 |
Trace("fmc") << "Finish preInitialize types" << std::endl; |
333 |
|
//do not have to introduce terms for sorts of domains of quantified formulas if we are allowed to assume empty sorts |
334 |
11881 |
for (unsigned i = 0, nquant = d_fm->getNumAssertedQuantifiers(); i < nquant; |
335 |
|
i++) |
336 |
|
{ |
337 |
19783 |
Node q = d_fm->getAssertedQuantifier(i); |
338 |
9947 |
registerQuantifiedFormula(q); |
339 |
9947 |
if (!isHandled(q)) |
340 |
|
{ |
341 |
111 |
continue; |
342 |
|
} |
343 |
|
// make sure all types are set |
344 |
24574 |
for (const Node& v : q[0]) |
345 |
|
{ |
346 |
14738 |
preInitializeType(m, v.getType()); |
347 |
|
} |
348 |
|
} |
349 |
1934 |
return true; |
350 |
|
} |
351 |
|
|
352 |
1934 |
bool FullModelChecker::processBuildModel(TheoryModel* m){ |
353 |
1934 |
if (!m->areFunctionValuesEnabled()) |
354 |
|
{ |
355 |
|
// nothing to do if no functions |
356 |
|
return true; |
357 |
|
} |
358 |
1934 |
FirstOrderModelFmc* fm = d_fm.get(); |
359 |
1934 |
Trace("fmc") << "---Full Model Check reset() " << std::endl; |
360 |
1934 |
d_quant_models.clear(); |
361 |
1934 |
d_rep_ids.clear(); |
362 |
1934 |
d_star_insts.clear(); |
363 |
|
//process representatives |
364 |
1934 |
RepSet* rs = m->getRepSetPtr(); |
365 |
8932 |
for (std::map<TypeNode, std::vector<Node> >::iterator it = |
366 |
1934 |
rs->d_type_reps.begin(); |
367 |
10866 |
it != rs->d_type_reps.end(); |
368 |
|
++it) |
369 |
|
{ |
370 |
8932 |
if( it->first.isSort() ){ |
371 |
2355 |
Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl; |
372 |
6923 |
for( size_t a=0; a<it->second.size(); a++ ){ |
373 |
9136 |
Node r = m->getRepresentative(it->second[a]); |
374 |
4568 |
if( Trace.isOn("fmc-model-debug") ){ |
375 |
|
std::vector< Node > eqc; |
376 |
|
d_qstate.getEquivalenceClass(r, eqc); |
377 |
|
Trace("fmc-model-debug") << " " << (it->second[a]==r); |
378 |
|
Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : "; |
379 |
|
//Trace("fmc-model-debug") << r2 << " : " << ir << " : "; |
380 |
|
Trace("fmc-model-debug") << " {"; |
381 |
|
for( size_t i=0; i<eqc.size(); i++ ){ |
382 |
|
Trace("fmc-model-debug") << eqc[i] << ", "; |
383 |
|
} |
384 |
|
Trace("fmc-model-debug") << "}" << std::endl; |
385 |
|
} |
386 |
4568 |
d_rep_ids[it->first][r] = (int)a; |
387 |
|
} |
388 |
2355 |
Trace("fmc-model-debug") << std::endl; |
389 |
|
} |
390 |
|
} |
391 |
|
|
392 |
|
//now, make models |
393 |
9579 |
for (std::pair<const Node, Def*>& fmm : d_fm->d_models) |
394 |
|
{ |
395 |
15290 |
Node op = fmm.first; |
396 |
|
//reset the model |
397 |
7645 |
d_fm->d_models[op]->reset(); |
398 |
|
|
399 |
15290 |
std::vector< Node > add_conds; |
400 |
15290 |
std::vector< Node > add_values; |
401 |
7645 |
bool needsDefault = true; |
402 |
7645 |
if (m->hasUfTerms(op)) |
403 |
|
{ |
404 |
6184 |
const std::vector<Node>& uft = m->getUfTerms(op); |
405 |
12368 |
Trace("fmc-model-debug") |
406 |
6184 |
<< uft.size() << " model values for " << op << " ... " << std::endl; |
407 |
45388 |
for (const Node& n : uft) |
408 |
|
{ |
409 |
|
// only consider unique up to congruence (in model equality engine)? |
410 |
39204 |
add_conds.push_back( n ); |
411 |
39204 |
add_values.push_back( n ); |
412 |
78408 |
Node r = m->getRepresentative(n); |
413 |
39204 |
Trace("fmc-model-debug") << n << " -> " << r << std::endl; |
414 |
|
} |
415 |
|
}else{ |
416 |
1461 |
Trace("fmc-model-debug") << "No model values for " << op << " ... " << std::endl; |
417 |
|
} |
418 |
7645 |
Trace("fmc-model-debug") << std::endl; |
419 |
|
//possibly get default |
420 |
7645 |
if( needsDefault ){ |
421 |
15290 |
Node nmb = d_fm->getModelBasisOpTerm(op); |
422 |
|
//add default value if necessary |
423 |
7645 |
if (m->hasTerm(nmb)) |
424 |
|
{ |
425 |
4229 |
Trace("fmc-model-debug") << "Add default " << nmb << std::endl; |
426 |
4229 |
add_conds.push_back( nmb ); |
427 |
4229 |
add_values.push_back( nmb ); |
428 |
|
}else{ |
429 |
6832 |
Node vmb = getSomeDomainElement(d_fm.get(), nmb.getType()); |
430 |
3416 |
Trace("fmc-model-debug") << "Add default to default representative " << nmb << " "; |
431 |
6832 |
Trace("fmc-model-debug") |
432 |
6832 |
<< m->getRepSet()->getNumRepresentatives(nmb.getType()) |
433 |
3416 |
<< std::endl; |
434 |
3416 |
add_conds.push_back( nmb ); |
435 |
3416 |
add_values.push_back( vmb ); |
436 |
|
} |
437 |
|
} |
438 |
|
|
439 |
15290 |
std::vector< Node > conds; |
440 |
15290 |
std::vector< Node > values; |
441 |
15290 |
std::vector< Node > entry_conds; |
442 |
|
//get the entries for the model |
443 |
54494 |
for( size_t i=0; i<add_conds.size(); i++ ){ |
444 |
93698 |
Node c = add_conds[i]; |
445 |
93698 |
Node v = add_values[i]; |
446 |
93698 |
Trace("fmc-model-debug") |
447 |
46849 |
<< "Add cond/value : " << c << " -> " << v << std::endl; |
448 |
93698 |
std::vector< Node > children; |
449 |
93698 |
std::vector< Node > entry_children; |
450 |
46849 |
children.push_back(op); |
451 |
46849 |
entry_children.push_back(op); |
452 |
46849 |
bool hasNonStar = false; |
453 |
130085 |
for (const Node& ci : c) |
454 |
|
{ |
455 |
166472 |
Node ri = fm->getRepresentative(ci); |
456 |
83236 |
children.push_back(ri); |
457 |
83236 |
bool isStar = false; |
458 |
83236 |
if (fm->isModelBasisTerm(ri)) |
459 |
|
{ |
460 |
22111 |
ri = fm->getStar(ri.getType()); |
461 |
22111 |
isStar = true; |
462 |
|
} |
463 |
|
else |
464 |
|
{ |
465 |
61125 |
hasNonStar = true; |
466 |
|
} |
467 |
83236 |
if( !isStar && !ri.isConst() ){ |
468 |
|
Trace("fmc-warn") << "Warning : model for " << op |
469 |
|
<< " has non-constant argument in model " << ri |
470 |
|
<< " (from " << ci << ")" << std::endl; |
471 |
|
Assert(false); |
472 |
|
} |
473 |
83236 |
entry_children.push_back(ri); |
474 |
|
} |
475 |
93698 |
Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children ); |
476 |
93698 |
Node nv = fm->getRepresentative( v ); |
477 |
93698 |
Trace("fmc-model-debug") |
478 |
46849 |
<< "Representative of " << v << " is " << nv << std::endl; |
479 |
46849 |
if( !nv.isConst() ){ |
480 |
|
Trace("fmc-warn") << "Warning : model for " << op << " has non-constant value in model " << nv << std::endl; |
481 |
|
Assert(false); |
482 |
|
} |
483 |
93698 |
Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children ); |
484 |
46849 |
if( std::find(conds.begin(), conds.end(), n )==conds.end() ){ |
485 |
26994 |
Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl; |
486 |
26994 |
conds.push_back(n); |
487 |
26994 |
values.push_back(nv); |
488 |
26994 |
entry_conds.push_back(en); |
489 |
|
} |
490 |
|
else { |
491 |
19855 |
Trace("fmc-model-debug") << "Already have entry for : " << n << " -> " << nv << " (entry is " << en << ")" << std::endl; |
492 |
|
} |
493 |
|
} |
494 |
|
|
495 |
|
|
496 |
|
//sort based on # default arguments |
497 |
15290 |
std::vector< int > indices; |
498 |
15290 |
ModelBasisArgSort mbas; |
499 |
34639 |
for (int i=0; i<(int)conds.size(); i++) { |
500 |
26994 |
mbas.d_terms.push_back(conds[i]); |
501 |
26994 |
mbas.d_mba_count[conds[i]] = fm->getModelBasisArg(conds[i]); |
502 |
26994 |
indices.push_back(i); |
503 |
|
} |
504 |
7645 |
std::sort( indices.begin(), indices.end(), mbas ); |
505 |
|
|
506 |
34639 |
for (int i=0; i<(int)indices.size(); i++) { |
507 |
26994 |
fm->d_models[op]->addEntry(fm, entry_conds[indices[i]], values[indices[i]]); |
508 |
|
} |
509 |
|
|
510 |
7645 |
Trace("fmc-model-simplify") << "Before simplification : " << std::endl; |
511 |
7645 |
fm->d_models[op]->debugPrint("fmc-model-simplify", op, this); |
512 |
7645 |
Trace("fmc-model-simplify") << std::endl; |
513 |
|
|
514 |
7645 |
Trace("fmc-model-simplify") << "Simplifying " << op << "..." << std::endl; |
515 |
7645 |
fm->d_models[op]->simplify( this, fm ); |
516 |
|
|
517 |
7645 |
fm->d_models[op]->debugPrint("fmc-model", op, this); |
518 |
7645 |
Trace("fmc-model") << std::endl; |
519 |
|
|
520 |
|
//for debugging |
521 |
|
/* |
522 |
|
for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){ |
523 |
|
std::vector< Node > inst; |
524 |
|
for( unsigned j=0; j<fm->d_uf_terms[op][i].getNumChildren(); j++ ){ |
525 |
|
Node r = fm->getRepresentative( fm->d_uf_terms[op][i][j] ); |
526 |
|
inst.push_back( r ); |
527 |
|
} |
528 |
|
Node ev = fm->d_models[op]->evaluate( fm, inst ); |
529 |
|
Trace("fmc-model-debug") << ".....Checking eval( " << |
530 |
|
fm->d_uf_terms[op][i] << " ) = " << ev << std::endl; AlwaysAssert( |
531 |
|
fm->areEqual( ev, fm->d_uf_terms[op][i] ) ); |
532 |
|
} |
533 |
|
*/ |
534 |
|
} |
535 |
1934 |
Assert(d_addedLemmas == 0); |
536 |
|
|
537 |
|
//make function values |
538 |
9579 |
for( std::map<Node, Def * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ){ |
539 |
15290 |
Node f_def = getFunctionValue( fm, it->first, "$x" ); |
540 |
7645 |
m->assignFunctionDefinition( it->first, f_def ); |
541 |
|
} |
542 |
1934 |
return TheoryEngineModelBuilder::processBuildModel( m ); |
543 |
|
} |
544 |
|
|
545 |
34914 |
void FullModelChecker::preInitializeType(TheoryModel* m, TypeNode tn) |
546 |
|
{ |
547 |
34914 |
if( d_preinitialized_types.find( tn )==d_preinitialized_types.end() ){ |
548 |
5216 |
d_preinitialized_types[tn] = true; |
549 |
5216 |
if (tn.isFirstClass()) |
550 |
|
{ |
551 |
5210 |
Trace("fmc") << "Get model basis term " << tn << "..." << std::endl; |
552 |
10420 |
Node mb = d_fm->getModelBasisTerm(tn); |
553 |
5210 |
Trace("fmc") << "...return " << mb << std::endl; |
554 |
|
// if the model basis term does not exist in the model, |
555 |
|
// either add it directly to the model's equality engine if no other terms |
556 |
|
// of this type exist, or otherwise assert that it is equal to the first |
557 |
|
// equivalence class of its type. |
558 |
5210 |
if (!m->hasTerm(mb) && !mb.isConst()) |
559 |
|
{ |
560 |
549 |
std::map<TypeNode, Node>::iterator itpe = d_preinitialized_eqc.find(tn); |
561 |
549 |
if (itpe == d_preinitialized_eqc.end()) |
562 |
|
{ |
563 |
406 |
Trace("fmc") << "...add model basis term to EE of model " << mb << " " |
564 |
203 |
<< tn << std::endl; |
565 |
203 |
m->getEqualityEngine()->addTerm(mb); |
566 |
|
} |
567 |
|
else |
568 |
|
{ |
569 |
692 |
Trace("fmc") << "...add model basis eqc equality to model " << mb |
570 |
346 |
<< " == " << itpe->second << " " << tn << std::endl; |
571 |
346 |
bool ret = m->assertEquality(mb, itpe->second, true); |
572 |
346 |
AlwaysAssert(ret); |
573 |
|
} |
574 |
|
} |
575 |
|
} |
576 |
|
} |
577 |
34914 |
} |
578 |
|
|
579 |
399956 |
void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) { |
580 |
399956 |
Trace(tr) << "("; |
581 |
1018537 |
for( unsigned j=0; j<n.getNumChildren(); j++) { |
582 |
618581 |
if( j>0 ) Trace(tr) << ", "; |
583 |
618581 |
debugPrint(tr, n[j], dispStar); |
584 |
|
} |
585 |
399956 |
Trace(tr) << ")"; |
586 |
399956 |
} |
587 |
|
|
588 |
1558069 |
void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) { |
589 |
1558069 |
if( n.isNull() ){ |
590 |
14750 |
Trace(tr) << "null"; |
591 |
|
} |
592 |
1543319 |
else if (FirstOrderModelFmc::isStar(n) && dispStar) |
593 |
|
{ |
594 |
693496 |
Trace(tr) << "*"; |
595 |
|
} |
596 |
|
else |
597 |
|
{ |
598 |
1699646 |
TypeNode tn = n.getType(); |
599 |
849823 |
if( tn.isSort() && d_rep_ids.find(tn)!=d_rep_ids.end() ){ |
600 |
418571 |
if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) { |
601 |
393585 |
Trace(tr) << d_rep_ids[tn][n]; |
602 |
|
}else{ |
603 |
24986 |
Trace(tr) << n; |
604 |
|
} |
605 |
|
}else{ |
606 |
431252 |
Trace(tr) << n; |
607 |
|
} |
608 |
|
} |
609 |
1558069 |
} |
610 |
|
|
611 |
|
|
612 |
11969 |
int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) { |
613 |
11969 |
Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl; |
614 |
|
// register the quantifier |
615 |
11969 |
registerQuantifiedFormula(f); |
616 |
11969 |
Assert(!d_qstate.isInConflict()); |
617 |
|
// we do not do model-based quantifier instantiation if the option |
618 |
|
// disables it, or if the quantified formula has an unhandled type. |
619 |
11969 |
if (!optUseModel() || !isHandled(f)) |
620 |
|
{ |
621 |
|
return 0; |
622 |
|
} |
623 |
11969 |
FirstOrderModelFmc* fmfmc = static_cast<FirstOrderModelFmc*>(fm); |
624 |
11969 |
if (effort == 0) |
625 |
|
{ |
626 |
9558 |
if (options::mbqiMode() == options::MbqiMode::NONE) |
627 |
|
{ |
628 |
|
// just exhaustive instantiate |
629 |
6316 |
Node c = mkCondDefault(fmfmc, f); |
630 |
3158 |
d_quant_models[f].addEntry(fmfmc, c, d_false); |
631 |
3158 |
if (!exhaustiveInstantiate(fmfmc, f, c)) |
632 |
|
{ |
633 |
22 |
return 0; |
634 |
|
} |
635 |
3136 |
return 1; |
636 |
|
} |
637 |
|
// model check the quantifier |
638 |
6400 |
doCheck(fmfmc, f, d_quant_models[f], f[1]); |
639 |
6400 |
std::vector<Node>& mcond = d_quant_models[f].d_cond; |
640 |
6400 |
Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl; |
641 |
6400 |
Assert(!mcond.empty()); |
642 |
6400 |
d_quant_models[f].debugPrint("fmc", Node::null(), this); |
643 |
6400 |
Trace("fmc") << std::endl; |
644 |
|
|
645 |
|
// consider all entries going to non-true |
646 |
6400 |
Instantiate* instq = d_qim.getInstantiate(); |
647 |
14842 |
for (unsigned i = 0, msize = mcond.size(); i < msize; i++) |
648 |
|
{ |
649 |
8442 |
if (d_quant_models[f].d_value[i] == d_true) |
650 |
|
{ |
651 |
|
// already satisfied |
652 |
11877 |
continue; |
653 |
|
} |
654 |
5016 |
Trace("fmc-inst") << "Instantiate based on " << mcond[i] << "..." |
655 |
2508 |
<< std::endl; |
656 |
2508 |
bool hasStar = false; |
657 |
5007 |
std::vector<Node> inst; |
658 |
6611 |
for (unsigned j = 0, nchild = mcond[i].getNumChildren(); j < nchild; j++) |
659 |
|
{ |
660 |
4103 |
if (fmfmc->isStar(mcond[i][j])) |
661 |
|
{ |
662 |
3140 |
hasStar = true; |
663 |
3140 |
inst.push_back(fmfmc->getModelBasisTerm(mcond[i][j].getType())); |
664 |
|
} |
665 |
|
else |
666 |
|
{ |
667 |
963 |
inst.push_back(mcond[i][j]); |
668 |
|
} |
669 |
|
} |
670 |
2508 |
bool addInst = true; |
671 |
2508 |
if (hasStar) |
672 |
|
{ |
673 |
|
// try obvious (specified by inst) |
674 |
4294 |
Node ev = d_quant_models[f].evaluate(fmfmc, inst); |
675 |
2147 |
if (ev == d_true) |
676 |
|
{ |
677 |
9 |
addInst = false; |
678 |
18 |
Trace("fmc-debug") |
679 |
9 |
<< "...do not instantiate, evaluation was " << ev << std::endl; |
680 |
|
} |
681 |
|
} |
682 |
|
else |
683 |
|
{ |
684 |
|
// for debugging |
685 |
361 |
if (Trace.isOn("fmc-test-inst")) |
686 |
|
{ |
687 |
|
Node ev = d_quant_models[f].evaluate(fmfmc, inst); |
688 |
|
if (ev == d_true) |
689 |
|
{ |
690 |
|
CVC5Message() << "WARNING: instantiation was true! " << f << " " |
691 |
|
<< mcond[i] << std::endl; |
692 |
|
AlwaysAssert(false); |
693 |
|
} |
694 |
|
else |
695 |
|
{ |
696 |
|
Trace("fmc-test-inst") |
697 |
|
<< "...instantiation evaluated to false." << std::endl; |
698 |
|
} |
699 |
|
} |
700 |
|
} |
701 |
2517 |
if (!addInst) |
702 |
|
{ |
703 |
18 |
Trace("fmc-debug-inst") |
704 |
9 |
<< "** Instantiation was already true." << std::endl; |
705 |
|
// might try it next effort level |
706 |
9 |
d_star_insts[f].push_back(i); |
707 |
9 |
continue; |
708 |
|
} |
709 |
2499 |
if (options::fmfBound()) |
710 |
|
{ |
711 |
|
std::vector<Node> cond; |
712 |
|
cond.push_back(d_quant_cond[f]); |
713 |
|
cond.insert(cond.end(), inst.begin(), inst.end()); |
714 |
|
// need to do exhaustive instantiate algorithm to set things properly |
715 |
|
// (should only add one instance) |
716 |
|
Node c = mkCond(cond); |
717 |
|
unsigned prevInst = d_addedLemmas; |
718 |
|
exhaustiveInstantiate(fmfmc, f, c); |
719 |
|
if (d_addedLemmas == prevInst) |
720 |
|
{ |
721 |
|
d_star_insts[f].push_back(i); |
722 |
|
} |
723 |
|
continue; |
724 |
|
} |
725 |
|
// just add the instance |
726 |
2499 |
d_triedLemmas++; |
727 |
2499 |
if (instq->addInstantiation( |
728 |
|
f, inst, InferenceId::QUANTIFIERS_INST_FMF_FMC, true)) |
729 |
|
{ |
730 |
785 |
Trace("fmc-debug-inst") << "** Added instantiation." << std::endl; |
731 |
785 |
d_addedLemmas++; |
732 |
6695 |
if (d_qstate.isInConflict() || options::fmfOneInstPerRound()) |
733 |
|
{ |
734 |
|
break; |
735 |
|
} |
736 |
|
} |
737 |
|
else |
738 |
|
{ |
739 |
3428 |
Trace("fmc-debug-inst") |
740 |
1714 |
<< "** Instantiation was duplicate." << std::endl; |
741 |
|
// might try it next effort level |
742 |
1714 |
d_star_insts[f].push_back(i); |
743 |
|
} |
744 |
|
} |
745 |
6400 |
return 1; |
746 |
|
} |
747 |
|
// Get the list of instantiation regions (described by "star entries" in the |
748 |
|
// definition) that were not tried at the previous effort level. For each |
749 |
|
// of these, we add one instantiation. |
750 |
2411 |
std::vector<Node>& mcond = d_quant_models[f].d_cond; |
751 |
2411 |
if (!d_star_insts[f].empty()) |
752 |
|
{ |
753 |
807 |
if (Trace.isOn("fmc-exh")) |
754 |
|
{ |
755 |
|
Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl; |
756 |
|
Trace("fmc-exh") << "Definition was : " << std::endl; |
757 |
|
d_quant_models[f].debugPrint("fmc-exh", Node::null(), this); |
758 |
|
Trace("fmc-exh") << std::endl; |
759 |
|
} |
760 |
1612 |
Def temp; |
761 |
|
// simplify the exceptions? |
762 |
1727 |
for (int i = (d_star_insts[f].size() - 1); i >= 0; i--) |
763 |
|
{ |
764 |
|
// get witness for d_star_insts[f][i] |
765 |
922 |
int j = d_star_insts[f][i]; |
766 |
922 |
if (temp.addEntry(fmfmc, mcond[j], d_quant_models[f].d_value[j])) |
767 |
|
{ |
768 |
890 |
if (!exhaustiveInstantiate(fmfmc, f, mcond[j])) |
769 |
|
{ |
770 |
|
// something went wrong, resort to exhaustive instantiation |
771 |
2 |
return 0; |
772 |
|
} |
773 |
|
} |
774 |
|
} |
775 |
|
} |
776 |
2409 |
return 1; |
777 |
|
} |
778 |
|
|
779 |
|
/** Representative bound fmc entry |
780 |
|
* |
781 |
|
* This bound information corresponds to one |
782 |
|
* entry in a term definition (see terminology in |
783 |
|
* Chapter 5 of Finite Model Finding for |
784 |
|
* Satisfiability Modulo Theories thesis). |
785 |
|
* For example, a term definition for the body |
786 |
|
* of a quantified formula: |
787 |
|
* forall xyz. P( x, y, z ) |
788 |
|
* may be: |
789 |
|
* ( 0, 0, 0 ) -> false |
790 |
|
* ( *, 1, 2 ) -> false |
791 |
|
* ( *, *, * ) -> true |
792 |
|
* Indicating that the quantified formula evaluates |
793 |
|
* to false in the current model for x=0, y=0, z=0, |
794 |
|
* or y=1, z=2 for any x, and evaluates to true |
795 |
|
* otherwise. |
796 |
|
* This class is used if we wish |
797 |
|
* to iterate over all values corresponding to one |
798 |
|
* of these entries. For example, for the second entry: |
799 |
|
* (*, 1, 2 ) |
800 |
|
* we iterate over all values of x, but only {1} |
801 |
|
* for y and {2} for z. |
802 |
|
*/ |
803 |
|
class RepBoundFmcEntry : public QRepBoundExt |
804 |
|
{ |
805 |
|
public: |
806 |
4048 |
RepBoundFmcEntry(QuantifiersBoundInference& qbi, |
807 |
|
Node e, |
808 |
|
FirstOrderModelFmc* f) |
809 |
4048 |
: QRepBoundExt(qbi, f), d_entry(e), d_fm(f) |
810 |
|
{ |
811 |
4048 |
} |
812 |
4048 |
~RepBoundFmcEntry() {} |
813 |
|
/** set bound */ |
814 |
5663 |
virtual RsiEnumType setBound(Node owner, |
815 |
|
unsigned i, |
816 |
|
std::vector<Node>& elements) override |
817 |
|
{ |
818 |
5663 |
if (!d_fm->isStar(d_entry[i])) |
819 |
|
{ |
820 |
|
// only need to consider the single point |
821 |
276 |
elements.push_back(d_entry[i]); |
822 |
276 |
return ENUM_DEFAULT; |
823 |
|
} |
824 |
5387 |
return QRepBoundExt::setBound(owner, i, elements); |
825 |
|
} |
826 |
|
|
827 |
|
private: |
828 |
|
/** the entry for this bound */ |
829 |
|
Node d_entry; |
830 |
|
/** the model builder associated with this bound */ |
831 |
|
FirstOrderModelFmc* d_fm; |
832 |
|
}; |
833 |
|
|
834 |
4048 |
bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc* fm, |
835 |
|
Node f, |
836 |
|
Node c) |
837 |
|
{ |
838 |
4048 |
Trace("fmc-exh") << "----Exhaustive instantiate based on " << c << " "; |
839 |
4048 |
debugPrintCond("fmc-exh", c, true); |
840 |
4048 |
Trace("fmc-exh")<< std::endl; |
841 |
4048 |
QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference(); |
842 |
8096 |
RepBoundFmcEntry rbfe(qbi, c, fm); |
843 |
8096 |
RepSetIterator riter(fm->getRepSet(), &rbfe); |
844 |
4048 |
Trace("fmc-exh-debug") << "Set quantifier..." << std::endl; |
845 |
|
//initialize |
846 |
4048 |
if (riter.setQuantifier(f)) |
847 |
|
{ |
848 |
4048 |
Trace("fmc-exh-debug") << "Set element domains..." << std::endl; |
849 |
4048 |
int addedLemmas = 0; |
850 |
|
//now do full iteration |
851 |
4048 |
Instantiate* ie = d_qim.getInstantiate(); |
852 |
62902 |
while( !riter.isFinished() ){ |
853 |
29427 |
d_triedLemmas++; |
854 |
29427 |
Trace("fmc-exh-debug") << "Inst : "; |
855 |
58854 |
std::vector< Node > ev_inst; |
856 |
58854 |
std::vector< Node > inst; |
857 |
103864 |
for (unsigned i = 0; i < riter.getNumTerms(); i++) |
858 |
|
{ |
859 |
148874 |
TypeNode tn = riter.getTypeOf(i); |
860 |
|
// if the type is not closed enumerable (see |
861 |
|
// TypeNode::isClosedEnumerable), then we must ensure that we are |
862 |
|
// using a term and not a value. This ensures that e.g. uninterpreted |
863 |
|
// constants do not appear in instantiations. |
864 |
148874 |
Node rr = riter.getCurrentTerm(i, !tn.isClosedEnumerable()); |
865 |
148874 |
Node r = fm->getRepresentative(rr); |
866 |
74437 |
debugPrint("fmc-exh-debug", r); |
867 |
74437 |
Trace("fmc-exh-debug") << " (term : " << rr << ")"; |
868 |
74437 |
ev_inst.push_back( r ); |
869 |
74437 |
inst.push_back( rr ); |
870 |
|
} |
871 |
29427 |
int ev_index = d_quant_models[f].getGeneralizationIndex(fm, ev_inst); |
872 |
29427 |
Trace("fmc-exh-debug") << ", index = " << ev_index << " / " << d_quant_models[f].d_value.size(); |
873 |
58854 |
Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index]; |
874 |
29427 |
if (ev!=d_true) { |
875 |
26609 |
Trace("fmc-exh-debug") << ", add!"; |
876 |
|
//add as instantiation |
877 |
26609 |
if (ie->addInstantiation( |
878 |
|
f, inst, InferenceId::QUANTIFIERS_INST_FMF_FMC_EXH, true)) |
879 |
|
{ |
880 |
4857 |
Trace("fmc-exh-debug") << " ...success."; |
881 |
4857 |
addedLemmas++; |
882 |
4857 |
if (d_qstate.isInConflict() || options::fmfOneInstPerRound()) |
883 |
|
{ |
884 |
|
break; |
885 |
|
} |
886 |
|
}else{ |
887 |
21752 |
Trace("fmc-exh-debug") << ", failed."; |
888 |
|
} |
889 |
|
}else{ |
890 |
2818 |
Trace("fmc-exh-debug") << ", already true"; |
891 |
|
} |
892 |
29427 |
Trace("fmc-exh-debug") << std::endl; |
893 |
29427 |
int index = riter.increment(); |
894 |
29427 |
Trace("fmc-exh-debug") << "Incremented index " << index << std::endl; |
895 |
29427 |
if( !riter.isFinished() ){ |
896 |
78807 |
if (index >= 0 && riter.d_index[index] > 0 && addedLemmas > 0 |
897 |
32842 |
&& riter.d_enum_type[index] == ENUM_CUSTOM) |
898 |
|
{ |
899 |
2800 |
Trace("fmc-exh-debug") |
900 |
1400 |
<< "Since this is a custom enumeration, skip to the next..." |
901 |
1400 |
<< std::endl; |
902 |
1400 |
riter.incrementAtIndex(index - 1); |
903 |
|
} |
904 |
|
} |
905 |
|
} |
906 |
4048 |
d_addedLemmas += addedLemmas; |
907 |
4048 |
Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.isIncomplete() << std::endl; |
908 |
4048 |
return addedLemmas>0 || !riter.isIncomplete(); |
909 |
|
}else{ |
910 |
|
Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl; |
911 |
|
return !riter.isIncomplete(); |
912 |
|
} |
913 |
|
} |
914 |
|
|
915 |
98877 |
void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n ) { |
916 |
98877 |
Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl; |
917 |
|
//first check if it is a bounding literal |
918 |
98877 |
if( n.hasAttribute(BoundIntLitAttribute()) ){ |
919 |
|
Trace("fmc-debug") << "It is a bounding literal, polarity = " << n.getAttribute(BoundIntLitAttribute()) << std::endl; |
920 |
|
d.addEntry(fm, mkCondDefault(fm, f), n.getAttribute(BoundIntLitAttribute())==1 ? d_false : d_true ); |
921 |
98877 |
}else if( n.getKind() == kind::BOUND_VARIABLE ){ |
922 |
25026 |
Trace("fmc-debug") << "Add default entry..." << std::endl; |
923 |
25026 |
d.addEntry(fm, mkCondDefault(fm, f), n); |
924 |
|
} |
925 |
73851 |
else if( n.getKind() == kind::NOT ){ |
926 |
|
//just do directly |
927 |
8177 |
doCheck( fm, f, d, n[0] ); |
928 |
8177 |
doNegate( d ); |
929 |
|
} |
930 |
65674 |
else if( n.getKind() == kind::FORALL ){ |
931 |
2975 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
932 |
|
} |
933 |
62699 |
else if( n.getType().isArray() ){ |
934 |
|
//Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl; |
935 |
|
//Trace("fmc-warn") << " Default value was : " << odefaultValue << std::endl; |
936 |
|
//Trace("fmc-debug") << "Can't process base array " << r << std::endl; |
937 |
|
//can't process this array |
938 |
452 |
d.reset(); |
939 |
452 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
940 |
|
} |
941 |
62247 |
else if( n.getNumChildren()==0 ){ |
942 |
20818 |
Node r = n; |
943 |
10409 |
if( !n.isConst() ){ |
944 |
6043 |
if( !fm->hasTerm(n) ){ |
945 |
203 |
r = getSomeDomainElement(fm, n.getType() ); |
946 |
|
} |
947 |
6043 |
r = fm->getRepresentative( r ); |
948 |
|
} |
949 |
10409 |
Trace("fmc-debug") << "Add constant entry..." << std::endl; |
950 |
10409 |
d.addEntry(fm, mkCondDefault(fm, f), r); |
951 |
|
} |
952 |
|
else{ |
953 |
103676 |
std::vector< int > var_ch; |
954 |
103676 |
std::vector< Def > children; |
955 |
136138 |
for( int i=0; i<(int)n.getNumChildren(); i++) { |
956 |
168600 |
Def dc; |
957 |
84300 |
doCheck(fm, f, dc, n[i]); |
958 |
84300 |
children.push_back(dc); |
959 |
84300 |
if( n[i].getKind() == kind::BOUND_VARIABLE ){ |
960 |
25022 |
var_ch.push_back(i); |
961 |
|
} |
962 |
|
} |
963 |
|
|
964 |
51838 |
if( n.getKind()==APPLY_UF ){ |
965 |
27287 |
Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl; |
966 |
|
//uninterpreted compose |
967 |
27287 |
doUninterpretedCompose( fm, f, d, n.getOperator(), children ); |
968 |
|
/* |
969 |
|
} else if( n.getKind()==SELECT ){ |
970 |
|
Trace("fmc-debug") << "Do select compose " << n << std::endl; |
971 |
|
std::vector< Def > children2; |
972 |
|
children2.push_back( children[1] ); |
973 |
|
std::vector< Node > cond; |
974 |
|
mkCondDefaultVec(fm, f, cond); |
975 |
|
std::vector< Node > val; |
976 |
|
doUninterpretedCompose(fm, f, d, children[0], children2, 0, cond, val ); |
977 |
|
*/ |
978 |
|
} else { |
979 |
24551 |
if( !var_ch.empty() ){ |
980 |
1441 |
if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){ |
981 |
818 |
if( var_ch.size()==2 ){ |
982 |
364 |
Trace("fmc-debug") << "Do variable equality " << n << std::endl; |
983 |
364 |
doVariableEquality( fm, f, d, n ); |
984 |
|
}else{ |
985 |
454 |
Trace("fmc-debug") << "Do variable relation " << n << std::endl; |
986 |
454 |
doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] ); |
987 |
|
} |
988 |
|
}else{ |
989 |
623 |
Trace("fmc-warn") << "Don't know how to check " << n << std::endl; |
990 |
623 |
d.addEntry(fm, mkCondDefault(fm, f), Node::null()); |
991 |
|
} |
992 |
|
}else{ |
993 |
23110 |
Trace("fmc-debug") << "Do interpreted compose " << n << std::endl; |
994 |
46220 |
std::vector< Node > cond; |
995 |
23110 |
mkCondDefaultVec(fm, f, cond); |
996 |
46220 |
std::vector< Node > val; |
997 |
|
//interpreted compose |
998 |
23110 |
doInterpretedCompose( fm, f, d, n, children, 0, cond, val ); |
999 |
|
} |
1000 |
|
} |
1001 |
51838 |
Trace("fmc-debug") << "Simplify the definition..." << std::endl; |
1002 |
51838 |
d.debugPrint("fmc-debug", Node::null(), this); |
1003 |
51838 |
d.simplify(this, fm); |
1004 |
51838 |
Trace("fmc-debug") << "Done simplifying" << std::endl; |
1005 |
|
} |
1006 |
98877 |
Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl; |
1007 |
98877 |
d.debugPrint("fmc-debug", Node::null(), this); |
1008 |
98877 |
Trace("fmc-debug") << std::endl; |
1009 |
98877 |
} |
1010 |
|
|
1011 |
8177 |
void FullModelChecker::doNegate( Def & dc ) { |
1012 |
19077 |
for (unsigned i=0; i<dc.d_cond.size(); i++) { |
1013 |
21800 |
Node v = dc.d_value[i]; |
1014 |
10900 |
if (!v.isNull()) |
1015 |
|
{ |
1016 |
|
// In the case that the value is not-constant, we cannot reason about |
1017 |
|
// its value (since the range of this must be a constant or variable). |
1018 |
|
// In particular, returning null here is important if we have (not x) |
1019 |
|
// where x is a bound variable. |
1020 |
7835 |
dc.d_value[i] = |
1021 |
15670 |
v == d_true ? d_false : (v == d_false ? d_true : Node::null()); |
1022 |
|
} |
1023 |
|
} |
1024 |
8177 |
} |
1025 |
|
|
1026 |
364 |
void FullModelChecker::doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq ) { |
1027 |
728 |
std::vector<Node> cond; |
1028 |
364 |
mkCondDefaultVec(fm, f, cond); |
1029 |
364 |
if (eq[0]==eq[1]){ |
1030 |
|
d.addEntry(fm, mkCond(cond), d_true); |
1031 |
|
}else{ |
1032 |
728 |
TypeNode tn = eq[0].getType(); |
1033 |
364 |
if( tn.isSort() ){ |
1034 |
364 |
int j = fm->getVariableId(f, eq[0]); |
1035 |
364 |
int k = fm->getVariableId(f, eq[1]); |
1036 |
364 |
const RepSet* rs = fm->getRepSet(); |
1037 |
364 |
if (!rs->hasType(tn)) |
1038 |
|
{ |
1039 |
|
getSomeDomainElement( fm, tn ); //to verify the type is initialized |
1040 |
|
} |
1041 |
364 |
unsigned nreps = rs->getNumRepresentatives(tn); |
1042 |
1004 |
for (unsigned i = 0; i < nreps; i++) |
1043 |
|
{ |
1044 |
1280 |
Node r = fm->getRepresentative(rs->getRepresentative(tn, i)); |
1045 |
640 |
cond[j+1] = r; |
1046 |
640 |
cond[k+1] = r; |
1047 |
640 |
d.addEntry( fm, mkCond(cond), d_true); |
1048 |
|
} |
1049 |
364 |
d.addEntry( fm, mkCondDefault(fm, f), d_false); |
1050 |
|
}else{ |
1051 |
|
d.addEntry( fm, mkCondDefault(fm, f), Node::null()); |
1052 |
|
} |
1053 |
|
} |
1054 |
364 |
} |
1055 |
|
|
1056 |
454 |
void FullModelChecker::doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v) { |
1057 |
454 |
int j = fm->getVariableId(f, v); |
1058 |
1038 |
for (unsigned i=0; i<dc.d_cond.size(); i++) { |
1059 |
1168 |
Node val = dc.d_value[i]; |
1060 |
584 |
if( val.isNull() ){ |
1061 |
9 |
d.addEntry( fm, dc.d_cond[i], val); |
1062 |
|
}else{ |
1063 |
575 |
if( dc.d_cond[i][j]!=val ){ |
1064 |
453 |
if (fm->isStar(dc.d_cond[i][j])) { |
1065 |
890 |
std::vector<Node> cond; |
1066 |
445 |
mkCondVec(dc.d_cond[i],cond); |
1067 |
445 |
cond[j+1] = val; |
1068 |
445 |
d.addEntry(fm, mkCond(cond), d_true); |
1069 |
445 |
cond[j+1] = fm->getStar(val.getType()); |
1070 |
445 |
d.addEntry(fm, mkCond(cond), d_false); |
1071 |
|
}else{ |
1072 |
8 |
d.addEntry( fm, dc.d_cond[i], d_false); |
1073 |
|
} |
1074 |
|
}else{ |
1075 |
122 |
d.addEntry( fm, dc.d_cond[i], d_true); |
1076 |
|
} |
1077 |
|
} |
1078 |
|
} |
1079 |
454 |
} |
1080 |
|
|
1081 |
27287 |
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) { |
1082 |
27287 |
Trace("fmc-uf-debug") << "Definition : " << std::endl; |
1083 |
27287 |
fm->d_models[op]->debugPrint("fmc-uf-debug", op, this); |
1084 |
27287 |
Trace("fmc-uf-debug") << std::endl; |
1085 |
|
|
1086 |
54574 |
std::vector< Node > cond; |
1087 |
27287 |
mkCondDefaultVec(fm, f, cond); |
1088 |
54574 |
std::vector< Node > val; |
1089 |
27287 |
doUninterpretedCompose( fm, f, d, *fm->d_models[op], dc, 0, cond, val); |
1090 |
27287 |
} |
1091 |
|
|
1092 |
74339 |
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, |
1093 |
|
Def & df, std::vector< Def > & dc, int index, |
1094 |
|
std::vector< Node > & cond, std::vector<Node> & val ) { |
1095 |
74339 |
Trace("fmc-uf-process") << "process at " << index << std::endl; |
1096 |
201183 |
for( unsigned i=1; i<cond.size(); i++) { |
1097 |
126844 |
debugPrint("fmc-uf-process", cond[i], true); |
1098 |
126844 |
Trace("fmc-uf-process") << " "; |
1099 |
|
} |
1100 |
74339 |
Trace("fmc-uf-process") << std::endl; |
1101 |
74339 |
if (index==(int)dc.size()) { |
1102 |
|
//we have an entry, now do actual compose |
1103 |
69462 |
std::map< int, Node > entries; |
1104 |
34731 |
doUninterpretedCompose2( fm, f, entries, 0, cond, val, df.d_et); |
1105 |
34731 |
if( entries.empty() ){ |
1106 |
189 |
d.addEntry(fm, mkCond(cond), Node::null()); |
1107 |
|
}else{ |
1108 |
|
//add them to the definition |
1109 |
132183 |
for( unsigned e=0; e<df.d_cond.size(); e++ ){ |
1110 |
97641 |
if ( entries.find(e)!=entries.end() ){ |
1111 |
60579 |
Trace("fmf-uf-process-debug") << "Add entry..." << std::endl; |
1112 |
60579 |
d.addEntry(fm, entries[e], df.d_value[e] ); |
1113 |
60579 |
Trace("fmf-uf-process-debug") << "Done add entry." << std::endl; |
1114 |
|
} |
1115 |
|
} |
1116 |
|
} |
1117 |
|
}else{ |
1118 |
92542 |
for (unsigned i=0; i<dc[index].d_cond.size(); i++) { |
1119 |
52934 |
if (isCompat(fm, cond, dc[index].d_cond[i])!=0) { |
1120 |
94104 |
std::vector< Node > new_cond; |
1121 |
47052 |
new_cond.insert(new_cond.end(), cond.begin(), cond.end()); |
1122 |
47052 |
if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){ |
1123 |
47052 |
Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl; |
1124 |
47052 |
val.push_back(dc[index].d_value[i]); |
1125 |
47052 |
doUninterpretedCompose(fm, f, d, df, dc, index+1, new_cond, val); |
1126 |
47052 |
val.pop_back(); |
1127 |
|
}else{ |
1128 |
|
Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl; |
1129 |
|
} |
1130 |
|
} |
1131 |
|
} |
1132 |
|
} |
1133 |
74339 |
} |
1134 |
|
|
1135 |
117318 |
void FullModelChecker::doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f, |
1136 |
|
std::map< int, Node > & entries, int index, |
1137 |
|
std::vector< Node > & cond, std::vector< Node > & val, |
1138 |
|
EntryTrie & curr ) { |
1139 |
117318 |
Trace("fmc-uf-process") << "compose " << index << " / " << val.size() << std::endl; |
1140 |
313306 |
for( unsigned i=1; i<cond.size(); i++) { |
1141 |
195988 |
debugPrint("fmc-uf-process", cond[i], true); |
1142 |
195988 |
Trace("fmc-uf-process") << " "; |
1143 |
|
} |
1144 |
117318 |
Trace("fmc-uf-process") << std::endl; |
1145 |
117318 |
if (index==(int)val.size()) { |
1146 |
121158 |
Node c = mkCond(cond); |
1147 |
60579 |
Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl; |
1148 |
60579 |
entries[curr.d_data] = c; |
1149 |
|
}else{ |
1150 |
113478 |
Node v = val[index]; |
1151 |
56739 |
Trace("fmc-uf-process") << "Process " << v << std::endl; |
1152 |
56739 |
bool bind_var = false; |
1153 |
56739 |
if( !v.isNull() && v.getKind()==kind::BOUND_VARIABLE ){ |
1154 |
26703 |
int j = fm->getVariableId(f, v); |
1155 |
26703 |
Trace("fmc-uf-process") << v << " is variable #" << j << std::endl; |
1156 |
26703 |
if (!fm->isStar(cond[j + 1])) |
1157 |
|
{ |
1158 |
38 |
v = cond[j+1]; |
1159 |
|
}else{ |
1160 |
26665 |
bind_var = true; |
1161 |
|
} |
1162 |
|
} |
1163 |
56739 |
if (bind_var) { |
1164 |
26665 |
Trace("fmc-uf-process") << "bind variable..." << std::endl; |
1165 |
26665 |
int j = fm->getVariableId(f, v); |
1166 |
26665 |
Assert(fm->isStar(cond[j + 1])); |
1167 |
73886 |
for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin(); |
1168 |
73886 |
it != curr.d_child.end(); |
1169 |
|
++it) |
1170 |
|
{ |
1171 |
47221 |
cond[j + 1] = it->first; |
1172 |
47221 |
doUninterpretedCompose2( |
1173 |
47221 |
fm, f, entries, index + 1, cond, val, it->second); |
1174 |
|
} |
1175 |
26665 |
cond[j + 1] = fm->getStar(v.getType()); |
1176 |
|
}else{ |
1177 |
30074 |
if( !v.isNull() ){ |
1178 |
29876 |
if (curr.d_child.find(v) != curr.d_child.end()) |
1179 |
|
{ |
1180 |
9496 |
Trace("fmc-uf-process") << "follow value..." << std::endl; |
1181 |
9496 |
doUninterpretedCompose2( |
1182 |
9496 |
fm, f, entries, index + 1, cond, val, curr.d_child[v]); |
1183 |
|
} |
1184 |
59752 |
Node st = fm->getStar(v.getType()); |
1185 |
29876 |
if (curr.d_child.find(st) != curr.d_child.end()) |
1186 |
|
{ |
1187 |
25870 |
Trace("fmc-uf-process") << "follow star..." << std::endl; |
1188 |
25870 |
doUninterpretedCompose2( |
1189 |
25870 |
fm, f, entries, index + 1, cond, val, curr.d_child[st]); |
1190 |
|
} |
1191 |
|
} |
1192 |
|
} |
1193 |
|
} |
1194 |
117318 |
} |
1195 |
|
|
1196 |
102756 |
void FullModelChecker::doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n, |
1197 |
|
std::vector< Def > & dc, int index, |
1198 |
|
std::vector< Node > & cond, std::vector<Node> & val ) { |
1199 |
102756 |
Trace("fmc-if-process") << "int compose " << index << " / " << dc.size() << std::endl; |
1200 |
249067 |
for( unsigned i=1; i<cond.size(); i++) { |
1201 |
146311 |
debugPrint("fmc-if-process", cond[i], true); |
1202 |
146311 |
Trace("fmc-if-process") << " "; |
1203 |
|
} |
1204 |
102756 |
Trace("fmc-if-process") << std::endl; |
1205 |
102756 |
if ( index==(int)dc.size() ){ |
1206 |
96214 |
Node c = mkCond(cond); |
1207 |
96214 |
Node v = evaluateInterpreted(n, val); |
1208 |
48107 |
d.addEntry(fm, c, v); |
1209 |
|
} |
1210 |
|
else { |
1211 |
109298 |
TypeNode vtn = n.getType(); |
1212 |
154356 |
for (unsigned i=0; i<dc[index].d_cond.size(); i++) { |
1213 |
99707 |
if (isCompat(fm, cond, dc[index].d_cond[i])!=0) { |
1214 |
175486 |
std::vector< Node > new_cond; |
1215 |
87743 |
new_cond.insert(new_cond.end(), cond.begin(), cond.end()); |
1216 |
87743 |
if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){ |
1217 |
87743 |
bool process = true; |
1218 |
87743 |
if (vtn.isBoolean()) { |
1219 |
|
//short circuit |
1220 |
130125 |
if( (n.getKind()==OR && dc[index].d_value[i]==d_true) || |
1221 |
61264 |
(n.getKind()==AND && dc[index].d_value[i]==d_false) ){ |
1222 |
16194 |
Node c = mkCond(new_cond); |
1223 |
8097 |
d.addEntry(fm, c, dc[index].d_value[i]); |
1224 |
8097 |
process = false; |
1225 |
|
} |
1226 |
|
} |
1227 |
87743 |
if (process) { |
1228 |
79646 |
val.push_back(dc[index].d_value[i]); |
1229 |
79646 |
doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val); |
1230 |
79646 |
val.pop_back(); |
1231 |
|
} |
1232 |
|
} |
1233 |
|
} |
1234 |
|
} |
1235 |
|
} |
1236 |
102756 |
} |
1237 |
|
|
1238 |
152641 |
int FullModelChecker::isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) { |
1239 |
152641 |
Trace("fmc-debug3") << "isCompat " << c << std::endl; |
1240 |
152641 |
Assert(cond.size() == c.getNumChildren() + 1); |
1241 |
388870 |
for (unsigned i=1; i<cond.size(); i++) { |
1242 |
254075 |
if (cond[i] != c[i - 1] && !fm->isStar(cond[i]) && !fm->isStar(c[i - 1])) |
1243 |
|
{ |
1244 |
17846 |
return 0; |
1245 |
|
} |
1246 |
|
} |
1247 |
134795 |
return 1; |
1248 |
|
} |
1249 |
|
|
1250 |
134795 |
bool FullModelChecker::doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) { |
1251 |
134795 |
Trace("fmc-debug3") << "doMeet " << c << std::endl; |
1252 |
134795 |
Assert(cond.size() == c.getNumChildren() + 1); |
1253 |
356310 |
for (unsigned i=1; i<cond.size(); i++) { |
1254 |
221515 |
if( cond[i]!=c[i-1] ) { |
1255 |
74178 |
if (fm->isStar(cond[i])) |
1256 |
|
{ |
1257 |
43491 |
cond[i] = c[i - 1]; |
1258 |
|
} |
1259 |
30687 |
else if (!fm->isStar(c[i - 1])) |
1260 |
|
{ |
1261 |
|
return false; |
1262 |
|
} |
1263 |
|
} |
1264 |
|
} |
1265 |
134795 |
return true; |
1266 |
|
} |
1267 |
|
|
1268 |
161509 |
Node FullModelChecker::mkCond( std::vector< Node > & cond ) { |
1269 |
161509 |
return NodeManager::currentNM()->mkNode(APPLY_UF, cond); |
1270 |
|
} |
1271 |
|
|
1272 |
43007 |
Node FullModelChecker::mkCondDefault( FirstOrderModelFmc * fm, Node f) { |
1273 |
86014 |
std::vector< Node > cond; |
1274 |
43007 |
mkCondDefaultVec(fm, f, cond); |
1275 |
86014 |
return mkCond(cond); |
1276 |
|
} |
1277 |
|
|
1278 |
93768 |
void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond ) { |
1279 |
93768 |
Trace("fmc-debug") << "Make default vec" << std::endl; |
1280 |
|
//get function symbol for f |
1281 |
93768 |
cond.push_back(d_quant_cond[f]); |
1282 |
244349 |
for (unsigned i=0; i<f[0].getNumChildren(); i++) { |
1283 |
301162 |
Node ts = fm->getStar(f[0][i].getType()); |
1284 |
150581 |
Assert(ts.getType() == f[0][i].getType()); |
1285 |
150581 |
cond.push_back(ts); |
1286 |
|
} |
1287 |
93768 |
} |
1288 |
|
|
1289 |
445 |
void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) { |
1290 |
445 |
cond.push_back(n.getOperator()); |
1291 |
1026 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1292 |
581 |
cond.push_back( n[i] ); |
1293 |
|
} |
1294 |
445 |
} |
1295 |
|
|
1296 |
48107 |
Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) { |
1297 |
48107 |
if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){ |
1298 |
12671 |
if (!vals[0].isNull() && !vals[1].isNull()) { |
1299 |
12369 |
return vals[0]==vals[1] ? d_true : d_false; |
1300 |
|
}else{ |
1301 |
302 |
return Node::null(); |
1302 |
|
} |
1303 |
35436 |
}else if( n.getKind()==ITE ){ |
1304 |
6291 |
if( vals[0]==d_true ){ |
1305 |
2789 |
return vals[1]; |
1306 |
3502 |
}else if( vals[0]==d_false ){ |
1307 |
3458 |
return vals[2]; |
1308 |
|
}else{ |
1309 |
44 |
return vals[1]==vals[2] ? vals[1] : Node::null(); |
1310 |
|
} |
1311 |
29145 |
}else if( n.getKind()==AND || n.getKind()==OR ){ |
1312 |
4951 |
bool isNull = false; |
1313 |
17647 |
for (unsigned i=0; i<vals.size(); i++) { |
1314 |
12696 |
if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) { |
1315 |
|
return vals[i]; |
1316 |
12696 |
}else if( vals[i].isNull() ){ |
1317 |
2547 |
isNull = true; |
1318 |
|
} |
1319 |
|
} |
1320 |
4951 |
return isNull ? Node::null() : vals[0]; |
1321 |
|
}else{ |
1322 |
48388 |
std::vector<Node> children; |
1323 |
24194 |
if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){ |
1324 |
15227 |
children.push_back( n.getOperator() ); |
1325 |
|
} |
1326 |
58559 |
for (unsigned i=0; i<vals.size(); i++) { |
1327 |
34645 |
if( vals[i].isNull() ){ |
1328 |
280 |
return Node::null(); |
1329 |
|
}else{ |
1330 |
34365 |
children.push_back( vals[i] ); |
1331 |
|
} |
1332 |
|
} |
1333 |
47828 |
Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children); |
1334 |
23914 |
Trace("fmc-eval") << "Evaluate " << nc << " to "; |
1335 |
23914 |
nc = Rewriter::rewrite(nc); |
1336 |
23914 |
Trace("fmc-eval") << nc << std::endl; |
1337 |
23914 |
return nc; |
1338 |
|
} |
1339 |
|
} |
1340 |
|
|
1341 |
3619 |
Node FullModelChecker::getSomeDomainElement( FirstOrderModelFmc * fm, TypeNode tn ) { |
1342 |
3619 |
bool addRepId = !fm->getRepSet()->hasType(tn); |
1343 |
3619 |
Node de = fm->getSomeDomainElement(tn); |
1344 |
3619 |
if( addRepId ){ |
1345 |
106 |
d_rep_ids[tn][de] = 0; |
1346 |
|
} |
1347 |
3619 |
return de; |
1348 |
|
} |
1349 |
|
|
1350 |
7645 |
Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix ) { |
1351 |
7645 |
return fm->getFunctionValue(op, argPrefix); |
1352 |
|
} |
1353 |
|
|
1354 |
|
|
1355 |
46849 |
bool FullModelChecker::useSimpleModels() { |
1356 |
93698 |
return options::fmfFmcSimple(); |
1357 |
|
} |
1358 |
21916 |
void FullModelChecker::registerQuantifiedFormula(Node q) |
1359 |
|
{ |
1360 |
21916 |
if (d_quant_cond.find(q) != d_quant_cond.end()) |
1361 |
|
{ |
1362 |
20570 |
return; |
1363 |
|
} |
1364 |
1346 |
NodeManager* nm = NodeManager::currentNM(); |
1365 |
1346 |
SkolemManager* sm = nm->getSkolemManager(); |
1366 |
2692 |
std::vector<TypeNode> types; |
1367 |
3317 |
for (const Node& v : q[0]) |
1368 |
|
{ |
1369 |
3942 |
TypeNode tn = v.getType(); |
1370 |
1971 |
if (tn.isFunction()) |
1371 |
|
{ |
1372 |
|
// we will not use model-based quantifier instantiation for q, since |
1373 |
|
// the model-based instantiation algorithm does not handle (universally |
1374 |
|
// quantified) functions |
1375 |
24 |
d_unhandledQuant.insert(q); |
1376 |
|
} |
1377 |
1971 |
types.push_back(tn); |
1378 |
|
} |
1379 |
2692 |
TypeNode typ = nm->mkFunctionType(types, nm->booleanType()); |
1380 |
2692 |
Node op = sm->mkDummySkolem("qfmc", typ, "op for full-model checking"); |
1381 |
1346 |
d_quant_cond[q] = op; |
1382 |
|
} |
1383 |
|
|
1384 |
21916 |
bool FullModelChecker::isHandled(Node q) const |
1385 |
|
{ |
1386 |
21916 |
return d_unhandledQuant.find(q) == d_unhandledQuant.end(); |
1387 |
|
} |
1388 |
|
|
1389 |
|
} // namespace fmcheck |
1390 |
|
} // namespace quantifiers |
1391 |
|
} // namespace theory |
1392 |
80950 |
} // namespace cvc5 |