1 /********************* */
2 /*! \file quantifiers_engine.cpp
4 ** Original author: Morgan Deters
5 ** Major contributors: Andrew Reynolds
6 ** Minor contributors (to current version): Francois Bobot
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2013 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief Implementation of quantifiers engine class
15 #include "theory/quantifiers_engine.h"
16 #include "theory/theory_engine.h"
17 #include "theory/uf/theory_uf_strong_solver.h"
18 #include "theory/uf/equality_engine.h"
19 #include "theory/arrays/theory_arrays.h"
20 #include "theory/datatypes/theory_datatypes.h"
21 #include "theory/quantifiers/quantifiers_rewriter.h"
22 #include "theory/quantifiers/options.h"
23 #include "theory/quantifiers/model_engine.h"
24 #include "theory/quantifiers/instantiation_engine.h"
25 #include "theory/quantifiers/first_order_model.h"
26 #include "theory/quantifiers/term_database.h"
27 #include "theory/quantifiers/trigger.h"
28 #include "theory/rewriterules/efficient_e_matching.h"
29 #include "theory/rewriterules/rr_trigger.h"
30 #include "theory/quantifiers/bounded_integers.h"
34 using namespace CVC4::kind
;
35 using namespace CVC4::context
;
36 using namespace CVC4::theory
;
37 using namespace CVC4::theory::inst
;
39 QuantifiersEngine::QuantifiersEngine(context::Context
* c
, context::UserContext
* u
, TheoryEngine
* te
):
42 d_lemmas_produced_c(u
){
43 d_eq_query
= new EqualityQueryQuantifiersEngine( this );
44 d_term_db
= new quantifiers::TermDb( this );
45 d_tr_trie
= new inst::TriggerTrie
;
46 d_rr_tr_trie
= new rrinst::TriggerTrie
;
47 d_eem
= new EfficientEMatcher( this );
48 d_hasAddedLemma
= false;
51 if( options::fmfFullModelCheck() ){
52 d_model
= new quantifiers::fmcheck::FirstOrderModelFmc( this, c
, "FirstOrderModelFmc" );
54 d_model
= new quantifiers::FirstOrderModelIG( c
, "FirstOrderModelIG" );
57 //add quantifiers modules
58 if( !options::finiteModelFind() || options::fmfInstEngine() ){
59 //the instantiation must set incomplete flag unless finite model finding is turned on
60 d_inst_engine
= new quantifiers::InstantiationEngine( this, !options::finiteModelFind() );
61 d_modules
.push_back( d_inst_engine
);
65 if( options::finiteModelFind() ){
66 d_model_engine
= new quantifiers::ModelEngine( c
, this );
67 d_modules
.push_back( d_model_engine
);
68 if( options::fmfBoundInt() ){
69 d_bint
= new quantifiers::BoundedIntegers( c
, this );
70 d_modules
.push_back( d_bint
);
75 d_model_engine
= NULL
;
80 d_optInstCheckDuplicate
= true;
81 d_optInstMakeRepresentative
= true;
82 d_optInstAddSplits
= false;
83 d_optMatchIgnoreModelBasis
= false;
84 d_optInstLimitActive
= false;
86 d_total_inst_count_debug
= 0;
89 QuantifiersEngine::~QuantifiersEngine(){
90 delete d_model_engine
;
97 EqualityQuery
* QuantifiersEngine::getEqualityQuery() {
101 //Instantiator* QuantifiersEngine::getInstantiator( theory::TheoryId id ){
102 // return d_te->theoryOf( id )->getInstantiator();
105 context::Context
* QuantifiersEngine::getSatContext(){
106 return d_te
->theoryOf( THEORY_QUANTIFIERS
)->getSatContext();
109 context::Context
* QuantifiersEngine::getUserContext(){
110 return d_te
->theoryOf( THEORY_QUANTIFIERS
)->getUserContext();
113 OutputChannel
& QuantifiersEngine::getOutputChannel(){
114 return d_te
->theoryOf( THEORY_QUANTIFIERS
)->getOutputChannel();
116 /** get default valuation for the quantifiers engine */
117 Valuation
& QuantifiersEngine::getValuation(){
118 return d_te
->theoryOf( THEORY_QUANTIFIERS
)->getValuation();
121 void QuantifiersEngine::finishInit(){
122 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
123 d_modules
[i
]->finishInit();
127 void QuantifiersEngine::check( Theory::Effort e
){
128 CodeTimer
codeTimer(d_time
);
129 bool needsCheck
= e
>=Theory::EFFORT_LAST_CALL
; //always need to check at or above last call
130 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
131 if( d_modules
[i
]->needsCheck( e
) ){
136 Trace("quant-engine") << "Quantifiers Engine check, level = " << e
<< std::endl
;
137 if( !getMasterEqualityEngine()->consistent() ){
138 Trace("quant-engine") << "Master equality engine not consistent, return." << std::endl
;
141 //reset relevant information
142 d_hasAddedLemma
= false;
143 d_term_db
->reset( e
);
145 if( e
==Theory::EFFORT_LAST_CALL
){
146 //if effort is last call, try to minimize model first
147 if( options::finiteModelFind() ){
148 //first, check if we can minimize the model further
149 if( !((uf::TheoryUF
*)getTheoryEngine()->theoryOf( THEORY_UF
))->getStrongSolver()->minimize() ){
153 ++(d_statistics
.d_instantiation_rounds_lc
);
154 }else if( e
==Theory::EFFORT_FULL
){
155 ++(d_statistics
.d_instantiation_rounds
);
157 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
158 d_modules
[i
]->check( e
);
160 //build the model if not done so already
161 // this happens if no quantifiers are currently asserted and no model-building module is enabled
162 if( e
==Theory::EFFORT_LAST_CALL
&& !d_hasAddedLemma
){
163 if( options::produceModels() && !d_model
->isModelSet() ){
164 d_te
->getModelBuilder()->buildModel( d_model
, true );
166 if( Trace
.isOn("inst-per-quant") ){
167 for( std::map
< Node
, int >::iterator it
= d_total_inst_debug
.begin(); it
!= d_total_inst_debug
.end(); ++it
){
168 Trace("inst-per-quant") << " * " << it
->second
<< " for " << it
->first
<< std::endl
;
172 if( Trace
.isOn("inst-per-quant-round") ){
173 for( std::map
< Node
, int >::iterator it
= d_temp_inst_debug
.begin(); it
!= d_temp_inst_debug
.end(); ++it
){
174 Trace("inst-per-quant-round") << " * " << it
->second
<< " for " << it
->first
<< std::endl
;
175 d_temp_inst_debug
[it
->first
] = 0;
179 Trace("quant-engine") << "Finished quantifiers engine check." << std::endl
;
183 void QuantifiersEngine::registerQuantifier( Node f
){
184 if( std::find( d_quants
.begin(), d_quants
.end(), f
)==d_quants
.end() ){
185 d_quants
.push_back( f
);
187 ++(d_statistics
.d_num_quant
);
188 Assert( f
.getKind()==FORALL
);
189 //make instantiation constants for f
190 d_term_db
->makeInstantiationConstantsFor( f
);
191 //register with quantifier relevance
192 d_quant_rel
.registerQuantifier( f
);
193 //register with each module
194 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
195 d_modules
[i
]->registerQuantifier( f
);
197 Node ceBody
= d_term_db
->getInstConstantBody( f
);
198 //generate the phase requirements
199 d_phase_reqs
[f
] = new QuantPhaseReq( ceBody
, true );
200 //also register it with the strong solver
201 if( options::finiteModelFind() ){
202 ((uf::TheoryUF
*)d_te
->theoryOf( THEORY_UF
))->getStrongSolver()->registerQuantifier( f
);
207 void QuantifiersEngine::registerPattern( std::vector
<Node
> & pattern
) {
208 for(std::vector
<Node
>::iterator p
= pattern
.begin(); p
!= pattern
.end(); ++p
){
209 std::set
< Node
> added
;
210 getTermDatabase()->addTerm(*p
,added
);
214 void QuantifiersEngine::assertNode( Node f
){
215 Assert( f
.getKind()==FORALL
);
216 d_model
->assertQuantifier( f
);
217 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
218 d_modules
[i
]->assertNode( f
);
222 void QuantifiersEngine::propagate( Theory::Effort level
){
223 CodeTimer
codeTimer(d_time
);
225 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
226 d_modules
[i
]->propagate( level
);
230 Node
QuantifiersEngine::getNextDecisionRequest(){
231 for( int i
=0; i
<(int)d_modules
.size(); i
++ ){
232 Node n
= d_modules
[i
]->getNextDecisionRequest();
240 void QuantifiersEngine::addTermToDatabase( Node n
, bool withinQuant
){
241 std::set
< Node
> added
;
242 getTermDatabase()->addTerm( n
, added
, withinQuant
);
243 if( options::efficientEMatching() ){
244 d_eem
->newTerms( added
);
246 //added contains also the Node that just have been asserted in this branch
247 for( std::set
< Node
>::iterator i
=added
.begin(), end
=added
.end(); i
!=end
; i
++ ){
249 d_quant_rel
.setRelevance( i
->getOperator(), 0 );
254 void QuantifiersEngine::computeTermVector( Node f
, InstMatch
& m
, std::vector
< Node
>& vars
, std::vector
< Node
>& terms
){
255 for( size_t i
=0; i
<d_term_db
->d_inst_constants
[f
].size(); i
++ ){
256 Node n
= m
.getValue( d_term_db
->d_inst_constants
[f
][i
] );
258 vars
.push_back( f
[0][i
] );
259 terms
.push_back( n
);
264 bool QuantifiersEngine::addInstantiation( Node f
, std::vector
< Node
>& vars
, std::vector
< Node
>& terms
){
265 Assert( f
.getKind()==FORALL
);
266 Assert( vars
.size()==terms
.size() );
267 Node body
= getInstantiation( f
, vars
, terms
);
269 NodeBuilder
<> nb(kind::OR
);
270 nb
<< f
.notNode() << body
;
272 //check for duplication
273 if( addLemma( lem
) ){
274 d_total_inst_debug
[f
]++;
275 d_temp_inst_debug
[f
]++;
276 d_total_inst_count_debug
++;
277 Trace("inst") << "*** Instantiate " << f
<< " with " << std::endl
;
278 uint64_t maxInstLevel
= 0;
279 for( int i
=0; i
<(int)terms
.size(); i
++ ){
280 if( quantifiers::TermDb::hasInstConstAttr(terms
[i
]) ){
281 Debug("inst")<< "***& Bad Instantiate " << f
<< " with " << std::endl
;
282 for( int i
=0; i
<(int)terms
.size(); i
++ ){
283 Debug("inst") << " " << terms
[i
] << std::endl
;
285 Unreachable("Bad instantiation");
287 Trace("inst") << " " << terms
[i
];
288 //Debug("inst-engine") << " " << terms[i].getAttribute(InstLevelAttribute());
289 Trace("inst") << std::endl
;
290 if( terms
[i
].hasAttribute(InstLevelAttribute()) ){
291 if( terms
[i
].getAttribute(InstLevelAttribute())>maxInstLevel
){
292 maxInstLevel
= terms
[i
].getAttribute(InstLevelAttribute());
295 setInstantiationLevelAttr( terms
[i
], 0 );
299 Trace("inst-debug") << "*** Lemma is " << lem
<< std::endl
;
300 setInstantiationLevelAttr( body
, maxInstLevel
+1 );
301 ++(d_statistics
.d_instantiations
);
302 d_statistics
.d_total_inst_var
+= (int)terms
.size();
303 d_statistics
.d_max_instantiation_level
.maxAssign( maxInstLevel
+1 );
306 ++(d_statistics
.d_inst_duplicate
);
311 void QuantifiersEngine::setInstantiationLevelAttr( Node n
, uint64_t level
){
312 if( !n
.hasAttribute(InstLevelAttribute()) ){
313 InstLevelAttribute ila
;
314 n
.setAttribute(ila
,level
);
316 for( int i
=0; i
<(int)n
.getNumChildren(); i
++ ){
317 setInstantiationLevelAttr( n
[i
], level
);
321 Node
QuantifiersEngine::getInstantiation( Node f
, std::vector
< Node
>& vars
, std::vector
< Node
>& terms
){
322 Node body
= f
[ 1 ].substitute( vars
.begin(), vars
.end(), terms
.begin(), terms
.end() );
323 //process partial instantiation if necessary
324 if( d_term_db
->d_vars
[f
].size()!=vars
.size() ){
325 std::vector
< Node
> uninst_vars
;
326 //doing a partial instantiation, must add quantifier for all uninstantiated variables
327 for( int i
=0; i
<(int)f
[0].getNumChildren(); i
++ ){
328 if( std::find( vars
.begin(), vars
.end(), f
[0][i
] )==vars
.end() ){
329 uninst_vars
.push_back( f
[0][i
] );
332 Node bvl
= NodeManager::currentNM()->mkNode( BOUND_VAR_LIST
, uninst_vars
);
333 body
= NodeManager::currentNM()->mkNode( FORALL
, bvl
, body
);
334 Trace("partial-inst") << "Partial instantiation : " << f
<< std::endl
;
335 Trace("partial-inst") << " : " << body
<< std::endl
;
340 Node
QuantifiersEngine::getInstantiation( Node f
, InstMatch
& m
){
341 std::vector
< Node
> vars
;
342 std::vector
< Node
> terms
;
343 computeTermVector( f
, m
, vars
, terms
);
344 return getInstantiation( f
, vars
, terms
);
347 bool QuantifiersEngine::existsInstantiation( Node f
, InstMatch
& m
, bool modEq
, bool modInst
){
348 if( d_inst_match_trie
.find( f
)!=d_inst_match_trie
.end() ){
349 if( d_inst_match_trie
[f
]->existsInstMatch( this, f
, m
, modEq
, modInst
) ){
353 //also check model engine (it may contain instantiations internally)
354 if( d_model_engine
->getModelBuilder()->existsInstantiation( f
, m
, modEq
, modInst
) ){
360 bool QuantifiersEngine::addLemma( Node lem
){
361 Debug("inst-engine-debug") << "Adding lemma : " << lem
<< std::endl
;
362 lem
= Rewriter::rewrite(lem
);
363 if( d_lemmas_produced_c
.find( lem
)==d_lemmas_produced_c
.end() ){
364 //d_curr_out->lemma( lem );
365 d_lemmas_produced_c
[ lem
] = true;
366 d_lemmas_waiting
.push_back( lem
);
367 Debug("inst-engine-debug") << "Added lemma : " << lem
<< std::endl
;
370 Debug("inst-engine-debug") << "Duplicate." << std::endl
;
375 bool QuantifiersEngine::addInstantiation( Node f
, InstMatch
& m
, bool modEq
, bool modInst
, bool mkRep
){
376 Trace("inst-add-debug") << "Add instantiation: " << m
<< std::endl
;
377 //make sure there are values for each variable we are instantiating
378 for( size_t i
=0; i
<f
[0].getNumChildren(); i
++ ){
379 Node ic
= d_term_db
->getInstantiationConstant( f
, i
);
380 Node val
= m
.getValue( ic
);
382 val
= d_term_db
->getFreeVariableForInstConstant( ic
);
383 Trace("inst-add-debug") << "mkComplete " << val
<< std::endl
;
386 //make it representative, this is helpful for recognizing duplication
388 //pick the best possible representative for instantiation, based on past use and simplicity of term
389 Node r
= d_eq_query
->getInternalRepresentative( val
, f
, i
);
390 Trace("inst-add-debug") << "mkRep " << r
<< " " << val
<< std::endl
;
394 //check for duplication modulo equality
395 inst::CDInstMatchTrie
* imt
;
396 std::map
< Node
, inst::CDInstMatchTrie
* >::iterator it
= d_inst_match_trie
.find( f
);
397 if( it
!=d_inst_match_trie
.end() ){
400 imt
= new CDInstMatchTrie( getUserContext() );
401 d_inst_match_trie
[f
] = imt
;
403 Trace("inst-add-debug") << "Adding into inst trie" << std::endl
;
404 if( !imt
->addInstMatch( this, f
, m
, getUserContext(), modEq
, modInst
) ){
405 Trace("inst-add-debug") << " -> Already exists." << std::endl
;
406 ++(d_statistics
.d_inst_duplicate
);
409 Trace("inst-add-debug") << "compute terms" << std::endl
;
410 //compute the vector of terms for the instantiation
411 std::vector
< Node
> terms
;
412 for( size_t i
=0; i
<d_term_db
->d_inst_constants
[f
].size(); i
++ ){
413 Node n
= m
.getValue( d_term_db
->d_inst_constants
[f
][i
] );
414 Assert( !n
.isNull() );
415 terms
.push_back( n
);
417 //add the instantiation
418 bool addedInst
= addInstantiation( f
, d_term_db
->d_vars
[f
], terms
);
421 Trace("inst-add") << "Added instantiation for " << f
<< ": " << std::endl
;
422 Trace("inst-add") << " " << m
<< std::endl
;
423 Trace("inst-add-debug") << " -> Success." << std::endl
;
426 Trace("inst-add-debug") << " -> Lemma already exists." << std::endl
;
431 bool QuantifiersEngine::addSplit( Node n
, bool reqPhase
, bool reqPhasePol
){
432 n
= Rewriter::rewrite( n
);
433 Node lem
= NodeManager::currentNM()->mkNode( OR
, n
, n
.notNode() );
434 if( addLemma( lem
) ){
435 ++(d_statistics
.d_splits
);
436 Debug("inst") << "*** Add split " << n
<< std::endl
;
438 // d_curr_out->requirePhase( n, reqPhasePol );
445 bool QuantifiersEngine::addSplitEquality( Node n1
, Node n2
, bool reqPhase
, bool reqPhasePol
){
446 //Assert( !areEqual( n1, n2 ) );
447 //Assert( !areDisequal( n1, n2 ) );
448 Kind knd
= n1
.getType()==NodeManager::currentNM()->booleanType() ? IFF
: EQUAL
;
449 Node fm
= NodeManager::currentNM()->mkNode( knd
, n1
, n2
);
450 return addSplit( fm
);
453 void QuantifiersEngine::flushLemmas( OutputChannel
* out
){
454 if( !d_lemmas_waiting
.empty() ){
455 //take default output channel if none is provided
456 d_hasAddedLemma
= true;
457 for( int i
=0; i
<(int)d_lemmas_waiting
.size(); i
++ ){
459 out
->lemma( d_lemmas_waiting
[i
] );
462 d_lemmas_waiting
.clear();
466 void QuantifiersEngine::getPhaseReqTerms( Node f
, std::vector
< Node
>& nodes
){
467 if( options::literalMatchMode()!=quantifiers::LITERAL_MATCH_NONE
&& d_phase_reqs
.find( f
)!=d_phase_reqs
.end() ){
468 // doing literal-based matching (consider polarity of literals)
469 for( int i
=0; i
<(int)nodes
.size(); i
++ ){
470 Node prev
= nodes
[i
];
471 bool nodeChanged
= false;
472 if( d_phase_reqs
[f
]->isPhaseReq( nodes
[i
] ) ){
473 bool preq
= d_phase_reqs
[f
]->getPhaseReq( nodes
[i
] );
474 nodes
[i
] = NodeManager::currentNM()->mkNode( IFF
, nodes
[i
], NodeManager::currentNM()->mkConst
<bool>(preq
) );
477 //else if( qe->isPhaseReqEquality( f, trNodes[i] ) ){
478 // Node req = qe->getPhaseReqEquality( f, trNodes[i] );
479 // trNodes[i] = NodeManager::currentNM()->mkNode( EQUAL, trNodes[i], req );
482 Debug("literal-matching") << " Make " << prev
<< " -> " << nodes
[i
] << std::endl
;
483 ++(d_statistics
.d_lit_phase_req
);
485 ++(d_statistics
.d_lit_phase_nreq
);
489 d_statistics
.d_lit_phase_nreq
+= (int)nodes
.size();
493 QuantifiersEngine::Statistics::Statistics():
494 d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
495 d_instantiation_rounds("QuantifiersEngine::Rounds_Instantiation_Full", 0),
496 d_instantiation_rounds_lc("QuantifiersEngine::Rounds_Instantiation_Last_Call", 0),
497 d_instantiations("QuantifiersEngine::Instantiations_Total", 0),
498 d_max_instantiation_level("QuantifiersEngine::Max_Instantiation_Level", 0),
499 d_splits("QuantifiersEngine::Total_Splits", 0),
500 d_total_inst_var("QuantifiersEngine::Vars_Inst", 0),
501 d_total_inst_var_unspec("QuantifiersEngine::Vars_Inst_Unspecified", 0),
502 d_inst_unspec("QuantifiersEngine::Unspecified_Inst", 0),
503 d_inst_duplicate("QuantifiersEngine::Duplicate_Inst", 0),
504 d_lit_phase_req("QuantifiersEngine::lit_phase_req", 0),
505 d_lit_phase_nreq("QuantifiersEngine::lit_phase_nreq", 0),
506 d_triggers("QuantifiersEngine::Triggers", 0),
507 d_simple_triggers("QuantifiersEngine::Triggers_Simple", 0),
508 d_multi_triggers("QuantifiersEngine::Triggers_Multi", 0),
509 d_multi_trigger_instantiations("QuantifiersEngine::Multi_Trigger_Instantiations", 0),
510 d_term_in_termdb("QuantifiersEngine::Term_in_TermDb", 0),
511 d_num_mono_candidates("QuantifiersEngine::NumMonoCandidates", 0),
512 d_num_mono_candidates_new_term("QuantifiersEngine::NumMonoCandidatesNewTerm", 0),
513 d_num_multi_candidates("QuantifiersEngine::NumMultiCandidates", 0),
514 d_mono_candidates_cache_hit("QuantifiersEngine::MonoCandidatesCacheHit", 0),
515 d_mono_candidates_cache_miss("QuantifiersEngine::MonoCandidatesCacheMiss", 0),
516 d_multi_candidates_cache_hit("QuantifiersEngine::MultiCandidatesCacheHit", 0),
517 d_multi_candidates_cache_miss("QuantifiersEngine::MultiCandidatesCacheMiss", 0)
519 StatisticsRegistry::registerStat(&d_num_quant
);
520 StatisticsRegistry::registerStat(&d_instantiation_rounds
);
521 StatisticsRegistry::registerStat(&d_instantiation_rounds_lc
);
522 StatisticsRegistry::registerStat(&d_instantiations
);
523 StatisticsRegistry::registerStat(&d_max_instantiation_level
);
524 StatisticsRegistry::registerStat(&d_splits
);
525 StatisticsRegistry::registerStat(&d_total_inst_var
);
526 StatisticsRegistry::registerStat(&d_total_inst_var_unspec
);
527 StatisticsRegistry::registerStat(&d_inst_unspec
);
528 StatisticsRegistry::registerStat(&d_inst_duplicate
);
529 StatisticsRegistry::registerStat(&d_lit_phase_req
);
530 StatisticsRegistry::registerStat(&d_lit_phase_nreq
);
531 StatisticsRegistry::registerStat(&d_triggers
);
532 StatisticsRegistry::registerStat(&d_simple_triggers
);
533 StatisticsRegistry::registerStat(&d_multi_triggers
);
534 StatisticsRegistry::registerStat(&d_multi_trigger_instantiations
);
535 StatisticsRegistry::registerStat(&d_term_in_termdb
);
536 StatisticsRegistry::registerStat(&d_num_mono_candidates
);
537 StatisticsRegistry::registerStat(&d_num_mono_candidates_new_term
);
538 StatisticsRegistry::registerStat(&d_num_multi_candidates
);
539 StatisticsRegistry::registerStat(&d_mono_candidates_cache_hit
);
540 StatisticsRegistry::registerStat(&d_mono_candidates_cache_miss
);
541 StatisticsRegistry::registerStat(&d_multi_candidates_cache_hit
);
542 StatisticsRegistry::registerStat(&d_multi_candidates_cache_miss
);
545 QuantifiersEngine::Statistics::~Statistics(){
546 StatisticsRegistry::unregisterStat(&d_num_quant
);
547 StatisticsRegistry::unregisterStat(&d_instantiation_rounds
);
548 StatisticsRegistry::unregisterStat(&d_instantiation_rounds_lc
);
549 StatisticsRegistry::unregisterStat(&d_instantiations
);
550 StatisticsRegistry::unregisterStat(&d_max_instantiation_level
);
551 StatisticsRegistry::unregisterStat(&d_splits
);
552 StatisticsRegistry::unregisterStat(&d_total_inst_var
);
553 StatisticsRegistry::unregisterStat(&d_total_inst_var_unspec
);
554 StatisticsRegistry::unregisterStat(&d_inst_unspec
);
555 StatisticsRegistry::unregisterStat(&d_inst_duplicate
);
556 StatisticsRegistry::unregisterStat(&d_lit_phase_req
);
557 StatisticsRegistry::unregisterStat(&d_lit_phase_nreq
);
558 StatisticsRegistry::unregisterStat(&d_triggers
);
559 StatisticsRegistry::unregisterStat(&d_simple_triggers
);
560 StatisticsRegistry::unregisterStat(&d_multi_triggers
);
561 StatisticsRegistry::unregisterStat(&d_multi_trigger_instantiations
);
562 StatisticsRegistry::unregisterStat(&d_term_in_termdb
);
563 StatisticsRegistry::unregisterStat(&d_num_mono_candidates
);
564 StatisticsRegistry::unregisterStat(&d_num_mono_candidates_new_term
);
565 StatisticsRegistry::unregisterStat(&d_num_multi_candidates
);
566 StatisticsRegistry::unregisterStat(&d_mono_candidates_cache_hit
);
567 StatisticsRegistry::unregisterStat(&d_mono_candidates_cache_miss
);
568 StatisticsRegistry::unregisterStat(&d_multi_candidates_cache_hit
);
569 StatisticsRegistry::unregisterStat(&d_multi_candidates_cache_miss
);
572 eq::EqualityEngine
* QuantifiersEngine::getMasterEqualityEngine(){
573 return ((quantifiers::TheoryQuantifiers
*)getTheoryEngine()->theoryOf( THEORY_QUANTIFIERS
))->getMasterEqualityEngine();
576 void EqualityQueryQuantifiersEngine::reset(){
581 bool EqualityQueryQuantifiersEngine::hasTerm( Node a
){
582 return getEngine()->hasTerm( a
);
585 Node
EqualityQueryQuantifiersEngine::getRepresentative( Node a
){
586 eq::EqualityEngine
* ee
= getEngine();
587 if( ee
->hasTerm( a
) ){
588 return ee
->getRepresentative( a
);
593 bool EqualityQueryQuantifiersEngine::areEqual( Node a
, Node b
){
597 eq::EqualityEngine
* ee
= getEngine();
599 return true;//!areDisequal( a, b );
601 if( ee
->hasTerm( a
) && ee
->hasTerm( b
) ){
602 if( ee
->areEqual( a
, b
) ){
611 bool EqualityQueryQuantifiersEngine::areDisequal( Node a
, Node b
){
612 eq::EqualityEngine
* ee
= getEngine();
613 if( ee
->hasTerm( a
) && ee
->hasTerm( b
) ){
614 if( ee
->areDisequal( a
, b
, false ) ){
621 Node
EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a
, Node f
, int index
){
622 Node r
= getRepresentative( a
);
623 if( !options::internalReps() ){
627 if( optInternalRepSortInference() ){
628 sortId
= d_qe
->getTheoryEngine()->getSortInference()->getSortId( f
, f
[0][index
] );
630 if( d_int_rep
[sortId
].find( r
)==d_int_rep
[sortId
].end() ){
631 std::vector
< Node
> eqc
;
632 getEquivalenceClass( r
, eqc
);
633 //find best selection for representative
635 int r_best_score
= -1;
636 for( size_t i
=0; i
<eqc
.size(); i
++ ){
637 int score
= getRepScore( eqc
[i
], f
, index
);
638 if( optInternalRepSortInference() ){
639 int e_sortId
= d_qe
->getTheoryEngine()->getSortInference()->getSortId( eqc
[i
]);
640 if( score
>=0 && e_sortId
!=sortId
){
644 //score prefers earliest use of this term as a representative
645 if( r_best
.isNull() || ( score
>=0 && ( r_best_score
<0 || score
<r_best_score
) ) ){
647 r_best_score
= score
;
650 //now, make sure that no other member of the class is an instance
651 if( !optInternalRepSortInference() ){
652 r_best
= getInstance( r_best
, eqc
);
654 //store that this representative was chosen at this point
655 if( d_rep_score
.find( r_best
)==d_rep_score
.end() ){
656 d_rep_score
[ r_best
] = d_reset_count
;
658 d_int_rep
[sortId
][r
] = r_best
;
660 Trace("internal-rep-debug") << "rep( " << a
<< " ) = " << r
<< ", " << std::endl
;
661 Trace("internal-rep-debug") << "int_rep( " << a
<< " ) = " << r_best
<< ", " << std::endl
;
663 if( optInternalRepSortInference() ){
664 int sortIdBest
= d_qe
->getTheoryEngine()->getSortInference()->getSortId( r_best
);
665 if( sortId
!=sortIdBest
){
666 Trace("sort-inf-rep") << "Choosing representative with bad type " << r_best
<< " " << sortId
<< " " << sortIdBest
<< std::endl
;
671 return d_int_rep
[sortId
][r
];
676 eq::EqualityEngine
* EqualityQueryQuantifiersEngine::getEngine(){
677 return d_qe
->getMasterEqualityEngine();
680 void EqualityQueryQuantifiersEngine::getEquivalenceClass( Node a
, std::vector
< Node
>& eqc
){
681 eq::EqualityEngine
* ee
= getEngine();
682 if( ee
->hasTerm( a
) ){
683 Node rep
= ee
->getRepresentative( a
);
684 eq::EqClassIterator
eqc_iter( rep
, ee
);
685 while( !eqc_iter
.isFinished() ){
686 eqc
.push_back( *eqc_iter
);
692 //a should be in its equivalence class
693 Assert( std::find( eqc
.begin(), eqc
.end(), a
)!=eqc
.end() );
698 Node
EqualityQueryQuantifiersEngine::getInstance( Node n
, std::vector
< Node
>& eqc
){
699 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
700 Node nn
= getInstance( n
[i
], eqc
);
705 if( std::find( eqc
.begin(), eqc
.end(), n
)!=eqc
.end() ){
712 int getDepth( Node n
){
713 if( n
.getNumChildren()==0 ){
717 for( int i
=0; i
<(int)n
.getNumChildren(); i
++ ){
718 int depth
= getDepth( n
[i
] );
719 if( depth
>maxDepth
){
727 int EqualityQueryQuantifiersEngine::getRepScore( Node n
, Node f
, int index
){
728 return d_rep_score
.find( n
)==d_rep_score
.end() ? -1 : d_rep_score
[n
]; //initial
729 //return ( d_rep_score.find( n )==d_rep_score.end() ? 100 : 0 ) + getDepth( n ); //term depth
732 bool EqualityQueryQuantifiersEngine::optInternalRepSortInference() {
733 return false; //shown to be not effective