1 /********************* */
2 /*! \file theory_sets_private.cpp
4 ** Top contributors (to current version):
5 ** Kshitij Bansal, Tim King, Andrew Reynolds
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2016 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 <boost/foreach.hpp>
22 #include "expr/emptyset.h"
23 #include "options/sets_options.h"
24 #include "smt/smt_statistics_registry.h"
25 #include "theory/sets/theory_sets.h"
26 #include "theory/sets/normal_form.h"
27 #include "theory/theory_model.h"
28 #include "util/result.h"
29 #include "theory/quantifiers/term_database.h"
31 #define AJR_IMPLEMENTATION
39 TheorySetsPrivate::TheorySetsPrivate(TheorySets
& external
,
41 context::UserContext
* u
):
53 d_equalityEngine(d_notify
, c
, "theory::sets::TheorySetsPrivate", true),
57 d_rels
= new TheorySetsRels(c
, u
, &d_equalityEngine
, &d_conflict
, external
);
59 d_true
= NodeManager::currentNM()->mkConst( true );
60 d_false
= NodeManager::currentNM()->mkConst( false );
61 d_zero
= NodeManager::currentNM()->mkConst( Rational(0) );
63 d_equalityEngine
.addFunctionKind(kind::SINGLETON
);
64 d_equalityEngine
.addFunctionKind(kind::UNION
);
65 d_equalityEngine
.addFunctionKind(kind::INTERSECTION
);
66 d_equalityEngine
.addFunctionKind(kind::SETMINUS
);
68 d_equalityEngine
.addFunctionKind(kind::MEMBER
);
69 d_equalityEngine
.addFunctionKind(kind::SUBSET
);
71 // If cardinality is on.
72 d_equalityEngine
.addFunctionKind(kind::CARD
);
74 d_card_enabled
= false;
75 d_rels_enabled
= false;
77 }/* TheorySetsPrivate::TheorySetsPrivate() */
79 TheorySetsPrivate::~TheorySetsPrivate(){
81 for(std::map
< Node
, EqcInfo
* >::iterator i
= d_eqc_info
.begin(), iend
= d_eqc_info
.end(); i
!= iend
; ++i
){
82 EqcInfo
* current
= (*i
).second
;
85 }/* TheorySetsPrivate::~TheorySetsPrivate() */
88 void TheorySetsPrivate::eqNotifyNewClass(TNode t
) {
89 if( t
.getKind()==kind::SINGLETON
|| t
.getKind()==kind::EMPTYSET
){
90 EqcInfo
* e
= getOrMakeEqcInfo( t
, true );
93 if( options::setsRelEager() ){
94 d_rels
->eqNotifyNewClass( t
);
98 void TheorySetsPrivate::eqNotifyPreMerge(TNode t1
, TNode t2
){
102 void TheorySetsPrivate::eqNotifyPostMerge(TNode t1
, TNode t2
){
104 Trace("sets-prop-debug") << "Merge " << t1
<< " and " << t2
<< "..." << std::endl
;
106 EqcInfo
* e2
= getOrMakeEqcInfo( t2
);
108 s2
= e2
->d_singleton
;
109 EqcInfo
* e1
= getOrMakeEqcInfo( t1
);
111 Trace("sets-prop-debug") << "Merging singletons..." << std::endl
;
113 s1
= e1
->d_singleton
;
114 if( !s1
.isNull() && !s2
.isNull() ){
115 if( s1
.getKind()==s2
.getKind() ){
116 Trace("sets-prop") << "Propagate eq inference : " << s1
<< " == " << s2
<< std::endl
;
117 //infer equality between elements of singleton
118 Node exp
= s1
.eqNode( s2
);
119 Node eq
= s1
[0].eqNode( s2
[0] );
120 d_keep
.insert( exp
);
122 assertFact( eq
, exp
);
124 //singleton equal to emptyset, conflict
125 Trace("sets-prop") << "Propagate conflict : " << s1
<< " == " << s2
<< std::endl
;
132 e1
= getOrMakeEqcInfo( t1
, true );
133 e1
->d_singleton
.set( e2
->d_singleton
);
136 //merge membership list
137 Trace("sets-prop-debug") << "Copying membership list..." << std::endl
;
138 NodeIntMap::iterator mem_i2
= d_members
.find( t2
);
139 if( mem_i2
!= d_members
.end() ) {
140 NodeIntMap::iterator mem_i1
= d_members
.find( t1
);
142 if( mem_i1
!= d_members
.end() ) {
143 n_members
= (*mem_i1
).second
;
145 for( int i
=0; i
<(*mem_i2
).second
; i
++ ){
146 Assert( i
<(int)d_members_data
[t2
].size() && d_members_data
[t2
][i
].getKind()==kind::MEMBER
);
147 Node m2
= d_members_data
[t2
][i
];
150 for( int j
=0; j
<n_members
; j
++ ){
151 Assert( j
<(int)d_members_data
[t1
].size() && d_members_data
[t1
][j
].getKind()==kind::MEMBER
);
152 if( ee_areEqual( m2
[0], d_members_data
[t1
][j
][0] ) ){
158 if( !s1
.isNull() && s2
.isNull() ){
159 Assert( m2
[1].getType()==s1
.getType() );
160 Assert( ee_areEqual( m2
[1], s1
) );
161 Node exp
= NodeManager::currentNM()->mkNode( kind::AND
, m2
[1].eqNode( s1
), m2
);
162 if( s1
.getKind()==kind::SINGLETON
){
164 Node eq
= s1
[0].eqNode( m2
[0] );
165 d_keep
.insert( exp
);
167 Trace("sets-prop") << "Propagate eq-mem eq inference : " << exp
<< " => " << eq
<< std::endl
;
168 assertFact( eq
, exp
);
172 Trace("sets-prop") << "Propagate eq-mem conflict : " << exp
<< std::endl
;
174 d_external
.d_out
->conflict( exp
);
178 if( n_members
<(int)d_members_data
[t1
].size() ){
179 d_members_data
[t1
][n_members
] = m2
;
181 d_members_data
[t1
].push_back( m2
);
186 d_members
[t1
] = n_members
;
188 if( options::setsRelEager() ){
189 d_rels
->eqNotifyPostMerge( t1
, t2
);
194 void TheorySetsPrivate::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
){
195 if( t1
.getType().isSet() ){
196 Node eq
= t1
.eqNode( t2
);
197 if( d_deq
.find( eq
)==d_deq
.end() ){
203 TheorySetsPrivate::EqcInfo::EqcInfo( context::Context
* c
) : d_singleton( c
){
207 TheorySetsPrivate::EqcInfo
* TheorySetsPrivate::getOrMakeEqcInfo( TNode n
, bool doMake
){
208 std::map
< Node
, EqcInfo
* >::iterator eqc_i
= d_eqc_info
.find( n
);
209 if( eqc_i
==d_eqc_info
.end() ){
212 ei
= new EqcInfo( d_external
.getSatContext() );
217 return eqc_i
->second
;
222 bool TheorySetsPrivate::ee_areEqual( Node a
, Node b
) {
226 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
227 return d_equalityEngine
.areEqual( a
, b
);
234 bool TheorySetsPrivate::ee_areDisequal( Node a
, Node b
) {
238 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
239 return d_equalityEngine
.areDisequal( a
, b
, false );
241 return a
.isConst() && b
.isConst();
246 bool TheorySetsPrivate::isEntailed( Node n
, bool polarity
) {
247 if( n
.getKind()==kind::NOT
){
248 return isEntailed( n
[0], !polarity
);
249 }else if( n
.getKind()==kind::EQUAL
){
251 return ee_areEqual( n
[0], n
[1] );
253 return ee_areDisequal( n
[0], n
[1] );
255 }else if( n
.getKind()==kind::MEMBER
){
256 if( ee_areEqual( n
, polarity
? d_true
: d_false
) ){
259 //check members cache
260 if( polarity
&& d_equalityEngine
.hasTerm( n
[1] ) ){
261 Node r
= d_equalityEngine
.getRepresentative( n
[1] );
262 if( isMember( n
[0], r
) ){
266 }else if( n
.getKind()==kind::AND
|| n
.getKind()==kind::OR
){
267 bool conj
= (n
.getKind()==kind::AND
)==polarity
;
268 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
269 bool isEnt
= isEntailed( n
[i
], polarity
);
275 }else if( n
.isConst() ){
276 return ( polarity
&& n
==d_true
) || ( !polarity
&& n
==d_false
);
281 bool TheorySetsPrivate::isMember( Node x
, Node s
) {
282 Assert( d_equalityEngine
.hasTerm( s
) && d_equalityEngine
.getRepresentative( s
)==s
);
283 NodeIntMap::iterator mem_i
= d_members
.find( s
);
284 if( mem_i
!= d_members
.end() ) {
285 for( int i
=0; i
<(*mem_i
).second
; i
++ ){
286 if( ee_areEqual( d_members_data
[s
][i
][0], x
) ){
294 bool TheorySetsPrivate::isSetDisequalityEntailed( Node r1
, Node r2
) {
295 Assert( d_equalityEngine
.hasTerm( r1
) && d_equalityEngine
.getRepresentative( r1
)==r1
);
296 Assert( d_equalityEngine
.hasTerm( r2
) && d_equalityEngine
.getRepresentative( r2
)==r2
);
297 TypeNode tn
= r1
.getType();
298 Node eqc_es
= d_eqc_emptyset
[tn
];
300 for( unsigned e
=0; e
<2; e
++ ){
301 Node a
= e
==0 ? r1
: r2
;
302 Node b
= e
==0 ? r2
: r1
;
303 //if there are members in a
304 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpma
= d_pol_mems
[0].find( a
);
305 if( itpma
!=d_pol_mems
[0].end() ){
306 Assert( !itpma
->second
.empty() );
309 if( !itpma
->second
.empty() ){
311 Trace("sets-deq") << "Disequality is satisfied because members are in " << a
<< " and " << b
<< " is empty" << std::endl
;
313 //a should not be singleton
314 Assert( d_eqc_singleton
.find( a
)==d_eqc_singleton
.end() );
317 std::map
< Node
, Node
>::iterator itsb
= d_eqc_singleton
.find( b
);
318 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpmb
= d_pol_mems
[1].find( b
);
319 std::vector
< Node
> prev
;
320 for( std::map
< Node
, Node
>::iterator itm
= itpma
->second
.begin(); itm
!= itpma
->second
.end(); ++itm
){
321 //if b is a singleton
322 if( itsb
!=d_eqc_singleton
.end() ){
323 if( ee_areDisequal( itm
->first
, itsb
->second
[0] ) ){
324 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< ", singleton eq " << itsb
->second
[0] << std::endl
;
327 //or disequal with another member
328 for( unsigned k
=0; k
<prev
.size(); k
++ ){
329 if( ee_areDisequal( itm
->first
, prev
[k
] ) ){
330 Trace("sets-deq") << "Disequality is satisfied because of disequal members " << itm
->first
<< " " << prev
[k
] << ", singleton eq " << std::endl
;
335 //TODO: this can be generalized : maintain map to abstract domain ( set -> cardinality )
336 //if a has positive member that is negative member in b
337 }else if( itpmb
!=d_pol_mems
[1].end() ){
338 for( std::map
< Node
, Node
>::iterator itnm
= itpmb
->second
.begin(); itnm
!= itpmb
->second
.end(); ++itnm
){
339 if( ee_areEqual( itm
->first
, itnm
->first
) ){
340 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< " " << itnm
->second
<< std::endl
;
349 prev
.push_back( itm
->first
);
360 bool TheorySetsPrivate::assertFact( Node fact
, Node exp
){
361 Trace("sets-assert") << "TheorySets::assertFact : " << fact
<< ", exp = " << exp
<< std::endl
;
362 bool polarity
= fact
.getKind() != kind::NOT
;
363 TNode atom
= polarity
? fact
: fact
[0];
364 if( !isEntailed( atom
, polarity
) ){
365 if( atom
.getKind()==kind::EQUAL
){
366 d_equalityEngine
.assertEquality( atom
, polarity
, exp
);
368 d_equalityEngine
.assertPredicate( atom
, polarity
, exp
);
371 if( atom
.getKind()==kind::MEMBER
&& polarity
){
372 //check if set has a value, if so, we can propagate
373 Node r
= d_equalityEngine
.getRepresentative( atom
[1] );
374 EqcInfo
* e
= getOrMakeEqcInfo( r
, true );
376 Node s
= e
->d_singleton
;
378 Node exp
= NodeManager::currentNM()->mkNode( kind::AND
, atom
, atom
[1].eqNode( s
) );
379 d_keep
.insert( exp
);
380 if( s
.getKind()==kind::SINGLETON
){
382 Trace("sets-prop") << "Propagate mem-eq : " << exp
<< std::endl
;
383 Node eq
= s
[0].eqNode( atom
[0] );
385 assertFact( eq
, exp
);
388 Trace("sets-prop") << "Propagate mem-eq conflict : " << exp
<< std::endl
;
390 d_external
.d_out
->conflict( exp
);
394 //add to membership list
395 NodeIntMap::iterator mem_i
= d_members
.find( r
);
397 if( mem_i
!= d_members
.end() ) {
398 n_members
= (*mem_i
).second
;
400 d_members
[r
] = n_members
+ 1;
401 if( n_members
<(int)d_members_data
[r
].size() ){
402 d_members_data
[r
][n_members
] = atom
;
404 d_members_data
[r
].push_back( atom
);
414 bool TheorySetsPrivate::assertFactRec( Node fact
, Node exp
, std::vector
< Node
>& lemma
, int inferType
) {
415 if( ( options::setsInferAsLemmas() && inferType
!=-1 ) || inferType
==1 ){
416 if( !isEntailed( fact
, true ) ){
417 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
421 Trace("sets-fact") << "Assert fact rec : " << fact
<< ", exp = " << exp
<< std::endl
;
422 if( fact
.isConst() ){
423 //either trivial or a conflict
425 Trace("sets-lemma") << "Conflict : " << exp
<< std::endl
;
427 d_external
.d_out
->conflict( exp
);
430 }else if( fact
.getKind()==kind::AND
|| ( fact
.getKind()==kind::NOT
&& fact
[0].getKind()==kind::OR
) ){
432 Node f
= fact
.getKind()==kind::NOT
? fact
[0] : fact
;
433 for( unsigned i
=0; i
<f
.getNumChildren(); i
++ ){
434 Node factc
= fact
.getKind()==kind::NOT
? f
[i
].negate() : f
[i
];
435 bool tret
= assertFactRec( factc
, exp
, lemma
, inferType
);
443 bool polarity
= fact
.getKind() != kind::NOT
;
444 TNode atom
= polarity
? fact
: fact
[0];
445 //things we can assert to equality engine
446 if( atom
.getKind()==kind::MEMBER
|| ( atom
.getKind()==kind::EQUAL
&& atom
[0].getType().isSet() ) ){
447 //send to equality engine
448 if( assertFact( fact
, exp
) ){
453 if( !isEntailed( fact
, true ) ){
455 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
463 void TheorySetsPrivate::assertInference( Node fact
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
464 d_keep
.insert( exp
);
465 d_keep
.insert( fact
);
466 if( assertFactRec( fact
, exp
, lemmas
, inferType
) ){
467 Trace("sets-lemma") << "Sets::Lemma : " << fact
<< " from " << exp
<< " by " << c
<< std::endl
;
468 Trace("sets-assertion") << "(assert (=> " << exp
<< " " << fact
<< ")) ; by " << c
<< std::endl
;
472 void TheorySetsPrivate::assertInference( Node fact
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
473 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
474 assertInference( fact
, exp_n
, lemmas
, c
, inferType
);
477 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
479 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
480 assertInference( fact
, exp
, lemmas
, c
, inferType
);
483 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
484 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
485 assertInference( conc
, exp_n
, lemmas
, c
, inferType
);
488 void TheorySetsPrivate::split( Node n
, int reqPol
) {
489 n
= Rewriter::rewrite( n
);
490 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, n
, n
.negate() );
491 std::vector
< Node
> lemmas
;
492 lemmas
.push_back( lem
);
493 flushLemmas( lemmas
);
494 Trace("sets-lemma") << "Sets::Lemma split : " << lem
<< std::endl
;
496 Trace("sets-lemma") << "Sets::Require phase " << n
<< " " << (reqPol
>0) << std::endl
;
497 d_external
.getOutputChannel().requirePhase( n
, reqPol
>0 );
501 void TheorySetsPrivate::fullEffortCheck(){
502 Trace("sets") << "----- Full effort check ------" << std::endl
;
504 Trace("sets") << "...iterate full effort check..." << std::endl
;
505 Assert( d_equalityEngine
.consistent() );
509 d_set_eqc_list
.clear();
510 d_eqc_emptyset
.clear();
511 d_eqc_univset
.clear();
512 d_eqc_singleton
.clear();
515 d_pol_mems
[0].clear();
516 d_pol_mems
[1].clear();
517 d_members_index
.clear();
518 d_singleton_index
.clear();
521 d_card_enabled
= false;
522 d_rels_enabled
= false;
523 d_eqc_to_card_term
.clear();
525 std::vector
< Node
> lemmas
;
526 Trace("sets-eqc") << "Equality Engine:" << std::endl
;
527 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator( &d_equalityEngine
);
528 while( !eqcs_i
.isFinished() ){
529 Node eqc
= (*eqcs_i
);
531 TypeNode tn
= eqc
.getType();
534 d_set_eqc
.push_back( eqc
);
536 Trace("sets-eqc") << "[" << eqc
<< "] : ";
537 eq::EqClassIterator eqc_i
= eq::EqClassIterator( eqc
, &d_equalityEngine
);
538 while( !eqc_i
.isFinished() ) {
541 Trace("sets-eqc") << n
<< " ";
543 if( n
.getKind()==kind::MEMBER
){
545 Node s
= d_equalityEngine
.getRepresentative( n
[1] );
546 Node x
= d_equalityEngine
.getRepresentative( n
[0] );
547 int pindex
= eqc
==d_true
? 0 : ( eqc
==d_false
? 1 : -1 );
549 if( d_pol_mems
[pindex
][s
].find( x
)==d_pol_mems
[pindex
][s
].end() ){
550 d_pol_mems
[pindex
][s
][x
] = n
;
551 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
<< ", pindex = " << pindex
<< std::endl
;
553 if( d_members_index
[s
].find( x
)==d_members_index
[s
].end() ){
554 d_members_index
[s
][x
] = n
;
555 d_op_list
[kind::MEMBER
].push_back( n
);
561 }else if( n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::UNION
|| n
.getKind()==kind::INTERSECTION
||
562 n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::EMPTYSET
|| n
.getKind()==kind::UNIVERSE_SET
){
563 if( n
.getKind()==kind::SINGLETON
){
566 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
567 if( d_singleton_index
.find( r
)==d_singleton_index
.end() ){
568 d_singleton_index
[r
] = n
;
569 d_eqc_singleton
[eqc
] = n
;
570 d_op_list
[kind::SINGLETON
].push_back( n
);
572 d_congruent
[n
] = d_singleton_index
[r
];
574 }else if( n
.getKind()==kind::EMPTYSET
){
575 d_eqc_emptyset
[tn
] = eqc
;
576 }else if( n
.getKind()==kind::UNIVERSE_SET
){
577 d_eqc_univset
[tn
] = eqc
;
579 Node r1
= d_equalityEngine
.getRepresentative( n
[0] );
580 Node r2
= d_equalityEngine
.getRepresentative( n
[1] );
581 if( d_bop_index
[n
.getKind()][r1
].find( r2
)==d_bop_index
[n
.getKind()][r1
].end() ){
582 d_bop_index
[n
.getKind()][r1
][r2
] = n
;
583 d_op_list
[n
.getKind()].push_back( n
);
585 d_congruent
[n
] = d_bop_index
[n
.getKind()][r1
][r2
];
588 d_nvar_sets
[eqc
].push_back( n
);
589 Trace("sets-debug2") << "Non-var-set[" << eqc
<< "] : " << n
<< std::endl
;
590 d_set_eqc_list
[eqc
].push_back( n
);
591 }else if( n
.getKind()==kind::CARD
){
592 d_card_enabled
= true;
593 TypeNode tn
= n
[0].getType().getSetElementType();
594 if( tn
.isInterpretedFinite() ){
595 std::stringstream ss
;
596 ss
<< "ERROR: cannot use cardinality on sets with finite element type." << std::endl
;
597 throw LogicException(ss
.str());
598 //TODO: extend approach for this case
600 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
601 if( d_eqc_to_card_term
.find( r
)==d_eqc_to_card_term
.end() ){
602 d_eqc_to_card_term
[ r
] = n
;
603 registerCardinalityTerm( n
[0], lemmas
);
606 if( d_rels
->isRelationKind( n
.getKind() ) ){
607 d_rels_enabled
= true;
610 d_set_eqc_list
[eqc
].push_back( n
);
615 Trace("sets-eqc") << std::endl
;
619 flushLemmas( lemmas
);
620 if( !hasProcessed() ){
621 if( Trace
.isOn("sets-mem") ){
622 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
623 Node s
= d_set_eqc
[i
];
624 Trace("sets-mem") << "Eqc " << s
<< " : ";
625 std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].find( s
);
626 if( it
!=d_pol_mems
[0].end() ){
627 Trace("sets-mem") << "Memberships : ";
628 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
629 Trace("sets-mem") << it2
->first
<< " ";
632 std::map
< Node
, Node
>::iterator its
= d_eqc_singleton
.find( s
);
633 if( its
!=d_eqc_singleton
.end() ){
634 Trace("sets-mem") << " : Singleton : " << its
->second
;
636 Trace("sets-mem") << std::endl
;
640 checkDownwardsClosure( lemmas
);
641 if( options::setsInferAsLemmas() ){
642 flushLemmas( lemmas
);
644 if( !hasProcessed() ){
645 checkUpwardsClosure( lemmas
);
646 flushLemmas( lemmas
);
647 if( !hasProcessed() ){
648 std::vector
< Node
> intro_sets
;
650 if( d_card_enabled
){
651 checkCardBuildGraph( lemmas
);
652 flushLemmas( lemmas
);
653 if( !hasProcessed() ){
654 checkMinCard( lemmas
);
655 flushLemmas( lemmas
);
656 if( !hasProcessed() ){
657 checkCardCycles( lemmas
);
658 flushLemmas( lemmas
);
659 if( !hasProcessed() ){
660 checkNormalForms( lemmas
, intro_sets
);
661 flushLemmas( lemmas
);
666 if( !hasProcessed() ){
667 checkDisequalities( lemmas
);
668 flushLemmas( lemmas
);
669 if( !hasProcessed() ){
670 //introduce splitting on venn regions (absolute last resort)
671 if( d_card_enabled
&& !hasProcessed() && !intro_sets
.empty() ){
672 Assert( intro_sets
.size()==1 );
673 Trace("sets-intro") << "Introduce term : " << intro_sets
[0] << std::endl
;
674 Trace("sets-intro") << " Actual Intro : ";
675 debugPrintSet( intro_sets
[0], "sets-nf" );
676 Trace("sets-nf") << std::endl
;
677 Node k
= getProxy( intro_sets
[0] );
685 }while( !d_sentLemma
&& !d_conflict
&& d_addedFact
);
686 Trace("sets") << "----- End full effort check, conflict=" << d_conflict
<< ", lemma=" << d_sentLemma
<< std::endl
;
689 void TheorySetsPrivate::checkDownwardsClosure( std::vector
< Node
>& lemmas
) {
690 Trace("sets") << "Downwards closure..." << std::endl
;
692 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].begin(); it
!= d_pol_mems
[0].end(); ++it
){
693 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( it
->first
);
694 if( itn
!=d_nvar_sets
.end() ){
695 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
696 if( d_congruent
.find( itn
->second
[j
] )==d_congruent
.end() ){
697 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
698 Node mem
= it2
->second
;
699 Node eq_set
= itn
->second
[j
];
700 Assert( d_equalityEngine
.areEqual( mem
[1], eq_set
) );
701 if( mem
[1]!=eq_set
){
702 Trace("sets-debug") << "Downwards closure based on " << mem
<< ", eq_set = " << eq_set
<< std::endl
;
703 if( !options::setsProxyLemmas() ){
704 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
705 nmem
= Rewriter::rewrite( nmem
);
706 std::vector
< Node
> exp
;
707 exp
.push_back( mem
);
708 exp
.push_back( mem
[1].eqNode( eq_set
) );
709 assertInference( nmem
, exp
, lemmas
, "downc" );
715 Node k
= getProxy( eq_set
);
716 Node pmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], k
);
717 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
718 nmem
= Rewriter::rewrite( nmem
);
719 std::vector
< Node
> exp
;
720 if( ee_areEqual( mem
, pmem
) ){
721 exp
.push_back( pmem
);
723 nmem
= NodeManager::currentNM()->mkNode( kind::OR
, pmem
.negate(), nmem
);
725 assertInference( nmem
, exp
, lemmas
, "downc" );
735 void TheorySetsPrivate::checkUpwardsClosure( std::vector
< Node
>& lemmas
) {
737 for( std::map
< Kind
, std::map
< Node
, std::map
< Node
, Node
> > >::iterator itb
= d_bop_index
.begin(); itb
!= d_bop_index
.end(); ++itb
){
739 Trace("sets") << "Upwards closure " << k
<< "..." << std::endl
;
740 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= itb
->second
.begin(); it
!= itb
->second
.end(); ++it
){
742 //see if there are members in first argument r1
743 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm1
= d_pol_mems
[0].find( r1
);
744 if( itm1
!=d_pol_mems
[0].end() || k
==kind::UNION
){
745 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
746 Node r2
= it2
->first
;
747 //see if there are members in second argument
748 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm2
= d_pol_mems
[0].find( r2
);
749 if( itm2
!=d_pol_mems
[0].end() || k
!=kind::INTERSECTION
){
750 Trace("sets-debug") << "Checking " << it2
->second
<< ", members = " << (itm1
!=d_pol_mems
[0].end()) << ", " << (itm2
!=d_pol_mems
[0].end()) << std::endl
;
751 //for all members of r1
752 if( itm1
!=d_pol_mems
[0].end() ){
753 for( std::map
< Node
, Node
>::iterator itm1m
= itm1
->second
.begin(); itm1m
!= itm1
->second
.end(); ++itm1m
){
754 Node xr
= itm1m
->first
;
755 Node x
= itm1m
->second
[0];
756 Trace("sets-debug") << "checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
757 std::vector
< Node
> exp
;
758 exp
.push_back( itm1m
->second
);
759 addEqualityToExp( it2
->second
[0], itm1m
->second
[1], exp
);
762 if( k
==kind::UNION
){
764 }else if( k
==kind::INTERSECTION
){
765 //conclude x is in it2->second
766 //if also existing in members of r2
767 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
769 exp
.push_back( itm2
->second
[xr
] );
770 addEqualityToExp( it2
->second
[1], itm2
->second
[xr
][1], exp
);
771 addEqualityToExp( x
, itm2
->second
[xr
][0], exp
);
775 Assert( k
==kind::SETMINUS
);
777 std::map< Node, std::map< Node, Node > >::iterator itnm2 = d_pol_mems[1].find( r2 );
778 if( itnm2!=d_pol_mems[1].end() ){
779 bool not_in_r2 = itnm2->second.find( xr )!=itnm2->second.end();
781 exp.push_back( itnm2->second[xr] );
782 if( it2->second[1]!=itnm2->second[xr][1] ){
783 Assert( d_equalityEngine.areEqual( it2->second[1], itnm2->second[xr][1] ) );
784 exp.push_back( it2->second[1].eqNode( itnm2->second[xr][1] ) );
786 if( x!=itnm2->second[xr][0] ){
787 Assert( d_equalityEngine.areEqual( x, itnm2->second[xr][0] ) );
788 exp.push_back( NodeManager::currentNM()->mkNode( kind::EQUAL, x, itnm2->second[xr][0] ) );
795 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
797 // must add lemma for set minus since non-membership in this case is not explained
798 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, it2
->second
[1] ).negate() );
805 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
806 if( !isMember( x
, rr
) ){
807 Node kk
= getProxy( it2
->second
);
808 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, kk
);
809 assertInference( fact
, exp
, lemmas
, "upc", inferType
);
815 Trace("sets-debug") << "done checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
818 if( k
==kind::UNION
){
819 if( itm2
!=d_pol_mems
[0].end() ){
820 //for all members of r2
821 for( std::map
< Node
, Node
>::iterator itm2m
= itm2
->second
.begin(); itm2m
!= itm2
->second
.end(); ++itm2m
){
822 Node x
= itm2m
->second
[0];
823 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
824 if( !isMember( x
, rr
) ){
825 std::vector
< Node
> exp
;
826 exp
.push_back( itm2m
->second
);
827 addEqualityToExp( it2
->second
[1], itm2m
->second
[1], exp
);
828 Node k
= getProxy( it2
->second
);
829 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, k
);
830 assertInference( fact
, exp
, lemmas
, "upc2" );
843 if( !hasProcessed() ){
845 Trace("sets-debug") << "Check universe sets..." << std::endl
;
846 //all elements must be in universal set
847 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].begin(); it
!= d_pol_mems
[0].end(); ++it
){
848 TypeNode tn
= it
->first
.getType();
849 std::map
< TypeNode
, Node
>::iterator itu
= d_eqc_univset
.find( tn
);
850 if( itu
==d_eqc_univset
.end() || itu
->second
!=it
->first
){
851 Node u
= getUnivSet( tn
);
852 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
853 Node mem
= it2
->second
;
854 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], u
);
855 assertInference( fact
, mem
, lemmas
, "upuniv" );
865 void TheorySetsPrivate::checkDisequalities( std::vector
< Node
>& lemmas
) {
867 Trace("sets") << "Disequalities..." << std::endl
;
868 for(NodeBoolMap::const_iterator it
=d_deq
.begin(); it
!=d_deq
.end(); ++it
) {
870 Node deq
= (*it
).first
;
871 //check if it is already satisfied
872 Assert( d_equalityEngine
.hasTerm( deq
[0] ) && d_equalityEngine
.hasTerm( deq
[1] ) );
873 Node r1
= d_equalityEngine
.getRepresentative( deq
[0] );
874 Node r2
= d_equalityEngine
.getRepresentative( deq
[1] );
875 bool is_sat
= isSetDisequalityEntailed( r1
, r2
);
878 //try to make one of them empty
879 for( unsigned e=0; e<2; e++ ){
883 Trace("sets-debug") << "Check disequality " << deq
<< ", is_sat = " << is_sat
<< std::endl
;
884 //will process regardless of sat/processed/unprocessed
888 if( d_deq_processed
.find( deq
)==d_deq_processed
.end() ){
889 d_deq_processed
.insert( deq
);
890 d_deq_processed
.insert( deq
[1].eqNode( deq
[0] ) );
891 Trace("sets") << "Process Disequality : " << deq
.negate() << std::endl
;
892 TypeNode elementType
= deq
[0].getType().getSetElementType();
893 Node x
= NodeManager::currentNM()->mkSkolem("sde_", elementType
);
894 Node mem1
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[0] );
895 Node mem2
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[1] );
896 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, deq
, NodeManager::currentNM()->mkNode( kind::EQUAL
, mem1
, mem2
).negate() );
897 lem
= Rewriter::rewrite( lem
);
898 assertInference( lem
, d_emp_exp
, lemmas
, "diseq", 1 );
899 flushLemmas( lemmas
);
900 if( hasProcessed() ){
909 void TheorySetsPrivate::checkCardBuildGraph( std::vector
< Node
>& lemmas
) {
910 Trace("sets") << "Cardinality graph..." << std::endl
;
911 //first, ensure cardinality relationships are added as lemmas for all non-basic set terms
912 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
913 Node eqc
= d_set_eqc
[i
];
914 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
915 if( itn
!=d_nvar_sets
.end() ){
916 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
917 Node n
= itn
->second
[j
];
918 if( d_congruent
.find( n
)==d_congruent
.end() ){
919 //if setminus, do for intersection instead
920 if( n
.getKind()==kind::SETMINUS
){
921 n
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
923 registerCardinalityTerm( n
, lemmas
);
928 Trace("sets") << "Done cardinality graph" << std::endl
;
931 void TheorySetsPrivate::registerCardinalityTerm( Node n
, std::vector
< Node
>& lemmas
){
932 if( d_card_processed
.find( n
)==d_card_processed
.end() ){
933 d_card_processed
.insert( n
);
934 Trace("sets-card") << "Cardinality lemmas for " << n
<< " : " << std::endl
;
935 std::vector
< Node
> cterms
;
936 if( n
.getKind()==kind::INTERSECTION
){
937 for( unsigned e
=0; e
<2; e
++ ){
938 Node s
= NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] );
939 cterms
.push_back( s
);
941 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, n
), d_zero
);
942 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
944 cterms
.push_back( n
);
946 for( unsigned k
=0; k
<cterms
.size(); k
++ ){
948 Node nk
= getProxy( nn
);
949 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
), d_zero
);
950 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
952 Node lem
= NodeManager::currentNM()->mkNode( kind::EQUAL
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
),
953 NodeManager::currentNM()->mkNode( kind::CARD
, nn
) );
954 lem
= Rewriter::rewrite( lem
);
955 Trace("sets-card") << " " << k
<< " : " << lem
<< std::endl
;
956 assertInference( lem
, d_emp_exp
, lemmas
, "card", 1 );
962 void TheorySetsPrivate::checkCardCycles( std::vector
< Node
>& lemmas
) {
963 Trace("sets") << "Check cardinality cycles..." << std::endl
;
964 //build order of equivalence classes, also build cardinality graph
965 std::vector
< Node
> set_eqc_tmp
;
966 set_eqc_tmp
.insert( set_eqc_tmp
.end(), d_set_eqc
.begin(), d_set_eqc
.end() );
968 d_card_parent
.clear();
969 for( unsigned i
=0; i
<set_eqc_tmp
.size(); i
++ ){
970 std::vector
< Node
> curr
;
971 std::vector
< Node
> exp
;
972 checkCardCyclesRec( set_eqc_tmp
[i
], curr
, exp
, lemmas
);
973 flushLemmas( lemmas
);
974 if( hasProcessed() ){
978 Trace("sets") << "Done check cardinality cycles" << std::endl
;
981 void TheorySetsPrivate::checkCardCyclesRec( Node eqc
, std::vector
< Node
>& curr
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
) {
982 if( std::find( curr
.begin(), curr
.end(), eqc
)!=curr
.end() ){
983 Trace("sets-debug") << "Found venn region loop..." << std::endl
;
985 //all regions must be equal
986 std::vector
< Node
> conc
;
987 for( unsigned i
=1; i
<curr
.size(); i
++ ){
988 conc
.push_back( curr
[0].eqNode( curr
[i
] ) );
990 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
991 assertInference( fact
, exp
, lemmas
, "card_cycle" );
992 flushLemmas( lemmas
);
994 //should be guaranteed based on not exploring equal parents
997 }else if( std::find( d_set_eqc
.begin(), d_set_eqc
.end(), eqc
)==d_set_eqc
.end() ){
998 curr
.push_back( eqc
);
999 TypeNode tn
= eqc
.getType();
1000 bool is_empty
= eqc
==d_eqc_emptyset
[tn
];
1001 Node emp_set
= getEmptySet( tn
);
1002 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1003 if( itn
!=d_nvar_sets
.end() ){
1004 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1005 Node n
= itn
->second
[j
];
1006 if( n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
){
1007 Trace("sets-debug") << "Build cardinality parents for " << n
<< "..." << std::endl
;
1008 std::vector
< Node
> sib
;
1009 unsigned true_sib
= 0;
1010 if( n
.getKind()==kind::INTERSECTION
){
1012 for( unsigned e
=0; e
<2; e
++ ){
1013 Node sm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] ) );
1014 sib
.push_back( sm
);
1018 Node si
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
1019 sib
.push_back( si
);
1020 d_card_base
[n
] = si
;
1021 Node osm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[1], n
[0] ) );
1022 sib
.push_back( osm
);
1025 Node u
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::UNION
, n
[0], n
[1] ) );
1026 if( !d_equalityEngine
.hasTerm( u
) ){
1029 unsigned n_parents
= true_sib
+ ( u
.isNull() ? 0 : 1 );
1030 //if this set is empty
1032 Assert( ee_areEqual( n
, emp_set
) );
1033 Trace("sets-debug") << " empty, parents equal siblings" << std::endl
;
1034 std::vector
< Node
> conc
;
1035 //parent equal siblings
1036 for( unsigned e
=0; e
<true_sib
; e
++ ){
1037 if( d_equalityEngine
.hasTerm( sib
[e
] ) && !ee_areEqual( n
[e
], sib
[e
] ) ){
1038 conc
.push_back( n
[e
].eqNode( sib
[e
] ) );
1041 assertInference( conc
, n
.eqNode( emp_set
), lemmas
, "cg_emp" );
1042 flushLemmas( lemmas
);
1043 if( hasProcessed() ){
1046 //justify why there is no edge to parents (necessary?)
1047 for( unsigned e
=0; e
<n_parents
; e
++ ){
1048 Node p
= (e
==true_sib
) ? u
: n
[e
];
1053 std::vector
< Node
> card_parents
;
1054 std::vector
< int > card_parent_ids
;
1055 //check if equal to a parent
1056 for( unsigned e
=0; e
<n_parents
; e
++ ){
1057 Trace("sets-debug") << " check parent " << e
<< "/" << n_parents
<< std::endl
;
1058 bool is_union
= e
==true_sib
;
1059 Node p
= (e
==true_sib
) ? u
: n
[e
];
1060 Trace("sets-debug") << " check relation to parent " << p
<< ", isu=" << is_union
<< "..." << std::endl
;
1061 //if parent is empty
1062 if( ee_areEqual( p
, emp_set
) ){
1063 Trace("sets-debug") << " it is empty..." << std::endl
;
1064 Assert( !ee_areEqual( n
, emp_set
) );
1065 assertInference( n
.eqNode( emp_set
), p
.eqNode( emp_set
), lemmas
, "cg_emppar" );
1066 if( hasProcessed() ){
1069 //if we are equal to a parent
1070 }else if( ee_areEqual( p
, n
) ){
1071 Trace("sets-debug") << " it is equal to this..." << std::endl
;
1072 std::vector
< Node
> conc
;
1073 std::vector
< int > sib_emp_indices
;
1075 for( unsigned s
=0; s
<sib
.size(); s
++ ){
1076 sib_emp_indices
.push_back( s
);
1079 sib_emp_indices
.push_back( e
);
1081 //sibling(s) are empty
1082 for( unsigned s
=0; s
<sib_emp_indices
.size(); s
++ ){
1083 unsigned si
= sib_emp_indices
[s
];
1084 if( !ee_areEqual( sib
[si
], emp_set
) ){
1085 conc
.push_back( sib
[si
].eqNode( emp_set
) );
1087 Trace("sets-debug") << "Sibling " << sib
[si
] << " is already empty." << std::endl
;
1090 if( !is_union
&& n
.getKind()==kind::INTERSECTION
&& !u
.isNull() ){
1091 //union is equal to other parent
1092 if( !ee_areEqual( u
, n
[1-e
] ) ){
1093 conc
.push_back( u
.eqNode( n
[1-e
] ) );
1096 Trace("sets-debug") << "...derived " << conc
.size() << " conclusions" << std::endl
;
1097 assertInference( conc
, n
.eqNode( p
), lemmas
, "cg_eqpar" );
1098 flushLemmas( lemmas
);
1099 if( hasProcessed() ){
1103 Trace("sets-cdg") << "Card graph : " << n
<< " -> " << p
<< std::endl
;
1104 //otherwise, we a syntactic subset of p
1105 card_parents
.push_back( p
);
1106 card_parent_ids
.push_back( is_union
? 2 : e
);
1109 Assert( d_card_parent
[n
].empty() );
1110 Trace("sets-debug") << "get parent representatives..." << std::endl
;
1111 //for each parent, take their representatives
1112 for( unsigned k
=0; k
<card_parents
.size(); k
++ ){
1113 Node eqcc
= d_equalityEngine
.getRepresentative( card_parents
[k
] );
1114 Trace("sets-debug") << "Check card parent " << k
<< "/" << card_parents
.size() << std::endl
;
1116 //if parent is singleton, then we should either be empty to equal to it
1117 std::map
< Node
, Node
>::iterator itps
= d_eqc_singleton
.find( eqcc
);
1118 if( itps
!=d_eqc_singleton
.end() ){
1119 bool eq_parent
= false;
1120 std::vector
< Node
> exp
;
1121 addEqualityToExp( card_parents
[k
], itps
->second
, exp
);
1122 if( ee_areDisequal( n
, emp_set
) ){
1123 exp
.push_back( n
.eqNode( emp_set
).negate() );
1126 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpm
= d_pol_mems
[0].find( eqc
);
1127 if( itpm
!=d_pol_mems
[0].end() && !itpm
->second
.empty() ){
1128 Node pmem
= itpm
->second
.begin()->second
;
1129 exp
.push_back( pmem
);
1130 addEqualityToExp( n
, pmem
[1], exp
);
1134 //must be equal to parent
1136 Node conc
= n
.eqNode( card_parents
[k
] );
1137 assertInference( conc
, exp
, lemmas
, "cg_par_sing" );
1138 flushLemmas( lemmas
);
1141 Trace("sets-nf") << "Split empty : " << n
<< std::endl
;
1142 split( n
.eqNode( emp_set
), 1 );
1144 Assert( hasProcessed() );
1148 for( unsigned l
=0; l
<d_card_parent
[n
].size(); l
++ ){
1149 if( eqcc
==d_card_parent
[n
][l
] ){
1150 Trace("sets-debug") << " parents " << l
<< " and " << k
<< " are equal, ids = " << card_parent_ids
[l
] << " " << card_parent_ids
[k
] << std::endl
;
1152 if( n
.getKind()==kind::INTERSECTION
){
1153 Assert( card_parent_ids
[l
]!=2 );
1154 std::vector
< Node
> conc
;
1155 if( card_parent_ids
[k
]==2 ){
1156 //intersection is equal to other parent
1157 unsigned pid
= 1-card_parent_ids
[l
];
1158 if( !ee_areEqual( n
[pid
], n
) ){
1159 Trace("sets-debug") << " one of them is union, make equal to other..." << std::endl
;
1160 conc
.push_back( n
[pid
].eqNode( n
) );
1163 if( !ee_areEqual( card_parents
[k
], n
) ){
1164 Trace("sets-debug") << " neither is union, make equal to one parent..." << std::endl
;
1165 //intersection is equal to one of the parents
1166 conc
.push_back( card_parents
[k
].eqNode( n
) );
1169 assertInference( conc
, card_parents
[k
].eqNode( d_card_parent
[n
][l
] ), lemmas
, "cg_pareq" );
1170 flushLemmas( lemmas
);
1171 if( hasProcessed() ){
1178 d_card_parent
[n
].push_back( eqcc
);
1182 //now recurse on parents (to ensure their normal will be computed after this eqc)
1183 exp
.push_back( eqc
.eqNode( n
) );
1184 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1185 checkCardCyclesRec( d_card_parent
[n
][k
], curr
, exp
, lemmas
);
1186 if( hasProcessed() ){
1196 //parents now processed, can add to ordered list
1197 d_set_eqc
.push_back( eqc
);
1203 void TheorySetsPrivate::checkNormalForms( std::vector
< Node
>& lemmas
, std::vector
< Node
>& intro_sets
){
1204 Trace("sets") << "Check normal forms..." << std::endl
;
1205 // now, build normal form for each equivalence class
1206 // d_set_eqc is now sorted such that for each d_set_eqc[i], d_set_eqc[j],
1207 // if d_set_eqc[i] is a strict syntactic subterm of d_set_eqc[j], then i<j.
1210 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1211 checkNormalForm( d_set_eqc
[i
], intro_sets
);
1212 if( hasProcessed() || !intro_sets
.empty() ){
1216 Trace("sets") << "Done check normal forms" << std::endl
;
1219 void TheorySetsPrivate::checkNormalForm( Node eqc
, std::vector
< Node
>& intro_sets
){
1220 TypeNode tn
= eqc
.getType();
1221 Trace("sets") << "Compute normal form for " << eqc
<< std::endl
;
1222 Trace("sets-nf") << "Compute N " << eqc
<< "..." << std::endl
;
1223 if( eqc
==d_eqc_emptyset
[tn
] ){
1225 Trace("sets-nf") << "----> N " << eqc
<< " => {}" << std::endl
;
1227 //flat/normal forms are sets of equivalence classes
1229 std::vector
< Node
> comps
;
1230 std::map
< Node
, std::map
< Node
, std::vector
< Node
> > >::iterator it
= d_ff
.find( eqc
);
1231 if( it
!=d_ff
.end() ){
1232 for( std::map
< Node
, std::vector
< Node
> >::iterator itf
= it
->second
.begin(); itf
!= it
->second
.end(); ++itf
){
1233 std::sort( itf
->second
.begin(), itf
->second
.end() );
1234 if( base
.isNull() ){
1237 comps
.push_back( itf
->first
);
1239 Trace("sets-nf") << " F " << itf
->first
<< " : ";
1240 if( Trace
.isOn("sets-nf") ){
1241 Trace("sets-nf") << "{ ";
1242 for( unsigned k
=0; k
<itf
->second
.size(); k
++ ){
1243 if( k
>0 ){ Trace("sets-nf") << ", "; }
1244 Trace("sets-nf") << "[" << itf
->second
[k
] << "]";
1246 Trace("sets-nf") << " }" << std::endl
;
1248 Trace("sets-nf-debug") << " ...";
1249 debugPrintSet( itf
->first
, "sets-nf-debug" );
1250 Trace("sets-nf-debug") << std::endl
;
1253 Trace("sets-nf") << "(no flat forms)" << std::endl
;
1256 Assert( d_nf
.find( eqc
)==d_nf
.end() );
1257 bool success
= true;
1258 if( !base
.isNull() ){
1259 Node emp_set
= getEmptySet( tn
);
1260 for( unsigned j
=0; j
<comps
.size(); j
++ ){
1262 std::vector
< Node
> c
;
1263 c
.push_back( base
);
1264 c
.push_back( comps
[j
] );
1265 std::vector
< Node
> only
[2];
1266 std::vector
< Node
> common
;
1267 Trace("sets-nf-debug") << "Compare venn regions of " << base
<< " vs " << comps
[j
] << std::endl
;
1268 unsigned k
[2] = { 0, 0 };
1269 while( k
[0]<d_ff
[eqc
][c
[0]].size() || k
[1]<d_ff
[eqc
][c
[1]].size() ){
1271 for( unsigned e
=0; e
<2; e
++ ){
1272 if( k
[e
]==d_ff
[eqc
][c
[e
]].size() ){
1273 for( ; k
[1-e
]<d_ff
[eqc
][c
[1-e
]].size(); ++k
[1-e
] ){
1274 only
[1-e
].push_back( d_ff
[eqc
][c
[1-e
]][k
[1-e
]] );
1280 if( d_ff
[eqc
][c
[0]][k
[0]]==d_ff
[eqc
][c
[1]][k
[1]] ){
1281 common
.push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1284 }else if( d_ff
[eqc
][c
[0]][k
[0]]<d_ff
[eqc
][c
[1]][k
[1]] ){
1285 only
[0].push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1288 only
[1].push_back( d_ff
[eqc
][c
[1]][k
[1]] );
1293 if( !only
[0].empty() || !only
[1].empty() ){
1294 if( Trace
.isOn("sets-nf-debug") ){
1295 Trace("sets-nf-debug") << "Unique venn regions : " << std::endl
;
1296 for( unsigned e
=0; e
<2; e
++ ){
1297 Trace("sets-nf-debug") << " " << c
[e
] << " : { ";
1298 for( unsigned l
=0; l
<only
[e
].size(); l
++ ){
1299 if( l
>0 ){ Trace("sets-nf-debug") << ", "; }
1300 Trace("sets-nf-debug") << "[" << only
[e
][l
] << "]";
1302 Trace("sets-nf-debug") << " }" << std::endl
;
1305 //try to make one empty, prefer the unique ones first
1306 for( unsigned e
=0; e
<3; e
++ ){
1307 unsigned sz
= e
==2 ? common
.size() : only
[e
].size();
1308 for( unsigned l
=0; l
<sz
; l
++ ){
1309 Node r
= e
==2 ? common
[l
] : only
[e
][l
];
1310 Trace("sets-nf-debug") << "Try split empty : " << r
<< std::endl
;
1311 Trace("sets-nf-debug") << " actual : ";
1312 debugPrintSet( r
, "sets-nf-debug" );
1313 Trace("sets-nf-debug") << std::endl
;
1314 Assert( !ee_areEqual( r
, emp_set
) );
1315 if( !ee_areDisequal( r
, emp_set
) && ( d_pol_mems
[0].find( r
)==d_pol_mems
[0].end() || d_pol_mems
[0][r
].empty() ) ){
1316 //guess that its equal empty if it has no explicit members
1317 Trace("sets-nf") << " Split empty : " << r
<< std::endl
;
1318 Trace("sets-nf") << "Actual Split : ";
1319 debugPrintSet( r
, "sets-nf" );
1320 Trace("sets-nf") << std::endl
;
1321 split( r
.eqNode( emp_set
), 1 );
1322 Assert( hasProcessed() );
1327 for( unsigned l
=0; l
<only
[0].size(); l
++ ){
1328 for( unsigned m
=0; m
<only
[1].size(); m
++ ){
1329 bool disjoint
= false;
1330 Trace("sets-nf-debug") << "Try split " << only
[0][l
] << " against " << only
[1][m
] << std::endl
;
1332 for( unsigned e
=0; e
<2; e
++ ){
1333 Node r1
= e
==0 ? only
[0][l
] : only
[1][m
];
1334 Node r2
= e
==0 ? only
[1][m
] : only
[0][l
];
1335 //check if their intersection exists modulo equality
1336 std::map
< Node
, Node
>::iterator itb
= d_bop_index
[kind::INTERSECTION
][r1
].find( r2
);
1337 if( itb
!=d_bop_index
[kind::INTERSECTION
][r1
].end() ){
1338 Trace("sets-nf-debug") << "Split term already exists, but not in cardinality graph : " << itb
->second
<< ", should be empty." << std::endl
;
1339 //their intersection is empty (probably?)
1340 // e.g. these are two disjoint venn regions, proceed to next pair
1341 Assert( ee_areEqual( emp_set
, itb
->second
) );
1347 //simply introduce their intersection
1348 Assert( only
[0][l
]!=only
[1][m
] );
1349 Node kca
= getProxy( only
[0][l
] );
1350 Node kcb
= getProxy( only
[1][m
] );
1351 Node intro
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, kca
, kcb
) );
1352 Trace("sets-nf") << " Intro split : " << only
[0][l
] << " against " << only
[1][m
] << ", term is " << intro
<< std::endl
;
1353 intro_sets
.push_back( intro
);
1354 Assert( !d_equalityEngine
.hasTerm( intro
) );
1359 //should never get here
1364 //normal form is flat form of base
1365 d_nf
[eqc
].insert( d_nf
[eqc
].end(), d_ff
[eqc
][base
].begin(), d_ff
[eqc
][base
].end() );
1366 Trace("sets-nf") << "----> N " << eqc
<< " => F " << base
<< std::endl
;
1368 Trace("sets-nf") << "failed to build N " << eqc
<< std::endl
;
1372 //normal form is this equivalence class
1373 d_nf
[eqc
].push_back( eqc
);
1374 Trace("sets-nf") << "----> N " << eqc
<< " => { " << eqc
<< " }" << std::endl
;
1378 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1379 if( itn
!=d_nvar_sets
.end() ){
1380 std::map
< Node
, std::map
< Node
, bool > > parents_proc
;
1381 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1382 Node n
= itn
->second
[j
];
1383 Trace("sets-nf-debug") << "Carry nf for term " << n
<< std::endl
;
1384 if( !d_card_parent
[n
].empty() ){
1385 Assert( d_card_base
.find( n
)!=d_card_base
.end() );
1386 Node cbase
= d_card_base
[n
];
1387 Trace("sets-nf-debug") << "Card base is " << cbase
<< std::endl
;
1388 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1389 Node p
= d_card_parent
[n
][k
];
1390 Trace("sets-nf-debug") << "Check parent " << p
<< std::endl
;
1391 if( parents_proc
[cbase
].find( p
)==parents_proc
[cbase
].end() ){
1392 parents_proc
[cbase
][p
] = true;
1393 Trace("sets-nf-debug") << "Carry nf to parent ( " << cbase
<< ", [" << p
<< "] ), from " << n
<< "..." << std::endl
;
1394 //for( unsigned i=0; i<d_nf[eqc].size(); i++ ){
1395 // Assert( std::find( d_ff[p][cbase].begin(), d_ff[p][cbase].end(), d_nf[eqc][i] )==d_ff[p][cbase].end() );
1397 for( unsigned i
=0; i
<d_nf
[eqc
].size(); i
++ ){
1398 if( std::find( d_ff
[p
][cbase
].begin(), d_ff
[p
][cbase
].end(), d_nf
[eqc
][i
] )==d_ff
[p
][cbase
].end() ){
1399 d_ff
[p
][cbase
].insert( d_ff
[p
][cbase
].end(), d_nf
[eqc
].begin(), d_nf
[eqc
].end() );
1401 //if it is a duplicate venn region, it must be empty since it is coming from syntactically disjoint siblings TODO?
1405 Trace("sets-nf-debug") << "..already processed parent " << p
<< " for " << cbase
<< std::endl
;
1412 Assert( hasProcessed() );
1417 void TheorySetsPrivate::checkMinCard( std::vector
< Node
>& lemmas
) {
1419 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1420 Node eqc
= d_set_eqc
[i
];
1421 //get members in class
1422 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1423 if( itm
!=d_pol_mems
[0].end() ){
1424 std::vector
< Node
> exp
;
1425 std::vector
< Node
> members
;
1427 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1428 if( it
!=d_eqc_to_card_term
.end() ){
1429 cardTerm
= it
->second
;
1431 cardTerm
= NodeManager::currentNM()->mkNode( kind::CARD
, eqc
);
1433 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1435 for( unsigned j=0; j<members.size(); j++ ){
1436 if( !ee_areDisequal( members[j], itmm->second ) ){
1437 Assert( !ee_areEqual( members[j], itmm->second ) );
1442 members
.push_back( itmm
->first
);
1443 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, itmm
->first
, cardTerm
[0] ) );
1445 if( members
.size()>1 ){
1446 exp
.push_back( NodeManager::currentNM()->mkNode( kind::DISTINCT
, members
) );
1448 if( !members
.empty() ){
1449 Node conc
= NodeManager::currentNM()->mkNode( kind::GEQ
, cardTerm
, NodeManager::currentNM()->mkConst( Rational( members
.size() ) ) );
1450 Node lem
= NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
), conc
);
1451 Trace("sets-lemma") << "Sets::Lemma : " << lem
<< " by mincard" << std::endl
;
1452 lemmas
.push_back( lem
);
1458 void TheorySetsPrivate::flushLemmas( std::vector
< Node
>& lemmas
) {
1460 for( unsigned i
=0; i
<lemmas
.size(); i
++ ){
1461 Node lem
= lemmas
[i
];
1462 if( d_lemmas_produced
.find(lem
)==d_lemmas_produced
.end() ){
1463 Trace("sets-lemma-debug") << "Send lemma : " << lem
<< std::endl
;
1464 d_lemmas_produced
.insert(lem
);
1465 d_external
.d_out
->lemma(lem
);
1468 Trace("sets-lemma-debug") << "Already sent lemma : " << lem
<< std::endl
;
1474 Node
TheorySetsPrivate::getProxy( Node n
) {
1475 if( n
.getKind()==kind::EMPTYSET
|| n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::UNION
){
1476 NodeMap::const_iterator it
= d_proxy
.find( n
);
1477 if( it
==d_proxy
.end() ){
1478 Node k
= NodeManager::currentNM()->mkSkolem( "sp", n
.getType(), "proxy for set" );
1480 d_proxy_to_term
[k
] = n
;
1481 Node eq
= k
.eqNode( n
);
1482 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
1483 d_external
.d_out
->lemma( eq
);
1484 if( n
.getKind()==kind::SINGLETON
){
1485 Node slem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, n
[0], k
);
1486 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton" << std::endl
;
1487 d_external
.d_out
->lemma( slem
);
1492 return (*it
).second
;
1499 Node
TheorySetsPrivate::getCongruent( Node n
) {
1500 Assert( d_equalityEngine
.hasTerm( n
) );
1501 std::map
< Node
, Node
>::iterator it
= d_congruent
.find( n
);
1502 if( it
==d_congruent
.end() ){
1509 Node
TheorySetsPrivate::getEmptySet( TypeNode tn
) {
1510 std::map
< TypeNode
, Node
>::iterator it
= d_emptyset
.find( tn
);
1511 if( it
==d_emptyset
.end() ){
1512 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
.toType()));
1519 Node
TheorySetsPrivate::getUnivSet( TypeNode tn
) {
1520 std::map
< TypeNode
, Node
>::iterator it
= d_univset
.find( tn
);
1521 if( it
==d_univset
.end() ){
1522 Node n
= NodeManager::currentNM()->mkUniqueVar(tn
, kind::UNIVERSE_SET
);
1530 bool TheorySetsPrivate::hasLemmaCached( Node lem
) {
1531 return d_lemmas_produced
.find(lem
)!=d_lemmas_produced
.end();
1534 bool TheorySetsPrivate::hasProcessed() {
1535 return d_conflict
|| d_sentLemma
|| d_addedFact
;
1538 void TheorySetsPrivate::debugPrintSet( Node s
, const char * c
) {
1539 if( s
.getNumChildren()==0 ){
1540 NodeMap::const_iterator it
= d_proxy_to_term
.find( s
);
1541 if( it
!=d_proxy_to_term
.end() ){
1542 debugPrintSet( (*it
).second
, c
);
1547 Trace(c
) << "(" << s
.getOperator();
1548 for( unsigned i
=0; i
<s
.getNumChildren(); i
++ ){
1550 debugPrintSet( s
[i
], c
);
1556 /**************************** TheorySetsPrivate *****************************/
1557 /**************************** TheorySetsPrivate *****************************/
1558 /**************************** TheorySetsPrivate *****************************/
1560 void TheorySetsPrivate::check(Theory::Effort level
) {
1561 Trace("sets-check") << "Sets check effort " << level
<< std::endl
;
1562 while(!d_external
.done() && !d_conflict
) {
1563 // Get all the assertions
1564 Assertion assertion
= d_external
.get();
1565 TNode fact
= assertion
.assertion
;
1566 Trace("sets-assert") << "Assert from input " << fact
<< std::endl
;
1568 assertFact( fact
, fact
);
1570 d_sentLemma
= false;
1571 Trace("sets-check") << "Sets finished assertions effort " << level
<< std::endl
;
1572 //invoke full effort check, relations check
1574 if( level
== Theory::EFFORT_FULL
){
1575 if( !d_external
.d_valuation
.needCheck() ){
1577 if( !d_conflict
&& !d_sentLemma
){
1578 //invoke relations solver
1579 d_rels
->check(level
);
1580 if( d_card_enabled
&& d_rels_enabled
){
1581 //incomplete if we have both cardinality constraints and relational operators?
1582 // TODO: should internally check model, return unknown if fail
1583 d_external
.d_out
->setIncomplete();
1588 if( options::setsRelEager() ){
1589 d_rels
->check(level
);
1593 Trace("sets-check") << "Sets finish Check effort " << level
<< std::endl
;
1594 }/* TheorySetsPrivate::check() */
1597 /************************ Sharing ************************/
1598 /************************ Sharing ************************/
1599 /************************ Sharing ************************/
1601 void TheorySetsPrivate::addSharedTerm(TNode n
) {
1602 Debug("sets") << "[sets] ThoerySetsPrivate::addSharedTerm( " << n
<< ")" << std::endl
;
1603 d_equalityEngine
.addTriggerTerm(n
, THEORY_SETS
);
1606 void TheorySetsPrivate::addCarePairs( quantifiers::TermArgTrie
* t1
, quantifiers::TermArgTrie
* t2
, unsigned arity
, unsigned depth
, unsigned& n_pairs
){
1609 Node f1
= t1
->getNodeData();
1610 Node f2
= t2
->getNodeData();
1611 if( !ee_areEqual( f1
, f2
) ){
1612 Trace("sets-cg") << "Check " << f1
<< " and " << f2
<< std::endl
;
1613 vector
< pair
<TNode
, TNode
> > currentPairs
;
1614 for (unsigned k
= 0; k
< f1
.getNumChildren(); ++ k
) {
1617 Assert( d_equalityEngine
.hasTerm(x
) );
1618 Assert( d_equalityEngine
.hasTerm(y
) );
1619 Assert( !ee_areDisequal( x
, y
) );
1620 if( !d_equalityEngine
.areEqual( x
, y
) ){
1621 Trace("sets-cg") << "Arg #" << k
<< " is " << x
<< " " << y
<< std::endl
;
1622 if( d_equalityEngine
.isTriggerTerm(x
, THEORY_SETS
) && d_equalityEngine
.isTriggerTerm(y
, THEORY_SETS
) ){
1623 TNode x_shared
= d_equalityEngine
.getTriggerTermRepresentative(x
, THEORY_SETS
);
1624 TNode y_shared
= d_equalityEngine
.getTriggerTermRepresentative(y
, THEORY_SETS
);
1625 Trace("sets-cg") << "Arg #" << k
<< " shared term is " << x_shared
<< " " << y_shared
<< std::endl
;
1626 EqualityStatus eqStatus
= d_external
.d_valuation
.getEqualityStatus(x_shared
, y_shared
);
1627 Trace("sets-cg") << "...eq status is " << eqStatus
<< std::endl
;
1628 if( eqStatus
==EQUALITY_FALSE_AND_PROPAGATED
|| eqStatus
==EQUALITY_FALSE
|| eqStatus
==EQUALITY_FALSE_IN_MODEL
){
1629 //an argument is disequal, we are done
1632 currentPairs
.push_back(make_pair(x_shared
, y_shared
));
1634 }else if( isCareArg( f1
, k
) && isCareArg( f2
, k
) ){
1635 //splitting on sets (necessary for handling set of sets properly)
1636 if( x
.getType().isSet() ){
1637 Assert( y
.getType().isSet() );
1638 if( !ee_areDisequal( x
, y
) ){
1639 Trace("sets-cg-lemma") << "Should split on : " << x
<< "==" << y
<< std::endl
;
1640 split( x
.eqNode( y
) );
1646 for (unsigned c
= 0; c
< currentPairs
.size(); ++ c
) {
1647 Trace("sets-cg-pair") << "Pair : " << currentPairs
[c
].first
<< " " << currentPairs
[c
].second
<< std::endl
;
1648 d_external
.addCarePair(currentPairs
[c
].first
, currentPairs
[c
].second
);
1655 if( depth
<(arity
-1) ){
1656 //add care pairs internal to each child
1657 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1658 addCarePairs( &it
->second
, NULL
, arity
, depth
+1, n_pairs
);
1661 //add care pairs based on each pair of non-disequal arguments
1662 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1663 std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= it
;
1665 for( ; it2
!= t1
->d_data
.end(); ++it2
){
1666 if( !ee_areDisequal(it
->first
, it2
->first
) ){
1667 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1672 //add care pairs based on product of indices, non-disequal arguments
1673 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1674 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= t2
->d_data
.begin(); it2
!= t2
->d_data
.end(); ++it2
){
1675 if( !ee_areDisequal(it
->first
, it2
->first
) ){
1676 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1684 void TheorySetsPrivate::computeCareGraph() {
1685 for( std::map
< Kind
, std::vector
< Node
> >::iterator it
= d_op_list
.begin(); it
!= d_op_list
.end(); ++it
){
1686 if( it
->first
==kind::SINGLETON
|| it
->first
==kind::MEMBER
){
1687 unsigned n_pairs
= 0;
1688 Trace("sets-cg-summary") << "Compute graph for sets, op=" << it
->first
<< "..." << it
->second
.size() << std::endl
;
1689 Trace("sets-cg") << "Build index for " << it
->first
<< "..." << std::endl
;
1690 std::map
< TypeNode
, quantifiers::TermArgTrie
> index
;
1693 for( unsigned i
=0; i
<it
->second
.size(); i
++ ){
1694 TNode f1
= it
->second
[i
];
1695 Assert(d_equalityEngine
.hasTerm(f1
));
1696 Trace("sets-cg-debug") << "...build for " << f1
<< std::endl
;
1697 //break into index based on operator, and type of first argument (since some operators are parametric)
1698 TypeNode tn
= f1
[0].getType();
1699 std::vector
< TNode
> reps
;
1700 bool hasCareArg
= false;
1701 for( unsigned j
=0; j
<f1
.getNumChildren(); j
++ ){
1702 reps
.push_back( d_equalityEngine
.getRepresentative( f1
[j
] ) );
1703 if( isCareArg( f1
, j
) ){
1708 index
[tn
].addTerm( f1
, reps
);
1709 arity
= reps
.size();
1714 for( std::map
< TypeNode
, quantifiers::TermArgTrie
>::iterator iti
= index
.begin(); iti
!= index
.end(); ++iti
){
1715 Trace("sets-cg") << "Process index " << iti
->first
<< "..." << std::endl
;
1716 addCarePairs( &iti
->second
, NULL
, arity
, 0, n_pairs
);
1719 Trace("sets-cg-summary") << "...done, # pairs = " << n_pairs
<< std::endl
;
1724 bool TheorySetsPrivate::isCareArg( Node n
, unsigned a
) {
1725 if( d_equalityEngine
.isTriggerTerm( n
[a
], THEORY_SETS
) ){
1727 }else if( ( n
.getKind()==kind::MEMBER
|| n
.getKind()==kind::SINGLETON
) && a
==0 && n
[0].getType().isSet() ){
1734 EqualityStatus
TheorySetsPrivate::getEqualityStatus(TNode a
, TNode b
) {
1735 Assert(d_equalityEngine
.hasTerm(a
) && d_equalityEngine
.hasTerm(b
));
1736 if (d_equalityEngine
.areEqual(a
, b
)) {
1737 // The terms are implied to be equal
1738 return EQUALITY_TRUE
;
1740 if (d_equalityEngine
.areDisequal(a
, b
, false)) {
1741 // The terms are implied to be dis-equal
1742 return EQUALITY_FALSE
;
1744 return EQUALITY_UNKNOWN
;
1746 Node aModelValue = d_external.d_valuation.getModelValue(a);
1747 if(aModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1748 Node bModelValue = d_external.d_valuation.getModelValue(b);
1749 if(bModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1750 if( aModelValue == bModelValue ) {
1751 // The term are true in current model
1752 return EQUALITY_TRUE_IN_MODEL;
1754 return EQUALITY_FALSE_IN_MODEL;
1758 // //TODO: can we be more precise sometimes?
1759 // return EQUALITY_UNKNOWN;
1762 /******************** Model generation ********************/
1763 /******************** Model generation ********************/
1764 /******************** Model generation ********************/
1767 void TheorySetsPrivate::collectModelInfo(TheoryModel
* m
, bool fullModel
) {
1768 Trace("sets-model") << "Set collect model info" << std::endl
;
1770 // Compute terms appearing in assertions and shared terms
1771 d_external
.computeRelevantTerms(termSet
);
1773 // Assert equalities and disequalities to the model
1774 m
->assertEqualityEngine(&d_equalityEngine
,&termSet
);
1776 std::map
< Node
, Node
> mvals
;
1777 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1778 Node eqc
= d_set_eqc
[i
];
1779 if( termSet
.find( eqc
)==termSet
.end() ){
1780 Trace("sets-model") << "* Do not assign value for " << eqc
<< " since is not relevant." << std::endl
;
1782 std::vector
< Node
> els
;
1783 bool is_base
= !d_card_enabled
|| ( d_nf
[eqc
].size()==1 && d_nf
[eqc
][0]==eqc
);
1785 Trace("sets-model") << "Collect elements of base eqc " << eqc
<< std::endl
;
1786 // members that must be in eqc
1787 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1788 if( itm
!=d_pol_mems
[0].end() ){
1789 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1790 Node t
= NodeManager::currentNM()->mkNode( kind::SINGLETON
, itmm
->first
);
1795 if( d_card_enabled
){
1796 TypeNode elementType
= eqc
.getType().getSetElementType();
1798 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1799 if( it
!=d_eqc_to_card_term
.end() ){
1800 //slack elements from cardinality value
1801 Node v
= d_external
.d_valuation
.getModelValue(it
->second
);
1802 Trace("sets-model") << "Cardinality of " << eqc
<< " is " << v
<< std::endl
;
1803 Assert(v
.getConst
<Rational
>() <= LONG_MAX
, "Exceeded LONG_MAX in sets model");
1804 unsigned vu
= v
.getConst
<Rational
>().getNumerator().toUnsignedInt();
1805 Assert( els
.size()<=vu
);
1806 while( els
.size()<vu
){
1807 els
.push_back( NodeManager::currentNM()->mkNode( kind::SINGLETON
, NodeManager::currentNM()->mkSkolem( "msde", elementType
) ) );
1810 Trace("sets-model") << "No slack elements for " << eqc
<< std::endl
;
1813 Trace("sets-model") << "Build value for " << eqc
<< " based on normal form, size = " << d_nf
[eqc
].size() << std::endl
;
1814 //it is union of venn regions
1815 for( unsigned j
=0; j
<d_nf
[eqc
].size(); j
++ ){
1816 Assert( mvals
.find( d_nf
[eqc
][j
] )!=mvals
.end() );
1817 els
.push_back( mvals
[d_nf
[eqc
][j
]] );
1821 Node rep
= NormalForm::mkBop( kind::UNION
, els
, eqc
.getType() );
1822 rep
= Rewriter::rewrite( rep
);
1823 Trace("sets-model") << "* Assign representative of " << eqc
<< " to " << rep
<< std::endl
;
1825 m
->assertEquality( eqc
, rep
, true );
1826 m
->assertRepresentative( rep
);
1831 /********************** Helper functions ***************************/
1832 /********************** Helper functions ***************************/
1833 /********************** Helper functions ***************************/
1835 void TheorySetsPrivate::addEqualityToExp( Node a
, Node b
, std::vector
< Node
>& exp
) {
1837 Assert( ee_areEqual( a
, b
) );
1838 exp
.push_back( a
.eqNode( b
) );
1842 Node
mkAnd(const std::vector
<TNode
>& conjunctions
) {
1843 Assert(conjunctions
.size() > 0);
1845 std::set
<TNode
> all
;
1846 for (unsigned i
= 0; i
< conjunctions
.size(); ++i
) {
1847 TNode t
= conjunctions
[i
];
1848 if (t
.getKind() == kind::AND
) {
1849 for(TNode::iterator child_it
= t
.begin();
1850 child_it
!= t
.end(); ++child_it
) {
1851 Assert((*child_it
).getKind() != kind::AND
);
1852 all
.insert(*child_it
);
1860 Assert(all
.size() > 0);
1861 if (all
.size() == 1) {
1862 // All the same, or just one
1863 return conjunctions
[0];
1866 NodeBuilder
<> conjunction(kind::AND
);
1867 std::set
<TNode
>::const_iterator it
= all
.begin();
1868 std::set
<TNode
>::const_iterator it_end
= all
.end();
1869 while (it
!= it_end
) {
1878 TheorySetsPrivate::Statistics::Statistics() :
1879 d_getModelValueTime("theory::sets::getModelValueTime")
1880 , d_mergeTime("theory::sets::merge_nodes::time")
1881 , d_processCard2Time("theory::sets::processCard2::time")
1882 , d_memberLemmas("theory::sets::lemmas::member", 0)
1883 , d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
1884 , d_numVertices("theory::sets::vertices", 0)
1885 , d_numVerticesMax("theory::sets::vertices-max", 0)
1886 , d_numMergeEq1or2("theory::sets::merge1or2", 0)
1887 , d_numMergeEq3("theory::sets::merge3", 0)
1888 , d_numLeaves("theory::sets::leaves", 0)
1889 , d_numLeavesMax("theory::sets::leaves-max", 0)
1891 smtStatisticsRegistry()->registerStat(&d_getModelValueTime
);
1892 smtStatisticsRegistry()->registerStat(&d_mergeTime
);
1893 smtStatisticsRegistry()->registerStat(&d_processCard2Time
);
1894 smtStatisticsRegistry()->registerStat(&d_memberLemmas
);
1895 smtStatisticsRegistry()->registerStat(&d_disequalityLemmas
);
1896 smtStatisticsRegistry()->registerStat(&d_numVertices
);
1897 smtStatisticsRegistry()->registerStat(&d_numVerticesMax
);
1898 smtStatisticsRegistry()->registerStat(&d_numMergeEq1or2
);
1899 smtStatisticsRegistry()->registerStat(&d_numMergeEq3
);
1900 smtStatisticsRegistry()->registerStat(&d_numLeaves
);
1901 smtStatisticsRegistry()->registerStat(&d_numLeavesMax
);
1905 TheorySetsPrivate::Statistics::~Statistics() {
1906 smtStatisticsRegistry()->unregisterStat(&d_getModelValueTime
);
1907 smtStatisticsRegistry()->unregisterStat(&d_mergeTime
);
1908 smtStatisticsRegistry()->unregisterStat(&d_processCard2Time
);
1909 smtStatisticsRegistry()->unregisterStat(&d_memberLemmas
);
1910 smtStatisticsRegistry()->unregisterStat(&d_disequalityLemmas
);
1911 smtStatisticsRegistry()->unregisterStat(&d_numVertices
);
1912 smtStatisticsRegistry()->unregisterStat(&d_numVerticesMax
);
1913 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq1or2
);
1914 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq3
);
1915 smtStatisticsRegistry()->unregisterStat(&d_numLeaves
);
1916 smtStatisticsRegistry()->unregisterStat(&d_numLeavesMax
);
1919 void TheorySetsPrivate::propagate(Theory::Effort effort
) {
1923 bool TheorySetsPrivate::propagate(TNode literal
) {
1924 Debug("sets-prop") << " propagate(" << literal
<< ")" << std::endl
;
1926 // If already in conflict, no more propagation
1928 Debug("sets-prop") << "TheoryUF::propagate(" << literal
<< "): already in conflict" << std::endl
;
1933 bool ok
= d_external
.d_out
->propagate(literal
);
1939 }/* TheorySetsPrivate::propagate(TNode) */
1942 void TheorySetsPrivate::setMasterEqualityEngine(eq::EqualityEngine
* eq
) {
1943 d_equalityEngine
.setMasterEqualityEngine(eq
);
1947 void TheorySetsPrivate::conflict(TNode a
, TNode b
)
1949 d_conflictNode
= explain(a
.eqNode(b
));
1950 d_external
.d_out
->conflict(d_conflictNode
);
1951 Debug("sets") << "[sets] conflict: " << a
<< " iff " << b
1952 << ", explaination " << d_conflictNode
<< std::endl
;
1953 Trace("sets-lemma") << "Equality Conflict : " << d_conflictNode
<< std::endl
;
1957 Node
TheorySetsPrivate::explain(TNode literal
)
1959 Debug("sets") << "TheorySetsPrivate::explain(" << literal
<< ")"
1962 bool polarity
= literal
.getKind() != kind::NOT
;
1963 TNode atom
= polarity
? literal
: literal
[0];
1964 std::vector
<TNode
> assumptions
;
1966 if(atom
.getKind() == kind::EQUAL
) {
1967 d_equalityEngine
.explainEquality(atom
[0], atom
[1], polarity
, assumptions
);
1968 } else if(atom
.getKind() == kind::MEMBER
) {
1969 d_equalityEngine
.explainPredicate(atom
, polarity
, assumptions
);
1971 Debug("sets") << "unhandled: " << literal
<< "; (" << atom
<< ", "
1972 << polarity
<< "); kind" << atom
.getKind() << std::endl
;
1976 return mkAnd(assumptions
);
1979 void TheorySetsPrivate::preRegisterTerm(TNode node
)
1981 Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node
<< ")"
1983 switch(node
.getKind()) {
1985 // TODO: what's the point of this
1986 d_equalityEngine
.addTriggerEquality(node
);
1989 // TODO: what's the point of this
1990 d_equalityEngine
.addTriggerPredicate(node
);
1993 d_equalityEngine
.addTriggerTerm(node
, THEORY_SETS
);
1996 //if( node.getType().isSet() ){
1997 // d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
1999 d_equalityEngine
.addTerm(node
);
2006 void TheorySetsPrivate::presolve() {
2010 /**************************** eq::NotifyClass *****************************/
2011 /**************************** eq::NotifyClass *****************************/
2012 /**************************** eq::NotifyClass *****************************/
2015 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerEquality(TNode equality
, bool value
)
2017 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerEquality: equality = " << equality
2018 << " value = " << value
<< std::endl
;
2020 return d_theory
.propagate(equality
);
2022 // We use only literal triggers so taking not is safe
2023 return d_theory
.propagate(equality
.notNode());
2027 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerPredicate(TNode predicate
, bool value
)
2029 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerPredicate: predicate = " << predicate
2030 << " value = " << value
<< std::endl
;
2032 return d_theory
.propagate(predicate
);
2034 return d_theory
.propagate(predicate
.notNode());
2038 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag
, TNode t1
, TNode t2
, bool value
)
2040 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerTermEquality: tag = " << tag
2041 << " t1 = " << t1
<< " t2 = " << t2
<< " value = " << value
<< std::endl
;
2042 d_theory
.propagate( value
? t1
.eqNode( t2
) : t1
.eqNode( t2
).negate() );
2046 void TheorySetsPrivate::NotifyClass::eqNotifyConstantTermMerge(TNode t1
, TNode t2
)
2048 Debug("sets-eq") << "[sets-eq] eqNotifyConstantTermMerge " << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2049 d_theory
.conflict(t1
, t2
);
2052 void TheorySetsPrivate::NotifyClass::eqNotifyNewClass(TNode t
)
2054 Debug("sets-eq") << "[sets-eq] eqNotifyNewClass:" << " t = " << t
<< std::endl
;
2055 d_theory
.eqNotifyNewClass(t
);
2058 void TheorySetsPrivate::NotifyClass::eqNotifyPreMerge(TNode t1
, TNode t2
)
2060 Debug("sets-eq") << "[sets-eq] eqNotifyPreMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2061 d_theory
.eqNotifyPreMerge(t1
, t2
);
2064 void TheorySetsPrivate::NotifyClass::eqNotifyPostMerge(TNode t1
, TNode t2
)
2066 Debug("sets-eq") << "[sets-eq] eqNotifyPostMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2067 d_theory
.eqNotifyPostMerge(t1
, t2
);
2070 void TheorySetsPrivate::NotifyClass::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
)
2072 Debug("sets-eq") << "[sets-eq] eqNotifyDisequal:" << " t1 = " << t1
<< " t2 = " << t2
<< " reason = " << reason
<< std::endl
;
2073 d_theory
.eqNotifyDisequal(t1
, t2
, reason
);
2076 }/* CVC4::theory::sets namespace */
2077 }/* CVC4::theory namespace */
2078 }/* CVC4 namespace */