1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Mathias Preiner, Aina Niemetz
5 * This file is part of the cvc5 project.
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 * ****************************************************************************
13 * Implementation of full model check class.
16 #include "theory/quantifiers/fmf/full_model_check.h"
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"
34 using namespace cvc5::kind
;
35 using namespace cvc5::context
;
39 namespace quantifiers
{
42 struct ModelBasisArgSort
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 bool operator() (int i
,int j
) {
48 return (d_mba_count
[d_terms
[i
]] < d_mba_count
[d_terms
[j
]]);
52 bool EntryTrie::hasGeneralization( FirstOrderModelFmc
* m
, Node c
, int index
) {
53 if (index
==(int)c
.getNumChildren()) {
56 TypeNode tn
= c
[index
].getType();
57 Node st
= m
->getStar(tn
);
58 if(d_child
.find(st
)!=d_child
.end()) {
59 if( d_child
[st
].hasGeneralization(m
, c
, index
+1) ){
63 if( c
[index
]!=st
&& d_child
.find( c
[index
] )!=d_child
.end() ){
64 if( d_child
[ c
[index
] ].hasGeneralization(m
, c
, index
+1) ){
68 if( c
[index
].getType().isSort() ){
69 //for star: check if all children are defined and have generalizations
70 if( c
[index
]==st
){ ///options::fmfFmcCoverSimplify()
71 //check if all children exist and are complete
72 unsigned num_child_def
=
73 d_child
.size() - (d_child
.find(st
) != d_child
.end() ? 1 : 0);
74 if (num_child_def
== m
->getRepSet()->getNumRepresentatives(tn
))
77 for ( std::map
<Node
,EntryTrie
>::iterator it
= d_child
.begin(); it
!= d_child
.end(); ++it
){
78 if( !m
->isStar(it
->first
) ){
79 if( !it
->second
.hasGeneralization(m
, c
, index
+1) ){
96 int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc
* m
, std::vector
<Node
> & inst
, int index
) {
97 Debug("fmc-entry-trie") << "Get generalization index " << inst
.size() << " " << index
<< std::endl
;
98 if (index
==(int)inst
.size()) {
102 Node st
= m
->getStar(inst
[index
].getType());
103 if (d_child
.find(st
) != d_child
.end())
105 minIndex
= d_child
[st
].getGeneralizationIndex(m
, inst
, index
+ 1);
107 Node cc
= inst
[index
];
108 if (cc
!= st
&& d_child
.find(cc
) != d_child
.end())
110 int gindex
= d_child
[cc
].getGeneralizationIndex(m
, inst
, index
+ 1);
111 if (minIndex
== -1 || (gindex
!= -1 && gindex
< minIndex
))
120 void EntryTrie::addEntry( FirstOrderModelFmc
* m
, Node c
, Node v
, int data
, int index
) {
121 if (index
==(int)c
.getNumChildren()) {
127 d_child
[ c
[index
] ].addEntry(m
,c
,v
,data
,index
+1);
134 void EntryTrie::getEntries( FirstOrderModelFmc
* m
, Node c
, std::vector
<int> & compat
, std::vector
<int> & gen
, int index
, bool is_gen
) {
135 if (index
==(int)c
.getNumChildren()) {
138 gen
.push_back(d_data
);
140 compat
.push_back(d_data
);
143 if (m
->isStar(c
[index
])) {
144 for ( std::map
<Node
,EntryTrie
>::iterator it
= d_child
.begin(); it
!= d_child
.end(); ++it
){
145 it
->second
.getEntries(m
, c
, compat
, gen
, index
+1, is_gen
);
148 Node st
= m
->getStar(c
[index
].getType());
149 if(d_child
.find(st
)!=d_child
.end()) {
150 d_child
[st
].getEntries(m
, c
, compat
, gen
, index
+1, false);
152 if( d_child
.find( c
[index
] )!=d_child
.end() ){
153 d_child
[ c
[index
] ].getEntries(m
, c
, compat
, gen
, index
+1, is_gen
);
160 bool Def::addEntry( FirstOrderModelFmc
* m
, Node c
, Node v
) {
161 if (d_et
.hasGeneralization(m
, c
)) {
162 Trace("fmc-debug") << "Already has generalization, skip." << std::endl
;
165 int newIndex
= (int)d_cond
.size();
166 if (!d_has_simplified
) {
167 std::vector
<int> compat
;
168 std::vector
<int> gen
;
169 d_et
.getEntries(m
, c
, compat
, gen
);
170 for( unsigned i
=0; i
<compat
.size(); i
++) {
171 if( d_status
[compat
[i
]]==status_unk
){
172 if( d_value
[compat
[i
]]!=v
){
173 d_status
[compat
[i
]] = status_non_redundant
;
177 for( unsigned i
=0; i
<gen
.size(); i
++) {
178 if( d_status
[gen
[i
]]==status_unk
){
179 if( d_value
[gen
[i
]]==v
){
180 d_status
[gen
[i
]] = status_redundant
;
184 d_status
.push_back( status_unk
);
186 d_et
.addEntry(m
, c
, v
, newIndex
);
188 d_value
.push_back(v
);
192 Node
Def::evaluate( FirstOrderModelFmc
* m
, std::vector
<Node
>& inst
) {
193 int gindex
= d_et
.getGeneralizationIndex(m
, inst
);
195 return d_value
[gindex
];
197 Trace("fmc-warn") << "Warning : evaluation came up null!" << std::endl
;
202 int Def::getGeneralizationIndex( FirstOrderModelFmc
* m
, std::vector
<Node
>& inst
) {
203 return d_et
.getGeneralizationIndex(m
, inst
);
206 void Def::basic_simplify( FirstOrderModelFmc
* m
) {
207 d_has_simplified
= true;
208 std::vector
< Node
> cond
;
209 cond
.insert( cond
.end(), d_cond
.begin(), d_cond
.end() );
211 std::vector
< Node
> value
;
212 value
.insert( value
.end(), d_value
.begin(), d_value
.end() );
215 for (unsigned i
=0; i
<d_status
.size(); i
++) {
216 if( d_status
[i
]!=status_redundant
){
217 addEntry(m
, cond
[i
], value
[i
]);
223 void Def::simplify(FullModelChecker
* mc
, FirstOrderModelFmc
* m
) {
224 Trace("fmc-simplify") << "Simplify definition, #cond = " << d_cond
.size() << std::endl
;
226 Trace("fmc-simplify") << "post-basic simplify, #cond = " << d_cond
.size() << std::endl
;
228 //check if the last entry is not all star, if so, we can make the last entry all stars
229 if( !d_cond
.empty() ){
230 bool last_all_stars
= true;
231 Node cc
= d_cond
[d_cond
.size()-1];
232 for( unsigned i
=0; i
<cc
.getNumChildren(); i
++ ){
233 if (!m
->isStar(cc
[i
]))
235 last_all_stars
= false;
239 if( !last_all_stars
){
240 Trace("fmc-cover-simplify") << "Need to modify last entry to be all stars." << std::endl
;
241 Trace("fmc-cover-simplify") << "Before: " << std::endl
;
242 debugPrint("fmc-cover-simplify",Node::null(), mc
);
243 Trace("fmc-cover-simplify") << std::endl
;
244 std::vector
< Node
> cond
;
245 cond
.insert( cond
.end(), d_cond
.begin(), d_cond
.end() );
247 std::vector
< Node
> value
;
248 value
.insert( value
.end(), d_value
.begin(), d_value
.end() );
251 d_has_simplified
= false;
252 //change the last to all star
253 std::vector
< Node
> nc
;
254 nc
.push_back( cc
.getOperator() );
255 for( unsigned j
=0; j
< cc
.getNumChildren(); j
++){
256 nc
.push_back(m
->getStar(cc
[j
].getType()));
258 cond
[cond
.size()-1] = NodeManager::currentNM()->mkNode( APPLY_UF
, nc
);
260 for (unsigned i
=0; i
<cond
.size(); i
++) {
261 addEntry(m
, cond
[i
], value
[i
]);
263 Trace("fmc-cover-simplify") << "Finished re-adding entries." << std::endl
;
265 Trace("fmc-cover-simplify") << "After: " << std::endl
;
266 debugPrint("fmc-cover-simplify",Node::null(), mc
);
267 Trace("fmc-cover-simplify") << std::endl
;
270 Trace("fmc-simplify") << "finish simplify, #cond = " << d_cond
.size() << std::endl
;
273 void Def::debugPrint(const char * tr
, Node op
, FullModelChecker
* m
) {
275 Trace(tr
) << "Model for " << op
<< " : " << std::endl
;
277 for( unsigned i
=0; i
<d_cond
.size(); i
++) {
278 //print the condition
282 m
->debugPrintCond(tr
, d_cond
[i
], true);
284 m
->debugPrint(tr
, d_value
[i
]);
285 Trace(tr
) << std::endl
;
289 FullModelChecker::FullModelChecker(QuantifiersState
& qs
,
290 QuantifiersInferenceManager
& qim
,
291 QuantifiersRegistry
& qr
,
293 : QModelBuilder(qs
, qim
, qr
, tr
), d_fm(new FirstOrderModelFmc(qs
, qr
, tr
))
295 d_true
= NodeManager::currentNM()->mkConst(true);
296 d_false
= NodeManager::currentNM()->mkConst(false);
299 void FullModelChecker::finishInit() { d_model
= d_fm
.get(); }
301 bool FullModelChecker::preProcessBuildModel(TheoryModel
* m
) {
302 //standard pre-process
303 if( !preProcessBuildModelStd( m
) ){
307 Trace("fmc") << "---Full Model Check preprocess() " << std::endl
;
308 d_preinitialized_eqc
.clear();
309 d_preinitialized_types
.clear();
310 //traverse equality engine
311 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator(m
->getEqualityEngine());
312 while( !eqcs_i
.isFinished() ){
314 TypeNode tr
= r
.getType();
315 d_preinitialized_eqc
[tr
] = r
;
319 //must ensure model basis terms exists in model for each relevant type
320 Trace("fmc") << "preInitialize types..." << std::endl
;
322 for (std::pair
<const Node
, Def
*>& mp
: d_fm
->d_models
)
325 Trace("fmc") << "preInitialize types for " << op
<< std::endl
;
326 TypeNode tno
= op
.getType();
327 for( unsigned i
=0; i
<tno
.getNumChildren(); i
++) {
328 Trace("fmc") << "preInitializeType " << tno
[i
] << std::endl
;
329 preInitializeType(m
, tno
[i
]);
330 Trace("fmc") << "finished preInitializeType " << tno
[i
] << std::endl
;
333 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 for (unsigned i
= 0, nquant
= d_fm
->getNumAssertedQuantifiers(); i
< nquant
;
338 Node q
= d_fm
->getAssertedQuantifier(i
);
339 registerQuantifiedFormula(q
);
344 // make sure all types are set
345 for (const Node
& v
: q
[0])
347 preInitializeType(m
, v
.getType());
353 bool FullModelChecker::processBuildModel(TheoryModel
* m
){
354 if (!m
->areFunctionValuesEnabled())
356 // nothing to do if no functions
359 FirstOrderModelFmc
* fm
= d_fm
.get();
360 Trace("fmc") << "---Full Model Check reset() " << std::endl
;
361 d_quant_models
.clear();
363 d_star_insts
.clear();
364 //process representatives
365 RepSet
* rs
= m
->getRepSetPtr();
366 for (std::map
<TypeNode
, std::vector
<Node
> >::iterator it
=
367 rs
->d_type_reps
.begin();
368 it
!= rs
->d_type_reps
.end();
371 if( it
->first
.isSort() ){
372 Trace("fmc") << "Cardinality( " << it
->first
<< " )" << " = " << it
->second
.size() << std::endl
;
373 for( size_t a
=0; a
<it
->second
.size(); a
++ ){
374 Node r
= m
->getRepresentative(it
->second
[a
]);
375 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
] << ", ";
385 Trace("fmc-model-debug") << "}" << std::endl
;
387 d_rep_ids
[it
->first
][r
] = (int)a
;
389 Trace("fmc-model-debug") << std::endl
;
394 for (std::pair
<const Node
, Def
*>& fmm
: d_fm
->d_models
)
398 d_fm
->d_models
[op
]->reset();
400 std::vector
< Node
> add_conds
;
401 std::vector
< Node
> add_values
;
402 bool needsDefault
= true;
403 if (m
->hasUfTerms(op
))
405 const std::vector
<Node
>& uft
= m
->getUfTerms(op
);
406 Trace("fmc-model-debug")
407 << uft
.size() << " model values for " << op
<< " ... " << std::endl
;
408 for (const Node
& n
: uft
)
410 // only consider unique up to congruence (in model equality engine)?
411 add_conds
.push_back( n
);
412 add_values
.push_back( n
);
413 Node r
= m
->getRepresentative(n
);
414 Trace("fmc-model-debug") << n
<< " -> " << r
<< std::endl
;
417 Trace("fmc-model-debug") << "No model values for " << op
<< " ... " << std::endl
;
419 Trace("fmc-model-debug") << std::endl
;
420 //possibly get default
422 Node nmb
= d_fm
->getModelBasisOpTerm(op
);
423 //add default value if necessary
426 Trace("fmc-model-debug") << "Add default " << nmb
<< std::endl
;
427 add_conds
.push_back( nmb
);
428 add_values
.push_back( nmb
);
430 Node vmb
= getSomeDomainElement(d_fm
.get(), nmb
.getType());
431 Trace("fmc-model-debug") << "Add default to default representative " << nmb
<< " ";
432 Trace("fmc-model-debug")
433 << m
->getRepSet()->getNumRepresentatives(nmb
.getType())
435 add_conds
.push_back( nmb
);
436 add_values
.push_back( vmb
);
440 std::vector
< Node
> conds
;
441 std::vector
< Node
> values
;
442 std::vector
< Node
> entry_conds
;
443 //get the entries for the model
444 for( size_t i
=0; i
<add_conds
.size(); i
++ ){
445 Node c
= add_conds
[i
];
446 Node v
= add_values
[i
];
447 Trace("fmc-model-debug")
448 << "Add cond/value : " << c
<< " -> " << v
<< std::endl
;
449 std::vector
< Node
> children
;
450 std::vector
< Node
> entry_children
;
451 children
.push_back(op
);
452 entry_children
.push_back(op
);
453 bool hasNonStar
= false;
454 for (const Node
& ci
: c
)
456 Node ri
= fm
->getRepresentative(ci
);
457 children
.push_back(ri
);
459 if (fm
->isModelBasisTerm(ri
))
461 ri
= fm
->getStar(ri
.getType());
468 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
;
474 entry_children
.push_back(ri
);
476 Node n
= NodeManager::currentNM()->mkNode( APPLY_UF
, children
);
477 Node nv
= fm
->getRepresentative( v
);
478 Trace("fmc-model-debug")
479 << "Representative of " << v
<< " is " << nv
<< std::endl
;
481 Trace("fmc-warn") << "Warning : model for " << op
<< " has non-constant value in model " << nv
<< std::endl
;
484 Node en
= (useSimpleModels() && hasNonStar
) ? n
: NodeManager::currentNM()->mkNode( APPLY_UF
, entry_children
);
485 if( std::find(conds
.begin(), conds
.end(), n
)==conds
.end() ){
486 Trace("fmc-model-debug") << "- add " << n
<< " -> " << nv
<< " (entry is " << en
<< ")" << std::endl
;
488 values
.push_back(nv
);
489 entry_conds
.push_back(en
);
492 Trace("fmc-model-debug") << "Already have entry for : " << n
<< " -> " << nv
<< " (entry is " << en
<< ")" << std::endl
;
497 //sort based on # default arguments
498 std::vector
< int > indices
;
499 ModelBasisArgSort mbas
;
500 for (int i
=0; i
<(int)conds
.size(); i
++) {
501 mbas
.d_terms
.push_back(conds
[i
]);
502 mbas
.d_mba_count
[conds
[i
]] = fm
->getModelBasisArg(conds
[i
]);
503 indices
.push_back(i
);
505 std::sort( indices
.begin(), indices
.end(), mbas
);
507 for (int i
=0; i
<(int)indices
.size(); i
++) {
508 fm
->d_models
[op
]->addEntry(fm
, entry_conds
[indices
[i
]], values
[indices
[i
]]);
511 Trace("fmc-model-simplify") << "Before simplification : " << std::endl
;
512 fm
->d_models
[op
]->debugPrint("fmc-model-simplify", op
, this);
513 Trace("fmc-model-simplify") << std::endl
;
515 Trace("fmc-model-simplify") << "Simplifying " << op
<< "..." << std::endl
;
516 fm
->d_models
[op
]->simplify( this, fm
);
518 fm
->d_models
[op
]->debugPrint("fmc-model", op
, this);
519 Trace("fmc-model") << std::endl
;
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] );
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] ) );
536 Assert(d_addedLemmas
== 0);
538 //make function values
539 for( std::map
<Node
, Def
* >::iterator it
= fm
->d_models
.begin(); it
!= fm
->d_models
.end(); ++it
){
540 Node f_def
= getFunctionValue( fm
, it
->first
, "$x" );
541 m
->assignFunctionDefinition( it
->first
, f_def
);
543 return TheoryEngineModelBuilder::processBuildModel( m
);
546 void FullModelChecker::preInitializeType(TheoryModel
* m
, TypeNode tn
)
548 if( d_preinitialized_types
.find( tn
)==d_preinitialized_types
.end() ){
549 d_preinitialized_types
[tn
] = true;
550 if (tn
.isFirstClass())
552 Trace("fmc") << "Get model basis term " << tn
<< "..." << std::endl
;
553 Node mb
= d_fm
->getModelBasisTerm(tn
);
554 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 if (!m
->hasTerm(mb
) && !mb
.isConst())
561 std::map
<TypeNode
, Node
>::iterator itpe
= d_preinitialized_eqc
.find(tn
);
562 if (itpe
== d_preinitialized_eqc
.end())
564 Trace("fmc") << "...add model basis term to EE of model " << mb
<< " "
566 m
->getEqualityEngine()->addTerm(mb
);
570 Trace("fmc") << "...add model basis eqc equality to model " << mb
571 << " == " << itpe
->second
<< " " << tn
<< std::endl
;
572 bool ret
= m
->assertEquality(mb
, itpe
->second
, true);
580 void FullModelChecker::debugPrintCond(const char * tr
, Node n
, bool dispStar
) {
582 for( unsigned j
=0; j
<n
.getNumChildren(); j
++) {
583 if( j
>0 ) Trace(tr
) << ", ";
584 debugPrint(tr
, n
[j
], dispStar
);
589 void FullModelChecker::debugPrint(const char * tr
, Node n
, bool dispStar
) {
593 else if (FirstOrderModelFmc::isStar(n
) && dispStar
)
599 TypeNode tn
= n
.getType();
600 if( tn
.isSort() && d_rep_ids
.find(tn
)!=d_rep_ids
.end() ){
601 if (d_rep_ids
[tn
].find(n
)!=d_rep_ids
[tn
].end()) {
602 Trace(tr
) << d_rep_ids
[tn
][n
];
613 int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel
* fm
, Node f
, int effort
) {
614 Trace("fmc") << "Full model check " << f
<< ", effort = " << effort
<< "..." << std::endl
;
615 // register the quantifier
616 registerQuantifiedFormula(f
);
617 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 if (!optUseModel() || !isHandled(f
))
624 FirstOrderModelFmc
* fmfmc
= static_cast<FirstOrderModelFmc
*>(fm
);
627 if (options::mbqiMode() == options::MbqiMode::NONE
)
629 // just exhaustive instantiate
630 Node c
= mkCondDefault(fmfmc
, f
);
631 d_quant_models
[f
].addEntry(fmfmc
, c
, d_false
);
632 if (!exhaustiveInstantiate(fmfmc
, f
, c
))
638 // model check the quantifier
639 doCheck(fmfmc
, f
, d_quant_models
[f
], f
[1]);
640 std::vector
<Node
>& mcond
= d_quant_models
[f
].d_cond
;
641 Trace("fmc") << "Definition for quantifier " << f
<< " is : " << std::endl
;
642 Assert(!mcond
.empty());
643 d_quant_models
[f
].debugPrint("fmc", Node::null(), this);
644 Trace("fmc") << std::endl
;
646 // consider all entries going to non-true
647 Instantiate
* instq
= d_qim
.getInstantiate();
648 for (unsigned i
= 0, msize
= mcond
.size(); i
< msize
; i
++)
650 if (d_quant_models
[f
].d_value
[i
] == d_true
)
655 Trace("fmc-inst") << "Instantiate based on " << mcond
[i
] << "..."
657 bool hasStar
= false;
658 std::vector
<Node
> inst
;
659 for (unsigned j
= 0, nchild
= mcond
[i
].getNumChildren(); j
< nchild
; j
++)
661 if (fmfmc
->isStar(mcond
[i
][j
]))
664 inst
.push_back(fmfmc
->getModelBasisTerm(mcond
[i
][j
].getType()));
668 inst
.push_back(mcond
[i
][j
]);
674 // try obvious (specified by inst)
675 Node ev
= d_quant_models
[f
].evaluate(fmfmc
, inst
);
680 << "...do not instantiate, evaluation was " << ev
<< std::endl
;
686 if (Trace
.isOn("fmc-test-inst"))
688 Node ev
= d_quant_models
[f
].evaluate(fmfmc
, inst
);
691 CVC5Message() << "WARNING: instantiation was true! " << f
<< " "
692 << mcond
[i
] << std::endl
;
697 Trace("fmc-test-inst")
698 << "...instantiation evaluated to false." << std::endl
;
704 Trace("fmc-debug-inst")
705 << "** Instantiation was already true." << std::endl
;
706 // might try it next effort level
707 d_star_insts
[f
].push_back(i
);
710 if (options::fmfBound() || options::stringExp())
712 std::vector
<Node
> cond
;
713 cond
.push_back(d_quant_cond
[f
]);
714 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 Node c
= mkCond(cond
);
718 unsigned prevInst
= d_addedLemmas
;
719 exhaustiveInstantiate(fmfmc
, f
, c
);
720 if (d_addedLemmas
== prevInst
)
722 d_star_insts
[f
].push_back(i
);
726 // just add the instance
728 if (instq
->addInstantiation(f
,
730 InferenceId::QUANTIFIERS_INST_FMF_FMC
,
734 Trace("fmc-debug-inst") << "** Added instantiation." << std::endl
;
736 if (d_qstate
.isInConflict() || options::fmfOneInstPerRound())
743 Trace("fmc-debug-inst")
744 << "** Instantiation was duplicate." << std::endl
;
745 // might try it next effort level
746 d_star_insts
[f
].push_back(i
);
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 std::vector
<Node
>& mcond
= d_quant_models
[f
].d_cond
;
755 if (!d_star_insts
[f
].empty())
757 if (Trace
.isOn("fmc-exh"))
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
;
765 // simplify the exceptions?
766 for (int i
= (d_star_insts
[f
].size() - 1); i
>= 0; i
--)
768 // get witness for d_star_insts[f][i]
769 int j
= d_star_insts
[f
][i
];
770 if (temp
.addEntry(fmfmc
, mcond
[j
], d_quant_models
[f
].d_value
[j
]))
772 if (!exhaustiveInstantiate(fmfmc
, f
, mcond
[j
]))
774 // something went wrong, resort to exhaustive instantiation
783 /** Representative bound fmc entry
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 )
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
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:
804 * we iterate over all values of x, but only {1}
805 * for y and {2} for z.
807 class RepBoundFmcEntry
: public QRepBoundExt
810 RepBoundFmcEntry(QuantifiersBoundInference
& qbi
,
812 FirstOrderModelFmc
* f
)
813 : QRepBoundExt(qbi
, f
), d_entry(e
), d_fm(f
)
816 ~RepBoundFmcEntry() {}
818 virtual RsiEnumType
setBound(Node owner
,
820 std::vector
<Node
>& elements
) override
822 if (!d_fm
->isStar(d_entry
[i
]))
824 // only need to consider the single point
825 elements
.push_back(d_entry
[i
]);
828 return QRepBoundExt::setBound(owner
, i
, elements
);
832 /** the entry for this bound */
834 /** the model builder associated with this bound */
835 FirstOrderModelFmc
* d_fm
;
838 bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc
* fm
,
842 Trace("fmc-exh") << "----Exhaustive instantiate based on " << c
<< " ";
843 debugPrintCond("fmc-exh", c
, true);
844 Trace("fmc-exh")<< std::endl
;
845 QuantifiersBoundInference
& qbi
= d_qreg
.getQuantifiersBoundInference();
846 RepBoundFmcEntry
rbfe(qbi
, c
, fm
);
847 RepSetIterator
riter(fm
->getRepSet(), &rbfe
);
848 Trace("fmc-exh-debug") << "Set quantifier..." << std::endl
;
850 if (riter
.setQuantifier(f
))
852 Trace("fmc-exh-debug") << "Set element domains..." << std::endl
;
854 //now do full iteration
855 Instantiate
* ie
= d_qim
.getInstantiate();
856 while( !riter
.isFinished() ){
858 Trace("fmc-exh-debug") << "Inst : ";
859 std::vector
< Node
> ev_inst
;
860 std::vector
< Node
> inst
;
861 for (unsigned i
= 0; i
< riter
.getNumTerms(); i
++)
863 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 Node rr
= riter
.getCurrentTerm(i
, !tn
.isClosedEnumerable());
869 Node r
= fm
->getRepresentative(rr
);
870 debugPrint("fmc-exh-debug", r
);
871 Trace("fmc-exh-debug") << " (term : " << rr
<< ")";
872 ev_inst
.push_back( r
);
873 inst
.push_back( rr
);
875 int ev_index
= d_quant_models
[f
].getGeneralizationIndex(fm
, ev_inst
);
876 Trace("fmc-exh-debug") << ", index = " << ev_index
<< " / " << d_quant_models
[f
].d_value
.size();
877 Node ev
= ev_index
==-1 ? Node::null() : d_quant_models
[f
].d_value
[ev_index
];
879 Trace("fmc-exh-debug") << ", add!";
880 //add as instantiation
881 if (ie
->addInstantiation(f
,
883 InferenceId::QUANTIFIERS_INST_FMF_FMC_EXH
,
887 Trace("fmc-exh-debug") << " ...success.";
889 if (d_qstate
.isInConflict() || options::fmfOneInstPerRound())
894 Trace("fmc-exh-debug") << ", failed.";
897 Trace("fmc-exh-debug") << ", already true";
899 Trace("fmc-exh-debug") << std::endl
;
900 int index
= riter
.increment();
901 Trace("fmc-exh-debug") << "Incremented index " << index
<< std::endl
;
902 if( !riter
.isFinished() ){
903 if (index
>= 0 && riter
.d_index
[index
] > 0 && addedLemmas
> 0
904 && riter
.d_enum_type
[index
] == ENUM_CUSTOM
)
906 Trace("fmc-exh-debug")
907 << "Since this is a custom enumeration, skip to the next..."
909 riter
.incrementAtIndex(index
- 1);
913 d_addedLemmas
+= addedLemmas
;
914 Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas
<< ", incomplete=" << riter
.isIncomplete() << std::endl
;
915 return addedLemmas
>0 || !riter
.isIncomplete();
917 Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl
;
918 return !riter
.isIncomplete();
922 void FullModelChecker::doCheck(FirstOrderModelFmc
* fm
, Node f
, Def
& d
, Node n
) {
923 Trace("fmc-debug") << "Check " << n
<< " " << n
.getKind() << std::endl
;
924 //first check if it is a bounding literal
925 if( n
.hasAttribute(BoundIntLitAttribute()) ){
926 Trace("fmc-debug") << "It is a bounding literal, polarity = " << n
.getAttribute(BoundIntLitAttribute()) << std::endl
;
927 d
.addEntry(fm
, mkCondDefault(fm
, f
), n
.getAttribute(BoundIntLitAttribute())==1 ? d_false
: d_true
);
928 }else if( n
.getKind() == kind::BOUND_VARIABLE
){
929 Trace("fmc-debug") << "Add default entry..." << std::endl
;
930 d
.addEntry(fm
, mkCondDefault(fm
, f
), n
);
932 else if( n
.getKind() == kind::NOT
){
934 doCheck( fm
, f
, d
, n
[0] );
937 else if( n
.getKind() == kind::FORALL
){
938 d
.addEntry(fm
, mkCondDefault(fm
, f
), Node::null());
940 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
946 d
.addEntry(fm
, mkCondDefault(fm
, f
), Node::null());
948 else if( n
.getNumChildren()==0 ){
951 TypeNode tn
= n
.getType();
952 if( !fm
->hasTerm(n
) && tn
.isFirstClass() ){
953 r
= getSomeDomainElement(fm
, tn
);
955 r
= fm
->getRepresentative( r
);
957 Trace("fmc-debug") << "Add constant entry..." << std::endl
;
958 d
.addEntry(fm
, mkCondDefault(fm
, f
), r
);
961 std::vector
< int > var_ch
;
962 std::vector
< Def
> children
;
963 for( int i
=0; i
<(int)n
.getNumChildren(); i
++) {
965 doCheck(fm
, f
, dc
, n
[i
]);
966 children
.push_back(dc
);
967 if( n
[i
].getKind() == kind::BOUND_VARIABLE
){
972 if( n
.getKind()==APPLY_UF
){
973 Trace("fmc-debug") << "Do uninterpreted compose " << n
<< std::endl
;
974 //uninterpreted compose
975 doUninterpretedCompose( fm
, f
, d
, n
.getOperator(), children
);
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 );
987 if( !var_ch
.empty() ){
988 if( n
.getKind()==EQUAL
&& !n
[0].getType().isBoolean() ){
989 if( var_ch
.size()==2 ){
990 Trace("fmc-debug") << "Do variable equality " << n
<< std::endl
;
991 doVariableEquality( fm
, f
, d
, n
);
993 Trace("fmc-debug") << "Do variable relation " << n
<< std::endl
;
994 doVariableRelation( fm
, f
, d
, var_ch
[0]==0 ? children
[1] : children
[0], var_ch
[0]==0 ? n
[0] : n
[1] );
997 Trace("fmc-warn") << "Don't know how to check " << n
<< std::endl
;
998 d
.addEntry(fm
, mkCondDefault(fm
, f
), Node::null());
1001 Trace("fmc-debug") << "Do interpreted compose " << n
<< std::endl
;
1002 std::vector
< Node
> cond
;
1003 mkCondDefaultVec(fm
, f
, cond
);
1004 std::vector
< Node
> val
;
1005 //interpreted compose
1006 doInterpretedCompose( fm
, f
, d
, n
, children
, 0, cond
, val
);
1009 Trace("fmc-debug") << "Simplify the definition..." << std::endl
;
1010 d
.debugPrint("fmc-debug", Node::null(), this);
1011 d
.simplify(this, fm
);
1012 Trace("fmc-debug") << "Done simplifying" << std::endl
;
1014 Trace("fmc-debug") << "Definition for " << n
<< " is : " << std::endl
;
1015 d
.debugPrint("fmc-debug", Node::null(), this);
1016 Trace("fmc-debug") << std::endl
;
1019 void FullModelChecker::doNegate( Def
& dc
) {
1020 for (unsigned i
=0; i
<dc
.d_cond
.size(); i
++) {
1021 Node v
= dc
.d_value
[i
];
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.
1029 v
== d_true
? d_false
: (v
== d_false
? d_true
: Node::null());
1034 void FullModelChecker::doVariableEquality( FirstOrderModelFmc
* fm
, Node f
, Def
& d
, Node eq
) {
1035 std::vector
<Node
> cond
;
1036 mkCondDefaultVec(fm
, f
, cond
);
1038 d
.addEntry(fm
, mkCond(cond
), d_true
);
1040 TypeNode tn
= eq
[0].getType();
1042 int j
= fm
->getVariableId(f
, eq
[0]);
1043 int k
= fm
->getVariableId(f
, eq
[1]);
1044 const RepSet
* rs
= fm
->getRepSet();
1045 if (!rs
->hasType(tn
))
1047 getSomeDomainElement( fm
, tn
); //to verify the type is initialized
1049 unsigned nreps
= rs
->getNumRepresentatives(tn
);
1050 for (unsigned i
= 0; i
< nreps
; i
++)
1052 Node r
= fm
->getRepresentative(rs
->getRepresentative(tn
, i
));
1055 d
.addEntry( fm
, mkCond(cond
), d_true
);
1057 d
.addEntry( fm
, mkCondDefault(fm
, f
), d_false
);
1059 d
.addEntry( fm
, mkCondDefault(fm
, f
), Node::null());
1064 void FullModelChecker::doVariableRelation( FirstOrderModelFmc
* fm
, Node f
, Def
& d
, Def
& dc
, Node v
) {
1065 int j
= fm
->getVariableId(f
, v
);
1066 for (unsigned i
=0; i
<dc
.d_cond
.size(); i
++) {
1067 Node val
= dc
.d_value
[i
];
1069 d
.addEntry( fm
, dc
.d_cond
[i
], val
);
1071 if( dc
.d_cond
[i
][j
]!=val
){
1072 if (fm
->isStar(dc
.d_cond
[i
][j
])) {
1073 std::vector
<Node
> cond
;
1074 mkCondVec(dc
.d_cond
[i
],cond
);
1076 d
.addEntry(fm
, mkCond(cond
), d_true
);
1077 cond
[j
+1] = fm
->getStar(val
.getType());
1078 d
.addEntry(fm
, mkCond(cond
), d_false
);
1080 d
.addEntry( fm
, dc
.d_cond
[i
], d_false
);
1083 d
.addEntry( fm
, dc
.d_cond
[i
], d_true
);
1089 void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc
* fm
, Node f
, Def
& d
, Node op
, std::vector
< Def
> & dc
) {
1090 Trace("fmc-uf-debug") << "Definition : " << std::endl
;
1091 fm
->d_models
[op
]->debugPrint("fmc-uf-debug", op
, this);
1092 Trace("fmc-uf-debug") << std::endl
;
1094 std::vector
< Node
> cond
;
1095 mkCondDefaultVec(fm
, f
, cond
);
1096 std::vector
< Node
> val
;
1097 doUninterpretedCompose( fm
, f
, d
, *fm
->d_models
[op
], dc
, 0, cond
, val
);
1100 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 Trace("fmc-uf-process") << "process at " << index
<< std::endl
;
1104 for( unsigned i
=1; i
<cond
.size(); i
++) {
1105 debugPrint("fmc-uf-process", cond
[i
], true);
1106 Trace("fmc-uf-process") << " ";
1108 Trace("fmc-uf-process") << std::endl
;
1109 if (index
==(int)dc
.size()) {
1110 //we have an entry, now do actual compose
1111 std::map
< int, Node
> entries
;
1112 doUninterpretedCompose2( fm
, f
, entries
, 0, cond
, val
, df
.d_et
);
1113 if( entries
.empty() ){
1114 d
.addEntry(fm
, mkCond(cond
), Node::null());
1116 //add them to the definition
1117 for( unsigned e
=0; e
<df
.d_cond
.size(); e
++ ){
1118 if ( entries
.find(e
)!=entries
.end() ){
1119 Trace("fmf-uf-process-debug") << "Add entry..." << std::endl
;
1120 d
.addEntry(fm
, entries
[e
], df
.d_value
[e
] );
1121 Trace("fmf-uf-process-debug") << "Done add entry." << std::endl
;
1126 for (unsigned i
=0; i
<dc
[index
].d_cond
.size(); i
++) {
1127 if (isCompat(fm
, cond
, dc
[index
].d_cond
[i
])!=0) {
1128 std::vector
< Node
> new_cond
;
1129 new_cond
.insert(new_cond
.end(), cond
.begin(), cond
.end());
1130 if( doMeet(fm
, new_cond
, dc
[index
].d_cond
[i
]) ){
1131 Trace("fmc-uf-process") << "index " << i
<< " succeeded meet." << std::endl
;
1132 val
.push_back(dc
[index
].d_value
[i
]);
1133 doUninterpretedCompose(fm
, f
, d
, df
, dc
, index
+1, new_cond
, val
);
1136 Trace("fmc-uf-process") << "index " << i
<< " failed meet." << std::endl
;
1143 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 Trace("fmc-uf-process") << "compose " << index
<< " / " << val
.size() << std::endl
;
1148 for( unsigned i
=1; i
<cond
.size(); i
++) {
1149 debugPrint("fmc-uf-process", cond
[i
], true);
1150 Trace("fmc-uf-process") << " ";
1152 Trace("fmc-uf-process") << std::endl
;
1153 if (index
==(int)val
.size()) {
1154 Node c
= mkCond(cond
);
1155 Trace("fmc-uf-entry") << "Entry : " << c
<< " -> index[" << curr
.d_data
<< "]" << std::endl
;
1156 entries
[curr
.d_data
] = c
;
1158 Node v
= val
[index
];
1159 Trace("fmc-uf-process") << "Process " << v
<< std::endl
;
1160 bool bind_var
= false;
1161 if( !v
.isNull() && v
.getKind()==kind::BOUND_VARIABLE
){
1162 int j
= fm
->getVariableId(f
, v
);
1163 Trace("fmc-uf-process") << v
<< " is variable #" << j
<< std::endl
;
1164 if (!fm
->isStar(cond
[j
+ 1]))
1172 Trace("fmc-uf-process") << "bind variable..." << std::endl
;
1173 int j
= fm
->getVariableId(f
, v
);
1174 Assert(fm
->isStar(cond
[j
+ 1]));
1175 for (std::map
<Node
, EntryTrie
>::iterator it
= curr
.d_child
.begin();
1176 it
!= curr
.d_child
.end();
1179 cond
[j
+ 1] = it
->first
;
1180 doUninterpretedCompose2(
1181 fm
, f
, entries
, index
+ 1, cond
, val
, it
->second
);
1183 cond
[j
+ 1] = fm
->getStar(v
.getType());
1186 if (curr
.d_child
.find(v
) != curr
.d_child
.end())
1188 Trace("fmc-uf-process") << "follow value..." << std::endl
;
1189 doUninterpretedCompose2(
1190 fm
, f
, entries
, index
+ 1, cond
, val
, curr
.d_child
[v
]);
1192 Node st
= fm
->getStar(v
.getType());
1193 if (curr
.d_child
.find(st
) != curr
.d_child
.end())
1195 Trace("fmc-uf-process") << "follow star..." << std::endl
;
1196 doUninterpretedCompose2(
1197 fm
, f
, entries
, index
+ 1, cond
, val
, curr
.d_child
[st
]);
1204 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 Trace("fmc-if-process") << "int compose " << index
<< " / " << dc
.size() << std::endl
;
1208 for( unsigned i
=1; i
<cond
.size(); i
++) {
1209 debugPrint("fmc-if-process", cond
[i
], true);
1210 Trace("fmc-if-process") << " ";
1212 Trace("fmc-if-process") << std::endl
;
1213 if ( index
==(int)dc
.size() ){
1214 Node c
= mkCond(cond
);
1215 Node v
= evaluateInterpreted(n
, val
);
1216 d
.addEntry(fm
, c
, v
);
1219 TypeNode vtn
= n
.getType();
1220 for (unsigned i
=0; i
<dc
[index
].d_cond
.size(); i
++) {
1221 if (isCompat(fm
, cond
, dc
[index
].d_cond
[i
])!=0) {
1222 std::vector
< Node
> new_cond
;
1223 new_cond
.insert(new_cond
.end(), cond
.begin(), cond
.end());
1224 if( doMeet(fm
, new_cond
, dc
[index
].d_cond
[i
]) ){
1225 bool process
= true;
1226 if (vtn
.isBoolean()) {
1228 if( (n
.getKind()==OR
&& dc
[index
].d_value
[i
]==d_true
) ||
1229 (n
.getKind()==AND
&& dc
[index
].d_value
[i
]==d_false
) ){
1230 Node c
= mkCond(new_cond
);
1231 d
.addEntry(fm
, c
, dc
[index
].d_value
[i
]);
1236 val
.push_back(dc
[index
].d_value
[i
]);
1237 doInterpretedCompose(fm
, f
, d
, n
, dc
, index
+1, new_cond
, val
);
1246 int FullModelChecker::isCompat( FirstOrderModelFmc
* fm
, std::vector
< Node
> & cond
, Node c
) {
1247 Trace("fmc-debug3") << "isCompat " << c
<< std::endl
;
1248 Assert(cond
.size() == c
.getNumChildren() + 1);
1249 for (unsigned i
=1; i
<cond
.size(); i
++) {
1250 if (cond
[i
] != c
[i
- 1] && !fm
->isStar(cond
[i
]) && !fm
->isStar(c
[i
- 1]))
1258 bool FullModelChecker::doMeet( FirstOrderModelFmc
* fm
, std::vector
< Node
> & cond
, Node c
) {
1259 Trace("fmc-debug3") << "doMeet " << c
<< std::endl
;
1260 Assert(cond
.size() == c
.getNumChildren() + 1);
1261 for (unsigned i
=1; i
<cond
.size(); i
++) {
1262 if( cond
[i
]!=c
[i
-1] ) {
1263 if (fm
->isStar(cond
[i
]))
1267 else if (!fm
->isStar(c
[i
- 1]))
1276 Node
FullModelChecker::mkCond( std::vector
< Node
> & cond
) {
1277 return NodeManager::currentNM()->mkNode(APPLY_UF
, cond
);
1280 Node
FullModelChecker::mkCondDefault( FirstOrderModelFmc
* fm
, Node f
) {
1281 std::vector
< Node
> cond
;
1282 mkCondDefaultVec(fm
, f
, cond
);
1283 return mkCond(cond
);
1286 void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc
* fm
, Node f
, std::vector
< Node
> & cond
) {
1287 Trace("fmc-debug") << "Make default vec" << std::endl
;
1288 //get function symbol for f
1289 cond
.push_back(d_quant_cond
[f
]);
1290 for (unsigned i
=0; i
<f
[0].getNumChildren(); i
++) {
1291 Node ts
= fm
->getStar(f
[0][i
].getType());
1292 Assert(ts
.getType() == f
[0][i
].getType());
1297 void FullModelChecker::mkCondVec( Node n
, std::vector
< Node
> & cond
) {
1298 cond
.push_back(n
.getOperator());
1299 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
1300 cond
.push_back( n
[i
] );
1304 Node
FullModelChecker::evaluateInterpreted( Node n
, std::vector
< Node
> & vals
) {
1305 if( n
.getKind()==EQUAL
&& !n
[0].getType().isBoolean() ){
1306 if (!vals
[0].isNull() && !vals
[1].isNull()) {
1307 return vals
[0]==vals
[1] ? d_true
: d_false
;
1309 return Node::null();
1311 }else if( n
.getKind()==ITE
){
1312 if( vals
[0]==d_true
){
1314 }else if( vals
[0]==d_false
){
1317 return vals
[1]==vals
[2] ? vals
[1] : Node::null();
1319 }else if( n
.getKind()==AND
|| n
.getKind()==OR
){
1320 bool isNull
= false;
1321 for (unsigned i
=0; i
<vals
.size(); i
++) {
1322 if((vals
[i
]==d_true
&& n
.getKind()==OR
) || (vals
[i
]==d_false
&& n
.getKind()==AND
)) {
1324 }else if( vals
[i
].isNull() ){
1328 return isNull
? Node::null() : vals
[0];
1330 std::vector
<Node
> children
;
1331 if( n
.getMetaKind() == kind::metakind::PARAMETERIZED
){
1332 children
.push_back( n
.getOperator() );
1334 for (unsigned i
=0; i
<vals
.size(); i
++) {
1335 if( vals
[i
].isNull() ){
1336 return Node::null();
1338 children
.push_back( vals
[i
] );
1341 Node nc
= NodeManager::currentNM()->mkNode(n
.getKind(), children
);
1342 Trace("fmc-eval") << "Evaluate " << nc
<< " to ";
1343 nc
= Rewriter::rewrite(nc
);
1344 Trace("fmc-eval") << nc
<< std::endl
;
1349 Node
FullModelChecker::getSomeDomainElement( FirstOrderModelFmc
* fm
, TypeNode tn
) {
1350 bool addRepId
= !fm
->getRepSet()->hasType(tn
);
1351 Node de
= fm
->getSomeDomainElement(tn
);
1353 d_rep_ids
[tn
][de
] = 0;
1358 Node
FullModelChecker::getFunctionValue(FirstOrderModelFmc
* fm
, Node op
, const char* argPrefix
) {
1359 return fm
->getFunctionValue(op
, argPrefix
);
1363 bool FullModelChecker::useSimpleModels() {
1364 return options::fmfFmcSimple();
1366 void FullModelChecker::registerQuantifiedFormula(Node q
)
1368 if (d_quant_cond
.find(q
) != d_quant_cond
.end())
1372 NodeManager
* nm
= NodeManager::currentNM();
1373 SkolemManager
* sm
= nm
->getSkolemManager();
1374 std::vector
<TypeNode
> types
;
1375 for (const Node
& v
: q
[0])
1377 TypeNode tn
= v
.getType();
1378 if (tn
.isFunction())
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 d_unhandledQuant
.insert(q
);
1385 types
.push_back(tn
);
1387 TypeNode typ
= nm
->mkFunctionType(types
, nm
->booleanType());
1388 Node op
= sm
->mkDummySkolem("qfmc", typ
, "op for full-model checking");
1389 d_quant_cond
[q
] = op
;
1392 bool FullModelChecker::isHandled(Node q
) const
1394 return d_unhandledQuant
.find(q
) == d_unhandledQuant
.end();
1397 } // namespace fmcheck
1398 } // namespace quantifiers
1399 } // namespace theory