1 /********************* */
2 /*! \file theory_sets_private.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Kshitij Bansal, Paul Meng
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 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 Sets theory implementation.
14 ** Sets theory implementation.
18 #include "theory/sets/theory_sets_private.h"
20 #include "expr/emptyset.h"
21 #include "options/sets_options.h"
22 #include "smt/smt_statistics_registry.h"
23 #include "theory/sets/theory_sets.h"
24 #include "theory/sets/normal_form.h"
25 #include "theory/theory_model.h"
26 #include "util/result.h"
27 #include "theory/quantifiers/term_database.h"
29 #define AJR_IMPLEMENTATION
37 TheorySetsPrivate::TheorySetsPrivate(TheorySets
& external
,
39 context::UserContext
* u
):
52 d_equalityEngine(d_notify
, c
, "theory::sets::ee", true),
56 d_rels
= new TheorySetsRels(c
, u
, &d_equalityEngine
, &d_conflict
, external
);
58 d_true
= NodeManager::currentNM()->mkConst( true );
59 d_false
= NodeManager::currentNM()->mkConst( false );
60 d_zero
= NodeManager::currentNM()->mkConst( Rational(0) );
62 d_equalityEngine
.addFunctionKind(kind::SINGLETON
);
63 d_equalityEngine
.addFunctionKind(kind::UNION
);
64 d_equalityEngine
.addFunctionKind(kind::INTERSECTION
);
65 d_equalityEngine
.addFunctionKind(kind::SETMINUS
);
67 d_equalityEngine
.addFunctionKind(kind::MEMBER
);
68 d_equalityEngine
.addFunctionKind(kind::SUBSET
);
70 // If cardinality is on.
71 d_equalityEngine
.addFunctionKind(kind::CARD
);
73 d_card_enabled
= false;
74 d_rels_enabled
= false;
76 }/* TheorySetsPrivate::TheorySetsPrivate() */
78 TheorySetsPrivate::~TheorySetsPrivate(){
80 for (std::pair
<const Node
, EqcInfo
*>& current_pair
: d_eqc_info
) {
81 delete current_pair
.second
;
83 }/* TheorySetsPrivate::~TheorySetsPrivate() */
86 void TheorySetsPrivate::eqNotifyNewClass(TNode t
) {
87 if( t
.getKind()==kind::SINGLETON
|| t
.getKind()==kind::EMPTYSET
){
88 EqcInfo
* e
= getOrMakeEqcInfo( t
, true );
91 if( options::setsRelEager() ){
92 d_rels
->eqNotifyNewClass( t
);
96 void TheorySetsPrivate::eqNotifyPreMerge(TNode t1
, TNode t2
){
100 void TheorySetsPrivate::eqNotifyPostMerge(TNode t1
, TNode t2
){
102 Trace("sets-prop-debug") << "Merge " << t1
<< " and " << t2
<< "..." << std::endl
;
104 EqcInfo
* e2
= getOrMakeEqcInfo( t2
);
106 s2
= e2
->d_singleton
;
107 EqcInfo
* e1
= getOrMakeEqcInfo( t1
);
109 Trace("sets-prop-debug") << "Merging singletons..." << std::endl
;
111 s1
= e1
->d_singleton
;
112 if( !s1
.isNull() && !s2
.isNull() ){
113 if( s1
.getKind()==s2
.getKind() ){
114 Trace("sets-prop") << "Propagate eq inference : " << s1
<< " == " << s2
<< std::endl
;
115 //infer equality between elements of singleton
116 Node exp
= s1
.eqNode( s2
);
117 Node eq
= s1
[0].eqNode( s2
[0] );
118 d_keep
.insert( exp
);
120 assertFact( eq
, exp
);
122 //singleton equal to emptyset, conflict
123 Trace("sets-prop") << "Propagate conflict : " << s1
<< " == " << s2
<< std::endl
;
130 e1
= getOrMakeEqcInfo( t1
, true );
131 e1
->d_singleton
.set( e2
->d_singleton
);
134 //merge membership list
135 Trace("sets-prop-debug") << "Copying membership list..." << std::endl
;
136 NodeIntMap::iterator mem_i2
= d_members
.find( t2
);
137 if( mem_i2
!= d_members
.end() ) {
138 NodeIntMap::iterator mem_i1
= d_members
.find( t1
);
140 if( mem_i1
!= d_members
.end() ) {
141 n_members
= (*mem_i1
).second
;
143 for( int i
=0; i
<(*mem_i2
).second
; i
++ ){
144 Assert( i
<(int)d_members_data
[t2
].size() && d_members_data
[t2
][i
].getKind()==kind::MEMBER
);
145 Node m2
= d_members_data
[t2
][i
];
148 for( int j
=0; j
<n_members
; j
++ ){
149 Assert( j
<(int)d_members_data
[t1
].size() && d_members_data
[t1
][j
].getKind()==kind::MEMBER
);
150 if( ee_areEqual( m2
[0], d_members_data
[t1
][j
][0] ) ){
156 if( !s1
.isNull() && s2
.isNull() ){
157 Assert( m2
[1].getType().isComparableTo( s1
.getType() ) );
158 Assert( ee_areEqual( m2
[1], s1
) );
159 Node exp
= NodeManager::currentNM()->mkNode( kind::AND
, m2
[1].eqNode( s1
), m2
);
160 if( s1
.getKind()==kind::SINGLETON
){
162 Node eq
= s1
[0].eqNode( m2
[0] );
163 d_keep
.insert( exp
);
165 Trace("sets-prop") << "Propagate eq-mem eq inference : " << exp
<< " => " << eq
<< std::endl
;
166 assertFact( eq
, exp
);
170 Trace("sets-prop") << "Propagate eq-mem conflict : " << exp
<< std::endl
;
172 d_external
.d_out
->conflict( exp
);
176 if( n_members
<(int)d_members_data
[t1
].size() ){
177 d_members_data
[t1
][n_members
] = m2
;
179 d_members_data
[t1
].push_back( m2
);
184 d_members
[t1
] = n_members
;
186 if( options::setsRelEager() ){
187 d_rels
->eqNotifyPostMerge( t1
, t2
);
192 void TheorySetsPrivate::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
){
193 if( t1
.getType().isSet() ){
194 Node eq
= t1
.eqNode( t2
);
195 if( d_deq
.find( eq
)==d_deq
.end() ){
201 TheorySetsPrivate::EqcInfo::EqcInfo( context::Context
* c
) : d_singleton( c
){
205 TheorySetsPrivate::EqcInfo
* TheorySetsPrivate::getOrMakeEqcInfo( TNode n
, bool doMake
){
206 std::map
< Node
, EqcInfo
* >::iterator eqc_i
= d_eqc_info
.find( n
);
207 if( eqc_i
==d_eqc_info
.end() ){
210 ei
= new EqcInfo( d_external
.getSatContext() );
215 return eqc_i
->second
;
220 bool TheorySetsPrivate::ee_areEqual( Node a
, Node b
) {
224 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
225 return d_equalityEngine
.areEqual( a
, b
);
232 bool TheorySetsPrivate::ee_areDisequal( Node a
, Node b
) {
236 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
237 return d_equalityEngine
.areDisequal( a
, b
, false );
239 return a
.isConst() && b
.isConst();
244 bool TheorySetsPrivate::ee_areCareDisequal( Node a
, Node b
) {
245 if( d_equalityEngine
.isTriggerTerm(a
, THEORY_SETS
) && d_equalityEngine
.isTriggerTerm(b
, THEORY_SETS
) ){
246 TNode a_shared
= d_equalityEngine
.getTriggerTermRepresentative(a
, THEORY_SETS
);
247 TNode b_shared
= d_equalityEngine
.getTriggerTermRepresentative(b
, THEORY_SETS
);
248 EqualityStatus eqStatus
= d_external
.d_valuation
.getEqualityStatus(a_shared
, b_shared
);
249 if( eqStatus
==EQUALITY_FALSE_AND_PROPAGATED
|| eqStatus
==EQUALITY_FALSE
|| eqStatus
==EQUALITY_FALSE_IN_MODEL
){
256 bool TheorySetsPrivate::isEntailed( Node n
, bool polarity
) {
257 if( n
.getKind()==kind::NOT
){
258 return isEntailed( n
[0], !polarity
);
259 }else if( n
.getKind()==kind::EQUAL
){
261 return ee_areEqual( n
[0], n
[1] );
263 return ee_areDisequal( n
[0], n
[1] );
265 }else if( n
.getKind()==kind::MEMBER
){
266 if( ee_areEqual( n
, polarity
? d_true
: d_false
) ){
269 //check members cache
270 if( polarity
&& d_equalityEngine
.hasTerm( n
[1] ) ){
271 Node r
= d_equalityEngine
.getRepresentative( n
[1] );
272 if( isMember( n
[0], r
) ){
276 }else if( n
.getKind()==kind::AND
|| n
.getKind()==kind::OR
){
277 bool conj
= (n
.getKind()==kind::AND
)==polarity
;
278 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
279 bool isEnt
= isEntailed( n
[i
], polarity
);
285 }else if( n
.isConst() ){
286 return ( polarity
&& n
==d_true
) || ( !polarity
&& n
==d_false
);
291 bool TheorySetsPrivate::isMember( Node x
, Node s
) {
292 Assert( d_equalityEngine
.hasTerm( s
) && d_equalityEngine
.getRepresentative( s
)==s
);
293 NodeIntMap::iterator mem_i
= d_members
.find( s
);
294 if( mem_i
!= d_members
.end() ) {
295 for( int i
=0; i
<(*mem_i
).second
; i
++ ){
296 if( ee_areEqual( d_members_data
[s
][i
][0], x
) ){
304 bool TheorySetsPrivate::isSetDisequalityEntailed( Node r1
, Node r2
) {
305 Assert( d_equalityEngine
.hasTerm( r1
) && d_equalityEngine
.getRepresentative( r1
)==r1
);
306 Assert( d_equalityEngine
.hasTerm( r2
) && d_equalityEngine
.getRepresentative( r2
)==r2
);
307 TypeNode tn
= r1
.getType();
308 Node eqc_es
= d_eqc_emptyset
[tn
];
310 for( unsigned e
=0; e
<2; e
++ ){
311 Node a
= e
==0 ? r1
: r2
;
312 Node b
= e
==0 ? r2
: r1
;
313 //if there are members in a
314 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpma
= d_pol_mems
[0].find( a
);
315 if( itpma
!=d_pol_mems
[0].end() ){
316 Assert( !itpma
->second
.empty() );
319 if( !itpma
->second
.empty() ){
321 Trace("sets-deq") << "Disequality is satisfied because members are in " << a
<< " and " << b
<< " is empty" << std::endl
;
323 //a should not be singleton
324 Assert( d_eqc_singleton
.find( a
)==d_eqc_singleton
.end() );
327 std::map
< Node
, Node
>::iterator itsb
= d_eqc_singleton
.find( b
);
328 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpmb
= d_pol_mems
[1].find( b
);
329 std::vector
< Node
> prev
;
330 for( std::map
< Node
, Node
>::iterator itm
= itpma
->second
.begin(); itm
!= itpma
->second
.end(); ++itm
){
331 //if b is a singleton
332 if( itsb
!=d_eqc_singleton
.end() ){
333 if( ee_areDisequal( itm
->first
, itsb
->second
[0] ) ){
334 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< ", singleton eq " << itsb
->second
[0] << std::endl
;
337 //or disequal with another member
338 for( unsigned k
=0; k
<prev
.size(); k
++ ){
339 if( ee_areDisequal( itm
->first
, prev
[k
] ) ){
340 Trace("sets-deq") << "Disequality is satisfied because of disequal members " << itm
->first
<< " " << prev
[k
] << ", singleton eq " << std::endl
;
345 //TODO: this can be generalized : maintain map to abstract domain ( set -> cardinality )
346 //if a has positive member that is negative member in b
347 }else if( itpmb
!=d_pol_mems
[1].end() ){
348 for( std::map
< Node
, Node
>::iterator itnm
= itpmb
->second
.begin(); itnm
!= itpmb
->second
.end(); ++itnm
){
349 if( ee_areEqual( itm
->first
, itnm
->first
) ){
350 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< " " << itnm
->second
<< std::endl
;
359 prev
.push_back( itm
->first
);
370 bool TheorySetsPrivate::assertFact( Node fact
, Node exp
){
371 Trace("sets-assert") << "TheorySets::assertFact : " << fact
<< ", exp = " << exp
<< std::endl
;
372 bool polarity
= fact
.getKind() != kind::NOT
;
373 TNode atom
= polarity
? fact
: fact
[0];
374 if( !isEntailed( atom
, polarity
) ){
375 if( atom
.getKind()==kind::EQUAL
){
376 d_equalityEngine
.assertEquality( atom
, polarity
, exp
);
378 d_equalityEngine
.assertPredicate( atom
, polarity
, exp
);
381 if( atom
.getKind()==kind::MEMBER
&& polarity
){
382 //check if set has a value, if so, we can propagate
383 Node r
= d_equalityEngine
.getRepresentative( atom
[1] );
384 EqcInfo
* e
= getOrMakeEqcInfo( r
, true );
386 Node s
= e
->d_singleton
;
388 Node exp
= NodeManager::currentNM()->mkNode( kind::AND
, atom
, atom
[1].eqNode( s
) );
389 d_keep
.insert( exp
);
390 if( s
.getKind()==kind::SINGLETON
){
392 Trace("sets-prop") << "Propagate mem-eq : " << exp
<< std::endl
;
393 Node eq
= s
[0].eqNode( atom
[0] );
395 assertFact( eq
, exp
);
398 Trace("sets-prop") << "Propagate mem-eq conflict : " << exp
<< std::endl
;
400 d_external
.d_out
->conflict( exp
);
404 //add to membership list
405 NodeIntMap::iterator mem_i
= d_members
.find( r
);
407 if( mem_i
!= d_members
.end() ) {
408 n_members
= (*mem_i
).second
;
410 d_members
[r
] = n_members
+ 1;
411 if( n_members
<(int)d_members_data
[r
].size() ){
412 d_members_data
[r
][n_members
] = atom
;
414 d_members_data
[r
].push_back( atom
);
424 bool TheorySetsPrivate::assertFactRec( Node fact
, Node exp
, std::vector
< Node
>& lemma
, int inferType
) {
425 if( ( options::setsInferAsLemmas() && inferType
!=-1 ) || inferType
==1 ){
426 if( !isEntailed( fact
, true ) ){
427 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
431 Trace("sets-fact") << "Assert fact rec : " << fact
<< ", exp = " << exp
<< std::endl
;
432 if( fact
.isConst() ){
433 //either trivial or a conflict
435 Trace("sets-lemma") << "Conflict : " << exp
<< std::endl
;
437 d_external
.d_out
->conflict( exp
);
440 }else if( fact
.getKind()==kind::AND
|| ( fact
.getKind()==kind::NOT
&& fact
[0].getKind()==kind::OR
) ){
442 Node f
= fact
.getKind()==kind::NOT
? fact
[0] : fact
;
443 for( unsigned i
=0; i
<f
.getNumChildren(); i
++ ){
444 Node factc
= fact
.getKind()==kind::NOT
? f
[i
].negate() : f
[i
];
445 bool tret
= assertFactRec( factc
, exp
, lemma
, inferType
);
453 bool polarity
= fact
.getKind() != kind::NOT
;
454 TNode atom
= polarity
? fact
: fact
[0];
455 //things we can assert to equality engine
456 if( atom
.getKind()==kind::MEMBER
|| ( atom
.getKind()==kind::EQUAL
&& atom
[0].getType().isSet() ) ){
457 //send to equality engine
458 if( assertFact( fact
, exp
) ){
463 if( !isEntailed( fact
, true ) ){
465 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
473 void TheorySetsPrivate::assertInference( Node fact
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
474 d_keep
.insert( exp
);
475 d_keep
.insert( fact
);
476 if( assertFactRec( fact
, exp
, lemmas
, inferType
) ){
477 Trace("sets-lemma") << "Sets::Lemma : " << fact
<< " from " << exp
<< " by " << c
<< std::endl
;
478 Trace("sets-assertion") << "(assert (=> " << exp
<< " " << fact
<< ")) ; by " << c
<< std::endl
;
482 void TheorySetsPrivate::assertInference( Node fact
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
483 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
484 assertInference( fact
, exp_n
, lemmas
, c
, inferType
);
487 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
489 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
490 assertInference( fact
, exp
, lemmas
, c
, inferType
);
493 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
494 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
495 assertInference( conc
, exp_n
, lemmas
, c
, inferType
);
498 void TheorySetsPrivate::split( Node n
, int reqPol
) {
499 n
= Rewriter::rewrite( n
);
500 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, n
, n
.negate() );
501 std::vector
< Node
> lemmas
;
502 lemmas
.push_back( lem
);
503 flushLemmas( lemmas
);
504 Trace("sets-lemma") << "Sets::Lemma split : " << lem
<< std::endl
;
506 Trace("sets-lemma") << "Sets::Require phase " << n
<< " " << (reqPol
>0) << std::endl
;
507 d_external
.getOutputChannel().requirePhase( n
, reqPol
>0 );
511 void TheorySetsPrivate::fullEffortCheck(){
512 Trace("sets") << "----- Full effort check ------" << std::endl
;
514 Trace("sets") << "...iterate full effort check..." << std::endl
;
515 Assert( d_equalityEngine
.consistent() );
518 d_full_check_incomplete
= false;
520 d_set_eqc_list
.clear();
521 d_eqc_emptyset
.clear();
522 d_eqc_univset
.clear();
523 d_eqc_singleton
.clear();
527 d_most_common_type
.clear();
528 d_most_common_type_term
.clear();
529 d_pol_mems
[0].clear();
530 d_pol_mems
[1].clear();
531 d_members_index
.clear();
532 d_singleton_index
.clear();
535 d_card_enabled
= false;
536 d_rels_enabled
= false;
537 d_eqc_to_card_term
.clear();
539 std::vector
< Node
> lemmas
;
540 Trace("sets-eqc") << "Equality Engine:" << std::endl
;
541 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator( &d_equalityEngine
);
542 while( !eqcs_i
.isFinished() ){
543 Node eqc
= (*eqcs_i
);
545 TypeNode tn
= eqc
.getType();
546 //common type node and term
551 d_set_eqc
.push_back( eqc
);
552 tnc
= tn
.getSetElementType();
555 Trace("sets-eqc") << "[" << eqc
<< "] : ";
556 eq::EqClassIterator eqc_i
= eq::EqClassIterator( eqc
, &d_equalityEngine
);
557 while( !eqc_i
.isFinished() ) {
560 Trace("sets-eqc") << n
<< " ";
562 TypeNode tnn
= n
.getType();
564 Assert( tnn
.isSet() );
565 TypeNode tnnel
= tnn
.getSetElementType();
566 tnc
= TypeNode::mostCommonTypeNode( tnc
, tnnel
);
567 Assert( !tnc
.isNull() );
568 //update the common type term
573 if( n
.getKind()==kind::MEMBER
){
575 Node s
= d_equalityEngine
.getRepresentative( n
[1] );
576 Node x
= d_equalityEngine
.getRepresentative( n
[0] );
577 int pindex
= eqc
==d_true
? 0 : ( eqc
==d_false
? 1 : -1 );
579 if( d_pol_mems
[pindex
][s
].find( x
)==d_pol_mems
[pindex
][s
].end() ){
580 d_pol_mems
[pindex
][s
][x
] = n
;
581 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
<< ", pindex = " << pindex
<< std::endl
;
583 if( d_members_index
[s
].find( x
)==d_members_index
[s
].end() ){
584 d_members_index
[s
][x
] = n
;
585 d_op_list
[kind::MEMBER
].push_back( n
);
591 }else if( n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::UNION
|| n
.getKind()==kind::INTERSECTION
||
592 n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::EMPTYSET
|| n
.getKind()==kind::UNIVERSE_SET
){
593 if( n
.getKind()==kind::SINGLETON
){
596 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
597 if( d_singleton_index
.find( r
)==d_singleton_index
.end() ){
598 d_singleton_index
[r
] = n
;
599 d_eqc_singleton
[eqc
] = n
;
600 d_op_list
[kind::SINGLETON
].push_back( n
);
602 d_congruent
[n
] = d_singleton_index
[r
];
604 }else if( n
.getKind()==kind::EMPTYSET
){
605 d_eqc_emptyset
[tnn
] = eqc
;
606 }else if( n
.getKind()==kind::UNIVERSE_SET
){
607 Assert( options::setsExt() );
608 d_eqc_univset
[tnn
] = eqc
;
610 Node r1
= d_equalityEngine
.getRepresentative( n
[0] );
611 Node r2
= d_equalityEngine
.getRepresentative( n
[1] );
612 if( d_bop_index
[n
.getKind()][r1
].find( r2
)==d_bop_index
[n
.getKind()][r1
].end() ){
613 d_bop_index
[n
.getKind()][r1
][r2
] = n
;
614 d_op_list
[n
.getKind()].push_back( n
);
616 d_congruent
[n
] = d_bop_index
[n
.getKind()][r1
][r2
];
619 d_nvar_sets
[eqc
].push_back( n
);
620 Trace("sets-debug2") << "Non-var-set[" << eqc
<< "] : " << n
<< std::endl
;
621 d_set_eqc_list
[eqc
].push_back( n
);
622 }else if( n
.getKind()==kind::CARD
){
623 d_card_enabled
= true;
624 TypeNode tnc
= n
[0].getType().getSetElementType();
625 if( tnc
.isInterpretedFinite() ){
626 std::stringstream ss
;
627 ss
<< "ERROR: cannot use cardinality on sets with finite element type." << std::endl
;
628 throw LogicException(ss
.str());
629 //TODO: extend approach for this case
631 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
632 if( d_eqc_to_card_term
.find( r
)==d_eqc_to_card_term
.end() ){
633 d_eqc_to_card_term
[ r
] = n
;
634 registerCardinalityTerm( n
[0], lemmas
);
637 if( d_rels
->isRelationKind( n
.getKind() ) ){
638 d_rels_enabled
= true;
641 d_set_eqc_list
[eqc
].push_back( n
);
642 if( n
.getKind()==kind::VARIABLE
){
643 if( d_var_set
.find( eqc
)==d_var_set
.end() ){
652 Assert( tnct
.getType().getSetElementType()==tnc
);
653 d_most_common_type
[eqc
] = tnc
;
654 d_most_common_type_term
[eqc
] = tnct
;
656 Trace("sets-eqc") << std::endl
;
660 flushLemmas( lemmas
);
661 if( !hasProcessed() ){
662 if( Trace
.isOn("sets-mem") ){
663 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
664 Node s
= d_set_eqc
[i
];
665 Trace("sets-mem") << "Eqc " << s
<< " : ";
666 std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].find( s
);
667 if( it
!=d_pol_mems
[0].end() ){
668 Trace("sets-mem") << "Memberships : ";
669 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
670 Trace("sets-mem") << it2
->first
<< " ";
673 std::map
< Node
, Node
>::iterator its
= d_eqc_singleton
.find( s
);
674 if( its
!=d_eqc_singleton
.end() ){
675 Trace("sets-mem") << " : Singleton : " << its
->second
;
677 Trace("sets-mem") << std::endl
;
680 checkSubtypes( lemmas
);
681 flushLemmas( lemmas
, true );
682 if( !hasProcessed() ){
684 checkDownwardsClosure( lemmas
);
685 if( options::setsInferAsLemmas() ){
686 flushLemmas( lemmas
);
688 if( !hasProcessed() ){
689 checkUpwardsClosure( lemmas
);
690 flushLemmas( lemmas
);
691 if( !hasProcessed() ){
692 std::vector
< Node
> intro_sets
;
694 if( d_card_enabled
){
695 checkCardBuildGraph( lemmas
);
696 flushLemmas( lemmas
);
697 if( !hasProcessed() ){
698 checkMinCard( lemmas
);
699 flushLemmas( lemmas
);
700 if( !hasProcessed() ){
701 checkCardCycles( lemmas
);
702 flushLemmas( lemmas
);
703 if( !hasProcessed() ){
704 checkNormalForms( lemmas
, intro_sets
);
705 flushLemmas( lemmas
);
710 if( !hasProcessed() ){
711 checkDisequalities( lemmas
);
712 flushLemmas( lemmas
);
713 if( !hasProcessed() ){
714 //introduce splitting on venn regions (absolute last resort)
715 if( d_card_enabled
&& !hasProcessed() && !intro_sets
.empty() ){
716 Assert( intro_sets
.size()==1 );
717 Trace("sets-intro") << "Introduce term : " << intro_sets
[0] << std::endl
;
718 Trace("sets-intro") << " Actual Intro : ";
719 debugPrintSet( intro_sets
[0], "sets-nf" );
720 Trace("sets-nf") << std::endl
;
721 Node k
= getProxy( intro_sets
[0] );
730 }while( !d_sentLemma
&& !d_conflict
&& d_addedFact
);
731 Trace("sets") << "----- End full effort check, conflict=" << d_conflict
<< ", lemma=" << d_sentLemma
<< std::endl
;
734 void TheorySetsPrivate::checkSubtypes( std::vector
< Node
>& lemmas
) {
735 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
736 Node s
= d_set_eqc
[i
];
737 TypeNode mct
= d_most_common_type
[s
];
738 std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].find( s
);
739 if( it
!=d_pol_mems
[0].end() ){
740 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
741 if (!it2
->first
.getType().isSubtypeOf(mct
))
743 Node mctt
= d_most_common_type_term
[s
];
744 std::vector
< Node
> exp
;
745 exp
.push_back( it2
->second
);
746 Assert( ee_areEqual( mctt
, it2
->second
[1] ) );
747 exp
.push_back( mctt
.eqNode( it2
->second
[1] ) );
748 Node tc_k
= getTypeConstraintSkolem(it2
->first
, mct
);
751 Node etc
= tc_k
.eqNode(it2
->first
);
752 assertInference( etc
, exp
, lemmas
, "subtype-clash" );
763 void TheorySetsPrivate::checkDownwardsClosure( std::vector
< Node
>& lemmas
) {
764 Trace("sets") << "Downwards closure..." << std::endl
;
766 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].begin(); it
!= d_pol_mems
[0].end(); ++it
){
767 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( it
->first
);
768 if( itn
!=d_nvar_sets
.end() ){
769 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
770 if( d_congruent
.find( itn
->second
[j
] )==d_congruent
.end() ){
771 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
772 Node mem
= it2
->second
;
773 Node eq_set
= itn
->second
[j
];
774 Assert( d_equalityEngine
.areEqual( mem
[1], eq_set
) );
775 if( mem
[1]!=eq_set
){
776 Trace("sets-debug") << "Downwards closure based on " << mem
<< ", eq_set = " << eq_set
<< std::endl
;
777 if( !options::setsProxyLemmas() ){
778 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
779 nmem
= Rewriter::rewrite( nmem
);
780 std::vector
< Node
> exp
;
781 exp
.push_back( mem
);
782 exp
.push_back( mem
[1].eqNode( eq_set
) );
783 assertInference( nmem
, exp
, lemmas
, "downc" );
789 Node k
= getProxy( eq_set
);
790 Node pmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], k
);
791 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
792 nmem
= Rewriter::rewrite( nmem
);
793 std::vector
< Node
> exp
;
794 if( ee_areEqual( mem
, pmem
) ){
795 exp
.push_back( pmem
);
797 nmem
= NodeManager::currentNM()->mkNode( kind::OR
, pmem
.negate(), nmem
);
799 assertInference( nmem
, exp
, lemmas
, "downc" );
809 void TheorySetsPrivate::checkUpwardsClosure( std::vector
< Node
>& lemmas
) {
811 for( std::map
< Kind
, std::map
< Node
, std::map
< Node
, Node
> > >::iterator itb
= d_bop_index
.begin(); itb
!= d_bop_index
.end(); ++itb
){
813 Trace("sets") << "Upwards closure " << k
<< "..." << std::endl
;
814 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= itb
->second
.begin(); it
!= itb
->second
.end(); ++it
){
816 //see if there are members in first argument r1
817 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm1
= d_pol_mems
[0].find( r1
);
818 if( itm1
!=d_pol_mems
[0].end() || k
==kind::UNION
){
819 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
820 Node r2
= it2
->first
;
821 //see if there are members in second argument
822 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm2
= d_pol_mems
[0].find( r2
);
823 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm2n
= d_pol_mems
[1].find( r2
);
824 if( itm2
!=d_pol_mems
[0].end() || k
!=kind::INTERSECTION
){
825 Trace("sets-debug") << "Checking " << it2
->second
<< ", members = " << (itm1
!=d_pol_mems
[0].end()) << ", " << (itm2
!=d_pol_mems
[0].end()) << std::endl
;
826 //for all members of r1
827 if( itm1
!=d_pol_mems
[0].end() ){
828 for( std::map
< Node
, Node
>::iterator itm1m
= itm1
->second
.begin(); itm1m
!= itm1
->second
.end(); ++itm1m
){
829 Node xr
= itm1m
->first
;
830 Node x
= itm1m
->second
[0];
831 Trace("sets-debug") << "checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
832 std::vector
< Node
> exp
;
833 exp
.push_back( itm1m
->second
);
834 addEqualityToExp( it2
->second
[0], itm1m
->second
[1], exp
);
837 if( k
==kind::UNION
){
839 }else if( k
==kind::INTERSECTION
){
840 //conclude x is in it2->second
841 //if also existing in members of r2
842 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
844 exp
.push_back( itm2
->second
[xr
] );
845 addEqualityToExp( it2
->second
[1], itm2
->second
[xr
][1], exp
);
846 addEqualityToExp( x
, itm2
->second
[xr
][0], exp
);
849 // if not, check whether it is definitely not a member, if unknown, split
850 bool not_in_r2
= itm2n
!=d_pol_mems
[1].end() && itm2n
->second
.find( xr
)!=itm2n
->second
.end();
852 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, it2
->second
[1] ) );
858 Assert( k
==kind::SETMINUS
);
860 std::map< Node, std::map< Node, Node > >::iterator itnm2 = d_pol_mems[1].find( r2 );
861 if( itnm2!=d_pol_mems[1].end() ){
862 bool not_in_r2 = itnm2->second.find( xr )!=itnm2->second.end();
864 exp.push_back( itnm2->second[xr] );
865 if( it2->second[1]!=itnm2->second[xr][1] ){
866 Assert( d_equalityEngine.areEqual( it2->second[1], itnm2->second[xr][1] ) );
867 exp.push_back( it2->second[1].eqNode( itnm2->second[xr][1] ) );
869 if( x!=itnm2->second[xr][0] ){
870 Assert( d_equalityEngine.areEqual( x, itnm2->second[xr][0] ) );
871 exp.push_back( NodeManager::currentNM()->mkNode( kind::EQUAL, x, itnm2->second[xr][0] ) );
878 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
880 // must add lemma for set minus since non-membership in this case is not explained
881 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, it2
->second
[1] ).negate() );
888 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
889 if( !isMember( x
, rr
) ){
890 Node kk
= getProxy( it2
->second
);
891 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, kk
);
892 assertInference( fact
, exp
, lemmas
, "upc", inferType
);
898 Trace("sets-debug") << "done checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
901 if( k
==kind::UNION
){
902 if( itm2
!=d_pol_mems
[0].end() ){
903 //for all members of r2
904 for( std::map
< Node
, Node
>::iterator itm2m
= itm2
->second
.begin(); itm2m
!= itm2
->second
.end(); ++itm2m
){
905 Node x
= itm2m
->second
[0];
906 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
907 if( !isMember( x
, rr
) ){
908 std::vector
< Node
> exp
;
909 exp
.push_back( itm2m
->second
);
910 addEqualityToExp( it2
->second
[1], itm2m
->second
[1], exp
);
911 Node k
= getProxy( it2
->second
);
912 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, k
);
913 assertInference( fact
, exp
, lemmas
, "upc2" );
926 if( !hasProcessed() ){
927 if( options::setsExt() ){
929 Trace("sets-debug") << "Check universe sets..." << std::endl
;
930 //all elements must be in universal set
931 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].begin(); it
!= d_pol_mems
[0].end(); ++it
){
932 //if equivalence class contains a variable
933 std::map
< Node
, Node
>::iterator itv
= d_var_set
.find( it
->first
);
934 if( itv
!=d_var_set
.end() ){
935 //the variable in the equivalence class
936 Node v
= itv
->second
;
937 std::map
< TypeNode
, Node
> univ_set
;
938 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
939 Node e
= it2
->second
[0];
940 TypeNode tn
= NodeManager::currentNM()->mkSetType( e
.getType() );
942 std::map
< TypeNode
, Node
>::iterator itu
= univ_set
.find( tn
);
943 if( itu
==univ_set
.end() ){
944 std::map
< TypeNode
, Node
>::iterator itu
= d_eqc_univset
.find( tn
);
945 // if the universe does not yet exist, or is not in this equivalence class
946 if( itu
==d_eqc_univset
.end() || itu
->second
!=it
->first
){
947 u
= getUnivSet( tn
);
954 Assert( it2
->second
.getKind()==kind::MEMBER
);
955 std::vector
< Node
> exp
;
956 exp
.push_back( it2
->second
);
957 if( v
!=it2
->second
[1] ){
958 exp
.push_back( v
.eqNode( it2
->second
[1] ) );
960 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, it2
->second
[0], u
);
961 assertInference( fact
, exp
, lemmas
, "upuniv" );
973 void TheorySetsPrivate::checkDisequalities( std::vector
< Node
>& lemmas
) {
975 Trace("sets") << "Disequalities..." << std::endl
;
976 for(NodeBoolMap::const_iterator it
=d_deq
.begin(); it
!=d_deq
.end(); ++it
) {
978 Node deq
= (*it
).first
;
979 //check if it is already satisfied
980 Assert( d_equalityEngine
.hasTerm( deq
[0] ) && d_equalityEngine
.hasTerm( deq
[1] ) );
981 Node r1
= d_equalityEngine
.getRepresentative( deq
[0] );
982 Node r2
= d_equalityEngine
.getRepresentative( deq
[1] );
983 bool is_sat
= isSetDisequalityEntailed( r1
, r2
);
986 //try to make one of them empty
987 for( unsigned e=0; e<2; e++ ){
991 Trace("sets-debug") << "Check disequality " << deq
<< ", is_sat = " << is_sat
<< std::endl
;
992 //will process regardless of sat/processed/unprocessed
996 if( d_deq_processed
.find( deq
)==d_deq_processed
.end() ){
997 d_deq_processed
.insert( deq
);
998 d_deq_processed
.insert( deq
[1].eqNode( deq
[0] ) );
999 Trace("sets") << "Process Disequality : " << deq
.negate() << std::endl
;
1000 TypeNode elementType
= deq
[0].getType().getSetElementType();
1001 Node x
= NodeManager::currentNM()->mkSkolem("sde_", elementType
);
1002 Node mem1
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[0] );
1003 Node mem2
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[1] );
1004 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, deq
, NodeManager::currentNM()->mkNode( kind::EQUAL
, mem1
, mem2
).negate() );
1005 lem
= Rewriter::rewrite( lem
);
1006 assertInference( lem
, d_emp_exp
, lemmas
, "diseq", 1 );
1007 flushLemmas( lemmas
);
1008 if( hasProcessed() ){
1017 void TheorySetsPrivate::checkCardBuildGraph( std::vector
< Node
>& lemmas
) {
1018 Trace("sets") << "Cardinality graph..." << std::endl
;
1019 //first, ensure cardinality relationships are added as lemmas for all non-basic set terms
1020 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
1021 Node eqc
= d_set_eqc
[i
];
1022 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1023 if( itn
!=d_nvar_sets
.end() ){
1024 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1025 Node n
= itn
->second
[j
];
1026 if( d_congruent
.find( n
)==d_congruent
.end() ){
1027 //if setminus, do for intersection instead
1028 if( n
.getKind()==kind::SETMINUS
){
1029 n
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
1031 registerCardinalityTerm( n
, lemmas
);
1036 Trace("sets") << "Done cardinality graph" << std::endl
;
1039 void TheorySetsPrivate::registerCardinalityTerm( Node n
, std::vector
< Node
>& lemmas
){
1040 if( d_card_processed
.find( n
)==d_card_processed
.end() ){
1041 d_card_processed
.insert( n
);
1042 Trace("sets-card") << "Cardinality lemmas for " << n
<< " : " << std::endl
;
1043 std::vector
< Node
> cterms
;
1044 if( n
.getKind()==kind::INTERSECTION
){
1045 for( unsigned e
=0; e
<2; e
++ ){
1046 Node s
= NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] );
1047 cterms
.push_back( s
);
1049 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, n
), d_zero
);
1050 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
1052 cterms
.push_back( n
);
1054 for( unsigned k
=0; k
<cterms
.size(); k
++ ){
1055 Node nn
= cterms
[k
];
1056 Node nk
= getProxy( nn
);
1057 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
), d_zero
);
1058 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
1060 Node lem
= NodeManager::currentNM()->mkNode( kind::EQUAL
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
),
1061 NodeManager::currentNM()->mkNode( kind::CARD
, nn
) );
1062 lem
= Rewriter::rewrite( lem
);
1063 Trace("sets-card") << " " << k
<< " : " << lem
<< std::endl
;
1064 assertInference( lem
, d_emp_exp
, lemmas
, "card", 1 );
1070 void TheorySetsPrivate::checkCardCycles( std::vector
< Node
>& lemmas
) {
1071 Trace("sets") << "Check cardinality cycles..." << std::endl
;
1072 //build order of equivalence classes, also build cardinality graph
1073 std::vector
< Node
> set_eqc_tmp
;
1074 set_eqc_tmp
.insert( set_eqc_tmp
.end(), d_set_eqc
.begin(), d_set_eqc
.end() );
1076 d_card_parent
.clear();
1077 for( unsigned i
=0; i
<set_eqc_tmp
.size(); i
++ ){
1078 std::vector
< Node
> curr
;
1079 std::vector
< Node
> exp
;
1080 checkCardCyclesRec( set_eqc_tmp
[i
], curr
, exp
, lemmas
);
1081 flushLemmas( lemmas
);
1082 if( hasProcessed() ){
1086 Trace("sets") << "Done check cardinality cycles" << std::endl
;
1089 void TheorySetsPrivate::checkCardCyclesRec( Node eqc
, std::vector
< Node
>& curr
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
) {
1090 if( std::find( curr
.begin(), curr
.end(), eqc
)!=curr
.end() ){
1091 Trace("sets-debug") << "Found venn region loop..." << std::endl
;
1092 if( curr
.size()>1 ){
1093 //all regions must be equal
1094 std::vector
< Node
> conc
;
1095 for( unsigned i
=1; i
<curr
.size(); i
++ ){
1096 conc
.push_back( curr
[0].eqNode( curr
[i
] ) );
1098 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
1099 assertInference( fact
, exp
, lemmas
, "card_cycle" );
1100 flushLemmas( lemmas
);
1102 //should be guaranteed based on not exploring equal parents
1105 }else if( std::find( d_set_eqc
.begin(), d_set_eqc
.end(), eqc
)==d_set_eqc
.end() ){
1106 curr
.push_back( eqc
);
1107 TypeNode tn
= eqc
.getType();
1108 bool is_empty
= eqc
==d_eqc_emptyset
[tn
];
1109 Node emp_set
= getEmptySet( tn
);
1110 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1111 if( itn
!=d_nvar_sets
.end() ){
1112 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1113 Node n
= itn
->second
[j
];
1114 if( n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
){
1115 Trace("sets-debug") << "Build cardinality parents for " << n
<< "..." << std::endl
;
1116 std::vector
< Node
> sib
;
1117 unsigned true_sib
= 0;
1118 if( n
.getKind()==kind::INTERSECTION
){
1120 for( unsigned e
=0; e
<2; e
++ ){
1121 Node sm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] ) );
1122 sib
.push_back( sm
);
1126 Node si
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
1127 sib
.push_back( si
);
1128 d_card_base
[n
] = si
;
1129 Node osm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[1], n
[0] ) );
1130 sib
.push_back( osm
);
1133 Node u
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::UNION
, n
[0], n
[1] ) );
1134 if( !d_equalityEngine
.hasTerm( u
) ){
1137 unsigned n_parents
= true_sib
+ ( u
.isNull() ? 0 : 1 );
1138 //if this set is empty
1140 Assert( ee_areEqual( n
, emp_set
) );
1141 Trace("sets-debug") << " empty, parents equal siblings" << std::endl
;
1142 std::vector
< Node
> conc
;
1143 //parent equal siblings
1144 for( unsigned e
=0; e
<true_sib
; e
++ ){
1145 if( d_equalityEngine
.hasTerm( sib
[e
] ) && !ee_areEqual( n
[e
], sib
[e
] ) ){
1146 conc
.push_back( n
[e
].eqNode( sib
[e
] ) );
1149 assertInference( conc
, n
.eqNode( emp_set
), lemmas
, "cg_emp" );
1150 flushLemmas( lemmas
);
1151 if( hasProcessed() ){
1154 //justify why there is no edge to parents (necessary?)
1155 for( unsigned e
=0; e
<n_parents
; e
++ ){
1156 Node p
= (e
==true_sib
) ? u
: n
[e
];
1161 std::vector
< Node
> card_parents
;
1162 std::vector
< int > card_parent_ids
;
1163 //check if equal to a parent
1164 for( unsigned e
=0; e
<n_parents
; e
++ ){
1165 Trace("sets-debug") << " check parent " << e
<< "/" << n_parents
<< std::endl
;
1166 bool is_union
= e
==true_sib
;
1167 Node p
= (e
==true_sib
) ? u
: n
[e
];
1168 Trace("sets-debug") << " check relation to parent " << p
<< ", isu=" << is_union
<< "..." << std::endl
;
1169 //if parent is empty
1170 if( ee_areEqual( p
, emp_set
) ){
1171 Trace("sets-debug") << " it is empty..." << std::endl
;
1172 Assert( !ee_areEqual( n
, emp_set
) );
1173 assertInference( n
.eqNode( emp_set
), p
.eqNode( emp_set
), lemmas
, "cg_emppar" );
1174 if( hasProcessed() ){
1177 //if we are equal to a parent
1178 }else if( ee_areEqual( p
, n
) ){
1179 Trace("sets-debug") << " it is equal to this..." << std::endl
;
1180 std::vector
< Node
> conc
;
1181 std::vector
< int > sib_emp_indices
;
1183 for( unsigned s
=0; s
<sib
.size(); s
++ ){
1184 sib_emp_indices
.push_back( s
);
1187 sib_emp_indices
.push_back( e
);
1189 //sibling(s) are empty
1190 for( unsigned s
=0; s
<sib_emp_indices
.size(); s
++ ){
1191 unsigned si
= sib_emp_indices
[s
];
1192 if( !ee_areEqual( sib
[si
], emp_set
) ){
1193 conc
.push_back( sib
[si
].eqNode( emp_set
) );
1195 Trace("sets-debug") << "Sibling " << sib
[si
] << " is already empty." << std::endl
;
1198 if( !is_union
&& n
.getKind()==kind::INTERSECTION
&& !u
.isNull() ){
1199 //union is equal to other parent
1200 if( !ee_areEqual( u
, n
[1-e
] ) ){
1201 conc
.push_back( u
.eqNode( n
[1-e
] ) );
1204 Trace("sets-debug") << "...derived " << conc
.size() << " conclusions" << std::endl
;
1205 assertInference( conc
, n
.eqNode( p
), lemmas
, "cg_eqpar" );
1206 flushLemmas( lemmas
);
1207 if( hasProcessed() ){
1211 Trace("sets-cdg") << "Card graph : " << n
<< " -> " << p
<< std::endl
;
1212 //otherwise, we a syntactic subset of p
1213 card_parents
.push_back( p
);
1214 card_parent_ids
.push_back( is_union
? 2 : e
);
1217 Assert( d_card_parent
[n
].empty() );
1218 Trace("sets-debug") << "get parent representatives..." << std::endl
;
1219 //for each parent, take their representatives
1220 for( unsigned k
=0; k
<card_parents
.size(); k
++ ){
1221 Node eqcc
= d_equalityEngine
.getRepresentative( card_parents
[k
] );
1222 Trace("sets-debug") << "Check card parent " << k
<< "/" << card_parents
.size() << std::endl
;
1224 //if parent is singleton, then we should either be empty to equal to it
1225 std::map
< Node
, Node
>::iterator itps
= d_eqc_singleton
.find( eqcc
);
1226 if( itps
!=d_eqc_singleton
.end() ){
1227 bool eq_parent
= false;
1228 std::vector
< Node
> exp
;
1229 addEqualityToExp( card_parents
[k
], itps
->second
, exp
);
1230 if( ee_areDisequal( n
, emp_set
) ){
1231 exp
.push_back( n
.eqNode( emp_set
).negate() );
1234 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpm
= d_pol_mems
[0].find( eqc
);
1235 if( itpm
!=d_pol_mems
[0].end() && !itpm
->second
.empty() ){
1236 Node pmem
= itpm
->second
.begin()->second
;
1237 exp
.push_back( pmem
);
1238 addEqualityToExp( n
, pmem
[1], exp
);
1242 //must be equal to parent
1244 Node conc
= n
.eqNode( card_parents
[k
] );
1245 assertInference( conc
, exp
, lemmas
, "cg_par_sing" );
1246 flushLemmas( lemmas
);
1249 Trace("sets-nf") << "Split empty : " << n
<< std::endl
;
1250 split( n
.eqNode( emp_set
), 1 );
1252 Assert( hasProcessed() );
1256 for( unsigned l
=0; l
<d_card_parent
[n
].size(); l
++ ){
1257 if( eqcc
==d_card_parent
[n
][l
] ){
1258 Trace("sets-debug") << " parents " << l
<< " and " << k
<< " are equal, ids = " << card_parent_ids
[l
] << " " << card_parent_ids
[k
] << std::endl
;
1260 if( n
.getKind()==kind::INTERSECTION
){
1261 Assert( card_parent_ids
[l
]!=2 );
1262 std::vector
< Node
> conc
;
1263 if( card_parent_ids
[k
]==2 ){
1264 //intersection is equal to other parent
1265 unsigned pid
= 1-card_parent_ids
[l
];
1266 if( !ee_areEqual( n
[pid
], n
) ){
1267 Trace("sets-debug") << " one of them is union, make equal to other..." << std::endl
;
1268 conc
.push_back( n
[pid
].eqNode( n
) );
1271 if( !ee_areEqual( card_parents
[k
], n
) ){
1272 Trace("sets-debug") << " neither is union, make equal to one parent..." << std::endl
;
1273 //intersection is equal to one of the parents
1274 conc
.push_back( card_parents
[k
].eqNode( n
) );
1277 assertInference( conc
, card_parents
[k
].eqNode( d_card_parent
[n
][l
] ), lemmas
, "cg_pareq" );
1278 flushLemmas( lemmas
);
1279 if( hasProcessed() ){
1286 d_card_parent
[n
].push_back( eqcc
);
1290 //now recurse on parents (to ensure their normal will be computed after this eqc)
1291 exp
.push_back( eqc
.eqNode( n
) );
1292 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1293 checkCardCyclesRec( d_card_parent
[n
][k
], curr
, exp
, lemmas
);
1294 if( hasProcessed() ){
1304 //parents now processed, can add to ordered list
1305 d_set_eqc
.push_back( eqc
);
1311 void TheorySetsPrivate::checkNormalForms( std::vector
< Node
>& lemmas
, std::vector
< Node
>& intro_sets
){
1312 Trace("sets") << "Check normal forms..." << std::endl
;
1313 // now, build normal form for each equivalence class
1314 // d_set_eqc is now sorted such that for each d_set_eqc[i], d_set_eqc[j],
1315 // if d_set_eqc[i] is a strict syntactic subterm of d_set_eqc[j], then i<j.
1318 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1319 checkNormalForm( d_set_eqc
[i
], intro_sets
);
1320 if( hasProcessed() || !intro_sets
.empty() ){
1324 Trace("sets") << "Done check normal forms" << std::endl
;
1327 void TheorySetsPrivate::checkNormalForm( Node eqc
, std::vector
< Node
>& intro_sets
){
1328 TypeNode tn
= eqc
.getType();
1329 Trace("sets") << "Compute normal form for " << eqc
<< std::endl
;
1330 Trace("sets-nf") << "Compute N " << eqc
<< "..." << std::endl
;
1331 if( eqc
==d_eqc_emptyset
[tn
] ){
1333 Trace("sets-nf") << "----> N " << eqc
<< " => {}" << std::endl
;
1335 //flat/normal forms are sets of equivalence classes
1337 std::vector
< Node
> comps
;
1338 std::map
< Node
, std::map
< Node
, std::vector
< Node
> > >::iterator it
= d_ff
.find( eqc
);
1339 if( it
!=d_ff
.end() ){
1340 for( std::map
< Node
, std::vector
< Node
> >::iterator itf
= it
->second
.begin(); itf
!= it
->second
.end(); ++itf
){
1341 std::sort( itf
->second
.begin(), itf
->second
.end() );
1342 if( base
.isNull() ){
1345 comps
.push_back( itf
->first
);
1347 Trace("sets-nf") << " F " << itf
->first
<< " : ";
1348 if( Trace
.isOn("sets-nf") ){
1349 Trace("sets-nf") << "{ ";
1350 for( unsigned k
=0; k
<itf
->second
.size(); k
++ ){
1351 if( k
>0 ){ Trace("sets-nf") << ", "; }
1352 Trace("sets-nf") << "[" << itf
->second
[k
] << "]";
1354 Trace("sets-nf") << " }" << std::endl
;
1356 Trace("sets-nf-debug") << " ...";
1357 debugPrintSet( itf
->first
, "sets-nf-debug" );
1358 Trace("sets-nf-debug") << std::endl
;
1361 Trace("sets-nf") << "(no flat forms)" << std::endl
;
1364 Assert( d_nf
.find( eqc
)==d_nf
.end() );
1365 bool success
= true;
1366 if( !base
.isNull() ){
1367 Node emp_set
= getEmptySet( tn
);
1368 for( unsigned j
=0; j
<comps
.size(); j
++ ){
1370 std::vector
< Node
> c
;
1371 c
.push_back( base
);
1372 c
.push_back( comps
[j
] );
1373 std::vector
< Node
> only
[2];
1374 std::vector
< Node
> common
;
1375 Trace("sets-nf-debug") << "Compare venn regions of " << base
<< " vs " << comps
[j
] << std::endl
;
1376 unsigned k
[2] = { 0, 0 };
1377 while( k
[0]<d_ff
[eqc
][c
[0]].size() || k
[1]<d_ff
[eqc
][c
[1]].size() ){
1379 for( unsigned e
=0; e
<2; e
++ ){
1380 if( k
[e
]==d_ff
[eqc
][c
[e
]].size() ){
1381 for( ; k
[1-e
]<d_ff
[eqc
][c
[1-e
]].size(); ++k
[1-e
] ){
1382 only
[1-e
].push_back( d_ff
[eqc
][c
[1-e
]][k
[1-e
]] );
1388 if( d_ff
[eqc
][c
[0]][k
[0]]==d_ff
[eqc
][c
[1]][k
[1]] ){
1389 common
.push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1392 }else if( d_ff
[eqc
][c
[0]][k
[0]]<d_ff
[eqc
][c
[1]][k
[1]] ){
1393 only
[0].push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1396 only
[1].push_back( d_ff
[eqc
][c
[1]][k
[1]] );
1401 if( !only
[0].empty() || !only
[1].empty() ){
1402 if( Trace
.isOn("sets-nf-debug") ){
1403 Trace("sets-nf-debug") << "Unique venn regions : " << std::endl
;
1404 for( unsigned e
=0; e
<2; e
++ ){
1405 Trace("sets-nf-debug") << " " << c
[e
] << " : { ";
1406 for( unsigned l
=0; l
<only
[e
].size(); l
++ ){
1407 if( l
>0 ){ Trace("sets-nf-debug") << ", "; }
1408 Trace("sets-nf-debug") << "[" << only
[e
][l
] << "]";
1410 Trace("sets-nf-debug") << " }" << std::endl
;
1413 //try to make one empty, prefer the unique ones first
1414 for( unsigned e
=0; e
<3; e
++ ){
1415 unsigned sz
= e
==2 ? common
.size() : only
[e
].size();
1416 for( unsigned l
=0; l
<sz
; l
++ ){
1417 Node r
= e
==2 ? common
[l
] : only
[e
][l
];
1418 Trace("sets-nf-debug") << "Try split empty : " << r
<< std::endl
;
1419 Trace("sets-nf-debug") << " actual : ";
1420 debugPrintSet( r
, "sets-nf-debug" );
1421 Trace("sets-nf-debug") << std::endl
;
1422 Assert( !ee_areEqual( r
, emp_set
) );
1423 if( !ee_areDisequal( r
, emp_set
) && ( d_pol_mems
[0].find( r
)==d_pol_mems
[0].end() || d_pol_mems
[0][r
].empty() ) ){
1424 //guess that its equal empty if it has no explicit members
1425 Trace("sets-nf") << " Split empty : " << r
<< std::endl
;
1426 Trace("sets-nf") << "Actual Split : ";
1427 debugPrintSet( r
, "sets-nf" );
1428 Trace("sets-nf") << std::endl
;
1429 split( r
.eqNode( emp_set
), 1 );
1430 Assert( hasProcessed() );
1435 for( unsigned l
=0; l
<only
[0].size(); l
++ ){
1436 for( unsigned m
=0; m
<only
[1].size(); m
++ ){
1437 bool disjoint
= false;
1438 Trace("sets-nf-debug") << "Try split " << only
[0][l
] << " against " << only
[1][m
] << std::endl
;
1440 for( unsigned e
=0; e
<2; e
++ ){
1441 Node r1
= e
==0 ? only
[0][l
] : only
[1][m
];
1442 Node r2
= e
==0 ? only
[1][m
] : only
[0][l
];
1443 //check if their intersection exists modulo equality
1444 std::map
< Node
, Node
>::iterator itb
= d_bop_index
[kind::INTERSECTION
][r1
].find( r2
);
1445 if( itb
!=d_bop_index
[kind::INTERSECTION
][r1
].end() ){
1446 Trace("sets-nf-debug") << "Split term already exists, but not in cardinality graph : " << itb
->second
<< ", should be empty." << std::endl
;
1447 //their intersection is empty (probably?)
1448 // e.g. these are two disjoint venn regions, proceed to next pair
1449 Assert( ee_areEqual( emp_set
, itb
->second
) );
1455 //simply introduce their intersection
1456 Assert( only
[0][l
]!=only
[1][m
] );
1457 Node kca
= getProxy( only
[0][l
] );
1458 Node kcb
= getProxy( only
[1][m
] );
1459 Node intro
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, kca
, kcb
) );
1460 Trace("sets-nf") << " Intro split : " << only
[0][l
] << " against " << only
[1][m
] << ", term is " << intro
<< std::endl
;
1461 intro_sets
.push_back( intro
);
1462 Assert( !d_equalityEngine
.hasTerm( intro
) );
1467 //should never get here
1472 //normal form is flat form of base
1473 d_nf
[eqc
].insert( d_nf
[eqc
].end(), d_ff
[eqc
][base
].begin(), d_ff
[eqc
][base
].end() );
1474 Trace("sets-nf") << "----> N " << eqc
<< " => F " << base
<< std::endl
;
1476 Trace("sets-nf") << "failed to build N " << eqc
<< std::endl
;
1480 //normal form is this equivalence class
1481 d_nf
[eqc
].push_back( eqc
);
1482 Trace("sets-nf") << "----> N " << eqc
<< " => { " << eqc
<< " }" << std::endl
;
1486 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1487 if( itn
!=d_nvar_sets
.end() ){
1488 std::map
< Node
, std::map
< Node
, bool > > parents_proc
;
1489 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1490 Node n
= itn
->second
[j
];
1491 Trace("sets-nf-debug") << "Carry nf for term " << n
<< std::endl
;
1492 if( !d_card_parent
[n
].empty() ){
1493 Assert( d_card_base
.find( n
)!=d_card_base
.end() );
1494 Node cbase
= d_card_base
[n
];
1495 Trace("sets-nf-debug") << "Card base is " << cbase
<< std::endl
;
1496 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1497 Node p
= d_card_parent
[n
][k
];
1498 Trace("sets-nf-debug") << "Check parent " << p
<< std::endl
;
1499 if( parents_proc
[cbase
].find( p
)==parents_proc
[cbase
].end() ){
1500 parents_proc
[cbase
][p
] = true;
1501 Trace("sets-nf-debug") << "Carry nf to parent ( " << cbase
<< ", [" << p
<< "] ), from " << n
<< "..." << std::endl
;
1502 //for( unsigned i=0; i<d_nf[eqc].size(); i++ ){
1503 // Assert( std::find( d_ff[p][cbase].begin(), d_ff[p][cbase].end(), d_nf[eqc][i] )==d_ff[p][cbase].end() );
1505 for( unsigned i
=0; i
<d_nf
[eqc
].size(); i
++ ){
1506 if( std::find( d_ff
[p
][cbase
].begin(), d_ff
[p
][cbase
].end(), d_nf
[eqc
][i
] )==d_ff
[p
][cbase
].end() ){
1507 d_ff
[p
][cbase
].insert( d_ff
[p
][cbase
].end(), d_nf
[eqc
].begin(), d_nf
[eqc
].end() );
1509 //if it is a duplicate venn region, it must be empty since it is coming from syntactically disjoint siblings TODO?
1513 Trace("sets-nf-debug") << "..already processed parent " << p
<< " for " << cbase
<< std::endl
;
1520 Assert( hasProcessed() );
1525 void TheorySetsPrivate::checkMinCard( std::vector
< Node
>& lemmas
) {
1527 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1528 Node eqc
= d_set_eqc
[i
];
1529 //get members in class
1530 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1531 if( itm
!=d_pol_mems
[0].end() ){
1532 std::vector
< Node
> exp
;
1533 std::vector
< Node
> members
;
1535 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1536 if( it
!=d_eqc_to_card_term
.end() ){
1537 cardTerm
= it
->second
;
1539 cardTerm
= NodeManager::currentNM()->mkNode( kind::CARD
, eqc
);
1541 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1543 for( unsigned j=0; j<members.size(); j++ ){
1544 if( !ee_areDisequal( members[j], itmm->second ) ){
1545 Assert( !ee_areEqual( members[j], itmm->second ) );
1550 members
.push_back( itmm
->first
);
1551 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, itmm
->first
, cardTerm
[0] ) );
1553 if( members
.size()>1 ){
1554 exp
.push_back( NodeManager::currentNM()->mkNode( kind::DISTINCT
, members
) );
1556 if( !members
.empty() ){
1557 Node conc
= NodeManager::currentNM()->mkNode( kind::GEQ
, cardTerm
, NodeManager::currentNM()->mkConst( Rational( members
.size() ) ) );
1558 Node lem
= NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
), conc
);
1559 Trace("sets-lemma") << "Sets::Lemma : " << lem
<< " by mincard" << std::endl
;
1560 lemmas
.push_back( lem
);
1566 void TheorySetsPrivate::flushLemmas( std::vector
< Node
>& lemmas
, bool preprocess
) {
1567 for( unsigned i
=0; i
<lemmas
.size(); i
++ ){
1568 flushLemma( lemmas
[i
], preprocess
);
1573 void TheorySetsPrivate::flushLemma( Node lem
, bool preprocess
) {
1574 if( d_lemmas_produced
.find(lem
)==d_lemmas_produced
.end() ){
1575 Trace("sets-lemma-debug") << "Send lemma : " << lem
<< std::endl
;
1576 d_lemmas_produced
.insert(lem
);
1577 d_external
.d_out
->lemma(lem
, false, preprocess
);
1580 Trace("sets-lemma-debug") << "Already sent lemma : " << lem
<< std::endl
;
1584 Node
TheorySetsPrivate::getProxy( Node n
) {
1585 if( n
.getKind()==kind::EMPTYSET
|| n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::UNION
){
1586 NodeMap::const_iterator it
= d_proxy
.find( n
);
1587 if( it
==d_proxy
.end() ){
1588 Node k
= NodeManager::currentNM()->mkSkolem( "sp", n
.getType(), "proxy for set" );
1590 d_proxy_to_term
[k
] = n
;
1591 Node eq
= k
.eqNode( n
);
1592 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
1593 d_external
.d_out
->lemma( eq
);
1594 if( n
.getKind()==kind::SINGLETON
){
1595 Node slem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, n
[0], k
);
1596 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton" << std::endl
;
1597 d_external
.d_out
->lemma( slem
);
1602 return (*it
).second
;
1609 Node
TheorySetsPrivate::getCongruent( Node n
) {
1610 Assert( d_equalityEngine
.hasTerm( n
) );
1611 std::map
< Node
, Node
>::iterator it
= d_congruent
.find( n
);
1612 if( it
==d_congruent
.end() ){
1619 Node
TheorySetsPrivate::getEmptySet( TypeNode tn
) {
1620 std::map
< TypeNode
, Node
>::iterator it
= d_emptyset
.find( tn
);
1621 if( it
==d_emptyset
.end() ){
1622 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
.toType()));
1629 Node
TheorySetsPrivate::getUnivSet( TypeNode tn
) {
1630 std::map
< TypeNode
, Node
>::iterator it
= d_univset
.find( tn
);
1631 if( it
==d_univset
.end() ){
1632 Node n
= NodeManager::currentNM()->mkNullaryOperator(tn
, kind::UNIVERSE_SET
);
1633 for( it
= d_univset
.begin(); it
!= d_univset
.end(); ++it
){
1636 if( tn
.isSubtypeOf( it
->first
) ){
1639 }else if( it
->first
.isSubtypeOf( tn
) ){
1644 Node ulem
= NodeManager::currentNM()->mkNode( kind::SUBSET
, n1
, n2
);
1645 Trace("sets-lemma") << "Sets::Lemma : " << ulem
<< " by univ-type" << std::endl
;
1646 d_external
.d_out
->lemma( ulem
);
1657 bool TheorySetsPrivate::hasLemmaCached( Node lem
) {
1658 return d_lemmas_produced
.find(lem
)!=d_lemmas_produced
.end();
1661 bool TheorySetsPrivate::hasProcessed() {
1662 return d_conflict
|| d_sentLemma
|| d_addedFact
;
1665 void TheorySetsPrivate::debugPrintSet( Node s
, const char * c
) {
1666 if( s
.getNumChildren()==0 ){
1667 NodeMap::const_iterator it
= d_proxy_to_term
.find( s
);
1668 if( it
!=d_proxy_to_term
.end() ){
1669 debugPrintSet( (*it
).second
, c
);
1674 Trace(c
) << "(" << s
.getOperator();
1675 for( unsigned i
=0; i
<s
.getNumChildren(); i
++ ){
1677 debugPrintSet( s
[i
], c
);
1683 void TheorySetsPrivate::lastCallEffortCheck() {
1684 Trace("sets") << "----- Last call effort check ------" << std::endl
;
1688 Node
TheorySetsPrivate::getTypeConstraintSkolem(Node n
, TypeNode tn
)
1690 std::map
<TypeNode
, Node
>::iterator it
= d_tc_skolem
[n
].find(tn
);
1691 if (it
== d_tc_skolem
[n
].end())
1693 Node k
= NodeManager::currentNM()->mkSkolem("tc_k", tn
);
1694 d_tc_skolem
[n
][tn
] = k
;
1700 /**************************** TheorySetsPrivate *****************************/
1701 /**************************** TheorySetsPrivate *****************************/
1702 /**************************** TheorySetsPrivate *****************************/
1704 void TheorySetsPrivate::check(Theory::Effort level
) {
1705 Trace("sets-check") << "Sets check effort " << level
<< std::endl
;
1706 if( level
== Theory::EFFORT_LAST_CALL
){
1707 lastCallEffortCheck();
1710 while(!d_external
.done() && !d_conflict
) {
1711 // Get all the assertions
1712 Assertion assertion
= d_external
.get();
1713 TNode fact
= assertion
.assertion
;
1714 Trace("sets-assert") << "Assert from input " << fact
<< std::endl
;
1716 assertFact( fact
, fact
);
1718 d_sentLemma
= false;
1719 Trace("sets-check") << "Sets finished assertions effort " << level
<< std::endl
;
1720 //invoke full effort check, relations check
1722 if( level
== Theory::EFFORT_FULL
){
1723 if( !d_external
.d_valuation
.needCheck() ){
1725 if( !d_conflict
&& !d_sentLemma
){
1726 //invoke relations solver
1727 d_rels
->check(level
);
1728 if( d_card_enabled
&& ( d_rels_enabled
|| options::setsExt() ) ){
1729 //if cardinality constraints are enabled,
1730 // then model construction may fail in there are relational operators, or universe set.
1731 // TODO: should internally check model, return unknown if fail
1732 d_full_check_incomplete
= true;
1733 Trace("sets-incomplete") << "Sets : incomplete because of extended operators." << std::endl
;
1736 if( d_full_check_incomplete
){
1737 d_external
.d_out
->setIncomplete();
1741 if( options::setsRelEager() ){
1742 d_rels
->check(level
);
1746 Trace("sets-check") << "Sets finish Check effort " << level
<< std::endl
;
1747 }/* TheorySetsPrivate::check() */
1749 bool TheorySetsPrivate::needsCheckLastEffort() {
1750 if( !d_var_elim
.empty() ){
1756 /************************ Sharing ************************/
1757 /************************ Sharing ************************/
1758 /************************ Sharing ************************/
1760 void TheorySetsPrivate::addSharedTerm(TNode n
) {
1761 Debug("sets") << "[sets] ThoerySetsPrivate::addSharedTerm( " << n
<< ")" << std::endl
;
1762 d_equalityEngine
.addTriggerTerm(n
, THEORY_SETS
);
1765 void TheorySetsPrivate::addCarePairs( quantifiers::TermArgTrie
* t1
, quantifiers::TermArgTrie
* t2
, unsigned arity
, unsigned depth
, unsigned& n_pairs
){
1768 Node f1
= t1
->getNodeData();
1769 Node f2
= t2
->getNodeData();
1770 if( !ee_areEqual( f1
, f2
) ){
1771 Trace("sets-cg") << "Check " << f1
<< " and " << f2
<< std::endl
;
1772 vector
< pair
<TNode
, TNode
> > currentPairs
;
1773 for (unsigned k
= 0; k
< f1
.getNumChildren(); ++ k
) {
1776 Assert( d_equalityEngine
.hasTerm(x
) );
1777 Assert( d_equalityEngine
.hasTerm(y
) );
1778 Assert( !ee_areDisequal( x
, y
) );
1779 Assert( !ee_areCareDisequal( x
, y
) );
1780 if( !d_equalityEngine
.areEqual( x
, y
) ){
1781 Trace("sets-cg") << "Arg #" << k
<< " is " << x
<< " " << y
<< std::endl
;
1782 if( d_equalityEngine
.isTriggerTerm(x
, THEORY_SETS
) && d_equalityEngine
.isTriggerTerm(y
, THEORY_SETS
) ){
1783 TNode x_shared
= d_equalityEngine
.getTriggerTermRepresentative(x
, THEORY_SETS
);
1784 TNode y_shared
= d_equalityEngine
.getTriggerTermRepresentative(y
, THEORY_SETS
);
1785 currentPairs
.push_back(make_pair(x_shared
, y_shared
));
1786 }else if( isCareArg( f1
, k
) && isCareArg( f2
, k
) ){
1787 //splitting on sets (necessary for handling set of sets properly)
1788 if( x
.getType().isSet() ){
1789 Assert( y
.getType().isSet() );
1790 if( !ee_areDisequal( x
, y
) ){
1791 Trace("sets-cg-lemma") << "Should split on : " << x
<< "==" << y
<< std::endl
;
1792 split( x
.eqNode( y
) );
1798 for (unsigned c
= 0; c
< currentPairs
.size(); ++ c
) {
1799 Trace("sets-cg-pair") << "Pair : " << currentPairs
[c
].first
<< " " << currentPairs
[c
].second
<< std::endl
;
1800 d_external
.addCarePair(currentPairs
[c
].first
, currentPairs
[c
].second
);
1807 if( depth
<(arity
-1) ){
1808 //add care pairs internal to each child
1809 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1810 addCarePairs( &it
->second
, NULL
, arity
, depth
+1, n_pairs
);
1813 //add care pairs based on each pair of non-disequal arguments
1814 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1815 std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= it
;
1817 for( ; it2
!= t1
->d_data
.end(); ++it2
){
1818 if( !d_equalityEngine
.areDisequal(it
->first
, it2
->first
, false) ){
1819 if( !ee_areCareDisequal(it
->first
, it2
->first
) ){
1820 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1826 //add care pairs based on product of indices, non-disequal arguments
1827 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1828 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= t2
->d_data
.begin(); it2
!= t2
->d_data
.end(); ++it2
){
1829 if( !d_equalityEngine
.areDisequal(it
->first
, it2
->first
, false) ){
1830 if( !ee_areCareDisequal(it
->first
, it2
->first
) ){
1831 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1840 void TheorySetsPrivate::computeCareGraph() {
1841 for( std::map
< Kind
, std::vector
< Node
> >::iterator it
= d_op_list
.begin(); it
!= d_op_list
.end(); ++it
){
1842 if( it
->first
==kind::SINGLETON
|| it
->first
==kind::MEMBER
){
1843 unsigned n_pairs
= 0;
1844 Trace("sets-cg-summary") << "Compute graph for sets, op=" << it
->first
<< "..." << it
->second
.size() << std::endl
;
1845 Trace("sets-cg") << "Build index for " << it
->first
<< "..." << std::endl
;
1846 std::map
< TypeNode
, quantifiers::TermArgTrie
> index
;
1849 for( unsigned i
=0; i
<it
->second
.size(); i
++ ){
1850 TNode f1
= it
->second
[i
];
1851 Assert(d_equalityEngine
.hasTerm(f1
));
1852 Trace("sets-cg-debug") << "...build for " << f1
<< std::endl
;
1853 //break into index based on operator, and type of first argument (since some operators are parametric)
1854 TypeNode tn
= f1
[0].getType();
1855 std::vector
< TNode
> reps
;
1856 bool hasCareArg
= false;
1857 for( unsigned j
=0; j
<f1
.getNumChildren(); j
++ ){
1858 reps
.push_back( d_equalityEngine
.getRepresentative( f1
[j
] ) );
1859 if( isCareArg( f1
, j
) ){
1864 Trace("sets-cg-debug") << "......adding." << std::endl
;
1865 index
[tn
].addTerm( f1
, reps
);
1866 arity
= reps
.size();
1868 Trace("sets-cg-debug") << "......skip." << std::endl
;
1873 for( std::map
< TypeNode
, quantifiers::TermArgTrie
>::iterator iti
= index
.begin(); iti
!= index
.end(); ++iti
){
1874 Trace("sets-cg") << "Process index " << iti
->first
<< "..." << std::endl
;
1875 addCarePairs( &iti
->second
, NULL
, arity
, 0, n_pairs
);
1878 Trace("sets-cg-summary") << "...done, # pairs = " << n_pairs
<< std::endl
;
1883 bool TheorySetsPrivate::isCareArg( Node n
, unsigned a
) {
1884 if( d_equalityEngine
.isTriggerTerm( n
[a
], THEORY_SETS
) ){
1886 }else if( ( n
.getKind()==kind::MEMBER
|| n
.getKind()==kind::SINGLETON
) && a
==0 && n
[0].getType().isSet() ){
1893 EqualityStatus
TheorySetsPrivate::getEqualityStatus(TNode a
, TNode b
) {
1894 Assert(d_equalityEngine
.hasTerm(a
) && d_equalityEngine
.hasTerm(b
));
1895 if (d_equalityEngine
.areEqual(a
, b
)) {
1896 // The terms are implied to be equal
1897 return EQUALITY_TRUE
;
1899 if (d_equalityEngine
.areDisequal(a
, b
, false)) {
1900 // The terms are implied to be dis-equal
1901 return EQUALITY_FALSE
;
1903 return EQUALITY_UNKNOWN
;
1905 Node aModelValue = d_external.d_valuation.getModelValue(a);
1906 if(aModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1907 Node bModelValue = d_external.d_valuation.getModelValue(b);
1908 if(bModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1909 if( aModelValue == bModelValue ) {
1910 // The term are true in current model
1911 return EQUALITY_TRUE_IN_MODEL;
1913 return EQUALITY_FALSE_IN_MODEL;
1917 // //TODO: can we be more precise sometimes?
1918 // return EQUALITY_UNKNOWN;
1921 /******************** Model generation ********************/
1922 /******************** Model generation ********************/
1923 /******************** Model generation ********************/
1925 bool TheorySetsPrivate::collectModelInfo(TheoryModel
* m
)
1927 Trace("sets-model") << "Set collect model info" << std::endl
;
1929 // Compute terms appearing in assertions and shared terms
1930 d_external
.computeRelevantTerms(termSet
);
1932 // Assert equalities and disequalities to the model
1933 if (!m
->assertEqualityEngine(&d_equalityEngine
, &termSet
))
1938 std::map
< Node
, Node
> mvals
;
1939 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1940 Node eqc
= d_set_eqc
[i
];
1941 if( termSet
.find( eqc
)==termSet
.end() ){
1942 Trace("sets-model") << "* Do not assign value for " << eqc
<< " since is not relevant." << std::endl
;
1944 std::vector
< Node
> els
;
1945 bool is_base
= !d_card_enabled
|| ( d_nf
[eqc
].size()==1 && d_nf
[eqc
][0]==eqc
);
1947 Trace("sets-model") << "Collect elements of base eqc " << eqc
<< std::endl
;
1948 // members that must be in eqc
1949 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1950 if( itm
!=d_pol_mems
[0].end() ){
1951 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1952 Node t
= NodeManager::currentNM()->mkNode( kind::SINGLETON
, itmm
->first
);
1957 if( d_card_enabled
){
1958 TypeNode elementType
= eqc
.getType().getSetElementType();
1960 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1961 if( it
!=d_eqc_to_card_term
.end() ){
1962 //slack elements from cardinality value
1963 Node v
= d_external
.d_valuation
.getModelValue(it
->second
);
1964 Trace("sets-model") << "Cardinality of " << eqc
<< " is " << v
<< std::endl
;
1965 Assert(v
.getConst
<Rational
>() <= LONG_MAX
, "Exceeded LONG_MAX in sets model");
1966 unsigned vu
= v
.getConst
<Rational
>().getNumerator().toUnsignedInt();
1967 Assert( els
.size()<=vu
);
1968 while( els
.size()<vu
){
1969 els
.push_back( NodeManager::currentNM()->mkNode( kind::SINGLETON
, NodeManager::currentNM()->mkSkolem( "msde", elementType
) ) );
1972 Trace("sets-model") << "No slack elements for " << eqc
<< std::endl
;
1975 Trace("sets-model") << "Build value for " << eqc
<< " based on normal form, size = " << d_nf
[eqc
].size() << std::endl
;
1976 //it is union of venn regions
1977 for( unsigned j
=0; j
<d_nf
[eqc
].size(); j
++ ){
1978 Assert( mvals
.find( d_nf
[eqc
][j
] )!=mvals
.end() );
1979 els
.push_back( mvals
[d_nf
[eqc
][j
]] );
1983 Node rep
= NormalForm::mkBop( kind::UNION
, els
, eqc
.getType() );
1984 rep
= Rewriter::rewrite( rep
);
1985 Trace("sets-model") << "* Assign representative of " << eqc
<< " to " << rep
<< std::endl
;
1987 if (!m
->assertEquality(eqc
, rep
, true))
1991 m
->assertSkeleton(rep
);
1997 /********************** Helper functions ***************************/
1998 /********************** Helper functions ***************************/
1999 /********************** Helper functions ***************************/
2001 void TheorySetsPrivate::addEqualityToExp( Node a
, Node b
, std::vector
< Node
>& exp
) {
2003 Assert( ee_areEqual( a
, b
) );
2004 exp
.push_back( a
.eqNode( b
) );
2008 Node
mkAnd(const std::vector
<TNode
>& conjunctions
) {
2009 Assert(conjunctions
.size() > 0);
2011 std::set
<TNode
> all
;
2012 for (unsigned i
= 0; i
< conjunctions
.size(); ++i
) {
2013 TNode t
= conjunctions
[i
];
2014 if (t
.getKind() == kind::AND
) {
2015 for(TNode::iterator child_it
= t
.begin();
2016 child_it
!= t
.end(); ++child_it
) {
2017 Assert((*child_it
).getKind() != kind::AND
);
2018 all
.insert(*child_it
);
2026 Assert(all
.size() > 0);
2027 if (all
.size() == 1) {
2028 // All the same, or just one
2029 return conjunctions
[0];
2032 NodeBuilder
<> conjunction(kind::AND
);
2033 std::set
<TNode
>::const_iterator it
= all
.begin();
2034 std::set
<TNode
>::const_iterator it_end
= all
.end();
2035 while (it
!= it_end
) {
2044 TheorySetsPrivate::Statistics::Statistics() :
2045 d_getModelValueTime("theory::sets::getModelValueTime")
2046 , d_mergeTime("theory::sets::merge_nodes::time")
2047 , d_processCard2Time("theory::sets::processCard2::time")
2048 , d_memberLemmas("theory::sets::lemmas::member", 0)
2049 , d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
2050 , d_numVertices("theory::sets::vertices", 0)
2051 , d_numVerticesMax("theory::sets::vertices-max", 0)
2052 , d_numMergeEq1or2("theory::sets::merge1or2", 0)
2053 , d_numMergeEq3("theory::sets::merge3", 0)
2054 , d_numLeaves("theory::sets::leaves", 0)
2055 , d_numLeavesMax("theory::sets::leaves-max", 0)
2057 smtStatisticsRegistry()->registerStat(&d_getModelValueTime
);
2058 smtStatisticsRegistry()->registerStat(&d_mergeTime
);
2059 smtStatisticsRegistry()->registerStat(&d_processCard2Time
);
2060 smtStatisticsRegistry()->registerStat(&d_memberLemmas
);
2061 smtStatisticsRegistry()->registerStat(&d_disequalityLemmas
);
2062 smtStatisticsRegistry()->registerStat(&d_numVertices
);
2063 smtStatisticsRegistry()->registerStat(&d_numVerticesMax
);
2064 smtStatisticsRegistry()->registerStat(&d_numMergeEq1or2
);
2065 smtStatisticsRegistry()->registerStat(&d_numMergeEq3
);
2066 smtStatisticsRegistry()->registerStat(&d_numLeaves
);
2067 smtStatisticsRegistry()->registerStat(&d_numLeavesMax
);
2071 TheorySetsPrivate::Statistics::~Statistics() {
2072 smtStatisticsRegistry()->unregisterStat(&d_getModelValueTime
);
2073 smtStatisticsRegistry()->unregisterStat(&d_mergeTime
);
2074 smtStatisticsRegistry()->unregisterStat(&d_processCard2Time
);
2075 smtStatisticsRegistry()->unregisterStat(&d_memberLemmas
);
2076 smtStatisticsRegistry()->unregisterStat(&d_disequalityLemmas
);
2077 smtStatisticsRegistry()->unregisterStat(&d_numVertices
);
2078 smtStatisticsRegistry()->unregisterStat(&d_numVerticesMax
);
2079 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq1or2
);
2080 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq3
);
2081 smtStatisticsRegistry()->unregisterStat(&d_numLeaves
);
2082 smtStatisticsRegistry()->unregisterStat(&d_numLeavesMax
);
2085 void TheorySetsPrivate::propagate(Theory::Effort effort
) {
2089 bool TheorySetsPrivate::propagate(TNode literal
) {
2090 Debug("sets-prop") << " propagate(" << literal
<< ")" << std::endl
;
2092 // If already in conflict, no more propagation
2094 Debug("sets-prop") << "TheoryUF::propagate(" << literal
<< "): already in conflict" << std::endl
;
2099 bool ok
= d_external
.d_out
->propagate(literal
);
2105 }/* TheorySetsPrivate::propagate(TNode) */
2108 void TheorySetsPrivate::setMasterEqualityEngine(eq::EqualityEngine
* eq
) {
2109 d_equalityEngine
.setMasterEqualityEngine(eq
);
2113 void TheorySetsPrivate::conflict(TNode a
, TNode b
)
2115 d_conflictNode
= explain(a
.eqNode(b
));
2116 d_external
.d_out
->conflict(d_conflictNode
);
2117 Debug("sets") << "[sets] conflict: " << a
<< " iff " << b
2118 << ", explaination " << d_conflictNode
<< std::endl
;
2119 Trace("sets-lemma") << "Equality Conflict : " << d_conflictNode
<< std::endl
;
2123 Node
TheorySetsPrivate::explain(TNode literal
)
2125 Debug("sets") << "TheorySetsPrivate::explain(" << literal
<< ")"
2128 bool polarity
= literal
.getKind() != kind::NOT
;
2129 TNode atom
= polarity
? literal
: literal
[0];
2130 std::vector
<TNode
> assumptions
;
2132 if(atom
.getKind() == kind::EQUAL
) {
2133 d_equalityEngine
.explainEquality(atom
[0], atom
[1], polarity
, assumptions
);
2134 } else if(atom
.getKind() == kind::MEMBER
) {
2135 d_equalityEngine
.explainPredicate(atom
, polarity
, assumptions
);
2137 Debug("sets") << "unhandled: " << literal
<< "; (" << atom
<< ", "
2138 << polarity
<< "); kind" << atom
.getKind() << std::endl
;
2142 return mkAnd(assumptions
);
2145 void TheorySetsPrivate::preRegisterTerm(TNode node
)
2147 Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node
<< ")"
2149 switch(node
.getKind()) {
2151 // TODO: what's the point of this
2152 d_equalityEngine
.addTriggerEquality(node
);
2155 // TODO: what's the point of this
2156 d_equalityEngine
.addTriggerPredicate(node
);
2159 d_equalityEngine
.addTriggerTerm(node
, THEORY_SETS
);
2162 //if( node.getType().isSet() ){
2163 // d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
2165 d_equalityEngine
.addTerm(node
);
2171 Node
TheorySetsPrivate::expandDefinition(LogicRequest
&logicRequest
, Node n
) {
2172 Debug("sets-proc") << "expandDefinition : " << n
<< std::endl
;
2173 if( n
.getKind()==kind::UNIVERSE_SET
|| n
.getKind()==kind::COMPLEMENT
|| n
.getKind()==kind::JOIN_IMAGE
){
2174 if( !options::setsExt() ){
2175 std::stringstream ss
;
2176 ss
<< "Extended set operators are not supported in default mode, try --sets-ext.";
2177 throw LogicException(ss
.str());
2183 Theory::PPAssertStatus
TheorySetsPrivate::ppAssert(TNode in
, SubstitutionMap
& outSubstitutions
) {
2184 Debug("sets-proc") << "ppAssert : " << in
<< std::endl
;
2185 Theory::PPAssertStatus status
= Theory::PP_ASSERT_STATUS_UNSOLVED
;
2187 //TODO: allow variable elimination for sets when setsExt = true
2189 //this is based off of Theory::ppAssert
2191 if (in
.getKind() == kind::EQUAL
) {
2192 if (in
[0].isVar() && !in
[1].hasSubterm(in
[0]) &&
2193 (in
[1].getType()).isSubtypeOf(in
[0].getType()) ){
2194 if( !in
[0].getType().isSet() || !options::setsExt() ){
2195 outSubstitutions
.addSubstitution(in
[0], in
[1]);
2197 status
= Theory::PP_ASSERT_STATUS_SOLVED
;
2199 }else if (in
[1].isVar() && !in
[0].hasSubterm(in
[1]) &&
2200 (in
[0].getType()).isSubtypeOf(in
[1].getType())){
2201 if( !in
[1].getType().isSet() || !options::setsExt() ){
2202 outSubstitutions
.addSubstitution(in
[1], in
[0]);
2204 status
= Theory::PP_ASSERT_STATUS_SOLVED
;
2206 }else if (in
[0].isConst() && in
[1].isConst()) {
2207 if (in
[0] != in
[1]) {
2208 status
= Theory::PP_ASSERT_STATUS_CONFLICT
;
2213 if( status
==Theory::PP_ASSERT_STATUS_SOLVED
){
2214 Trace("sets-var-elim") << "Sets : ppAssert variable eliminated : " << in
<< ", var = " << var
<< std::endl
;
2216 if( var.getType().isSet() ){
2217 //we must ensure that subs is included in the universe set
2218 d_var_elim[var] = true;
2221 if( options::setsExt() ){
2222 Assert( !var
.getType().isSet() );
2228 void TheorySetsPrivate::presolve() {
2232 /**************************** eq::NotifyClass *****************************/
2233 /**************************** eq::NotifyClass *****************************/
2234 /**************************** eq::NotifyClass *****************************/
2237 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerEquality(TNode equality
, bool value
)
2239 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerEquality: equality = " << equality
2240 << " value = " << value
<< std::endl
;
2242 return d_theory
.propagate(equality
);
2244 // We use only literal triggers so taking not is safe
2245 return d_theory
.propagate(equality
.notNode());
2249 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerPredicate(TNode predicate
, bool value
)
2251 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerPredicate: predicate = " << predicate
2252 << " value = " << value
<< std::endl
;
2254 return d_theory
.propagate(predicate
);
2256 return d_theory
.propagate(predicate
.notNode());
2260 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag
, TNode t1
, TNode t2
, bool value
)
2262 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerTermEquality: tag = " << tag
2263 << " t1 = " << t1
<< " t2 = " << t2
<< " value = " << value
<< std::endl
;
2264 d_theory
.propagate( value
? t1
.eqNode( t2
) : t1
.eqNode( t2
).negate() );
2268 void TheorySetsPrivate::NotifyClass::eqNotifyConstantTermMerge(TNode t1
, TNode t2
)
2270 Debug("sets-eq") << "[sets-eq] eqNotifyConstantTermMerge " << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2271 d_theory
.conflict(t1
, t2
);
2274 void TheorySetsPrivate::NotifyClass::eqNotifyNewClass(TNode t
)
2276 Debug("sets-eq") << "[sets-eq] eqNotifyNewClass:" << " t = " << t
<< std::endl
;
2277 d_theory
.eqNotifyNewClass(t
);
2280 void TheorySetsPrivate::NotifyClass::eqNotifyPreMerge(TNode t1
, TNode t2
)
2282 Debug("sets-eq") << "[sets-eq] eqNotifyPreMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2283 d_theory
.eqNotifyPreMerge(t1
, t2
);
2286 void TheorySetsPrivate::NotifyClass::eqNotifyPostMerge(TNode t1
, TNode t2
)
2288 Debug("sets-eq") << "[sets-eq] eqNotifyPostMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2289 d_theory
.eqNotifyPostMerge(t1
, t2
);
2292 void TheorySetsPrivate::NotifyClass::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
)
2294 Debug("sets-eq") << "[sets-eq] eqNotifyDisequal:" << " t1 = " << t1
<< " t2 = " << t2
<< " reason = " << reason
<< std::endl
;
2295 d_theory
.eqNotifyDisequal(t1
, t2
, reason
);
2298 }/* CVC4::theory::sets namespace */
2299 }/* CVC4::theory namespace */
2300 }/* CVC4 namespace */