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 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()==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 d_rels
->eqNotifyPostMerge( t1
, t2
);
190 void TheorySetsPrivate::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
){
191 if( t1
.getType().isSet() ){
192 Node eq
= t1
.eqNode( t2
);
193 if( d_deq
.find( eq
)==d_deq
.end() ){
199 TheorySetsPrivate::EqcInfo::EqcInfo( context::Context
* c
) : d_singleton( c
){
203 TheorySetsPrivate::EqcInfo
* TheorySetsPrivate::getOrMakeEqcInfo( TNode n
, bool doMake
){
204 std::map
< Node
, EqcInfo
* >::iterator eqc_i
= d_eqc_info
.find( n
);
205 if( eqc_i
==d_eqc_info
.end() ){
208 ei
= new EqcInfo( d_external
.getSatContext() );
213 return eqc_i
->second
;
218 bool TheorySetsPrivate::ee_areEqual( Node a
, Node b
) {
222 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
223 return d_equalityEngine
.areEqual( a
, b
);
230 bool TheorySetsPrivate::ee_areDisequal( Node a
, Node b
) {
234 if( d_equalityEngine
.hasTerm( a
) && d_equalityEngine
.hasTerm( b
) ){
235 return d_equalityEngine
.areDisequal( a
, b
, false );
237 return a
.isConst() && b
.isConst();
242 bool TheorySetsPrivate::isEntailed( Node n
, bool polarity
) {
243 if( n
.getKind()==kind::NOT
){
244 return isEntailed( n
[0], !polarity
);
245 }else if( n
.getKind()==kind::EQUAL
){
247 return ee_areEqual( n
[0], n
[1] );
249 return ee_areDisequal( n
[0], n
[1] );
251 }else if( n
.getKind()==kind::MEMBER
){
252 if( ee_areEqual( n
, polarity
? d_true
: d_false
) ){
255 //check members cache
256 if( polarity
&& d_equalityEngine
.hasTerm( n
[1] ) ){
257 Node r
= d_equalityEngine
.getRepresentative( n
[1] );
258 if( isMember( n
[0], r
) ){
262 }else if( n
.getKind()==kind::AND
|| n
.getKind()==kind::OR
){
263 bool conj
= (n
.getKind()==kind::AND
)==polarity
;
264 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
265 bool isEnt
= isEntailed( n
[i
], polarity
);
271 }else if( n
.isConst() ){
272 return ( polarity
&& n
==d_true
) || ( !polarity
&& n
==d_false
);
277 bool TheorySetsPrivate::isMember( Node x
, Node s
) {
278 Assert( d_equalityEngine
.hasTerm( s
) && d_equalityEngine
.getRepresentative( s
)==s
);
279 NodeIntMap::iterator mem_i
= d_members
.find( s
);
280 if( mem_i
!= d_members
.end() ) {
281 for( int i
=0; i
<(*mem_i
).second
; i
++ ){
282 if( ee_areEqual( d_members_data
[s
][i
][0], x
) ){
290 bool TheorySetsPrivate::isSetDisequalityEntailed( Node r1
, Node r2
) {
291 Assert( d_equalityEngine
.hasTerm( r1
) && d_equalityEngine
.getRepresentative( r1
)==r1
);
292 Assert( d_equalityEngine
.hasTerm( r2
) && d_equalityEngine
.getRepresentative( r2
)==r2
);
293 TypeNode tn
= r1
.getType();
294 Node eqc_es
= d_eqc_emptyset
[tn
];
296 for( unsigned e
=0; e
<2; e
++ ){
297 Node a
= e
==0 ? r1
: r2
;
298 Node b
= e
==0 ? r2
: r1
;
299 //if there are members in a
300 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpma
= d_pol_mems
[0].find( a
);
301 if( itpma
!=d_pol_mems
[0].end() ){
302 Assert( !itpma
->second
.empty() );
305 if( !itpma
->second
.empty() ){
307 Trace("sets-deq") << "Disequality is satisfied because members are in " << a
<< " and " << b
<< " is empty" << std::endl
;
309 //a should not be singleton
310 Assert( d_eqc_singleton
.find( a
)==d_eqc_singleton
.end() );
313 std::map
< Node
, Node
>::iterator itsb
= d_eqc_singleton
.find( b
);
314 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpmb
= d_pol_mems
[1].find( b
);
315 std::vector
< Node
> prev
;
316 for( std::map
< Node
, Node
>::iterator itm
= itpma
->second
.begin(); itm
!= itpma
->second
.end(); ++itm
){
317 //if b is a singleton
318 if( itsb
!=d_eqc_singleton
.end() ){
319 if( ee_areDisequal( itm
->first
, itsb
->second
[0] ) ){
320 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< ", singleton eq " << itsb
->second
[0] << std::endl
;
323 //or disequal with another member
324 for( unsigned k
=0; k
<prev
.size(); k
++ ){
325 if( ee_areDisequal( itm
->first
, prev
[k
] ) ){
326 Trace("sets-deq") << "Disequality is satisfied because of disequal members " << itm
->first
<< " " << prev
[k
] << ", singleton eq " << std::endl
;
331 //TODO: this can be generalized : maintain map to abstract domain ( set -> cardinality )
332 //if a has positive member that is negative member in b
333 }else if( itpmb
!=d_pol_mems
[1].end() ){
334 for( std::map
< Node
, Node
>::iterator itnm
= itpmb
->second
.begin(); itnm
!= itpmb
->second
.end(); ++itnm
){
335 if( ee_areEqual( itm
->first
, itnm
->first
) ){
336 Trace("sets-deq") << "Disequality is satisfied because of " << itm
->second
<< " " << itnm
->second
<< std::endl
;
345 prev
.push_back( itm
->first
);
356 bool TheorySetsPrivate::assertFact( Node fact
, Node exp
){
357 Trace("sets-assert") << "TheorySets::assertFact : " << fact
<< ", exp = " << exp
<< std::endl
;
358 bool polarity
= fact
.getKind() != kind::NOT
;
359 TNode atom
= polarity
? fact
: fact
[0];
360 if( !isEntailed( atom
, polarity
) ){
361 if( atom
.getKind()==kind::EQUAL
){
362 d_equalityEngine
.assertEquality( atom
, polarity
, exp
);
364 d_equalityEngine
.assertPredicate( atom
, polarity
, exp
);
367 if( atom
.getKind()==kind::MEMBER
&& polarity
){
368 //check if set has a value, if so, we can propagate
369 Node r
= d_equalityEngine
.getRepresentative( atom
[1] );
370 EqcInfo
* e
= getOrMakeEqcInfo( r
, true );
372 Node s
= e
->d_singleton
;
374 Node exp
= NodeManager::currentNM()->mkNode( kind::AND
, atom
, atom
[1].eqNode( s
) );
375 d_keep
.insert( exp
);
376 if( s
.getKind()==kind::SINGLETON
){
378 Trace("sets-prop") << "Propagate mem-eq : " << exp
<< std::endl
;
379 Node eq
= s
[0].eqNode( atom
[0] );
381 assertFact( eq
, exp
);
384 Trace("sets-prop") << "Propagate mem-eq conflict : " << exp
<< std::endl
;
386 d_external
.d_out
->conflict( exp
);
390 //add to membership list
391 NodeIntMap::iterator mem_i
= d_members
.find( r
);
393 if( mem_i
!= d_members
.end() ) {
394 n_members
= (*mem_i
).second
;
396 d_members
[r
] = n_members
+ 1;
397 if( n_members
<(int)d_members_data
[r
].size() ){
398 d_members_data
[r
][n_members
] = atom
;
400 d_members_data
[r
].push_back( atom
);
410 bool TheorySetsPrivate::assertFactRec( Node fact
, Node exp
, std::vector
< Node
>& lemma
, int inferType
) {
411 if( ( options::setsInferAsLemmas() && inferType
!=-1 ) || inferType
==1 ){
412 if( !isEntailed( fact
, true ) ){
413 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
417 Trace("sets-fact") << "Assert fact rec : " << fact
<< ", exp = " << exp
<< std::endl
;
418 if( fact
.isConst() ){
419 //either trivial or a conflict
421 Trace("sets-lemma") << "Conflict : " << exp
<< std::endl
;
423 d_external
.d_out
->conflict( exp
);
426 }else if( fact
.getKind()==kind::AND
|| ( fact
.getKind()==kind::NOT
&& fact
[0].getKind()==kind::OR
) ){
428 Node f
= fact
.getKind()==kind::NOT
? fact
[0] : fact
;
429 for( unsigned i
=0; i
<f
.getNumChildren(); i
++ ){
430 Node factc
= fact
.getKind()==kind::NOT
? f
[i
].negate() : f
[i
];
431 bool tret
= assertFactRec( factc
, exp
, lemma
, inferType
);
439 bool polarity
= fact
.getKind() != kind::NOT
;
440 TNode atom
= polarity
? fact
: fact
[0];
441 //things we can assert to equality engine
442 if( atom
.getKind()==kind::MEMBER
|| ( atom
.getKind()==kind::EQUAL
&& atom
[0].getType().isSet() ) ){
443 //send to equality engine
444 if( assertFact( fact
, exp
) ){
449 if( !isEntailed( fact
, true ) ){
451 lemma
.push_back( exp
==d_true
? fact
: NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
, fact
) );
459 void TheorySetsPrivate::assertInference( Node fact
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
460 d_keep
.insert( exp
);
461 d_keep
.insert( fact
);
462 if( assertFactRec( fact
, exp
, lemmas
, inferType
) ){
463 Trace("sets-lemma") << "Sets::Lemma : " << fact
<< " from " << exp
<< " by " << c
<< std::endl
;
464 Trace("sets-assertion") << "(assert (=> " << exp
<< " " << fact
<< ")) ; by " << c
<< std::endl
;
468 void TheorySetsPrivate::assertInference( Node fact
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
469 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
470 assertInference( fact
, exp_n
, lemmas
, c
, inferType
);
473 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, Node exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
){
475 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
476 assertInference( fact
, exp
, lemmas
, c
, inferType
);
479 void TheorySetsPrivate::assertInference( std::vector
< Node
>& conc
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
, const char * c
, int inferType
) {
480 Node exp_n
= exp
.empty() ? d_true
: ( exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
) );
481 assertInference( conc
, exp_n
, lemmas
, c
, inferType
);
484 void TheorySetsPrivate::split( Node n
, int reqPol
) {
485 n
= Rewriter::rewrite( n
);
486 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, n
, n
.negate() );
487 std::vector
< Node
> lemmas
;
488 lemmas
.push_back( lem
);
489 flushLemmas( lemmas
);
490 Trace("sets-lemma") << "Sets::Lemma split : " << lem
<< std::endl
;
492 Trace("sets-lemma") << "Sets::Require phase " << n
<< " " << (reqPol
>0) << std::endl
;
493 d_external
.getOutputChannel().requirePhase( n
, reqPol
>0 );
497 void TheorySetsPrivate::fullEffortCheck(){
498 Trace("sets") << "----- Full effort check ------" << std::endl
;
500 Trace("sets") << "...iterate full effort check..." << std::endl
;
501 Assert( d_equalityEngine
.consistent() );
505 d_set_eqc_list
.clear();
506 d_eqc_emptyset
.clear();
507 d_eqc_singleton
.clear();
510 d_pol_mems
[0].clear();
511 d_pol_mems
[1].clear();
512 d_members_index
.clear();
513 d_singleton_index
.clear();
516 d_card_enabled
= false;
517 d_rels_enabled
= false;
518 d_eqc_to_card_term
.clear();
520 std::vector
< Node
> lemmas
;
521 Trace("sets-eqc") << "Equality Engine:" << std::endl
;
522 eq::EqClassesIterator eqcs_i
= eq::EqClassesIterator( &d_equalityEngine
);
523 while( !eqcs_i
.isFinished() ){
524 Node eqc
= (*eqcs_i
);
526 TypeNode tn
= eqc
.getType();
529 d_set_eqc
.push_back( eqc
);
531 Trace("sets-eqc") << "[" << eqc
<< "] : ";
532 eq::EqClassIterator eqc_i
= eq::EqClassIterator( eqc
, &d_equalityEngine
);
533 while( !eqc_i
.isFinished() ) {
536 Trace("sets-eqc") << n
<< " ";
538 if( n
.getKind()==kind::MEMBER
){
539 Node s
= d_equalityEngine
.getRepresentative( n
[1] );
540 Node x
= d_equalityEngine
.getRepresentative( n
[0] );
541 int pindex
= eqc
==d_true
? 0 : ( eqc
==d_false
? 1 : -1 );
543 if( d_pol_mems
[pindex
][s
].find( x
)==d_pol_mems
[pindex
][s
].end() ){
544 d_pol_mems
[pindex
][s
][x
] = n
;
545 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
<< ", pindex = " << pindex
<< std::endl
;
548 if( d_members_index
[s
].find( x
)==d_members_index
[s
].end() ){
549 d_members_index
[s
][x
] = n
;
550 d_op_list
[kind::MEMBER
].push_back( n
);
552 }else if( n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::UNION
|| n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::EMPTYSET
){
553 if( n
.getKind()==kind::SINGLETON
){
556 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
557 if( d_singleton_index
.find( r
)==d_singleton_index
.end() ){
558 d_singleton_index
[r
] = n
;
559 d_eqc_singleton
[eqc
] = n
;
560 d_op_list
[kind::SINGLETON
].push_back( n
);
562 d_congruent
[n
] = d_singleton_index
[r
];
564 }else if( n
.getKind()==kind::EMPTYSET
){
565 d_eqc_emptyset
[tn
] = eqc
;
567 Node r1
= d_equalityEngine
.getRepresentative( n
[0] );
568 Node r2
= d_equalityEngine
.getRepresentative( n
[1] );
569 if( d_bop_index
[n
.getKind()][r1
].find( r2
)==d_bop_index
[n
.getKind()][r1
].end() ){
570 d_bop_index
[n
.getKind()][r1
][r2
] = n
;
571 d_op_list
[n
.getKind()].push_back( n
);
573 d_congruent
[n
] = d_bop_index
[n
.getKind()][r1
][r2
];
576 d_nvar_sets
[eqc
].push_back( n
);
577 Trace("sets-debug2") << "Non-var-set[" << eqc
<< "] : " << n
<< std::endl
;
578 d_set_eqc_list
[eqc
].push_back( n
);
579 }else if( n
.getKind()==kind::CARD
){
580 d_card_enabled
= true;
581 TypeNode tn
= n
[0].getType().getSetElementType();
582 if( tn
.isInterpretedFinite() ){
583 std::stringstream ss
;
584 ss
<< "ERROR: cannot use cardinality on sets with finite element type." << std::endl
;
585 throw LogicException(ss
.str());
586 //TODO: extend approach for this case
588 Node r
= d_equalityEngine
.getRepresentative( n
[0] );
589 if( d_eqc_to_card_term
.find( r
)==d_eqc_to_card_term
.end() ){
590 d_eqc_to_card_term
[ r
] = n
;
591 registerCardinalityTerm( n
[0], lemmas
);
594 if( d_rels
->isRelationKind( n
.getKind() ) ){
595 d_rels_enabled
= true;
598 d_set_eqc_list
[eqc
].push_back( n
);
603 Trace("sets-eqc") << std::endl
;
607 flushLemmas( lemmas
);
608 if( !hasProcessed() ){
609 if( Trace
.isOn("sets-mem") ){
610 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
611 Node s
= d_set_eqc
[i
];
612 Trace("sets-mem") << "Eqc " << s
<< " : ";
613 std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].find( s
);
614 if( it
!=d_pol_mems
[0].end() ){
615 Trace("sets-mem") << "Memberships : ";
616 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
617 Trace("sets-mem") << it2
->first
<< " ";
620 std::map
< Node
, Node
>::iterator its
= d_eqc_singleton
.find( s
);
621 if( its
!=d_eqc_singleton
.end() ){
622 Trace("sets-mem") << " : Singleton : " << its
->second
;
624 Trace("sets-mem") << std::endl
;
628 checkDownwardsClosure( lemmas
);
629 if( options::setsInferAsLemmas() ){
630 flushLemmas( lemmas
);
632 if( !hasProcessed() ){
633 checkUpwardsClosure( lemmas
);
634 flushLemmas( lemmas
);
635 if( !hasProcessed() ){
636 if( d_card_enabled
){
638 checkCardBuildGraph( lemmas
);
639 flushLemmas( lemmas
);
640 if( !hasProcessed() ){
641 checkMinCard( lemmas
);
642 flushLemmas( lemmas
);
643 if( !hasProcessed() ){
644 checkCardCycles( lemmas
);
645 flushLemmas( lemmas
);
646 if( !hasProcessed() ){
647 std::vector
< Node
> intro_sets
;
648 checkNormalForms( lemmas
, intro_sets
);
649 flushLemmas( lemmas
);
650 if( !hasProcessed() ){
651 checkDisequalities( lemmas
);
652 flushLemmas( lemmas
);
653 if( !hasProcessed() && !intro_sets
.empty() ){
654 Assert( intro_sets
.size()==1 );
655 Trace("sets-intro") << "Introduce term : " << intro_sets
[0] << std::endl
;
656 Trace("sets-intro") << " Actual Intro : ";
657 debugPrintSet( intro_sets
[0], "sets-nf" );
658 Trace("sets-nf") << std::endl
;
659 Node k
= getProxy( intro_sets
[0] );
667 checkDisequalities( lemmas
);
668 flushLemmas( lemmas
);
673 }while( !d_sentLemma
&& !d_conflict
&& d_addedFact
);
674 Trace("sets") << "----- End full effort check, conflict=" << d_conflict
<< ", lemma=" << d_sentLemma
<< std::endl
;
678 void TheorySetsPrivate::checkDownwardsClosure( std::vector
< Node
>& lemmas
) {
679 Trace("sets") << "Downwards closure..." << std::endl
;
681 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= d_pol_mems
[0].begin(); it
!= d_pol_mems
[0].end(); ++it
){
682 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( it
->first
);
683 if( itn
!=d_nvar_sets
.end() ){
684 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
685 if( d_congruent
.find( itn
->second
[j
] )==d_congruent
.end() ){
686 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
687 Node mem
= it2
->second
;
688 Node eq_set
= itn
->second
[j
];
689 Assert( d_equalityEngine
.areEqual( mem
[1], eq_set
) );
690 if( mem
[1]!=eq_set
){
691 Trace("sets-debug") << "Downwards closure based on " << mem
<< ", eq_set = " << eq_set
<< std::endl
;
692 if( !options::setsProxyLemmas() ){
693 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
694 nmem
= Rewriter::rewrite( nmem
);
695 std::vector
< Node
> exp
;
696 exp
.push_back( mem
);
697 exp
.push_back( mem
[1].eqNode( eq_set
) );
698 assertInference( nmem
, exp
, lemmas
, "downc" );
704 Node k
= getProxy( eq_set
);
705 Node pmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], k
);
706 Node nmem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, mem
[0], eq_set
);
707 nmem
= Rewriter::rewrite( nmem
);
708 std::vector
< Node
> exp
;
709 if( ee_areEqual( mem
, pmem
) ){
710 exp
.push_back( pmem
);
712 nmem
= NodeManager::currentNM()->mkNode( kind::OR
, pmem
.negate(), nmem
);
714 assertInference( nmem
, exp
, lemmas
, "downc" );
724 void TheorySetsPrivate::checkUpwardsClosure( std::vector
< Node
>& lemmas
) {
726 for( std::map
< Kind
, std::map
< Node
, std::map
< Node
, Node
> > >::iterator itb
= d_bop_index
.begin(); itb
!= d_bop_index
.end(); ++itb
){
728 Trace("sets") << "Upwards closure " << k
<< "..." << std::endl
;
729 for( std::map
< Node
, std::map
< Node
, Node
> >::iterator it
= itb
->second
.begin(); it
!= itb
->second
.end(); ++it
){
731 //see if there are members in first argument r1
732 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm1
= d_pol_mems
[0].find( r1
);
733 if( itm1
!=d_pol_mems
[0].end() || k
==kind::UNION
){
734 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
735 Node r2
= it2
->first
;
736 //see if there are members in second argument
737 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm2
= d_pol_mems
[0].find( r2
);
738 if( itm2
!=d_pol_mems
[0].end() || k
!=kind::INTERSECTION
){
739 Trace("sets-debug") << "Checking " << it2
->second
<< ", members = " << (itm1
!=d_pol_mems
[0].end()) << ", " << (itm2
!=d_pol_mems
[0].end()) << std::endl
;
740 //for all members of r1
741 if( itm1
!=d_pol_mems
[0].end() ){
742 for( std::map
< Node
, Node
>::iterator itm1m
= itm1
->second
.begin(); itm1m
!= itm1
->second
.end(); ++itm1m
){
743 Node xr
= itm1m
->first
;
744 Node x
= itm1m
->second
[0];
745 Trace("sets-debug") << "checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
746 std::vector
< Node
> exp
;
747 exp
.push_back( itm1m
->second
);
748 addEqualityToExp( it2
->second
[0], itm1m
->second
[1], exp
);
751 if( k
==kind::UNION
){
753 }else if( k
==kind::INTERSECTION
){
754 //conclude x is in it2->second
755 //if also existing in members of r2
756 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
758 exp
.push_back( itm2
->second
[xr
] );
759 addEqualityToExp( it2
->second
[1], itm2
->second
[xr
][1], exp
);
760 addEqualityToExp( x
, itm2
->second
[xr
][0], exp
);
764 Assert( k
==kind::SETMINUS
);
766 std::map< Node, std::map< Node, Node > >::iterator itnm2 = d_pol_mems[1].find( r2 );
767 if( itnm2!=d_pol_mems[1].end() ){
768 bool not_in_r2 = itnm2->second.find( xr )!=itnm2->second.end();
770 exp.push_back( itnm2->second[xr] );
771 if( it2->second[1]!=itnm2->second[xr][1] ){
772 Assert( d_equalityEngine.areEqual( it2->second[1], itnm2->second[xr][1] ) );
773 exp.push_back( it2->second[1].eqNode( itnm2->second[xr][1] ) );
775 if( x!=itnm2->second[xr][0] ){
776 Assert( d_equalityEngine.areEqual( x, itnm2->second[xr][0] ) );
777 exp.push_back( NodeManager::currentNM()->mkNode( x.getType().isBoolean() ? kind::IFF : kind::EQUAL, x, itnm2->second[xr][0] ) );
784 bool in_r2
= itm2
!=d_pol_mems
[0].end() && itm2
->second
.find( xr
)!=itm2
->second
.end();
786 // must add lemma for set minus since non-membership in this case is not explained
787 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, it2
->second
[1] ).negate() );
794 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
795 if( !isMember( x
, rr
) ){
796 Node kk
= getProxy( it2
->second
);
797 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, kk
);
798 assertInference( fact
, exp
, lemmas
, "upc", inferType
);
804 Trace("sets-debug") << "done checking membership " << xr
<< " " << itm1m
->second
<< std::endl
;
807 if( k
==kind::UNION
){
808 if( itm2
!=d_pol_mems
[0].end() ){
809 //for all members of r2
810 for( std::map
< Node
, Node
>::iterator itm2m
= itm2
->second
.begin(); itm2m
!= itm2
->second
.end(); ++itm2m
){
811 Node x
= itm2m
->second
[0];
812 Node rr
= d_equalityEngine
.getRepresentative( it2
->second
);
813 if( !isMember( x
, rr
) ){
814 std::vector
< Node
> exp
;
815 exp
.push_back( itm2m
->second
);
816 addEqualityToExp( it2
->second
[1], itm2m
->second
[1], exp
);
817 Node k
= getProxy( it2
->second
);
818 Node fact
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, k
);
819 assertInference( fact
, exp
, lemmas
, "upc2" );
834 void TheorySetsPrivate::checkDisequalities( std::vector
< Node
>& lemmas
) {
836 Trace("sets") << "Disequalities..." << std::endl
;
837 for(NodeBoolMap::const_iterator it
=d_deq
.begin(); it
!=d_deq
.end(); ++it
) {
839 Node deq
= (*it
).first
;
840 //check if it is already satisfied
841 Assert( d_equalityEngine
.hasTerm( deq
[0] ) && d_equalityEngine
.hasTerm( deq
[1] ) );
842 Node r1
= d_equalityEngine
.getRepresentative( deq
[0] );
843 Node r2
= d_equalityEngine
.getRepresentative( deq
[1] );
844 bool is_sat
= isSetDisequalityEntailed( r1
, r2
);
847 //try to make one of them empty
848 for( unsigned e=0; e<2; e++ ){
852 Trace("sets-debug") << "Check disequality " << deq
<< ", is_sat = " << is_sat
<< std::endl
;
853 //will process regardless of sat/processed/unprocessed
857 if( d_deq_processed
.find( deq
)==d_deq_processed
.end() ){
858 d_deq_processed
.insert( deq
);
859 d_deq_processed
.insert( deq
[1].eqNode( deq
[0] ) );
860 Trace("sets") << "Process Disequality : " << deq
.negate() << std::endl
;
861 TypeNode elementType
= deq
[0].getType().getSetElementType();
862 Node x
= NodeManager::currentNM()->mkSkolem("sde_", elementType
);
863 Node mem1
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[0] );
864 Node mem2
= NodeManager::currentNM()->mkNode( kind::MEMBER
, x
, deq
[1] );
865 Node lem
= NodeManager::currentNM()->mkNode( kind::OR
, deq
, NodeManager::currentNM()->mkNode( kind::IFF
, mem1
, mem2
).negate() );
866 lem
= Rewriter::rewrite( lem
);
867 assertInference( lem
, d_emp_exp
, lemmas
, "diseq", 1 );
868 flushLemmas( lemmas
);
869 if( hasProcessed() ){
878 void TheorySetsPrivate::checkCardBuildGraph( std::vector
< Node
>& lemmas
) {
879 Trace("sets") << "Cardinality graph..." << std::endl
;
880 //first, ensure cardinality relationships are added as lemmas for all non-basic set terms
881 for( unsigned i
=0; i
<d_set_eqc
.size(); i
++ ){
882 Node eqc
= d_set_eqc
[i
];
883 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
884 if( itn
!=d_nvar_sets
.end() ){
885 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
886 Node n
= itn
->second
[j
];
887 if( d_congruent
.find( n
)==d_congruent
.end() ){
888 //if setminus, do for intersection instead
889 if( n
.getKind()==kind::SETMINUS
){
890 n
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
892 registerCardinalityTerm( n
, lemmas
);
897 Trace("sets") << "Done cardinality graph" << std::endl
;
900 void TheorySetsPrivate::registerCardinalityTerm( Node n
, std::vector
< Node
>& lemmas
){
901 if( d_card_processed
.find( n
)==d_card_processed
.end() ){
902 d_card_processed
.insert( n
);
903 Trace("sets-card") << "Cardinality lemmas for " << n
<< " : " << std::endl
;
904 std::vector
< Node
> cterms
;
905 if( n
.getKind()==kind::INTERSECTION
){
906 for( unsigned e
=0; e
<2; e
++ ){
907 Node s
= NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] );
908 cterms
.push_back( s
);
910 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, n
), d_zero
);
911 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
913 cterms
.push_back( n
);
915 for( unsigned k
=0; k
<cterms
.size(); k
++ ){
917 Node nk
= getProxy( nn
);
918 Node pos_lem
= NodeManager::currentNM()->mkNode( kind::GEQ
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
), d_zero
);
919 assertInference( pos_lem
, d_emp_exp
, lemmas
, "pcard", 1 );
921 Node lem
= NodeManager::currentNM()->mkNode( kind::EQUAL
, NodeManager::currentNM()->mkNode( kind::CARD
, nk
),
922 NodeManager::currentNM()->mkNode( kind::CARD
, nn
) );
923 lem
= Rewriter::rewrite( lem
);
924 Trace("sets-card") << " " << k
<< " : " << lem
<< std::endl
;
925 assertInference( lem
, d_emp_exp
, lemmas
, "card", 1 );
931 void TheorySetsPrivate::checkCardCycles( std::vector
< Node
>& lemmas
) {
932 Trace("sets") << "Check cardinality cycles..." << std::endl
;
933 //build order of equivalence classes, also build cardinality graph
934 std::vector
< Node
> set_eqc_tmp
;
935 set_eqc_tmp
.insert( set_eqc_tmp
.end(), d_set_eqc
.begin(), d_set_eqc
.end() );
937 d_card_parent
.clear();
938 for( unsigned i
=0; i
<set_eqc_tmp
.size(); i
++ ){
939 std::vector
< Node
> curr
;
940 std::vector
< Node
> exp
;
941 checkCardCyclesRec( set_eqc_tmp
[i
], curr
, exp
, lemmas
);
942 flushLemmas( lemmas
);
943 if( hasProcessed() ){
947 Trace("sets") << "Done check cardinality cycles" << std::endl
;
950 void TheorySetsPrivate::checkCardCyclesRec( Node eqc
, std::vector
< Node
>& curr
, std::vector
< Node
>& exp
, std::vector
< Node
>& lemmas
) {
951 if( std::find( curr
.begin(), curr
.end(), eqc
)!=curr
.end() ){
952 Trace("sets-debug") << "Found venn region loop..." << std::endl
;
954 //all regions must be equal
955 std::vector
< Node
> conc
;
956 for( unsigned i
=1; i
<curr
.size(); i
++ ){
957 conc
.push_back( curr
[0].eqNode( curr
[i
] ) );
959 Node fact
= conc
.size()==1 ? conc
[0] : NodeManager::currentNM()->mkNode( kind::AND
, conc
);
960 assertInference( fact
, exp
, lemmas
, "card_cycle" );
961 flushLemmas( lemmas
);
963 //should be guaranteed based on not exploring equal parents
966 }else if( std::find( d_set_eqc
.begin(), d_set_eqc
.end(), eqc
)==d_set_eqc
.end() ){
967 curr
.push_back( eqc
);
968 TypeNode tn
= eqc
.getType();
969 bool is_empty
= eqc
==d_eqc_emptyset
[tn
];
970 Node emp_set
= getEmptySet( tn
);
971 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
972 if( itn
!=d_nvar_sets
.end() ){
973 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
974 Node n
= itn
->second
[j
];
975 if( n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
){
976 Trace("sets-debug") << "Build cardinality parents for " << n
<< "..." << std::endl
;
977 std::vector
< Node
> sib
;
978 unsigned true_sib
= 0;
979 if( n
.getKind()==kind::INTERSECTION
){
981 for( unsigned e
=0; e
<2; e
++ ){
982 Node sm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[e
], n
[1-e
] ) );
987 Node si
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, n
[0], n
[1] ) );
990 Node osm
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::SETMINUS
, n
[1], n
[0] ) );
991 sib
.push_back( osm
);
994 Node u
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::UNION
, n
[0], n
[1] ) );
995 if( !d_equalityEngine
.hasTerm( u
) ){
998 unsigned n_parents
= true_sib
+ ( u
.isNull() ? 0 : 1 );
999 //if this set is empty
1001 Assert( ee_areEqual( n
, emp_set
) );
1002 Trace("sets-debug") << " empty, parents equal siblings" << std::endl
;
1003 std::vector
< Node
> conc
;
1004 //parent equal siblings
1005 for( unsigned e
=0; e
<true_sib
; e
++ ){
1006 if( d_equalityEngine
.hasTerm( sib
[e
] ) && !ee_areEqual( n
[e
], sib
[e
] ) ){
1007 conc
.push_back( n
[e
].eqNode( sib
[e
] ) );
1010 assertInference( conc
, n
.eqNode( emp_set
), lemmas
, "cg_emp" );
1011 flushLemmas( lemmas
);
1012 if( hasProcessed() ){
1015 //justify why there is no edge to parents (necessary?)
1016 for( unsigned e
=0; e
<n_parents
; e
++ ){
1017 Node p
= (e
==true_sib
) ? u
: n
[e
];
1022 std::vector
< Node
> card_parents
;
1023 std::vector
< int > card_parent_ids
;
1024 //check if equal to a parent
1025 for( unsigned e
=0; e
<n_parents
; e
++ ){
1026 Trace("sets-debug") << " check parent " << e
<< "/" << n_parents
<< std::endl
;
1027 bool is_union
= e
==true_sib
;
1028 Node p
= (e
==true_sib
) ? u
: n
[e
];
1029 Trace("sets-debug") << " check relation to parent " << p
<< ", isu=" << is_union
<< "..." << std::endl
;
1030 //if parent is empty
1031 if( ee_areEqual( p
, emp_set
) ){
1032 Trace("sets-debug") << " it is empty..." << std::endl
;
1033 Assert( !ee_areEqual( n
, emp_set
) );
1034 assertInference( n
.eqNode( emp_set
), p
.eqNode( emp_set
), lemmas
, "cg_emppar" );
1035 if( hasProcessed() ){
1038 //if we are equal to a parent
1039 }else if( ee_areEqual( p
, n
) ){
1040 Trace("sets-debug") << " it is equal to this..." << std::endl
;
1041 std::vector
< Node
> conc
;
1042 std::vector
< int > sib_emp_indices
;
1044 for( unsigned s
=0; s
<sib
.size(); s
++ ){
1045 sib_emp_indices
.push_back( s
);
1048 sib_emp_indices
.push_back( e
);
1050 //sibling(s) are empty
1051 for( unsigned s
=0; s
<sib_emp_indices
.size(); s
++ ){
1052 unsigned si
= sib_emp_indices
[s
];
1053 if( !ee_areEqual( sib
[si
], emp_set
) ){
1054 conc
.push_back( sib
[si
].eqNode( emp_set
) );
1056 Trace("sets-debug") << "Sibling " << sib
[si
] << " is already empty." << std::endl
;
1059 if( !is_union
&& n
.getKind()==kind::INTERSECTION
&& !u
.isNull() ){
1060 //union is equal to other parent
1061 if( !ee_areEqual( u
, n
[1-e
] ) ){
1062 conc
.push_back( u
.eqNode( n
[1-e
] ) );
1065 Trace("sets-debug") << "...derived " << conc
.size() << " conclusions" << std::endl
;
1066 assertInference( conc
, n
.eqNode( p
), lemmas
, "cg_eqpar" );
1067 flushLemmas( lemmas
);
1068 if( hasProcessed() ){
1072 Trace("sets-cdg") << "Card graph : " << n
<< " -> " << p
<< std::endl
;
1073 //otherwise, we a syntactic subset of p
1074 card_parents
.push_back( p
);
1075 card_parent_ids
.push_back( is_union
? 2 : e
);
1078 Assert( d_card_parent
[n
].empty() );
1079 Trace("sets-debug") << "get parent representatives..." << std::endl
;
1080 //for each parent, take their representatives
1081 for( unsigned k
=0; k
<card_parents
.size(); k
++ ){
1082 Node eqcc
= d_equalityEngine
.getRepresentative( card_parents
[k
] );
1083 Trace("sets-debug") << "Check card parent " << k
<< "/" << card_parents
.size() << std::endl
;
1085 //if parent is singleton, then we should either be empty to equal to it
1086 std::map
< Node
, Node
>::iterator itps
= d_eqc_singleton
.find( eqcc
);
1087 if( itps
!=d_eqc_singleton
.end() ){
1088 bool eq_parent
= false;
1089 std::vector
< Node
> exp
;
1090 addEqualityToExp( card_parents
[k
], itps
->second
, exp
);
1091 if( ee_areDisequal( n
, emp_set
) ){
1092 exp
.push_back( n
.eqNode( emp_set
).negate() );
1095 std::map
< Node
, std::map
< Node
, Node
> >::iterator itpm
= d_pol_mems
[0].find( eqc
);
1096 if( itpm
!=d_pol_mems
[0].end() && !itpm
->second
.empty() ){
1097 Node pmem
= itpm
->second
.begin()->second
;
1098 exp
.push_back( pmem
);
1099 addEqualityToExp( n
, pmem
[1], exp
);
1103 //must be equal to parent
1105 Node conc
= n
.eqNode( card_parents
[k
] );
1106 assertInference( conc
, exp
, lemmas
, "cg_par_sing" );
1107 flushLemmas( lemmas
);
1110 Trace("sets-nf") << "Split empty : " << n
<< std::endl
;
1111 split( n
.eqNode( emp_set
), 1 );
1113 Assert( hasProcessed() );
1117 for( unsigned l
=0; l
<d_card_parent
[n
].size(); l
++ ){
1118 if( eqcc
==d_card_parent
[n
][l
] ){
1119 Trace("sets-debug") << " parents " << l
<< " and " << k
<< " are equal, ids = " << card_parent_ids
[l
] << " " << card_parent_ids
[k
] << std::endl
;
1121 if( n
.getKind()==kind::INTERSECTION
){
1122 Assert( card_parent_ids
[l
]!=2 );
1123 std::vector
< Node
> conc
;
1124 if( card_parent_ids
[k
]==2 ){
1125 //intersection is equal to other parent
1126 unsigned pid
= 1-card_parent_ids
[l
];
1127 if( !ee_areEqual( n
[pid
], n
) ){
1128 Trace("sets-debug") << " one of them is union, make equal to other..." << std::endl
;
1129 conc
.push_back( n
[pid
].eqNode( n
) );
1132 if( !ee_areEqual( card_parents
[k
], n
) ){
1133 Trace("sets-debug") << " neither is union, make equal to one parent..." << std::endl
;
1134 //intersection is equal to one of the parents
1135 conc
.push_back( card_parents
[k
].eqNode( n
) );
1138 assertInference( conc
, card_parents
[k
].eqNode( d_card_parent
[n
][l
] ), lemmas
, "cg_pareq" );
1139 flushLemmas( lemmas
);
1140 if( hasProcessed() ){
1147 d_card_parent
[n
].push_back( eqcc
);
1151 //now recurse on parents (to ensure their normal will be computed after this eqc)
1152 exp
.push_back( eqc
.eqNode( n
) );
1153 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1154 checkCardCyclesRec( d_card_parent
[n
][k
], curr
, exp
, lemmas
);
1155 if( hasProcessed() ){
1165 //parents now processed, can add to ordered list
1166 d_set_eqc
.push_back( eqc
);
1172 void TheorySetsPrivate::checkNormalForms( std::vector
< Node
>& lemmas
, std::vector
< Node
>& intro_sets
){
1173 Trace("sets") << "Check normal forms..." << std::endl
;
1174 // now, build normal form for each equivalence class
1175 // d_set_eqc is now sorted such that for each d_set_eqc[i], d_set_eqc[j],
1176 // if d_set_eqc[i] is a strict syntactic subterm of d_set_eqc[j], then i<j.
1179 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1180 checkNormalForm( d_set_eqc
[i
], intro_sets
);
1181 if( hasProcessed() || !intro_sets
.empty() ){
1185 Trace("sets") << "Done check normal forms" << std::endl
;
1188 void TheorySetsPrivate::checkNormalForm( Node eqc
, std::vector
< Node
>& intro_sets
){
1189 TypeNode tn
= eqc
.getType();
1190 Trace("sets") << "Compute normal form for " << eqc
<< std::endl
;
1191 Trace("sets-nf") << "Compute N " << eqc
<< "..." << std::endl
;
1192 if( eqc
==d_eqc_emptyset
[tn
] ){
1194 Trace("sets-nf") << "----> N " << eqc
<< " => {}" << std::endl
;
1196 //flat/normal forms are sets of equivalence classes
1198 std::vector
< Node
> comps
;
1199 std::map
< Node
, std::map
< Node
, std::vector
< Node
> > >::iterator it
= d_ff
.find( eqc
);
1200 if( it
!=d_ff
.end() ){
1201 for( std::map
< Node
, std::vector
< Node
> >::iterator itf
= it
->second
.begin(); itf
!= it
->second
.end(); ++itf
){
1202 std::sort( itf
->second
.begin(), itf
->second
.end() );
1203 if( base
.isNull() ){
1206 comps
.push_back( itf
->first
);
1208 Trace("sets-nf") << " F " << itf
->first
<< " : ";
1209 if( Trace
.isOn("sets-nf") ){
1210 Trace("sets-nf") << "{ ";
1211 for( unsigned k
=0; k
<itf
->second
.size(); k
++ ){
1212 if( k
>0 ){ Trace("sets-nf") << ", "; }
1213 Trace("sets-nf") << "[" << itf
->second
[k
] << "]";
1215 Trace("sets-nf") << " }" << std::endl
;
1217 Trace("sets-nf-debug") << " ...";
1218 debugPrintSet( itf
->first
, "sets-nf-debug" );
1219 Trace("sets-nf-debug") << std::endl
;
1222 Trace("sets-nf") << "(no flat forms)" << std::endl
;
1225 Assert( d_nf
.find( eqc
)==d_nf
.end() );
1226 bool success
= true;
1227 if( !base
.isNull() ){
1228 Node emp_set
= getEmptySet( tn
);
1229 for( unsigned j
=0; j
<comps
.size(); j
++ ){
1231 std::vector
< Node
> c
;
1232 c
.push_back( base
);
1233 c
.push_back( comps
[j
] );
1234 std::vector
< Node
> only
[2];
1235 std::vector
< Node
> common
;
1236 Trace("sets-nf-debug") << "Compare venn regions of " << base
<< " vs " << comps
[j
] << std::endl
;
1237 unsigned k
[2] = { 0, 0 };
1238 while( k
[0]<d_ff
[eqc
][c
[0]].size() || k
[1]<d_ff
[eqc
][c
[1]].size() ){
1240 for( unsigned e
=0; e
<2; e
++ ){
1241 if( k
[e
]==d_ff
[eqc
][c
[e
]].size() ){
1242 for( ; k
[1-e
]<d_ff
[eqc
][c
[1-e
]].size(); ++k
[1-e
] ){
1243 only
[1-e
].push_back( d_ff
[eqc
][c
[1-e
]][k
[1-e
]] );
1249 if( d_ff
[eqc
][c
[0]][k
[0]]==d_ff
[eqc
][c
[1]][k
[1]] ){
1250 common
.push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1253 }else if( d_ff
[eqc
][c
[0]][k
[0]]<d_ff
[eqc
][c
[1]][k
[1]] ){
1254 only
[0].push_back( d_ff
[eqc
][c
[0]][k
[0]] );
1257 only
[1].push_back( d_ff
[eqc
][c
[1]][k
[1]] );
1262 if( !only
[0].empty() || !only
[1].empty() ){
1263 if( Trace
.isOn("sets-nf-debug") ){
1264 Trace("sets-nf-debug") << "Unique venn regions : " << std::endl
;
1265 for( unsigned e
=0; e
<2; e
++ ){
1266 Trace("sets-nf-debug") << " " << c
[e
] << " : { ";
1267 for( unsigned l
=0; l
<only
[e
].size(); l
++ ){
1268 if( l
>0 ){ Trace("sets-nf-debug") << ", "; }
1269 Trace("sets-nf-debug") << "[" << only
[e
][l
] << "]";
1271 Trace("sets-nf-debug") << " }" << std::endl
;
1274 //try to make one empty, prefer the unique ones first
1275 for( unsigned e
=0; e
<3; e
++ ){
1276 unsigned sz
= e
==2 ? common
.size() : only
[e
].size();
1277 for( unsigned l
=0; l
<sz
; l
++ ){
1278 Node r
= e
==2 ? common
[l
] : only
[e
][l
];
1279 Trace("sets-nf-debug") << "Try split empty : " << r
<< std::endl
;
1280 Trace("sets-nf-debug") << " actual : ";
1281 debugPrintSet( r
, "sets-nf-debug" );
1282 Trace("sets-nf-debug") << std::endl
;
1283 Assert( !ee_areEqual( r
, emp_set
) );
1284 if( !ee_areDisequal( r
, emp_set
) && ( d_pol_mems
[0].find( r
)==d_pol_mems
[0].end() || d_pol_mems
[0][r
].empty() ) ){
1285 //guess that its equal empty if it has no explicit members
1286 Trace("sets-nf") << " Split empty : " << r
<< std::endl
;
1287 Trace("sets-nf") << "Actual Split : ";
1288 debugPrintSet( r
, "sets-nf" );
1289 Trace("sets-nf") << std::endl
;
1290 split( r
.eqNode( emp_set
), 1 );
1291 Assert( hasProcessed() );
1296 for( unsigned l
=0; l
<only
[0].size(); l
++ ){
1297 for( unsigned m
=0; m
<only
[1].size(); m
++ ){
1298 bool disjoint
= false;
1299 Trace("sets-nf-debug") << "Try split " << only
[0][l
] << " against " << only
[1][m
] << std::endl
;
1301 for( unsigned e
=0; e
<2; e
++ ){
1302 Node r1
= e
==0 ? only
[0][l
] : only
[1][m
];
1303 Node r2
= e
==0 ? only
[1][m
] : only
[0][l
];
1304 //check if their intersection exists modulo equality
1305 std::map
< Node
, Node
>::iterator itb
= d_bop_index
[kind::INTERSECTION
][r1
].find( r2
);
1306 if( itb
!=d_bop_index
[kind::INTERSECTION
][r1
].end() ){
1307 Trace("sets-nf-debug") << "Split term already exists, but not in cardinality graph : " << itb
->second
<< ", should be empty." << std::endl
;
1308 //their intersection is empty (probably?)
1309 // e.g. these are two disjoint venn regions, proceed to next pair
1310 Assert( ee_areEqual( emp_set
, itb
->second
) );
1316 //simply introduce their intersection
1317 Assert( only
[0][l
]!=only
[1][m
] );
1318 Node kca
= getProxy( only
[0][l
] );
1319 Node kcb
= getProxy( only
[1][m
] );
1320 Node intro
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::INTERSECTION
, kca
, kcb
) );
1321 Trace("sets-nf") << " Intro split : " << only
[0][l
] << " against " << only
[1][m
] << ", term is " << intro
<< std::endl
;
1322 intro_sets
.push_back( intro
);
1323 Assert( !d_equalityEngine
.hasTerm( intro
) );
1328 //should never get here
1333 //normal form is flat form of base
1334 d_nf
[eqc
].insert( d_nf
[eqc
].end(), d_ff
[eqc
][base
].begin(), d_ff
[eqc
][base
].end() );
1335 Trace("sets-nf") << "----> N " << eqc
<< " => F " << base
<< std::endl
;
1337 Trace("sets-nf") << "failed to build N " << eqc
<< std::endl
;
1341 //normal form is this equivalence class
1342 d_nf
[eqc
].push_back( eqc
);
1343 Trace("sets-nf") << "----> N " << eqc
<< " => { " << eqc
<< " }" << std::endl
;
1347 std::map
< Node
, std::vector
< Node
> >::iterator itn
= d_nvar_sets
.find( eqc
);
1348 if( itn
!=d_nvar_sets
.end() ){
1349 std::map
< Node
, std::map
< Node
, bool > > parents_proc
;
1350 for( unsigned j
=0; j
<itn
->second
.size(); j
++ ){
1351 Node n
= itn
->second
[j
];
1352 Trace("sets-nf-debug") << "Carry nf for term " << n
<< std::endl
;
1353 if( !d_card_parent
[n
].empty() ){
1354 Assert( d_card_base
.find( n
)!=d_card_base
.end() );
1355 Node cbase
= d_card_base
[n
];
1356 Trace("sets-nf-debug") << "Card base is " << cbase
<< std::endl
;
1357 for( unsigned k
=0; k
<d_card_parent
[n
].size(); k
++ ){
1358 Node p
= d_card_parent
[n
][k
];
1359 Trace("sets-nf-debug") << "Check parent " << p
<< std::endl
;
1360 if( parents_proc
[cbase
].find( p
)==parents_proc
[cbase
].end() ){
1361 parents_proc
[cbase
][p
] = true;
1362 Trace("sets-nf-debug") << "Carry nf to parent ( " << cbase
<< ", [" << p
<< "] ), from " << n
<< "..." << std::endl
;
1363 //for( unsigned i=0; i<d_nf[eqc].size(); i++ ){
1364 // Assert( std::find( d_ff[p][cbase].begin(), d_ff[p][cbase].end(), d_nf[eqc][i] )==d_ff[p][cbase].end() );
1366 for( unsigned i
=0; i
<d_nf
[eqc
].size(); i
++ ){
1367 if( std::find( d_ff
[p
][cbase
].begin(), d_ff
[p
][cbase
].end(), d_nf
[eqc
][i
] )==d_ff
[p
][cbase
].end() ){
1368 d_ff
[p
][cbase
].insert( d_ff
[p
][cbase
].end(), d_nf
[eqc
].begin(), d_nf
[eqc
].end() );
1370 //if it is a duplicate venn region, it must be empty since it is coming from syntactically disjoint siblings TODO?
1374 Trace("sets-nf-debug") << "..already processed parent " << p
<< " for " << cbase
<< std::endl
;
1381 Assert( hasProcessed() );
1386 void TheorySetsPrivate::checkMinCard( std::vector
< Node
>& lemmas
) {
1388 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1389 Node eqc
= d_set_eqc
[i
];
1390 //get members in class
1391 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1392 if( itm
!=d_pol_mems
[0].end() ){
1393 std::vector
< Node
> exp
;
1394 std::vector
< Node
> members
;
1396 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1397 if( it
!=d_eqc_to_card_term
.end() ){
1398 cardTerm
= it
->second
;
1400 cardTerm
= NodeManager::currentNM()->mkNode( kind::CARD
, eqc
);
1402 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1404 for( unsigned j=0; j<members.size(); j++ ){
1405 if( !ee_areDisequal( members[j], itmm->second ) ){
1406 Assert( !ee_areEqual( members[j], itmm->second ) );
1411 members
.push_back( itmm
->first
);
1412 exp
.push_back( NodeManager::currentNM()->mkNode( kind::MEMBER
, itmm
->first
, cardTerm
[0] ) );
1414 if( members
.size()>1 ){
1415 exp
.push_back( NodeManager::currentNM()->mkNode( kind::DISTINCT
, members
) );
1417 if( !members
.empty() ){
1418 Node conc
= NodeManager::currentNM()->mkNode( kind::GEQ
, cardTerm
, NodeManager::currentNM()->mkConst( Rational( members
.size() ) ) );
1419 Node lem
= NodeManager::currentNM()->mkNode( kind::IMPLIES
, exp
.size()==1 ? exp
[0] : NodeManager::currentNM()->mkNode( kind::AND
, exp
), conc
);
1420 Trace("sets-lemma") << "Sets::Lemma : " << lem
<< " by mincard" << std::endl
;
1421 lemmas
.push_back( lem
);
1427 void TheorySetsPrivate::flushLemmas( std::vector
< Node
>& lemmas
) {
1429 for( unsigned i
=0; i
<lemmas
.size(); i
++ ){
1430 Node lem
= lemmas
[i
];
1431 if( d_lemmas_produced
.find(lem
)==d_lemmas_produced
.end() ){
1432 Trace("sets-lemma-debug") << "Send lemma : " << lem
<< std::endl
;
1433 d_lemmas_produced
.insert(lem
);
1434 d_external
.d_out
->lemma(lem
);
1437 Trace("sets-lemma-debug") << "Already sent lemma : " << lem
<< std::endl
;
1443 Node
TheorySetsPrivate::getProxy( Node n
) {
1444 if( n
.getKind()==kind::EMPTYSET
|| n
.getKind()==kind::SINGLETON
|| n
.getKind()==kind::INTERSECTION
|| n
.getKind()==kind::SETMINUS
|| n
.getKind()==kind::UNION
){
1445 NodeMap::const_iterator it
= d_proxy
.find( n
);
1446 if( it
==d_proxy
.end() ){
1447 Node k
= NodeManager::currentNM()->mkSkolem( "sp", n
.getType(), "proxy for set" );
1449 d_proxy_to_term
[k
] = n
;
1450 Node eq
= k
.eqNode( n
);
1451 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
1452 d_external
.d_out
->lemma( eq
);
1453 if( n
.getKind()==kind::SINGLETON
){
1454 Node slem
= NodeManager::currentNM()->mkNode( kind::MEMBER
, n
[0], k
);
1455 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton" << std::endl
;
1456 d_external
.d_out
->lemma( slem
);
1461 return (*it
).second
;
1468 Node
TheorySetsPrivate::getCongruent( Node n
) {
1469 Assert( d_equalityEngine
.hasTerm( n
) );
1470 std::map
< Node
, Node
>::iterator it
= d_congruent
.find( n
);
1471 if( it
==d_congruent
.end() ){
1478 Node
TheorySetsPrivate::getEmptySet( TypeNode tn
) {
1479 std::map
< TypeNode
, Node
>::iterator it
= d_emptyset
.find( tn
);
1480 if( it
==d_emptyset
.end() ){
1481 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
.toType()));
1489 bool TheorySetsPrivate::hasLemmaCached( Node lem
) {
1490 return d_lemmas_produced
.find(lem
)!=d_lemmas_produced
.end();
1493 bool TheorySetsPrivate::hasProcessed() {
1494 return d_conflict
|| d_sentLemma
|| d_addedFact
;
1497 void TheorySetsPrivate::debugPrintSet( Node s
, const char * c
) {
1498 if( s
.getNumChildren()==0 ){
1499 NodeMap::const_iterator it
= d_proxy_to_term
.find( s
);
1500 if( it
!=d_proxy_to_term
.end() ){
1501 debugPrintSet( (*it
).second
, c
);
1506 Trace(c
) << "(" << s
.getOperator();
1507 for( unsigned i
=0; i
<s
.getNumChildren(); i
++ ){
1509 debugPrintSet( s
[i
], c
);
1515 /**************************** TheorySetsPrivate *****************************/
1516 /**************************** TheorySetsPrivate *****************************/
1517 /**************************** TheorySetsPrivate *****************************/
1519 void TheorySetsPrivate::check(Theory::Effort level
) {
1520 Trace("sets-check") << "Sets check effort " << level
<< std::endl
;
1521 while(!d_external
.done() && !d_conflict
) {
1522 // Get all the assertions
1523 Assertion assertion
= d_external
.get();
1524 TNode fact
= assertion
.assertion
;
1525 Trace("sets-assert") << "Assert from input " << fact
<< std::endl
;
1527 assertFact( fact
, fact
);
1529 d_sentLemma
= false;
1530 Trace("sets-check") << "Sets finished assertions effort " << level
<< std::endl
;
1531 if( level
== Theory::EFFORT_FULL
&& !d_conflict
&& !d_external
.d_valuation
.needCheck() ){
1534 // invoke the relational solver
1535 if( !d_conflict
&& !d_sentLemma
){
1536 d_rels
->check(level
);
1537 //incomplete if we have both cardinality constraints and relational operators?
1538 // TODO: should internally check model, return unknown if fail
1539 if( level
== Theory::EFFORT_FULL
&& d_card_enabled
&& d_rels_enabled
){
1540 d_external
.d_out
->setIncomplete();
1543 Trace("sets-check") << "Sets finish Check effort " << level
<< std::endl
;
1544 }/* TheorySetsPrivate::check() */
1547 /************************ Sharing ************************/
1548 /************************ Sharing ************************/
1549 /************************ Sharing ************************/
1551 void TheorySetsPrivate::addSharedTerm(TNode n
) {
1552 Debug("sets") << "[sets] ThoerySetsPrivate::addSharedTerm( " << n
<< ")" << std::endl
;
1553 d_equalityEngine
.addTriggerTerm(n
, THEORY_SETS
);
1556 void TheorySetsPrivate::addCarePairs( quantifiers::TermArgTrie
* t1
, quantifiers::TermArgTrie
* t2
, unsigned arity
, unsigned depth
, unsigned& n_pairs
){
1559 Node f1
= t1
->getNodeData();
1560 Node f2
= t2
->getNodeData();
1561 if( !ee_areEqual( f1
, f2
) ){
1562 Trace("sets-cg") << "Check " << f1
<< " and " << f2
<< std::endl
;
1563 vector
< pair
<TNode
, TNode
> > currentPairs
;
1564 for (unsigned k
= 0; k
< f1
.getNumChildren(); ++ k
) {
1567 Assert( d_equalityEngine
.hasTerm(x
) );
1568 Assert( d_equalityEngine
.hasTerm(y
) );
1569 Assert( !ee_areDisequal( x
, y
) );
1570 if( !d_equalityEngine
.areEqual( x
, y
) ){
1571 Trace("sets-cg") << "Arg #" << k
<< " is " << x
<< " " << y
<< std::endl
;
1572 if( d_equalityEngine
.isTriggerTerm(x
, THEORY_SETS
) && d_equalityEngine
.isTriggerTerm(y
, THEORY_SETS
) ){
1573 TNode x_shared
= d_equalityEngine
.getTriggerTermRepresentative(x
, THEORY_SETS
);
1574 TNode y_shared
= d_equalityEngine
.getTriggerTermRepresentative(y
, THEORY_SETS
);
1575 Trace("sets-cg") << "Arg #" << k
<< " shared term is " << x_shared
<< " " << y_shared
<< std::endl
;
1576 EqualityStatus eqStatus
= d_external
.d_valuation
.getEqualityStatus(x_shared
, y_shared
);
1577 Trace("sets-cg") << "...eq status is " << eqStatus
<< std::endl
;
1578 if( eqStatus
==EQUALITY_FALSE_AND_PROPAGATED
|| eqStatus
==EQUALITY_FALSE
|| eqStatus
==EQUALITY_FALSE_IN_MODEL
){
1579 //an argument is disequal, we are done
1582 currentPairs
.push_back(make_pair(x_shared
, y_shared
));
1584 }else if( isCareArg( f1
, k
) && isCareArg( f2
, k
) ){
1585 //splitting on sets (necessary for handling set of sets properly)
1586 if( x
.getType().isSet() ){
1587 Assert( y
.getType().isSet() );
1588 if( !ee_areDisequal( x
, y
) ){
1589 Trace("sets-cg-lemma") << "Should split on : " << x
<< "==" << y
<< std::endl
;
1590 split( x
.eqNode( y
) );
1596 for (unsigned c
= 0; c
< currentPairs
.size(); ++ c
) {
1597 Trace("sets-cg-pair") << "Pair : " << currentPairs
[c
].first
<< " " << currentPairs
[c
].second
<< std::endl
;
1598 d_external
.addCarePair(currentPairs
[c
].first
, currentPairs
[c
].second
);
1605 if( depth
<(arity
-1) ){
1606 //add care pairs internal to each child
1607 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1608 addCarePairs( &it
->second
, NULL
, arity
, depth
+1, n_pairs
);
1611 //add care pairs based on each pair of non-disequal arguments
1612 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1613 std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= it
;
1615 for( ; it2
!= t1
->d_data
.end(); ++it2
){
1616 if( !ee_areDisequal(it
->first
, it2
->first
) ){
1617 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1622 //add care pairs based on product of indices, non-disequal arguments
1623 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it
= t1
->d_data
.begin(); it
!= t1
->d_data
.end(); ++it
){
1624 for( std::map
< TNode
, quantifiers::TermArgTrie
>::iterator it2
= t2
->d_data
.begin(); it2
!= t2
->d_data
.end(); ++it2
){
1625 if( !ee_areDisequal(it
->first
, it2
->first
) ){
1626 addCarePairs( &it
->second
, &it2
->second
, arity
, depth
+1, n_pairs
);
1634 void TheorySetsPrivate::computeCareGraph() {
1635 for( std::map
< Kind
, std::vector
< Node
> >::iterator it
= d_op_list
.begin(); it
!= d_op_list
.end(); ++it
){
1636 if( it
->first
==kind::SINGLETON
|| it
->first
==kind::MEMBER
){
1637 unsigned n_pairs
= 0;
1638 Trace("sets-cg-summary") << "Compute graph for sets, op=" << it
->first
<< "..." << it
->second
.size() << std::endl
;
1639 Trace("sets-cg") << "Build index for " << it
->first
<< "..." << std::endl
;
1640 std::map
< TypeNode
, quantifiers::TermArgTrie
> index
;
1643 for( unsigned i
=0; i
<it
->second
.size(); i
++ ){
1644 TNode f1
= it
->second
[i
];
1645 Assert(d_equalityEngine
.hasTerm(f1
));
1646 Trace("sets-cg-debug") << "...build for " << f1
<< std::endl
;
1647 //break into index based on operator, and type of first argument (since some operators are parametric)
1648 TypeNode tn
= f1
[0].getType();
1649 std::vector
< TNode
> reps
;
1650 bool hasCareArg
= false;
1651 for( unsigned j
=0; j
<f1
.getNumChildren(); j
++ ){
1652 reps
.push_back( d_equalityEngine
.getRepresentative( f1
[j
] ) );
1653 if( isCareArg( f1
, j
) ){
1658 index
[tn
].addTerm( f1
, reps
);
1659 arity
= reps
.size();
1664 for( std::map
< TypeNode
, quantifiers::TermArgTrie
>::iterator iti
= index
.begin(); iti
!= index
.end(); ++iti
){
1665 Trace("sets-cg") << "Process index " << iti
->first
<< "..." << std::endl
;
1666 addCarePairs( &iti
->second
, NULL
, arity
, 0, n_pairs
);
1669 Trace("sets-cg-summary") << "...done, # pairs = " << n_pairs
<< std::endl
;
1674 bool TheorySetsPrivate::isCareArg( Node n
, unsigned a
) {
1675 if( d_equalityEngine
.isTriggerTerm( n
[a
], THEORY_SETS
) ){
1677 }else if( ( n
.getKind()==kind::MEMBER
|| n
.getKind()==kind::SINGLETON
) && a
==0 && n
[0].getType().isSet() ){
1684 EqualityStatus
TheorySetsPrivate::getEqualityStatus(TNode a
, TNode b
) {
1685 Assert(d_equalityEngine
.hasTerm(a
) && d_equalityEngine
.hasTerm(b
));
1686 if (d_equalityEngine
.areEqual(a
, b
)) {
1687 // The terms are implied to be equal
1688 return EQUALITY_TRUE
;
1690 if (d_equalityEngine
.areDisequal(a
, b
, false)) {
1691 // The terms are implied to be dis-equal
1692 return EQUALITY_FALSE
;
1694 return EQUALITY_UNKNOWN
;
1696 Node aModelValue = d_external.d_valuation.getModelValue(a);
1697 if(aModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1698 Node bModelValue = d_external.d_valuation.getModelValue(b);
1699 if(bModelValue.isNull()) { return EQUALITY_UNKNOWN; }
1700 if( aModelValue == bModelValue ) {
1701 // The term are true in current model
1702 return EQUALITY_TRUE_IN_MODEL;
1704 return EQUALITY_FALSE_IN_MODEL;
1708 // //TODO: can we be more precise sometimes?
1709 // return EQUALITY_UNKNOWN;
1712 /******************** Model generation ********************/
1713 /******************** Model generation ********************/
1714 /******************** Model generation ********************/
1717 void TheorySetsPrivate::collectModelInfo(TheoryModel
* m
, bool fullModel
) {
1718 Trace("sets") << "Set collect model info" << std::endl
;
1719 // Assert equalities and disequalities to the model
1720 m
->assertEqualityEngine(&d_equalityEngine
);
1722 std::map
< Node
, Node
> mvals
;
1723 for( int i
=(int)(d_set_eqc
.size()-1); i
>=0; i
-- ){
1724 Node eqc
= d_set_eqc
[i
];
1725 std::vector
< Node
> els
;
1726 bool is_base
= !d_card_enabled
|| ( d_nf
[eqc
].size()==1 && d_nf
[eqc
][0]==eqc
);
1728 Trace("sets-model") << "Collect elements of base eqc " << eqc
<< std::endl
;
1729 // members that must be in eqc
1730 std::map
< Node
, std::map
< Node
, Node
> >::iterator itm
= d_pol_mems
[0].find( eqc
);
1731 if( itm
!=d_pol_mems
[0].end() ){
1732 for( std::map
< Node
, Node
>::iterator itmm
= itm
->second
.begin(); itmm
!= itm
->second
.end(); ++itmm
){
1733 Node t
= NodeManager::currentNM()->mkNode( kind::SINGLETON
, itmm
->first
);
1738 if( d_card_enabled
){
1739 TypeNode elementType
= eqc
.getType().getSetElementType();
1741 std::map
< Node
, Node
>::iterator it
= d_eqc_to_card_term
.find( eqc
);
1742 if( it
!=d_eqc_to_card_term
.end() ){
1743 //slack elements from cardinality value
1744 Node v
= d_external
.d_valuation
.getModelValue(it
->second
);
1745 Trace("sets-model") << "Cardinality of " << eqc
<< " is " << v
<< std::endl
;
1746 Assert(v
.getConst
<Rational
>() <= LONG_MAX
, "Exceeded LONG_MAX in sets model");
1747 unsigned vu
= v
.getConst
<Rational
>().getNumerator().toUnsignedInt();
1748 Assert( els
.size()<=vu
);
1749 while( els
.size()<vu
){
1750 els
.push_back( NodeManager::currentNM()->mkNode( kind::SINGLETON
, NodeManager::currentNM()->mkSkolem( "msde", elementType
) ) );
1753 Trace("sets-model") << "No slack elements for " << eqc
<< std::endl
;
1756 Trace("sets-model") << "Build value for " << eqc
<< " based on normal form, size = " << d_nf
[eqc
].size() << std::endl
;
1757 //it is union of venn regions
1758 for( unsigned j
=0; j
<d_nf
[eqc
].size(); j
++ ){
1759 Assert( mvals
.find( d_nf
[eqc
][j
] )!=mvals
.end() );
1760 els
.push_back( mvals
[d_nf
[eqc
][j
]] );
1764 Node rep
= NormalForm::mkBop( kind::UNION
, els
, eqc
.getType() );
1765 rep
= Rewriter::rewrite( rep
);
1766 Trace("sets-model") << "Set representative of " << eqc
<< " to " << rep
<< std::endl
;
1768 m
->assertEquality( eqc
, rep
, true );
1769 m
->assertRepresentative( rep
);
1773 /********************** Helper functions ***************************/
1774 /********************** Helper functions ***************************/
1775 /********************** Helper functions ***************************/
1777 void TheorySetsPrivate::addEqualityToExp( Node a
, Node b
, std::vector
< Node
>& exp
) {
1779 Assert( ee_areEqual( a
, b
) );
1780 exp
.push_back( a
.eqNode( b
) );
1784 Node
mkAnd(const std::vector
<TNode
>& conjunctions
) {
1785 Assert(conjunctions
.size() > 0);
1787 std::set
<TNode
> all
;
1788 for (unsigned i
= 0; i
< conjunctions
.size(); ++i
) {
1789 TNode t
= conjunctions
[i
];
1790 if (t
.getKind() == kind::AND
) {
1791 for(TNode::iterator child_it
= t
.begin();
1792 child_it
!= t
.end(); ++child_it
) {
1793 Assert((*child_it
).getKind() != kind::AND
);
1794 all
.insert(*child_it
);
1802 Assert(all
.size() > 0);
1803 if (all
.size() == 1) {
1804 // All the same, or just one
1805 return conjunctions
[0];
1808 NodeBuilder
<> conjunction(kind::AND
);
1809 std::set
<TNode
>::const_iterator it
= all
.begin();
1810 std::set
<TNode
>::const_iterator it_end
= all
.end();
1811 while (it
!= it_end
) {
1820 TheorySetsPrivate::Statistics::Statistics() :
1821 d_getModelValueTime("theory::sets::getModelValueTime")
1822 , d_mergeTime("theory::sets::merge_nodes::time")
1823 , d_processCard2Time("theory::sets::processCard2::time")
1824 , d_memberLemmas("theory::sets::lemmas::member", 0)
1825 , d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
1826 , d_numVertices("theory::sets::vertices", 0)
1827 , d_numVerticesMax("theory::sets::vertices-max", 0)
1828 , d_numMergeEq1or2("theory::sets::merge1or2", 0)
1829 , d_numMergeEq3("theory::sets::merge3", 0)
1830 , d_numLeaves("theory::sets::leaves", 0)
1831 , d_numLeavesMax("theory::sets::leaves-max", 0)
1833 smtStatisticsRegistry()->registerStat(&d_getModelValueTime
);
1834 smtStatisticsRegistry()->registerStat(&d_mergeTime
);
1835 smtStatisticsRegistry()->registerStat(&d_processCard2Time
);
1836 smtStatisticsRegistry()->registerStat(&d_memberLemmas
);
1837 smtStatisticsRegistry()->registerStat(&d_disequalityLemmas
);
1838 smtStatisticsRegistry()->registerStat(&d_numVertices
);
1839 smtStatisticsRegistry()->registerStat(&d_numVerticesMax
);
1840 smtStatisticsRegistry()->registerStat(&d_numMergeEq1or2
);
1841 smtStatisticsRegistry()->registerStat(&d_numMergeEq3
);
1842 smtStatisticsRegistry()->registerStat(&d_numLeaves
);
1843 smtStatisticsRegistry()->registerStat(&d_numLeavesMax
);
1847 TheorySetsPrivate::Statistics::~Statistics() {
1848 smtStatisticsRegistry()->unregisterStat(&d_getModelValueTime
);
1849 smtStatisticsRegistry()->unregisterStat(&d_mergeTime
);
1850 smtStatisticsRegistry()->unregisterStat(&d_processCard2Time
);
1851 smtStatisticsRegistry()->unregisterStat(&d_memberLemmas
);
1852 smtStatisticsRegistry()->unregisterStat(&d_disequalityLemmas
);
1853 smtStatisticsRegistry()->unregisterStat(&d_numVertices
);
1854 smtStatisticsRegistry()->unregisterStat(&d_numVerticesMax
);
1855 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq1or2
);
1856 smtStatisticsRegistry()->unregisterStat(&d_numMergeEq3
);
1857 smtStatisticsRegistry()->unregisterStat(&d_numLeaves
);
1858 smtStatisticsRegistry()->unregisterStat(&d_numLeavesMax
);
1861 void TheorySetsPrivate::propagate(Theory::Effort effort
) {
1865 bool TheorySetsPrivate::propagate(TNode literal
) {
1866 Debug("sets-prop") << " propagate(" << literal
<< ")" << std::endl
;
1868 // If already in conflict, no more propagation
1870 Debug("sets-prop") << "TheoryUF::propagate(" << literal
<< "): already in conflict" << std::endl
;
1875 bool ok
= d_external
.d_out
->propagate(literal
);
1881 }/* TheorySetsPrivate::propagate(TNode) */
1884 void TheorySetsPrivate::setMasterEqualityEngine(eq::EqualityEngine
* eq
) {
1885 d_equalityEngine
.setMasterEqualityEngine(eq
);
1889 void TheorySetsPrivate::conflict(TNode a
, TNode b
)
1891 if (a
.getKind() == kind::CONST_BOOLEAN
) {
1892 d_conflictNode
= explain(a
.iffNode(b
));
1894 d_conflictNode
= explain(a
.eqNode(b
));
1896 d_external
.d_out
->conflict(d_conflictNode
);
1897 Debug("sets") << "[sets] conflict: " << a
<< " iff " << b
1898 << ", explaination " << d_conflictNode
<< std::endl
;
1899 Trace("sets-lemma") << "Equality Conflict : " << d_conflictNode
<< std::endl
;
1903 Node
TheorySetsPrivate::explain(TNode literal
)
1905 Debug("sets") << "TheorySetsPrivate::explain(" << literal
<< ")"
1908 bool polarity
= literal
.getKind() != kind::NOT
;
1909 TNode atom
= polarity
? literal
: literal
[0];
1910 std::vector
<TNode
> assumptions
;
1912 if(atom
.getKind() == kind::EQUAL
|| atom
.getKind() == kind::IFF
) {
1913 d_equalityEngine
.explainEquality(atom
[0], atom
[1], polarity
, assumptions
);
1914 } else if(atom
.getKind() == kind::MEMBER
) {
1915 if( !d_equalityEngine
.hasTerm(atom
)) {
1916 d_equalityEngine
.addTerm(atom
);
1918 d_equalityEngine
.explainPredicate(atom
, polarity
, assumptions
);
1920 Debug("sets") << "unhandled: " << literal
<< "; (" << atom
<< ", "
1921 << polarity
<< "); kind" << atom
.getKind() << std::endl
;
1925 return mkAnd(assumptions
);
1928 void TheorySetsPrivate::preRegisterTerm(TNode node
)
1930 Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node
<< ")"
1932 switch(node
.getKind()) {
1934 // TODO: what's the point of this
1935 d_equalityEngine
.addTriggerEquality(node
);
1938 // TODO: what's the point of this
1939 d_equalityEngine
.addTriggerPredicate(node
);
1942 d_equalityEngine
.addTriggerTerm(node
, THEORY_SETS
);
1945 //if( node.getType().isSet() ){
1946 // d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
1948 d_equalityEngine
.addTerm(node
);
1955 void TheorySetsPrivate::presolve() {
1959 /**************************** eq::NotifyClass *****************************/
1960 /**************************** eq::NotifyClass *****************************/
1961 /**************************** eq::NotifyClass *****************************/
1964 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerEquality(TNode equality
, bool value
)
1966 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerEquality: equality = " << equality
1967 << " value = " << value
<< std::endl
;
1969 return d_theory
.propagate(equality
);
1971 // We use only literal triggers so taking not is safe
1972 return d_theory
.propagate(equality
.notNode());
1976 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerPredicate(TNode predicate
, bool value
)
1978 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerPredicate: predicate = " << predicate
1979 << " value = " << value
<< std::endl
;
1981 return d_theory
.propagate(predicate
);
1983 return d_theory
.propagate(predicate
.notNode());
1987 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag
, TNode t1
, TNode t2
, bool value
)
1989 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerTermEquality: tag = " << tag
1990 << " t1 = " << t1
<< " t2 = " << t2
<< " value = " << value
<< std::endl
;
1991 d_theory
.propagate( value
? t1
.eqNode( t2
) : t1
.eqNode( t2
).negate() );
1995 void TheorySetsPrivate::NotifyClass::eqNotifyConstantTermMerge(TNode t1
, TNode t2
)
1997 Debug("sets-eq") << "[sets-eq] eqNotifyConstantTermMerge " << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
1998 d_theory
.conflict(t1
, t2
);
2001 void TheorySetsPrivate::NotifyClass::eqNotifyNewClass(TNode t
)
2003 Debug("sets-eq") << "[sets-eq] eqNotifyNewClass:" << " t = " << t
<< std::endl
;
2004 d_theory
.eqNotifyNewClass(t
);
2007 void TheorySetsPrivate::NotifyClass::eqNotifyPreMerge(TNode t1
, TNode t2
)
2009 Debug("sets-eq") << "[sets-eq] eqNotifyPreMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2010 d_theory
.eqNotifyPreMerge(t1
, t2
);
2013 void TheorySetsPrivate::NotifyClass::eqNotifyPostMerge(TNode t1
, TNode t2
)
2015 Debug("sets-eq") << "[sets-eq] eqNotifyPostMerge:" << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
2016 d_theory
.eqNotifyPostMerge(t1
, t2
);
2019 void TheorySetsPrivate::NotifyClass::eqNotifyDisequal(TNode t1
, TNode t2
, TNode reason
)
2021 Debug("sets-eq") << "[sets-eq] eqNotifyDisequal:" << " t1 = " << t1
<< " t2 = " << t2
<< " reason = " << reason
<< std::endl
;
2022 d_theory
.eqNotifyDisequal(t1
, t2
, reason
);
2025 }/* CVC4::theory::sets namespace */
2026 }/* CVC4::theory namespace */
2027 }/* CVC4 namespace */