c4b10eb6f286ece6b684b417e6126cd556ca5bd7
1 /********************* */
2 /*! \file term_database.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Tim King, Morgan Deters
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
12 ** \brief Implementation of term databse class
15 #include "theory/quantifiers/term_database.h"
17 #include "options/base_options.h"
18 #include "options/quantifiers_options.h"
19 #include "options/uf_options.h"
20 #include "theory/quantifiers/quantifiers_attributes.h"
21 #include "theory/quantifiers/term_util.h"
22 #include "theory/quantifiers/ematching/trigger.h"
23 #include "theory/quantifiers_engine.h"
24 #include "theory/theory_engine.h"
27 using namespace CVC4::kind
;
28 using namespace CVC4::context
;
29 using namespace CVC4::theory::inst
;
33 namespace quantifiers
{
35 TermDb::TermDb(context::Context
* c
, context::UserContext
* u
,
36 QuantifiersEngine
* qe
)
39 d_consistent_ee
= true;
40 d_true
= NodeManager::currentNM()->mkConst(true);
41 d_false
= NodeManager::currentNM()->mkConst(false);
48 void TermDb::registerQuantifier( Node q
) {
49 Assert( q
[0].getNumChildren()==d_quantEngine
->getTermUtil()->getNumInstantiationConstants( q
) );
50 for( unsigned i
=0; i
<q
[0].getNumChildren(); i
++ ){
51 Node ic
= d_quantEngine
->getTermUtil()->getInstantiationConstant( q
, i
);
52 setTermInactive( ic
);
56 unsigned TermDb::getNumOperators() { return d_ops
.size(); }
57 Node
TermDb::getOperator(unsigned i
)
59 Assert(i
< d_ops
.size());
64 unsigned TermDb::getNumGroundTerms(Node f
) const
66 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_op_map
.find(f
);
67 if( it
!=d_op_map
.end() ){
68 return it
->second
.size();
74 Node
TermDb::getGroundTerm(Node f
, unsigned i
) const
76 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_op_map
.find(f
);
77 if (it
!= d_op_map
.end())
79 Assert(i
< it
->second
.size());
89 unsigned TermDb::getNumTypeGroundTerms(TypeNode tn
) const
91 std::map
<TypeNode
, std::vector
<Node
> >::const_iterator it
=
93 if( it
!=d_type_map
.end() ){
94 return it
->second
.size();
100 Node
TermDb::getTypeGroundTerm(TypeNode tn
, unsigned i
) const
102 std::map
<TypeNode
, std::vector
<Node
> >::const_iterator it
=
104 if (it
!= d_type_map
.end())
106 Assert(i
< it
->second
.size());
107 return it
->second
[i
];
116 Node
TermDb::getOrMakeTypeGroundTerm(TypeNode tn
)
118 std::map
<TypeNode
, std::vector
<Node
> >::const_iterator it
=
120 if (it
!= d_type_map
.end())
122 Assert(!it
->second
.empty());
123 return it
->second
[0];
127 return getOrMakeTypeFreshVariable(tn
);
131 Node
TermDb::getOrMakeTypeFreshVariable(TypeNode tn
)
133 std::unordered_map
<TypeNode
, Node
, TypeNodeHashFunction
>::iterator it
=
135 if (it
== d_type_fv
.end())
137 std::stringstream ss
;
138 ss
<< language::SetLanguage(options::outputLanguage());
140 Node k
= NodeManager::currentNM()->mkSkolem(
141 ss
.str(), tn
, "is a termDb fresh variable");
142 Trace("mkVar") << "TermDb:: Make variable " << k
<< " : " << tn
144 if (options::instMaxLevel() != -1)
146 QuantAttributes::setInstantiationLevelAttr(k
, 0);
157 Node
TermDb::getMatchOperator( Node n
) {
158 Kind k
= n
.getKind();
159 //datatype operators may be parametric, always assume they are
160 if( k
==SELECT
|| k
==STORE
|| k
==UNION
|| k
==INTERSECTION
|| k
==SUBSET
|| k
==SETMINUS
|| k
==MEMBER
|| k
==SINGLETON
||
161 k
==APPLY_SELECTOR_TOTAL
|| k
==APPLY_TESTER
|| k
==SEP_PTO
|| k
==HO_APPLY
){
162 //since it is parametric, use a particular one as op
163 TypeNode tn
= n
[0].getType();
164 Node op
= n
.getOperator();
165 std::map
< Node
, std::map
< TypeNode
, Node
> >::iterator ito
= d_par_op_map
.find( op
);
166 if( ito
!=d_par_op_map
.end() ){
167 std::map
< TypeNode
, Node
>::iterator it
= ito
->second
.find( tn
);
168 if( it
!=ito
->second
.end() ){
172 Trace("par-op") << "Parametric operator : " << k
<< ", " << n
.getOperator() << ", " << tn
<< " : " << n
<< std::endl
;
173 d_par_op_map
[op
][tn
] = n
;
175 }else if( inst::Trigger::isAtomicTriggerKind( k
) ){
176 return n
.getOperator();
182 void TermDb::addTerm(Node n
,
183 std::set
<Node
>& added
,
185 bool withinInstClosure
)
187 //don't add terms in quantifier bodies
188 if( withinQuant
&& !options::registerQuantBodyTerms() ){
192 if (d_processed
.find(n
) == d_processed
.end())
194 d_processed
.insert(n
);
195 if (!TermUtil::hasInstConstAttr(n
))
197 Trace("term-db-debug") << "register term : " << n
<< std::endl
;
198 d_type_map
[n
.getType()].push_back(n
);
199 // if this is an atomic trigger, consider adding it
200 if (inst::Trigger::isAtomicTrigger(n
))
202 Trace("term-db") << "register term in db " << n
<< std::endl
;
204 Node op
= getMatchOperator(n
);
205 Trace("term-db-debug") << " match operator is : " << op
<< std::endl
;
206 if (d_op_map
.find(op
) == d_op_map
.end())
210 d_op_map
[op
].push_back(n
);
212 // If we are higher-order, we may need to register more terms.
215 addTermHo(n
, added
, withinQuant
, withinInstClosure
);
225 if (withinInstClosure
226 && d_iclosure_processed
.find(n
) == d_iclosure_processed
.end())
228 d_iclosure_processed
.insert(n
);
231 if (rec
&& !n
.isClosure())
233 for (const Node
& nc
: n
)
235 addTerm(nc
, added
, withinQuant
, withinInstClosure
);
240 void TermDb::computeArgReps( TNode n
) {
241 if (d_arg_reps
.find(n
) == d_arg_reps
.end())
243 eq::EqualityEngine
* ee
= d_quantEngine
->getActiveEqualityEngine();
244 for (const TNode
& nc
: n
)
246 TNode r
= ee
->hasTerm(nc
) ? ee
->getRepresentative(nc
) : nc
;
247 d_arg_reps
[n
].push_back( r
);
252 void TermDb::computeUfEqcTerms( TNode f
) {
253 Assert( f
==getOperatorRepresentative( f
) );
254 if (d_func_map_eqc_trie
.find(f
) != d_func_map_eqc_trie
.end())
258 d_func_map_eqc_trie
[f
].clear();
259 // get the matchable operators in the equivalence class of f
260 std::vector
<TNode
> ops
;
264 ops
.insert(ops
.end(), d_ho_op_slaves
[f
].begin(), d_ho_op_slaves
[f
].end());
266 eq::EqualityEngine
* ee
= d_quantEngine
->getActiveEqualityEngine();
267 for (const Node
& ff
: ops
)
269 for (const TNode
& n
: d_op_map
[ff
])
271 if (hasTermCurrent(n
) && isTermActive(n
))
274 TNode r
= ee
->hasTerm(n
) ? ee
->getRepresentative(n
) : n
;
275 d_func_map_eqc_trie
[f
].d_data
[r
].addTerm(n
, d_arg_reps
[n
]);
281 void TermDb::computeUfTerms( TNode f
) {
282 if (d_op_nonred_count
.find(f
) != d_op_nonred_count
.end())
287 Assert( f
==getOperatorRepresentative( f
) );
288 d_op_nonred_count
[f
] = 0;
289 // get the matchable operators in the equivalence class of f
290 std::vector
<TNode
> ops
;
294 ops
.insert(ops
.end(), d_ho_op_slaves
[f
].begin(), d_ho_op_slaves
[f
].end());
296 Trace("term-db-debug") << "computeUfTerms for " << f
<< std::endl
;
297 unsigned congruentCount
= 0;
298 unsigned nonCongruentCount
= 0;
299 unsigned alreadyCongruentCount
= 0;
300 unsigned relevantCount
= 0;
301 eq::EqualityEngine
* ee
= d_quantEngine
->getActiveEqualityEngine();
302 NodeManager
* nm
= NodeManager::currentNM();
303 for (const Node
& ff
: ops
)
305 std::map
<Node
, std::vector
<Node
> >::iterator it
= d_op_map
.find(ff
);
306 if (it
== d_op_map
.end())
308 // no terms for this operator
311 Trace("term-db-debug") << "Adding terms for operator " << ff
<< std::endl
;
312 for (const Node
& n
: it
->second
)
314 // to be added to term index, term must be relevant, and exist in EE
315 if (!hasTermCurrent(n
) || !ee
->hasTerm(n
))
317 Trace("term-db-debug") << n
<< " is not relevant." << std::endl
;
322 if (!isTermActive(n
))
324 Trace("term-db-debug") << n
<< " is already redundant." << std::endl
;
325 alreadyCongruentCount
++;
330 Trace("term-db-debug") << "Adding term " << n
<< " with arg reps : ";
331 for (unsigned i
= 0, size
= d_arg_reps
[n
].size(); i
< size
; i
++)
333 Trace("term-db-debug") << d_arg_reps
[n
][i
] << " ";
334 if (std::find(d_func_map_rel_dom
[f
][i
].begin(),
335 d_func_map_rel_dom
[f
][i
].end(),
337 == d_func_map_rel_dom
[f
][i
].end())
339 d_func_map_rel_dom
[f
][i
].push_back(d_arg_reps
[n
][i
]);
342 Trace("term-db-debug") << std::endl
;
343 Assert(ee
->hasTerm(n
));
344 Trace("term-db-debug") << " and value : " << ee
->getRepresentative(n
)
346 Node at
= d_func_map_trie
[f
].addOrGetTerm(n
, d_arg_reps
[n
]);
347 Assert(ee
->hasTerm(at
));
348 Trace("term-db-debug2") << "...add term returned " << at
<< std::endl
;
349 if (at
!= n
&& ee
->areEqual(at
, n
))
352 Trace("term-db-debug") << n
<< " is redundant." << std::endl
;
356 if (ee
->areDisequal(at
, n
, false))
358 std::vector
<Node
> lits
;
359 lits
.push_back(nm
->mkNode(EQUAL
, at
, n
));
363 // operators might be disequal
366 Node atf
= getMatchOperator(at
);
367 Node nf
= getMatchOperator(n
);
370 if (at
.getKind() == APPLY_UF
&& n
.getKind() == APPLY_UF
)
372 lits
.push_back(atf
.eqNode(nf
).negate());
384 Assert(at
.getNumChildren() == n
.getNumChildren());
385 for (unsigned k
= 0, size
= at
.getNumChildren(); k
< size
; k
++)
389 lits
.push_back(nm
->mkNode(EQUAL
, at
[k
], n
[k
]).negate());
392 Node lem
= lits
.size() == 1 ? lits
[0] : nm
->mkNode(OR
, lits
);
393 if (Trace
.isOn("term-db-lemma"))
395 Trace("term-db-lemma") << "Disequal congruent terms : " << at
<< " "
396 << n
<< "!!!!" << std::endl
;
397 if (!d_quantEngine
->getTheoryEngine()->needCheck())
399 Trace("term-db-lemma") << " all theories passed with no lemmas."
401 // we should be a full effort check, prior to theory combination
403 Trace("term-db-lemma") << " add lemma : " << lem
<< std::endl
;
405 d_quantEngine
->addLemma(lem
);
406 d_quantEngine
->setConflict();
407 d_consistent_ee
= false;
412 d_op_nonred_count
[f
]++;
414 if (Trace
.isOn("tdb"))
416 Trace("tdb") << "Term db size [" << f
<< "] : " << nonCongruentCount
418 Trace("tdb") << (nonCongruentCount
+ congruentCount
) << " / "
419 << (nonCongruentCount
+ congruentCount
420 + alreadyCongruentCount
)
422 Trace("tdb") << relevantCount
<< " / " << it
->second
.size() << std::endl
;
427 void TermDb::addTermHo(Node n
,
428 std::set
<Node
>& added
,
430 bool withinInstClosure
)
432 Assert(options::ufHo());
433 if (n
.getType().isFunction())
435 // nothing special to do with functions
438 NodeManager
* nm
= NodeManager::currentNM();
440 std::vector
<Node
> args
;
441 while (curr
.getKind() == HO_APPLY
)
443 args
.insert(args
.begin(), curr
[1]);
448 std::map
<Node
, Node
>::iterator itp
= d_ho_fun_op_purify
.find(curr
);
450 if (itp
== d_ho_fun_op_purify
.end())
452 psk
= nm
->mkSkolem("pfun",
454 "purify for function operator term indexing");
455 d_ho_fun_op_purify
[curr
] = psk
;
456 // we do not add it to d_ops since it is an internal operator
462 std::vector
<Node
> children
;
463 children
.push_back(psk
);
464 children
.insert(children
.end(), args
.begin(), args
.end());
465 Node p_n
= nm
->mkNode(APPLY_UF
, children
);
466 Trace("term-db") << "register term in db (via purify) " << p_n
468 // also add this one internally
469 d_op_map
[psk
].push_back(p_n
);
470 // maintain backwards mapping
471 d_ho_purify_to_term
[p_n
] = n
;
474 if (!args
.empty() && curr
.isVar())
476 // also add standard application version
477 args
.insert(args
.begin(), curr
);
478 Node uf_n
= nm
->mkNode(APPLY_UF
, args
);
479 addTerm(uf_n
, added
, withinQuant
, withinInstClosure
);
483 Node
TermDb::getOperatorRepresentative( TNode op
) const {
484 std::map
< TNode
, TNode
>::const_iterator it
= d_ho_op_rep
.find( op
);
485 if( it
!=d_ho_op_rep
.end() ){
492 bool TermDb::inRelevantDomain( TNode f
, unsigned i
, TNode r
) {
493 if( options::ufHo() ){
494 f
= getOperatorRepresentative( f
);
497 Assert( !d_quantEngine
->getActiveEqualityEngine()->hasTerm( r
) ||
498 d_quantEngine
->getActiveEqualityEngine()->getRepresentative( r
)==r
);
499 std::map
< Node
, std::map
< unsigned, std::vector
< Node
> > >::iterator it
= d_func_map_rel_dom
.find( f
);
500 if( it
!= d_func_map_rel_dom
.end() ){
501 std::map
< unsigned, std::vector
< Node
> >::iterator it2
= it
->second
.find( i
);
502 if( it2
!=it
->second
.end() ){
503 return std::find( it2
->second
.begin(), it2
->second
.end(), r
)!=it2
->second
.end();
512 Node
TermDb::evaluateTerm2(TNode n
,
513 std::map
<TNode
, Node
>& visited
,
514 std::vector
<Node
>& exp
,
516 bool useEntailmentTests
,
520 std::map
< TNode
, Node
>::iterator itv
= visited
.find( n
);
521 if( itv
!= visited
.end() ){
524 size_t prevSize
= exp
.size();
525 Trace("term-db-eval") << "evaluate term : " << n
<< std::endl
;
527 if( n
.getKind()==FORALL
|| n
.getKind()==BOUND_VARIABLE
){
530 else if (qy
->hasTerm(n
))
532 Trace("term-db-eval") << "...exists in ee, return rep" << std::endl
;
533 ret
= qy
->getRepresentative(n
);
538 exp
.push_back(n
.eqNode(ret
));
543 else if (n
.hasOperator())
545 std::vector
<TNode
> args
;
546 bool ret_set
= false;
547 Kind k
= n
.getKind();
548 std::vector
<Node
> tempExp
;
549 for (unsigned i
= 0, nchild
= n
.getNumChildren(); i
< nchild
; i
++)
551 TNode c
= evaluateTerm2(n
[i
],
564 else if (c
== d_true
|| c
== d_false
)
567 if ((k
== AND
&& c
== d_false
) || (k
== OR
&& c
== d_true
))
574 else if (k
== ITE
&& i
== 0)
576 ret
= evaluateTerm2(n
[c
== d_true
? 1 : 2],
590 exp
.insert(exp
.end(), tempExp
.begin(), tempExp
.end());
592 Trace("term-db-eval") << " child " << i
<< " : " << c
<< std::endl
;
597 // if we short circuited
601 exp
.insert(exp
.end(), tempExp
.begin(), tempExp
.end());
606 // get the (indexed) operator of n, if it exists
607 TNode f
= getMatchOperator(n
);
608 // if it is an indexed term, return the congruent term
611 // if f is congruent to a term indexed by this class
612 TNode nn
= qy
->getCongruentTerm(f
, args
);
613 Trace("term-db-eval") << " got congruent term " << nn
614 << " from DB for " << n
<< std::endl
;
619 Assert(nn
.getNumChildren() == n
.getNumChildren());
620 for (unsigned i
= 0, nchild
= nn
.getNumChildren(); i
< nchild
; i
++)
624 exp
.push_back(nn
[i
].eqNode(n
[i
]));
628 ret
= qy
->getRepresentative(nn
);
629 Trace("term-db-eval") << "return rep" << std::endl
;
632 Assert(!ret
.isNull());
637 exp
.push_back(nn
.eqNode(ret
));
643 Trace("term-db-eval") << "return rewrite" << std::endl
;
644 // a theory symbol or a new UF term
645 if (n
.getMetaKind() == metakind::PARAMETERIZED
)
647 args
.insert(args
.begin(), n
.getOperator());
649 ret
= NodeManager::currentNM()->mkNode(n
.getKind(), args
);
650 ret
= Rewriter::rewrite(ret
);
651 if (ret
.getKind() == EQUAL
)
653 if (qy
->areDisequal(ret
[0], ret
[1]))
658 if (useEntailmentTests
)
660 if (ret
.getKind() == EQUAL
|| ret
.getKind() == GEQ
)
662 TheoryEngine
* te
= d_quantEngine
->getTheoryEngine();
663 for (unsigned j
= 0; j
< 2; j
++)
665 std::pair
<bool, Node
> et
= te
->entailmentCheck(
666 THEORY_OF_TYPE_BASED
, j
== 0 ? ret
: ret
.negate());
669 ret
= j
== 0 ? d_true
: d_false
;
672 exp
.push_back(et
.second
);
682 // must have the term
683 if (reqHasTerm
&& !ret
.isNull())
685 Kind k
= ret
.getKind();
686 if (k
!= OR
&& k
!= AND
&& k
!= EQUAL
&& k
!= ITE
&& k
!= NOT
689 if (!qy
->hasTerm(ret
))
695 Trace("term-db-eval") << "evaluated term : " << n
<< ", got : " << ret
696 << ", reqHasTerm = " << reqHasTerm
<< std::endl
;
697 // clear the explanation if failed
698 if (computeExp
&& ret
.isNull())
700 exp
.resize(prevSize
);
707 TNode
TermDb::getEntailedTerm2( TNode n
, std::map
< TNode
, TNode
>& subs
, bool subsRep
, bool hasSubs
, EqualityQuery
* qy
) {
708 Assert( !qy
->extendsEngine() );
709 Trace("term-db-entail") << "get entailed term : " << n
<< std::endl
;
710 if( qy
->getEngine()->hasTerm( n
) ){
711 Trace("term-db-entail") << "...exists in ee, return rep " << std::endl
;
713 }else if( n
.getKind()==BOUND_VARIABLE
){
715 std::map
< TNode
, TNode
>::iterator it
= subs
.find( n
);
716 if( it
!=subs
.end() ){
717 Trace("term-db-entail") << "...substitution is : " << it
->second
<< std::endl
;
719 Assert( qy
->getEngine()->hasTerm( it
->second
) );
720 Assert( qy
->getEngine()->getRepresentative( it
->second
)==it
->second
);
723 return getEntailedTerm2( it
->second
, subs
, subsRep
, hasSubs
, qy
);
727 }else if( n
.getKind()==ITE
){
728 for( unsigned i
=0; i
<2; i
++ ){
729 if( isEntailed2( n
[0], subs
, subsRep
, hasSubs
, i
==0, qy
) ){
730 return getEntailedTerm2( n
[ i
==0 ? 1 : 2 ], subs
, subsRep
, hasSubs
, qy
);
734 if( n
.hasOperator() ){
735 TNode f
= getMatchOperator( n
);
737 std::vector
< TNode
> args
;
738 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
739 TNode c
= getEntailedTerm2( n
[i
], subs
, subsRep
, hasSubs
, qy
);
741 return TNode::null();
743 c
= qy
->getEngine()->getRepresentative( c
);
744 Trace("term-db-entail") << " child " << i
<< " : " << c
<< std::endl
;
747 TNode nn
= qy
->getCongruentTerm( f
, args
);
748 Trace("term-db-entail") << " got congruent term " << nn
<< " for " << n
<< std::endl
;
753 return TNode::null();
756 Node
TermDb::evaluateTerm(TNode n
,
758 bool useEntailmentTests
,
762 qy
= d_quantEngine
->getEqualityQuery();
764 std::map
< TNode
, Node
> visited
;
765 std::vector
<Node
> exp
;
766 return evaluateTerm2(
767 n
, visited
, exp
, qy
, useEntailmentTests
, false, reqHasTerm
);
770 Node
TermDb::evaluateTerm(TNode n
,
771 std::vector
<Node
>& exp
,
773 bool useEntailmentTests
,
778 qy
= d_quantEngine
->getEqualityQuery();
780 std::map
<TNode
, Node
> visited
;
781 return evaluateTerm2(
782 n
, visited
, exp
, qy
, useEntailmentTests
, true, reqHasTerm
);
785 TNode
TermDb::getEntailedTerm( TNode n
, std::map
< TNode
, TNode
>& subs
, bool subsRep
, EqualityQuery
* qy
) {
787 qy
= d_quantEngine
->getEqualityQuery();
789 return getEntailedTerm2( n
, subs
, subsRep
, true, qy
);
792 TNode
TermDb::getEntailedTerm( TNode n
, EqualityQuery
* qy
) {
794 qy
= d_quantEngine
->getEqualityQuery();
796 std::map
< TNode
, TNode
> subs
;
797 return getEntailedTerm2( n
, subs
, false, false, qy
);
800 bool TermDb::isEntailed2( TNode n
, std::map
< TNode
, TNode
>& subs
, bool subsRep
, bool hasSubs
, bool pol
, EqualityQuery
* qy
) {
801 Assert( !qy
->extendsEngine() );
802 Trace("term-db-entail") << "Check entailed : " << n
<< ", pol = " << pol
<< std::endl
;
803 Assert( n
.getType().isBoolean() );
804 if( n
.getKind()==EQUAL
&& !n
[0].getType().isBoolean() ){
805 TNode n1
= getEntailedTerm2( n
[0], subs
, subsRep
, hasSubs
, qy
);
807 TNode n2
= getEntailedTerm2( n
[1], subs
, subsRep
, hasSubs
, qy
);
812 Assert( qy
->getEngine()->hasTerm( n1
) );
813 Assert( qy
->getEngine()->hasTerm( n2
) );
815 return qy
->getEngine()->areEqual( n1
, n2
);
817 return qy
->getEngine()->areDisequal( n1
, n2
, false );
822 }else if( n
.getKind()==NOT
){
823 return isEntailed2( n
[0], subs
, subsRep
, hasSubs
, !pol
, qy
);
824 }else if( n
.getKind()==OR
|| n
.getKind()==AND
){
825 bool simPol
= ( pol
&& n
.getKind()==OR
) || ( !pol
&& n
.getKind()==AND
);
826 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
827 if( isEntailed2( n
[i
], subs
, subsRep
, hasSubs
, pol
, qy
) ){
838 //Boolean equality here
839 }else if( n
.getKind()==EQUAL
|| n
.getKind()==ITE
){
840 for( unsigned i
=0; i
<2; i
++ ){
841 if( isEntailed2( n
[0], subs
, subsRep
, hasSubs
, i
==0, qy
) ){
842 unsigned ch
= ( n
.getKind()==EQUAL
|| i
==0 ) ? 1 : 2;
843 bool reqPol
= ( n
.getKind()==ITE
|| i
==0 ) ? pol
: !pol
;
844 return isEntailed2( n
[ch
], subs
, subsRep
, hasSubs
, reqPol
, qy
);
847 }else if( n
.getKind()==APPLY_UF
){
848 TNode n1
= getEntailedTerm2( n
, subs
, subsRep
, hasSubs
, qy
);
850 Assert( qy
->hasTerm( n1
) );
853 }else if( n1
==d_false
){
856 return qy
->getEngine()->getRepresentative( n1
) == ( pol
? d_true
: d_false
);
859 }else if( n
.getKind()==FORALL
&& !pol
){
860 return isEntailed2( n
[1], subs
, subsRep
, hasSubs
, pol
, qy
);
865 bool TermDb::isEntailed( TNode n
, bool pol
, EqualityQuery
* qy
) {
867 Assert( d_consistent_ee
);
868 qy
= d_quantEngine
->getEqualityQuery();
870 std::map
< TNode
, TNode
> subs
;
871 return isEntailed2( n
, subs
, false, false, pol
, qy
);
874 bool TermDb::isEntailed( TNode n
, std::map
< TNode
, TNode
>& subs
, bool subsRep
, bool pol
, EqualityQuery
* qy
) {
876 Assert( d_consistent_ee
);
877 qy
= d_quantEngine
->getEqualityQuery();
879 return isEntailed2( n
, subs
, subsRep
, true, pol
, qy
);
882 bool TermDb::isTermActive( Node n
) {
883 return d_inactive_map
.find( n
)==d_inactive_map
.end();
884 //return !n.getAttribute(NoMatchAttribute());
887 void TermDb::setTermInactive( Node n
) {
888 d_inactive_map
[n
] = true;
889 //Trace("term-db-debug2") << "set no match attribute" << std::endl;
890 //NoMatchAttribute nma;
891 //n.setAttribute(nma,true);
894 bool TermDb::hasTermCurrent( Node n
, bool useMode
) {
896 return d_has_map
.find( n
)!=d_has_map
.end();
898 //return d_quantEngine->getActiveEqualityEngine()->hasTerm( n ); //some assertions are not sent to EE
899 if( options::termDbMode()==TERM_DB_ALL
){
901 }else if( options::termDbMode()==TERM_DB_RELEVANT
){
902 return d_has_map
.find( n
)!=d_has_map
.end();
910 bool TermDb::isTermEligibleForInstantiation(TNode n
, TNode f
)
912 if( options::lteRestrictInstClosure() ){
913 //has to be both in inst closure and in ground assertions
914 if( !isInstClosure( n
) ){
915 Trace("inst-add-debug") << "Term " << n
<< " is not an inst-closure term." << std::endl
;
918 // hack : since theories preregister terms not in assertions, we are using hasTermCurrent to approximate this
919 if( !hasTermCurrent( n
, false ) ){
920 Trace("inst-add-debug") << "Term " << n
<< " is not in a ground assertion." << std::endl
;
924 if( options::instMaxLevel()!=-1 ){
925 if( n
.hasAttribute(InstLevelAttribute()) ){
926 int fml
= f
.isNull() ? -1 : d_quantEngine
->getQuantAttributes()->getQuantInstLevel( f
);
927 unsigned ml
= fml
>=0 ? fml
: options::instMaxLevel();
929 if( n
.getAttribute(InstLevelAttribute())>ml
){
930 Trace("inst-add-debug") << "Term " << n
<< " has instantiation level " << n
.getAttribute(InstLevelAttribute());
931 Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml
<< " for this quantified formula." << std::endl
;
935 if( options::instLevelInputOnly() ){
936 Trace("inst-add-debug") << "Term " << n
<< " does not have an instantiation level." << std::endl
;
941 // it cannot have instantiation constants, which originate from
942 // counterexample-guided instantiation strategies.
943 return !TermUtil::hasInstConstAttr(n
);
946 Node
TermDb::getEligibleTermInEqc( TNode r
) {
947 if( isTermEligibleForInstantiation( r
, TNode::null() ) ){
950 std::map
< Node
, Node
>::iterator it
= d_term_elig_eqc
.find( r
);
951 if( it
==d_term_elig_eqc
.end() ){
953 eq::EqualityEngine
* ee
= d_quantEngine
->getActiveEqualityEngine();
954 eq::EqClassIterator eqc_i
= eq::EqClassIterator( r
, ee
);
955 while (!eqc_i
.isFinished())
959 if (isTermEligibleForInstantiation(n
, TNode::null()))
965 d_term_elig_eqc
[r
] = h
;
973 bool TermDb::isInstClosure( Node r
) {
974 return d_iclosure_processed
.find( r
)!=d_iclosure_processed
.end();
977 void TermDb::setHasTerm( Node n
) {
978 Trace("term-db-debug2") << "hasTerm : " << n
<< std::endl
;
979 //if( inst::Trigger::isAtomicTrigger( n ) ){
980 if( d_has_map
.find( n
)==d_has_map
.end() ){
982 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
988 void TermDb::presolve() {
989 if( options::incrementalSolving() ){
990 // reset the caches that are SAT context-independent but user
996 d_iclosure_processed
.clear();
1000 bool TermDb::reset( Theory::Effort effort
){
1001 d_op_nonred_count
.clear();
1003 d_func_map_trie
.clear();
1004 d_func_map_eqc_trie
.clear();
1005 d_func_map_rel_dom
.clear();
1006 d_consistent_ee
= true;
1008 eq::EqualityEngine
* ee
= d_quantEngine
->getActiveEqualityEngine();
1010 Assert(ee
->consistent());
1011 // if higher-order, add equalities for the purification terms now
1012 if (options::ufHo())
1015 << "TermDb::reset : assert higher-order purify equalities..."
1017 for (std::pair
<const Node
, Node
>& pp
: d_ho_purify_to_term
)
1019 if (ee
->hasTerm(pp
.second
)
1020 && (!ee
->hasTerm(pp
.first
) || !ee
->areEqual(pp
.second
, pp
.first
)))
1023 std::map
<Node
, Node
>::iterator itpe
= d_ho_purify_to_eq
.find(pp
.first
);
1024 if (itpe
== d_ho_purify_to_eq
.end())
1026 eq
= Rewriter::rewrite(pp
.first
.eqNode(pp
.second
));
1027 d_ho_purify_to_eq
[pp
.first
] = eq
;
1033 Trace("quant-ho") << "- assert purify equality : " << eq
<< std::endl
;
1034 ee
->assertEquality(eq
, true, eq
);
1035 Assert(ee
->consistent());
1041 if( options::termDbMode()==TERM_DB_RELEVANT
|| options::lteRestrictInstClosure() ){
1043 d_term_elig_eqc
.clear();
1044 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator( ee
);
1045 while( !eqcs_i
.isFinished() ){
1046 TNode r
= (*eqcs_i
);
1047 bool addedFirst
= false;
1049 //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
1050 eq::EqClassIterator eqc_i
= eq::EqClassIterator( r
, ee
);
1051 while( !eqc_i
.isFinished() ){
1053 if( first
.isNull() ){
1058 setHasTerm( first
);
1066 for (TheoryId theoryId
= THEORY_FIRST
; theoryId
< THEORY_LAST
; ++theoryId
) {
1067 Theory
* theory
= d_quantEngine
->getTheoryEngine()->d_theoryTable
[theoryId
];
1068 if (theory
&& d_quantEngine
->getTheoryEngine()->d_logicInfo
.isTheoryEnabled(theoryId
)) {
1069 context::CDList
<Assertion
>::const_iterator it
= theory
->facts_begin(), it_end
= theory
->facts_end();
1070 for (unsigned i
= 0; it
!= it_end
; ++ it
, ++i
) {
1071 if( (*it
).assertion
.getKind()!=INST_CLOSURE
){
1072 setHasTerm( (*it
).assertion
);
1078 //explicitly add inst closure terms to the equality engine to ensure only EE terms are indexed
1079 for (const Node
& n
: d_iclosure_processed
)
1081 if( !ee
->hasTerm( n
) ){
1086 if( options::ufHo() && options::hoMergeTermDb() ){
1087 Trace("quant-ho") << "TermDb::reset : compute equal functions..." << std::endl
;
1088 // build operator representative map
1089 d_ho_op_rep
.clear();
1090 d_ho_op_slaves
.clear();
1091 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator( ee
);
1092 while( !eqcs_i
.isFinished() ){
1093 TNode r
= (*eqcs_i
);
1094 if( r
.getType().isFunction() ){
1095 Trace("quant-ho") << " process function eqc " << r
<< std::endl
;
1097 eq::EqClassIterator eqc_i
= eq::EqClassIterator( r
, ee
);
1098 while( !eqc_i
.isFinished() ){
1107 // use its purified variable, if it exists
1108 std::map
<Node
, Node
>::iterator itp
= d_ho_fun_op_purify
.find(n
);
1109 if (itp
!= d_ho_fun_op_purify
.end())
1111 n_use
= itp
->second
;
1114 Trace("quant-ho") << " - process " << n_use
<< ", from " << n
1116 if (!n_use
.isNull() && d_op_map
.find(n_use
) != d_op_map
.end())
1121 d_ho_op_rep
[n_use
] = n_use
;
1125 Trace("quant-ho") << " have : " << n_use
<< " == " << first
1126 << ", type = " << n_use
.getType() << std::endl
;
1127 d_ho_op_rep
[n_use
] = first
;
1128 d_ho_op_slaves
[first
].push_back(n_use
);
1136 Trace("quant-ho") << "...finished compute equal functions." << std::endl
;
1140 //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
1141 for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
1142 computeUfTerms( it->first );
1143 if( !d_consistent_ee ){
1151 TNodeTrie
* TermDb::getTermArgTrie(Node f
)
1153 if( options::ufHo() ){
1154 f
= getOperatorRepresentative( f
);
1156 computeUfTerms( f
);
1157 std::map
<Node
, TNodeTrie
>::iterator itut
= d_func_map_trie
.find(f
);
1158 if( itut
!=d_func_map_trie
.end() ){
1159 return &itut
->second
;
1165 TNodeTrie
* TermDb::getTermArgTrie(Node eqc
, Node f
)
1167 if( options::ufHo() ){
1168 f
= getOperatorRepresentative( f
);
1170 computeUfEqcTerms( f
);
1171 std::map
<Node
, TNodeTrie
>::iterator itut
= d_func_map_eqc_trie
.find(f
);
1172 if( itut
==d_func_map_eqc_trie
.end() ){
1176 return &itut
->second
;
1178 std::map
<TNode
, TNodeTrie
>::iterator itute
=
1179 itut
->second
.d_data
.find(eqc
);
1180 if( itute
!=itut
->second
.d_data
.end() ){
1181 return &itute
->second
;
1189 TNode
TermDb::getCongruentTerm( Node f
, Node n
) {
1190 if( options::ufHo() ){
1191 f
= getOperatorRepresentative( f
);
1193 computeUfTerms( f
);
1194 std::map
<Node
, TNodeTrie
>::iterator itut
= d_func_map_trie
.find(f
);
1195 if( itut
!=d_func_map_trie
.end() ){
1196 computeArgReps( n
);
1197 return itut
->second
.existsTerm( d_arg_reps
[n
] );
1199 return TNode::null();
1203 TNode
TermDb::getCongruentTerm( Node f
, std::vector
< TNode
>& args
) {
1204 if( options::ufHo() ){
1205 f
= getOperatorRepresentative( f
);
1207 computeUfTerms( f
);
1208 return d_func_map_trie
[f
].existsTerm( args
);
1211 }/* CVC4::theory::quantifiers namespace */
1212 }/* CVC4::theory namespace */
1213 }/* CVC4 namespace */