1 /********************* */
2 /*! \file theory_sets_private.cpp
4 ** Original author: Kshitij Bansal
5 ** Major contributors: none
6 ** Minor contributors (to current version): Andrew Reynolds
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2014 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief Sets theory implementation.
14 ** Sets theory implementation.
17 #include <boost/foreach.hpp>
19 #include "theory/theory_model.h"
20 #include "theory/sets/scrutinize.h"
21 #include "theory/sets/theory_sets.h"
22 #include "theory/sets/theory_sets_private.h"
24 #include "theory/sets/options.h"
25 #include "theory/sets/expr_patterns.h" // ONLY included here
27 #include "util/emptyset.h"
28 #include "util/result.h"
31 using namespace CVC4::expr::pattern
;
37 const char* element_of_str
= " \u2208 ";
39 /**************************** TheorySetsPrivate *****************************/
40 /**************************** TheorySetsPrivate *****************************/
41 /**************************** TheorySetsPrivate *****************************/
43 void TheorySetsPrivate::check(Theory::Effort level
) {
45 CodeTimer
checkCodeTimer(d_statistics
.d_checkTime
);
47 while(!d_external
.done() && !d_conflict
) {
48 // Get all the assertions
49 Assertion assertion
= d_external
.get();
50 TNode fact
= assertion
.assertion
;
52 Debug("sets") << "\n\n[sets] TheorySetsPrivate::check(): processing "
55 bool polarity
= fact
.getKind() != kind::NOT
;
56 TNode atom
= polarity
? fact
: fact
[0];
58 if (!assertion
.isPreregistered
) {
59 if (atom
.getKind() == kind::EQUAL
) {
60 if (!d_equalityEngine
.hasTerm(atom
[0])) {
61 Assert(atom
[0].isConst());
62 d_equalityEngine
.addTerm(atom
[0]);
63 d_termInfoManager
->addTerm(atom
[0]);
65 if (!d_equalityEngine
.hasTerm(atom
[1])) {
66 Assert(atom
[1].isConst());
67 d_equalityEngine
.addTerm(atom
[1]);
68 d_termInfoManager
->addTerm(atom
[1]);
74 switch(atom
.getKind()) {
76 Debug("sets") << atom
[0] << " should " << (polarity
? "":"NOT ")
77 << "be equal to " << atom
[1] << std::endl
;
78 assertEquality(fact
, fact
, /* learnt = */ false);
82 Debug("sets") << atom
[0] << " should " << (polarity
? "":"NOT ")
83 << "be in " << atom
[1] << std::endl
;
84 assertMemebership(fact
, fact
, /* learnt = */ false);
88 Unhandled(fact
.getKind());
92 Debug("sets") << "[sets] in conflict = " << d_conflict
<< std::endl
;
93 // Assert( d_conflict ^ d_equalityEngine.consistent() );
94 // ^ doesn't hold when we propagate equality/disequality between shared terms
95 // and that leads to conflict (externally).
96 if(d_conflict
) { return; }
97 Debug("sets") << "[sets] is complete = " << isComplete() << std::endl
;
100 if( (level
== Theory::EFFORT_FULL
|| options::setsEagerLemmas() ) && !isComplete()) {
101 d_external
.d_out
->lemma(getLemma());
105 // if we are here, there is no conflict and we are complete
106 if(Debug
.isOn("sets-scrutinize")) { d_scrutinize
->postCheckInvariants(); }
109 }/* TheorySetsPrivate::check() */
112 void TheorySetsPrivate::assertEquality(TNode fact
, TNode reason
, bool learnt
)
114 Debug("sets-assert") << "\n[sets-assert] adding equality: " << fact
116 << ", " << learnt
<< std::endl
;
118 bool polarity
= fact
.getKind() != kind::NOT
;
119 TNode atom
= polarity
? fact
: fact
[0];
121 // fact already holds
122 if( holds(atom
, polarity
) ) {
123 Debug("sets-assert") << "[sets-assert] already present, skipping" << std::endl
;
127 // assert fact & check for conflict
129 registerReason(reason
, /*save=*/ true);
131 d_equalityEngine
.assertEquality(atom
, polarity
, reason
);
133 if(!d_equalityEngine
.consistent()) {
134 Debug("sets-assert") << "[sets-assert] running into a conflict" << std::endl
;
139 if(!polarity
&& atom
[0].getType().isSet()) {
143 }/* TheorySetsPrivate::assertEquality() */
146 void TheorySetsPrivate::assertMemebership(TNode fact
, TNode reason
, bool learnt
)
148 Debug("sets-assert") << "\n[sets-assert] adding membership: " << fact
150 << ", " << learnt
<< std::endl
;
152 bool polarity
= fact
.getKind() == kind::NOT
? false : true;
153 TNode atom
= polarity
? fact
: fact
[0];
155 // fact already holds
156 if( holds(atom
, polarity
) ) {
157 Debug("sets-assert") << "[sets-assert] already present, skipping" << std::endl
;
161 // assert fact & check for conflict
163 registerReason(reason
, true);
165 d_equalityEngine
.assertPredicate(atom
, polarity
, reason
);
167 if(!d_equalityEngine
.consistent()) {
168 Debug("sets-assert") << "[sets-assert] running into a conflict" << std::endl
;
173 // update term info data structures
174 d_termInfoManager
->notifyMembership(fact
);
177 TNode x
= d_equalityEngine
.getRepresentative(atom
[0]);
178 eq::EqClassIterator
j(d_equalityEngine
.getRepresentative(atom
[1]),
181 Node cur_atom
= MEMBER(x
, S
);
184 * It is sufficient to do emptyset propagation outside the loop as
185 * constant term is guaranteed to be class representative.
187 if(polarity
&& S
.getKind() == kind::EMPTYSET
) {
188 Debug("sets-prop") << "[sets-prop] something in empty set? conflict."
190 learnLiteral(cur_atom
, false, cur_atom
);
196 * Disequality propagation if element type is set
198 if(x
.getType().isSet()) {
200 const CDTNodeList
* l
= d_termInfoManager
->getNonMembers(S
);
201 for(typeof(l
->begin()) it
= l
->begin(); it
!= l
->end(); ++it
) {
203 learnLiteral( /* atom = */ EQUAL(x
, n
),
204 /* polarity = */ false,
205 /* reason = */ AND( MEMBER(x
, S
), NOT( MEMBER(n
, S
)) ) );
208 const CDTNodeList
* l
= d_termInfoManager
->getMembers(S
);
209 for(typeof(l
->begin()) it
= l
->begin(); it
!= l
->end(); ++it
) {
211 learnLiteral( /* atom = */ EQUAL(x
, n
),
212 /* polarity = */ false,
213 /* reason = */ AND( NOT(MEMBER(x
, S
)), MEMBER(n
, S
)) );
218 for(; !j
.isFinished(); ++j
) {
220 Node cur_atom
= MEMBER(x
, S
);
222 // propagation : children
223 Debug("sets-prop") << "[sets-prop] Propagating 'down' for "
224 << x
<< element_of_str
<< S
<< std::endl
;
225 if(S
.getKind() == kind::UNION
||
226 S
.getKind() == kind::INTERSECTION
||
227 S
.getKind() == kind::SETMINUS
||
228 S
.getKind() == kind::SINGLETON
) {
229 doSettermPropagation(x
, S
);
230 if(d_conflict
) return;
231 }// propagation: children
234 // propagation : parents
235 Debug("sets-prop") << "[sets-prop] Propagating 'up' for "
236 << x
<< element_of_str
<< S
<< std::endl
;
237 const CDTNodeList
* parentList
= d_termInfoManager
->getParents(S
);
238 for(typeof(parentList
->begin()) k
= parentList
->begin();
239 k
!= parentList
->end(); ++k
) {
240 doSettermPropagation(x
, *k
);
241 if(d_conflict
) return;
242 }// propagation : parents
247 }/* TheorySetsPrivate::assertMemebership() */
250 void TheorySetsPrivate::doSettermPropagation(TNode x
, TNode S
)
252 Debug("sets-prop") << "[sets-prop] doSettermPropagation("
253 << x
<< ", " << S
<< std::endl
;
255 Assert(S
.getType().isSet() && S
.getType().getSetElementType() == x
.getType(),
256 ( std::string("types of S and x are ") + S
.getType().toString() +
257 std::string(" and ") + x
.getType().toString() +
258 std::string(" respectively") ).c_str() );
260 Node literal
, left_literal
, right_literal
;
262 // axiom: literal <=> left_literal AND right_literal
263 switch(S
.getKind()) {
264 case kind::INTERSECTION
:
265 literal
= MEMBER(x
, S
) ;
266 left_literal
= MEMBER(x
, S
[0]) ;
267 right_literal
= MEMBER(x
, S
[1]) ;
270 literal
= NOT( MEMBER(x
, S
) );
271 left_literal
= NOT( MEMBER(x
, S
[0]) );
272 right_literal
= NOT( MEMBER(x
, S
[1]) );
275 literal
= MEMBER(x
, S
) ;
276 left_literal
= MEMBER(x
, S
[0]) ;
277 right_literal
= NOT( MEMBER(x
, S
[1]) );
279 case kind::SINGLETON
: {
280 Node atom
= MEMBER(x
, S
);
281 if(holds(atom
, true)) {
282 learnLiteral(EQUAL(x
, S
[0]), true, atom
);
283 } else if(holds(atom
, false)) {
284 learnLiteral(EQUAL(x
, S
[0]), false, NOT(atom
));
292 Debug("sets-prop-details")
293 << "[sets-prop-details] " << literal
<< " IFF " << left_literal
294 << " AND " << right_literal
<< std::endl
;
296 Debug("sets-prop-details")
297 << "[sets-prop-details] "
298 << (holds(literal
) ? "yes" : (holds(literal
.negate()) ? " no" : " _ "))
300 << (holds(left_literal
) ? "yes" : (holds(left_literal
.negate()) ? "no " : " _ "))
302 << (holds(right_literal
) ? "yes" : (holds(right_literal
.negate()) ? "no " : " _ "))
305 Assert( present( MEMBER(x
, S
) ) ||
306 present( MEMBER(x
, S
[0]) ) ||
307 present( MEMBER(x
, S
[1]) ) );
309 if( holds(literal
) ) {
310 // 1a. literal => left_literal
311 Debug("sets-prop") << "[sets-prop] ... via case 1a. ..." << std::endl
;
312 learnLiteral(left_literal
, literal
);
313 if(d_conflict
) return;
315 // 1b. literal => right_literal
316 Debug("sets-prop") << "[sets-prop] ... via case 1b. ..." << std::endl
;
317 learnLiteral(right_literal
, literal
);
318 if(d_conflict
) return;
320 // subsumption requirement met, exit
323 else if( holds(literal
.negate() ) ) {
324 // 4. neg(literal), left_literal => neg(right_literal)
325 if( holds(left_literal
) ) {
326 Debug("sets-prop") << "[sets-prop] ... via case 4. ..." << std::endl
;
327 learnLiteral(right_literal
.negate(), AND( literal
.negate(),
329 if(d_conflict
) return;
332 // 5. neg(literal), right_literal => neg(left_literal)
333 if( holds(right_literal
) ) {
334 Debug("sets-prop") << "[sets-prop] ... via case 5. ..." << std::endl
;
335 learnLiteral(left_literal
.negate(), AND( literal
.negate(),
337 if(d_conflict
) return;
341 // 2,3. neg(left_literal) v neg(right_literal) => neg(literal)
342 if(holds(left_literal
.negate())) {
343 Debug("sets-prop") << "[sets-prop] ... via case 2. ..." << std::endl
;
344 learnLiteral(literal
.negate(), left_literal
.negate());
345 if(d_conflict
) return;
347 else if(holds(right_literal
.negate())) {
348 Debug("sets-prop") << "[sets-prop] ... via case 3. ..." << std::endl
;
349 learnLiteral(literal
.negate(), right_literal
.negate());
350 if(d_conflict
) return;
353 // 6. the axiom itself:
354 else if(holds(left_literal
) && holds(right_literal
)) {
355 Debug("sets-prop") << "[sets-prop] ... via case 6. ..." << std::endl
;
356 learnLiteral(literal
, AND(left_literal
, right_literal
) );
357 if(d_conflict
) return;
361 // check fulfilling rule
363 switch(S
.getKind()) {
365 if( holds(MEMBER(x
, S
)) &&
366 !present( MEMBER(x
, S
[0]) ) )
367 addToPending( MEMBER(x
, S
[0]) );
369 case kind::SETMINUS
: // intentional fallthrough
370 case kind::INTERSECTION
:
371 if( holds(MEMBER(x
, S
[0])) &&
372 !present( MEMBER(x
, S
[1]) ))
373 addToPending( MEMBER(x
, S
[1]) );
376 Assert(false, "MembershipEngine::doSettermPropagation");
381 void TheorySetsPrivate::learnLiteral(TNode atom
, bool polarity
, Node reason
) {
382 Debug("sets-learn") << "[sets-learn] learnLiteral(" << atom
383 << ", " << polarity
<< ")" << std::endl
;
385 if( holds(atom
, polarity
) ) {
386 Debug("sets-learn") << "[sets-learn] \u2514 already known, skipping" << std::endl
;
390 if( holds(atom
, !polarity
) ) {
391 Debug("sets-learn") << "[sets-learn] \u2514 conflict found" << std::endl
;
393 registerReason(reason
, /*save=*/ true);
395 if(atom
.getKind() == kind::EQUAL
) {
396 d_equalityEngine
.assertEquality(atom
, polarity
, reason
);
398 d_equalityEngine
.assertPredicate(atom
, polarity
, reason
);
400 Assert(d_conflict
); // should be marked due to equality engine
404 Assert(atom
.getKind() == kind::EQUAL
|| atom
.getKind() == kind::MEMBER
);
406 Node learnt_literal
= polarity
? Node(atom
) : NOT(atom
);
407 d_propagationQueue
.push_back( make_pair(learnt_literal
, reason
) );
408 }/*TheorySetsPrivate::learnLiteral(...)*/
411 /************************ Sharing ************************/
412 /************************ Sharing ************************/
413 /************************ Sharing ************************/
415 void TheorySetsPrivate::addSharedTerm(TNode n
) {
416 Debug("sets") << "[sets] ThoerySetsPrivate::addSharedTerm( " << n
<< ")" << std::endl
;
417 d_termInfoManager
->addTerm(n
);
418 d_equalityEngine
.addTriggerTerm(n
, THEORY_SETS
);
421 void TheorySetsPrivate::dumpAssertionsHumanified() const
423 std::string tag
= "sets-assertions";
425 if(Trace
.isOn(tag
)) { /* condition can't be !Trace.isOn, that's why this empty block */ }
428 context::CDList
<Assertion
>::const_iterator it
= d_external
.facts_begin(), it_end
= d_external
.facts_end();
430 std::map
<TNode
, std::set
<TNode
> > equalities
;
431 std::set
< pair
<TNode
, TNode
> > disequalities
;
432 std::map
<TNode
, std::pair
<std::set
<TNode
>, std::set
<TNode
> > > members
;
433 static std::map
<TNode
, int> numbering
;
434 static int number
= 0;
436 for (unsigned i
= 0; it
!= it_end
; ++ it
, ++i
) {
437 TNode ass
= (*it
).assertion
;
438 // Trace("sets-care-dump") << AssertCommand(ass.toExpr()) << endl;
439 bool polarity
= ass
.getKind() != kind::NOT
;
440 ass
= polarity
? ass
: ass
[0];
441 Assert( ass
.getNumChildren() == 2);
442 TNode left
= d_equalityEngine
.getRepresentative(ass
[0]);
443 TNode right
= d_equalityEngine
.getRepresentative(ass
[1]);
444 if(numbering
[left
] == 0) numbering
[left
] = ++number
;
445 if(numbering
[right
] == 0) numbering
[right
] = ++number
;
446 equalities
[left
].insert(ass
[0]);
447 equalities
[right
].insert(ass
[1]);
448 if(ass
.getKind() == kind::EQUAL
) {
450 Assert(left
== right
);
452 if(left
> right
) std::swap(left
, right
);
453 disequalities
.insert(make_pair(left
, right
));
455 } else if(ass
.getKind() == kind::MEMBER
) {
456 (polarity
? members
[right
].first
: members
[right
].second
).insert(left
);
459 #define FORIT(it, container) for(typeof((container).begin()) it=(container).begin(); (it) != (container).end(); ++(it))
460 FORIT(kt
, equalities
) {
461 Trace(tag
) << " Eq class of t" << numbering
[(*kt
).first
] << ": " << std::endl
;
462 FORIT(jt
, (*kt
).second
) {
464 if( S
.getKind() != kind::UNION
&& S
.getKind() != kind::INTERSECTION
&& S
.getKind() != kind::SETMINUS
) {
465 Trace(tag
) << " " << *jt
<< ((*jt
).getType().isSet() ? "\n": " ");
468 if(S
[0].isConst() || numbering
.find(d_equalityEngine
.getRepresentative(S
[0])) == numbering
.end()) {
471 Trace(tag
) << "t" << numbering
[d_equalityEngine
.getRepresentative(S
[0])];
473 Trace(tag
) << " " << (S
.getKind() == kind::UNION
? "|" : (S
.getKind() == kind::INTERSECTION
? "&" : "-")) << " ";
474 if(S
[1].isConst() || numbering
.find(d_equalityEngine
.getRepresentative(S
[1])) == numbering
.end()) {
477 Trace(tag
) << "t" << numbering
[d_equalityEngine
.getRepresentative(S
[1])];
479 Trace(tag
) << std::endl
;
482 Trace(tag
) << std::endl
;
484 FORIT(kt
, disequalities
) Trace(tag
) << "NOT(t"<<numbering
[(*kt
).first
]<<" = t" <<numbering
[(*kt
).second
] <<")"<< std::endl
;
486 if( (*kt
).second
.first
.size() > 0) {
487 Trace(tag
) << "IN t" << numbering
[(*kt
).first
] << ": ";
488 FORIT(jt
, (*kt
).second
.first
) {
490 if(x
.isConst() || numbering
.find(d_equalityEngine
.getRepresentative(x
)) == numbering
.end()) {
491 Trace(tag
) << x
<< ", ";
493 Trace(tag
) << "t" << numbering
[d_equalityEngine
.getRepresentative(x
)] << ", ";
496 Trace(tag
) << std::endl
;
498 if( (*kt
).second
.second
.size() > 0) {
499 Trace(tag
) << "NOT IN t" << numbering
[(*kt
).first
] << ": ";
500 FORIT(jt
, (*kt
).second
.second
) {
502 if(x
.isConst() || numbering
.find(d_equalityEngine
.getRepresentative(x
)) == numbering
.end()) {
503 Trace(tag
) << x
<< ", ";
505 Trace(tag
) << "t" << numbering
[d_equalityEngine
.getRepresentative(x
)] << ", ";
508 Trace(tag
) << std::endl
;
511 Trace(tag
) << std::endl
;
515 void TheorySetsPrivate::computeCareGraph() {
516 Debug("sharing") << "Theory::computeCareGraph<" << d_external
.identify() << ">()" << endl
;
518 if(Trace
.isOn("sets-assertions")) {
519 // dump our understanding of assertions
520 dumpAssertionsHumanified();
523 CVC4_UNUSED
unsigned edgesAddedCnt
= 0;
526 if(options::setsCare1()) { i_st
= d_ccg_i
; }
527 for (unsigned i
= i_st
; i
< d_external
.d_sharedTerms
.size(); ++ i
) {
528 TNode a
= d_external
.d_sharedTerms
[i
];
529 TypeNode aType
= a
.getType();
531 unsigned j_st
= i
+ 1;
532 if(options::setsCare1()) { if(i
== d_ccg_i
) j_st
= d_ccg_j
+ 1; }
534 for (unsigned j
= j_st
; j
< d_external
.d_sharedTerms
.size(); ++ j
) {
535 TNode b
= d_external
.d_sharedTerms
[j
];
536 if (b
.getType() != aType
) {
537 // We don't care about the terms of different types
541 switch (d_external
.d_valuation
.getEqualityStatus(a
, b
)) {
542 case EQUALITY_TRUE_AND_PROPAGATED
:
543 // If we know about it, we should have propagated it, so we can skip
544 Trace("sets-care") << "[sets-care] Know: " << EQUAL(a
, b
) << std::endl
;
546 case EQUALITY_FALSE_AND_PROPAGATED
:
547 // If we know about it, we should have propagated it, so we can skip
548 Trace("sets-care") << "[sets-care] Know: " << NOT(EQUAL(a
, b
)) << std::endl
;
552 Assert(false, "ERROR: Equality status true/false but not propagated (sets care graph computation).");
554 case EQUALITY_TRUE_IN_MODEL
:
555 d_external
.addCarePair(a
, b
);
556 if(Trace
.isOn("sharing")) {
559 if(Debug
.isOn("sets-care")) {
560 Debug("sets-care") << "[sets-care] Requesting split between" << a
<< " and "
561 << b
<< "." << std::endl
<< "[sets-care] "
562 << " Both current have value "
563 << d_external
.d_valuation
.getModelValue(a
) << std::endl
;
565 case EQUALITY_FALSE_IN_MODEL
:
566 if(Trace
.isOn("sets-care-performance-test")) {
567 // TODO: delete these lines, only for performance testing for now
568 d_external
.addCarePair(a
, b
);
571 case EQUALITY_UNKNOWN
:
573 d_external
.addCarePair(a
, b
);
574 if(options::setsCare1()) {
585 Trace("sharing") << "TheorySetsPrivate::computeCareGraph(): size = " << edgesAddedCnt
<< std::endl
;
588 EqualityStatus
TheorySetsPrivate::getEqualityStatus(TNode a
, TNode b
) {
589 Assert(d_equalityEngine
.hasTerm(a
) && d_equalityEngine
.hasTerm(b
));
590 if (d_equalityEngine
.areEqual(a
, b
)) {
591 // The terms are implied to be equal
592 return EQUALITY_TRUE
;
594 if (d_equalityEngine
.areDisequal(a
, b
, false)) {
595 // The terms are implied to be dis-equal
596 return EQUALITY_FALSE
;
598 if( d_external
.d_valuation
.getModelValue(a
) == d_external
.d_valuation
.getModelValue(b
) ) {
599 // Ther term are true in current model
600 return EQUALITY_TRUE_IN_MODEL
;
602 return EQUALITY_FALSE_IN_MODEL
;
604 // //TODO: can we be more precise sometimes?
605 // return EQUALITY_UNKNOWN;
608 /******************** Model generation ********************/
609 /******************** Model generation ********************/
610 /******************** Model generation ********************/
612 const TheorySetsPrivate::Elements
& TheorySetsPrivate::getElements
613 (TNode setterm
, SettermElementsMap
& settermElementsMap
) const {
614 SettermElementsMap::const_iterator it
= settermElementsMap
.find(setterm
);
615 bool alreadyCalculated
= (it
!= settermElementsMap
.end());
616 if( !alreadyCalculated
) {
618 Kind k
= setterm
.getKind();
623 const Elements
& left
= getElements(setterm
[0], settermElementsMap
);
624 const Elements
& right
= getElements(setterm
[1], settermElementsMap
);
625 if(left
.size() >= right
.size()) {
626 cur
= left
; cur
.insert(right
.begin(), right
.end());
628 cur
= right
; cur
.insert(left
.begin(), left
.end());
632 case kind::INTERSECTION
: {
633 const Elements
& left
= getElements(setterm
[0], settermElementsMap
);
634 const Elements
& right
= getElements(setterm
[1], settermElementsMap
);
635 std::set_intersection(left
.begin(), left
.end(), right
.begin(), right
.end(),
636 std::inserter(cur
, cur
.begin()) );
639 case kind::SETMINUS
: {
640 const Elements
& left
= getElements(setterm
[0], settermElementsMap
);
641 const Elements
& right
= getElements(setterm
[1], settermElementsMap
);
642 std::set_difference(left
.begin(), left
.end(), right
.begin(), right
.end(),
643 std::inserter(cur
, cur
.begin()) );
647 Assert(theory::kindToTheoryId(k
) != theory::THEORY_SETS
,
648 (std::string("Kind belonging to set theory not explicitly handled: ") + kindToString(k
)).c_str());
649 // Assert(k == kind::VARIABLE || k == kind::APPLY_UF || k == kind::SKOLEM,
650 // (std::string("Expect variable or UF got ") + kindToString(k)).c_str() );
651 /* assign emptyset, which is default */
654 it
= settermElementsMap
.insert(SettermElementsMap::value_type(setterm
, cur
)).first
;
660 bool TheorySetsPrivate::checkModel(const SettermElementsMap
& settermElementsMap
, TNode S
) const {
662 Debug("sets-model") << "[sets-model] checkModel(..., " << S
<< "): "
665 Assert(S
.getType().isSet());
667 const Elements emptySetOfElements
;
668 const Elements
& saved
=
669 d_equalityEngine
.getRepresentative(S
).getKind() == kind::EMPTYSET
||
670 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
)) == settermElementsMap
.end() ?
672 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
))->second
;
673 Debug("sets-model") << "[sets-model] saved : { ";
674 BOOST_FOREACH(TNode element
, saved
) { Debug("sets-model") << element
<< ", "; }
675 Debug("sets-model") << " }" << std::endl
;
677 if(theory::kindToTheoryId(S
.getKind()) == THEORY_SETS
&& S
.getNumChildren() == 2) {
681 const Elements
& left
=
682 d_equalityEngine
.getRepresentative(S
[0]).getKind() == kind::EMPTYSET
||
683 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
[0])) == settermElementsMap
.end() ?
685 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
[0]))->second
;
687 const Elements
& right
=
688 d_equalityEngine
.getRepresentative(S
[1]).getKind() == kind::EMPTYSET
||
689 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
[1])) == settermElementsMap
.end() ?
691 settermElementsMap
.find(d_equalityEngine
.getRepresentative(S
[1]))->second
;
693 switch(S
.getKind()) {
695 if(left
.size() >= right
.size()) {
696 cur
= left
; cur
.insert(right
.begin(), right
.end());
698 cur
= right
; cur
.insert(left
.begin(), left
.end());
701 case kind::INTERSECTION
:
702 std::set_intersection(left
.begin(), left
.end(), right
.begin(), right
.end(),
703 std::inserter(cur
, cur
.begin()) );
706 std::set_difference(left
.begin(), left
.end(), right
.begin(), right
.end(),
707 std::inserter(cur
, cur
.begin()) );
713 Debug("sets-model") << "[sets-model] cur : { ";
714 BOOST_FOREACH(TNode element
, cur
) { Debug("sets-model") << element
<< ", "; }
715 Debug("sets-model") << " }" << std::endl
;
718 Debug("sets-model") << "[sets-model] *** ERROR *** cur != saved "
721 << "[sets-model] FYI: "
722 << " [" << S
<< "] = " << d_equalityEngine
.getRepresentative(S
) << ", "
723 << " [" << S
[0] << "] = " << d_equalityEngine
.getRepresentative(S
[0]) << ", "
724 << " [" << S
[1] << "] = " << d_equalityEngine
.getRepresentative(S
[1]) << "\n";
732 Node
TheorySetsPrivate::elementsToShape(Elements elements
, TypeNode setType
) const
734 NodeManager
* nm
= NodeManager::currentNM();
736 if(elements
.size() == 0) {
737 return nm
->mkConst(EmptySet(nm
->toType(setType
)));
739 Elements::iterator it
= elements
.begin();
740 Node cur
= SINGLETON(*it
);
741 while( ++it
!= elements
.end() ) {
742 cur
= nm
->mkNode(kind::UNION
, cur
, SINGLETON(*it
));
747 Node
TheorySetsPrivate::elementsToShape(set
<Node
> elements
, TypeNode setType
) const
749 NodeManager
* nm
= NodeManager::currentNM();
751 if(elements
.size() == 0) {
752 return nm
->mkConst(EmptySet(nm
->toType(setType
)));
754 typeof(elements
.begin()) it
= elements
.begin();
755 Node cur
= SINGLETON(*it
);
756 while( ++it
!= elements
.end() ) {
757 cur
= nm
->mkNode(kind::UNION
, cur
, SINGLETON(*it
));
763 void TheorySetsPrivate::collectModelInfo(TheoryModel
* m
, bool fullModel
)
765 Debug("sets-model") << "[sets-model] collectModelInfo(..., fullModel="
766 << (fullModel
? "true)" : "false)") << std::endl
;
770 // Compute terms appearing assertions and shared terms
771 d_external
.computeRelevantTerms(terms
);
773 // Compute for each setterm elements that it contains
774 SettermElementsMap settermElementsMap
;
775 TNode true_atom
= NodeManager::currentNM()->mkConst
<bool>(true);
776 TNode false_atom
= NodeManager::currentNM()->mkConst
<bool>(false);
777 for(eq::EqClassIterator
it_eqclasses(true_atom
, &d_equalityEngine
);
778 ! it_eqclasses
.isFinished() ; ++it_eqclasses
) {
779 TNode n
= (*it_eqclasses
);
780 if(n
.getKind() == kind::MEMBER
) {
781 Assert(d_equalityEngine
.areEqual(n
, true_atom
));
782 TNode x
= d_equalityEngine
.getRepresentative(n
[0]);
783 TNode S
= d_equalityEngine
.getRepresentative(n
[1]);
784 settermElementsMap
[S
].insert(x
);
786 if(Debug
.isOn("sets-model-details")) {
787 vector
<TNode
> explanation
;
788 d_equalityEngine
.explainPredicate(n
, true, explanation
);
789 Debug("sets-model-details")
790 << "[sets-model-details] > node: " << n
<< ", explanation:" << std::endl
;
791 BOOST_FOREACH(TNode m
, explanation
) {
792 Debug("sets-model-details") << "[sets-model-details] >> " << m
<< std::endl
;
797 if(Debug
.isOn("sets-model-details")) {
798 for(eq::EqClassIterator
it_eqclasses(false_atom
, &d_equalityEngine
);
799 ! it_eqclasses
.isFinished() ; ++it_eqclasses
) {
800 TNode n
= (*it_eqclasses
);
801 vector
<TNode
> explanation
;
802 d_equalityEngine
.explainPredicate(n
, false, explanation
);
803 Debug("sets-model-details")
804 << "[sets-model-details] > node: not: " << n
<< ", explanation:" << std::endl
;
805 BOOST_FOREACH(TNode m
, explanation
) {
806 Debug("sets-model-details") << "[sets-model-details] >> " << m
<< std::endl
;
811 // Assert equalities and disequalities to the model
812 m
->assertEqualityEngine(&d_equalityEngine
, &terms
);
814 // Loop over terms to collect set-terms for which we generate models
815 set
<Node
> settermsModEq
;
816 BOOST_FOREACH(TNode term
, terms
) {
817 TNode n
= term
.getKind() == kind::NOT
? term
[0] : term
;
819 Debug("sets-model-details") << "[sets-model-details] > " << n
<< std::endl
;
821 if(n
.getType().isSet()) {
822 n
= d_equalityEngine
.getRepresentative(n
);
824 settermsModEq
.insert(n
);
830 if(Debug
.isOn("sets-model")) {
831 BOOST_FOREACH( TNode node
, settermsModEq
) {
832 Debug("sets-model") << "[sets-model] " << node
<< std::endl
;
836 BOOST_FOREACH( SettermElementsMap::value_type
&it
, settermElementsMap
) {
837 BOOST_FOREACH( TNode element
, it
.second
/* elements */ ) {
838 Debug("sets-model-details") << "[sets-model-details] > " <<
839 (it
.first
/* setterm */) << ": " << element
<< std::endl
;
843 // assign representatives to equivalence class
844 BOOST_FOREACH( TNode setterm
, settermsModEq
) {
845 Elements elements
= getElements(setterm
, settermElementsMap
);
846 Node shape
= elementsToShape(elements
, setterm
.getType());
847 shape
= theory::Rewriter::rewrite(shape
);
848 m
->assertEquality(shape
, setterm
, true);
849 m
->assertRepresentative(shape
);
852 #ifdef CVC4_ASSERTIONS
853 bool checkPassed
= true;
854 BOOST_FOREACH(TNode term
, terms
) {
855 if( term
.getType().isSet() ) {
856 checkPassed
&= checkModel(settermElementsMap
, term
);
859 if(Debug
.isOn("sets-checkmodel-ignore")) {
860 Debug("sets-checkmodel-ignore") << "[sets-checkmodel-ignore] checkPassed value was " << checkPassed
<< std::endl
;
863 "THEORY_SETS check-model failed. Run with -d sets-model for details." );
868 Node
TheorySetsPrivate::getModelValue(TNode n
)
870 CodeTimer
codeTimer(d_statistics
.d_getModelValueTime
);
871 return d_termInfoManager
->getModelValue(n
);
874 /********************** Helper functions ***************************/
875 /********************** Helper functions ***************************/
876 /********************** Helper functions ***************************/
878 Node
mkAnd(const std::vector
<TNode
>& conjunctions
) {
879 Assert(conjunctions
.size() > 0);
883 for (unsigned i
= 0; i
< conjunctions
.size(); ++i
) {
884 TNode t
= conjunctions
[i
];
886 if (t
.getKind() == kind::AND
) {
887 for(TNode::iterator child_it
= t
.begin();
888 child_it
!= t
.end(); ++child_it
) {
889 Assert((*child_it
).getKind() != kind::AND
);
890 all
.insert(*child_it
);
899 Assert(all
.size() > 0);
901 if (all
.size() == 1) {
902 // All the same, or just one
903 return conjunctions
[0];
906 NodeBuilder
<> conjunction(kind::AND
);
907 std::set
<TNode
>::const_iterator it
= all
.begin();
908 std::set
<TNode
>::const_iterator it_end
= all
.end();
909 while (it
!= it_end
) {
918 TheorySetsPrivate::Statistics::Statistics() :
919 d_checkTime("theory::sets::time")
920 , d_getModelValueTime("theory::sets::getModelValueTime")
921 , d_memberLemmas("theory::sets::lemmas::member", 0)
922 , d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
924 StatisticsRegistry::registerStat(&d_checkTime
);
925 StatisticsRegistry::registerStat(&d_getModelValueTime
);
926 StatisticsRegistry::registerStat(&d_memberLemmas
);
927 StatisticsRegistry::registerStat(&d_disequalityLemmas
);
931 TheorySetsPrivate::Statistics::~Statistics() {
932 StatisticsRegistry::unregisterStat(&d_checkTime
);
933 StatisticsRegistry::unregisterStat(&d_getModelValueTime
);
934 StatisticsRegistry::unregisterStat(&d_memberLemmas
);
935 StatisticsRegistry::unregisterStat(&d_disequalityLemmas
);
939 bool TheorySetsPrivate::present(TNode atom
) {
940 return holds(atom
) || holds(atom
.notNode());
944 bool TheorySetsPrivate::holds(TNode atom
, bool polarity
) {
945 Node polarity_atom
= NodeManager::currentNM()->mkConst
<bool>(polarity
);
947 Node atomModEq
= NodeManager::currentNM()->mkNode
948 (atom
.getKind(), d_equalityEngine
.getRepresentative(atom
[0]),
949 d_equalityEngine
.getRepresentative(atom
[1]) );
951 d_equalityEngine
.addTerm(atomModEq
);
953 return d_equalityEngine
.areEqual(atomModEq
, polarity_atom
);
957 void TheorySetsPrivate::registerReason(TNode reason
, bool save
)
959 if(save
) d_nodeSaver
.insert(reason
);
961 if(reason
.getKind() == kind::AND
) {
962 Assert(reason
.getNumChildren() == 2);
963 registerReason(reason
[0], false);
964 registerReason(reason
[1], false);
965 } else if(reason
.getKind() == kind::NOT
) {
966 registerReason(reason
[0], false);
967 } else if(reason
.getKind() == kind::MEMBER
) {
968 d_equalityEngine
.addTerm(reason
);
969 Assert(present(reason
));
970 } else if(reason
.getKind() == kind::EQUAL
) {
971 d_equalityEngine
.addTerm(reason
);
972 Assert(present(reason
));
973 } else if(reason
.getKind() == kind::CONST_BOOLEAN
) {
974 // That's OK, already in EqEngine
980 void TheorySetsPrivate::finishPropagation()
982 while(!d_conflict
&& !d_settermPropagationQueue
.empty()) {
983 std::pair
<TNode
,TNode
> np
= d_settermPropagationQueue
.front();
984 d_settermPropagationQueue
.pop();
985 doSettermPropagation(np
.first
, np
.second
);
987 while(!d_conflict
&& !d_propagationQueue
.empty()) {
988 std::pair
<Node
,Node
> np
= d_propagationQueue
.front();
989 d_propagationQueue
.pop();
990 TNode atom
= np
.first
.getKind() == kind::NOT
? np
.first
[0] : np
.first
;
991 if(atom
.getKind() == kind::MEMBER
) {
992 assertMemebership(np
.first
, np
.second
, /* learnt = */ true);
994 assertEquality(np
.first
, np
.second
, /* learnt = */ true);
999 void TheorySetsPrivate::addToPending(Node n
) {
1000 Debug("sets-pending") << "[sets-pending] addToPending " << n
<< std::endl
;
1001 if(d_pendingEverInserted
.find(n
) == d_pendingEverInserted
.end()) {
1002 if(n
.getKind() == kind::MEMBER
) {
1003 Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
1005 ++d_statistics
.d_memberLemmas
;
1008 Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
1010 Assert(n
.getKind() == kind::EQUAL
);
1011 ++d_statistics
.d_disequalityLemmas
;
1012 d_pendingDisequal
.push(n
);
1014 d_external
.d_out
->lemma(getLemma());
1015 Assert(isComplete());
1019 bool TheorySetsPrivate::isComplete() {
1020 // while(!d_pending.empty() &&
1021 // (d_pendingEverInserted.find(d_pending.front()) != d_pendingEverInserted.end()
1022 // || present(d_pending.front()) ) ) {
1023 // Debug("sets-pending") << "[sets-pending] removing as already present: "
1024 // << d_pending.front() << std::endl;
1027 return d_pending
.empty() && d_pendingDisequal
.empty();
1030 Node
TheorySetsPrivate::getLemma() {
1031 Assert(!d_pending
.empty() || !d_pendingDisequal
.empty());
1035 if(!d_pending
.empty()) {
1036 n
= d_pending
.front();
1038 d_pendingEverInserted
.insert(n
);
1040 Assert(!present(n
));
1041 Assert(n
.getKind() == kind::MEMBER
);
1043 lemma
= OR(n
, NOT(n
));
1045 n
= d_pendingDisequal
.front();
1046 d_pendingDisequal
.pop();
1047 d_pendingEverInserted
.insert(n
);
1049 Assert(n
.getKind() == kind::EQUAL
&& n
[0].getType().isSet());
1050 Node x
= NodeManager::currentNM()->mkSkolem("sde_", n
[0].getType().getSetElementType() );
1051 Node l1
= MEMBER(x
, n
[0]), l2
= MEMBER(x
, n
[1]);
1053 lemma
= OR(n
, AND(l1
, NOT(l2
)), AND(NOT(l1
), l2
));
1056 Debug("sets-lemma") << "[sets-lemma] Generating for " << n
<< ", lemma: " << lemma
<< std::endl
;
1062 TheorySetsPrivate::TheorySetsPrivate(TheorySets
& external
,
1063 context::Context
* c
,
1064 context::UserContext
* u
):
1065 d_external(external
),
1067 d_equalityEngine(d_notify
, c
, "theory::sets::TheorySetsPrivate"),
1069 d_termInfoManager(NULL
),
1070 d_propagationQueue(c
),
1071 d_settermPropagationQueue(c
),
1074 d_pendingDisequal(c
),
1075 d_pendingEverInserted(u
),
1081 d_termInfoManager
= new TermInfoManager(*this, c
, &d_equalityEngine
);
1083 d_equalityEngine
.addFunctionKind(kind::UNION
);
1084 d_equalityEngine
.addFunctionKind(kind::INTERSECTION
);
1085 d_equalityEngine
.addFunctionKind(kind::SETMINUS
);
1087 d_equalityEngine
.addFunctionKind(kind::MEMBER
);
1088 d_equalityEngine
.addFunctionKind(kind::SUBSET
);
1090 if( Debug
.isOn("sets-scrutinize") ) {
1091 d_scrutinize
= new TheorySetsScrutinize(this);
1093 }/* TheorySetsPrivate::TheorySetsPrivate() */
1096 TheorySetsPrivate::~TheorySetsPrivate()
1098 delete d_termInfoManager
;
1099 if( Debug
.isOn("sets-scrutinize") ) {
1100 Assert(d_scrutinize
!= NULL
);
1101 delete d_scrutinize
;
1103 }/* TheorySetsPrivate::~TheorySetsPrivate() */
1105 void TheorySetsPrivate::propagate(Theory::Effort effort
) {
1106 if(effort
!= Theory::EFFORT_FULL
|| !options::setsPropFull()) {
1111 Trace("sets-prop-full") << "[sets-prop-full] propagate(FULL_EFFORT)" << std::endl
;
1112 if(Trace
.isOn("sets-assertions")) {
1113 dumpAssertionsHumanified();
1116 const CDNodeSet
& terms
= (d_termInfoManager
->d_terms
);
1117 for(typeof(terms
.begin()) it
= terms
.begin(); it
!= terms
.end(); ++it
) {
1119 Kind k
= node
.getKind();
1120 if(k
== kind::UNION
&& node
[0].getKind() == kind::SINGLETON
) {
1122 if(holds(MEMBER(node
[0][0], node
[1]))) {
1123 Trace("sets-prop-full") << "[sets-prop-full] " << MEMBER(node
[0][0], node
[1])
1124 << " => " << EQUAL(node
[1], node
) << std::endl
;
1125 learnLiteral(EQUAL(node
[1], node
), MEMBER(node
[0][0], node
[1]));
1128 } else if(k
== kind::UNION
&& node
[1].getKind() == kind::SINGLETON
) {
1130 if(holds(MEMBER(node
[1][0], node
[0]))) {
1131 Trace("sets-prop-full") << "[sets-prop-full] " << MEMBER(node
[1][0], node
[0])
1132 << " => " << EQUAL(node
[0], node
) << std::endl
;
1133 learnLiteral(EQUAL(node
[0], node
), MEMBER(node
[1][0], node
[0]));
1139 finishPropagation();
1142 bool TheorySetsPrivate::propagate(TNode literal
) {
1143 Debug("sets-prop") << " propagate(" << literal
<< ")" << std::endl
;
1145 // If already in conflict, no more propagation
1147 Debug("sets-prop") << "TheoryUF::propagate(" << literal
<< "): already in conflict" << std::endl
;
1152 bool ok
= d_external
.d_out
->propagate(literal
);
1158 }/* TheorySetsPrivate::propagate(TNode) */
1161 void TheorySetsPrivate::setMasterEqualityEngine(eq::EqualityEngine
* eq
) {
1162 d_equalityEngine
.setMasterEqualityEngine(eq
);
1166 void TheorySetsPrivate::conflict(TNode a
, TNode b
)
1168 if (a
.getKind() == kind::CONST_BOOLEAN
) {
1169 d_conflictNode
= explain(a
.iffNode(b
));
1171 d_conflictNode
= explain(a
.eqNode(b
));
1173 d_external
.d_out
->conflict(d_conflictNode
);
1174 Debug("sets") << "[sets] conflict: " << a
<< " iff " << b
1175 << ", explaination " << d_conflictNode
<< std::endl
;
1179 Node
TheorySetsPrivate::explain(TNode literal
)
1181 Debug("sets") << "TheorySetsPrivate::explain(" << literal
<< ")"
1184 bool polarity
= literal
.getKind() != kind::NOT
;
1185 TNode atom
= polarity
? literal
: literal
[0];
1186 std::vector
<TNode
> assumptions
;
1188 if(atom
.getKind() == kind::EQUAL
|| atom
.getKind() == kind::IFF
) {
1189 d_equalityEngine
.explainEquality(atom
[0], atom
[1], polarity
, assumptions
);
1190 } else if(atom
.getKind() == kind::MEMBER
) {
1191 if( !d_equalityEngine
.hasTerm(atom
)) {
1192 d_equalityEngine
.addTerm(atom
);
1194 d_equalityEngine
.explainPredicate(atom
, polarity
, assumptions
);
1196 Debug("sets") << "unhandled: " << literal
<< "; (" << atom
<< ", "
1197 << polarity
<< "); kind" << atom
.getKind() << std::endl
;
1201 return mkAnd(assumptions
);
1205 void TheorySetsPrivate::preRegisterTerm(TNode node
)
1207 Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node
<< ")"
1210 switch(node
.getKind()) {
1212 // TODO: what's the point of this
1213 d_equalityEngine
.addTriggerEquality(node
);
1216 // TODO: what's the point of this
1217 d_equalityEngine
.addTriggerPredicate(node
);
1220 d_termInfoManager
->addTerm(node
);
1221 d_equalityEngine
.addTriggerTerm(node
, THEORY_SETS
);
1222 // d_equalityEngine.addTerm(node);
1224 if(node
.getKind() == kind::SINGLETON
) {
1225 Node true_node
= NodeManager::currentNM()->mkConst
<bool>(true);
1226 learnLiteral(MEMBER(node
[0], node
), true, true_node
);
1227 //intentional fallthrough
1233 /**************************** eq::NotifyClass *****************************/
1234 /**************************** eq::NotifyClass *****************************/
1235 /**************************** eq::NotifyClass *****************************/
1238 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerEquality(TNode equality
, bool value
)
1240 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerEquality: equality = " << equality
1241 << " value = " << value
<< std::endl
;
1243 return d_theory
.propagate(equality
);
1245 // We use only literal triggers so taking not is safe
1246 return d_theory
.propagate(equality
.notNode());
1250 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerPredicate(TNode predicate
, bool value
)
1252 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerPredicate: predicate = " << predicate
1253 << " value = " << value
<< std::endl
;
1255 return d_theory
.propagate(predicate
);
1257 return d_theory
.propagate(predicate
.notNode());
1261 bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag
, TNode t1
, TNode t2
, bool value
)
1263 Debug("sets-eq") << "[sets-eq] eqNotifyTriggerTermEquality: tag = " << tag
1264 << " t1 = " << t1
<< " t2 = " << t2
<< " value = " << value
<< std::endl
;
1266 d_theory
.d_termInfoManager
->mergeTerms(t1
, t2
);
1268 d_theory
.propagate( value
? EQUAL(t1
, t2
) : NOT(EQUAL(t1
, t2
)) );
1272 void TheorySetsPrivate::NotifyClass::eqNotifyConstantTermMerge(TNode t1
, TNode t2
)
1274 Debug("sets-eq") << "[sets-eq] eqNotifyConstantTermMerge " << " t1 = " << t1
<< " t2 = " << t2
<< std::endl
;
1275 d_theory
.conflict(t1
, t2
);
1278 // void TheorySetsPrivate::NotifyClass::eqNotifyNewClass(TNode t)
1280 // Debug("sets-eq") << "[sets-eq] eqNotifyNewClass:" << " t = " << t << std::endl;
1283 // void TheorySetsPrivate::NotifyClass::eqNotifyPreMerge(TNode t1, TNode t2)
1285 // Debug("sets-eq") << "[sets-eq] eqNotifyPreMerge:" << " t1 = " << t1 << " t2 = " << t2 << std::endl;
1288 // void TheorySetsPrivate::NotifyClass::eqNotifyPostMerge(TNode t1, TNode t2)
1290 // Debug("sets-eq") << "[sets-eq] eqNotifyPostMerge:" << " t1 = " << t1 << " t2 = " << t2 << std::endl;
1293 // void TheorySetsPrivate::NotifyClass::eqNotifyDisequal(TNode t1, TNode t2, TNode reason)
1295 // Debug("sets-eq") << "[sets-eq] eqNotifyDisequal:" << " t1 = " << t1 << " t2 = " << t2 << " reason = " << reason << std::endl;
1299 /**************************** TermInfoManager *****************************/
1300 /**************************** TermInfoManager *****************************/
1301 /**************************** TermInfoManager *****************************/
1303 void TheorySetsPrivate::TermInfoManager::mergeLists
1304 (CDTNodeList
* la
, const CDTNodeList
* lb
) const {
1305 // straight from theory/arrays/array_info.cpp
1306 std::set
<TNode
> temp
;
1307 CDTNodeList::const_iterator it
;
1308 for(it
= la
->begin() ; it
!= la
->end(); it
++ ) {
1312 for(it
= lb
->begin() ; it
!= lb
->end(); it
++ ) {
1313 if(temp
.count(*it
) == 0) {
1319 TheorySetsPrivate::TermInfoManager::TermInfoManager
1320 (TheorySetsPrivate
& theory
, context::Context
* satContext
, eq::EqualityEngine
* eq
):
1322 d_context(satContext
),
1324 d_terms(satContext
),
1328 TheorySetsPrivate::TermInfoManager::~TermInfoManager() {
1329 for( typeof(d_info
.begin()) it
= d_info
.begin();
1330 it
!= d_info
.end(); ++it
) {
1331 delete (*it
).second
;
1335 void TheorySetsPrivate::TermInfoManager::notifyMembership(TNode fact
) {
1336 bool polarity
= fact
.getKind() != kind::NOT
;
1337 TNode atom
= polarity
? fact
: fact
[0];
1339 TNode x
= d_eqEngine
->getRepresentative(atom
[0]);
1340 TNode S
= d_eqEngine
->getRepresentative(atom
[1]);
1342 Debug("sets-terminfo") << "[sets-terminfo] Adding membership " << x
1343 << " in " << S
<< " " << polarity
<< std::endl
;
1345 d_info
[S
]->addToElementList(x
, polarity
);
1346 d_info
[x
]->addToSetList(S
, polarity
);
1348 d_theory
.d_modelCache
.clear();
1351 const CDTNodeList
* TheorySetsPrivate::TermInfoManager::getParents(TNode x
) {
1352 return d_info
[x
]->parents
;
1355 const CDTNodeList
* TheorySetsPrivate::TermInfoManager::getMembers(TNode S
) {
1356 return d_info
[S
]->elementsInThisSet
;
1359 const CDTNodeList
* TheorySetsPrivate::TermInfoManager::getNonMembers(TNode S
) {
1360 return d_info
[S
]->elementsNotInThisSet
;
1363 void TheorySetsPrivate::TermInfoManager::addTerm(TNode n
) {
1364 unsigned numChild
= n
.getNumChildren();
1366 if(!d_terms
.contains(n
)) {
1368 d_info
[n
] = new TheorySetsTermInfo(d_context
);
1371 if(n
.getKind() == kind::UNION
||
1372 n
.getKind() == kind::INTERSECTION
||
1373 n
.getKind() == kind::SETMINUS
) {
1375 for(unsigned i
= 0; i
< numChild
; ++i
) {
1376 if(d_terms
.contains(n
[i
])) {
1377 Debug("sets-parent") << "Adding " << n
<< " to parent list of "
1378 << n
[i
] << std::endl
;
1379 d_info
[n
[i
]]->parents
->push_back(n
);
1386 void TheorySetsPrivate::TermInfoManager::pushToSettermPropagationQueue
1387 (TNode x
, TNode S
, bool polarity
)
1389 Node cur_atom
= MEMBER(x
, S
);
1391 // propagation : empty set
1392 if(polarity
&& S
.getKind() == kind::EMPTYSET
) {
1393 Debug("sets-prop") << "[sets-prop] something in empty set? conflict."
1395 d_theory
.learnLiteral(cur_atom
, false, cur_atom
);
1397 }// propagation: empty set
1399 // propagation : children
1400 if(S
.getKind() == kind::UNION
||
1401 S
.getKind() == kind::INTERSECTION
||
1402 S
.getKind() == kind::SETMINUS
||
1403 S
.getKind() == kind::SINGLETON
) {
1404 d_theory
.d_settermPropagationQueue
.push_back(std::make_pair(x
, S
));
1405 }// propagation: children
1407 // propagation : parents
1408 const CDTNodeList
* parentList
= getParents(S
);
1409 for(typeof(parentList
->begin()) k
= parentList
->begin();
1410 k
!= parentList
->end(); ++k
) {
1411 d_theory
.d_settermPropagationQueue
.push_back(std::make_pair(x
, *k
));
1412 }// propagation : parents
1416 void TheorySetsPrivate::TermInfoManager::pushToSettermPropagationQueue
1417 (TNode x
, CDTNodeList
* l
, bool polarity
)
1419 set
<TNode
> alreadyProcessed
;
1421 BOOST_FOREACH(TNode S
, (*l
) ) {
1422 Debug("sets-prop") << "[sets-terminfo] setterm todo: "
1423 << MEMBER(x
, d_eqEngine
->getRepresentative(S
))
1426 TNode repS
= d_eqEngine
->getRepresentative(S
);
1427 if(alreadyProcessed
.find(repS
) != alreadyProcessed
.end()) {
1430 alreadyProcessed
.insert(repS
);
1433 d_eqEngine
->addTerm(MEMBER(d_eqEngine
->getRepresentative(x
), repS
));
1435 for(eq::EqClassIterator
j(d_eqEngine
->getRepresentative(S
), d_eqEngine
);
1436 !j
.isFinished(); ++j
) {
1438 pushToSettermPropagationQueue(x
, *j
, polarity
);
1444 void TheorySetsPrivate::TermInfoManager::pushToSettermPropagationQueue
1445 (CDTNodeList
* l
, TNode S
, bool polarity
)
1447 BOOST_FOREACH(TNode x
, (*l
) ) {
1448 Debug("sets-prop") << "[sets-terminfo] setterm todo: "
1449 << MEMBER(x
, d_eqEngine
->getRepresentative(S
))
1452 d_eqEngine
->addTerm(MEMBER(d_eqEngine
->getRepresentative(x
),
1453 d_eqEngine
->getRepresentative(S
)));
1455 for(eq::EqClassIterator
j(d_eqEngine
->getRepresentative(S
), d_eqEngine
);
1456 !j
.isFinished(); ++j
) {
1458 pushToSettermPropagationQueue(x
, *j
, polarity
);
1468 void TheorySetsPrivate::TermInfoManager::mergeTerms(TNode a
, TNode b
) {
1470 Debug("sets-terminfo") << "[sets-terminfo] Merging (into) a = " << a
1471 << ", b = " << b
<< std::endl
;
1472 Debug("sets-terminfo") << "[sets-terminfo] reps"
1473 << ", a: " << d_eqEngine
->getRepresentative(a
)
1474 << ", b: " << d_eqEngine
->getRepresentative(b
)
1477 typeof(d_info
.begin()) ita
= d_info
.find(a
);
1478 typeof(d_info
.begin()) itb
= d_info
.find(b
);
1480 Assert(ita
!= d_info
.end());
1481 Assert(itb
!= d_info
.end());
1483 /* elements in this sets */
1484 pushToSettermPropagationQueue( (*ita
).second
->elementsInThisSet
, b
, true );
1485 pushToSettermPropagationQueue( (*ita
).second
->elementsNotInThisSet
, b
, false );
1486 pushToSettermPropagationQueue( (*itb
).second
->elementsNotInThisSet
, a
, false );
1487 pushToSettermPropagationQueue( (*itb
).second
->elementsInThisSet
, a
, true );
1488 mergeLists((*ita
).second
->elementsInThisSet
,
1489 (*itb
).second
->elementsInThisSet
);
1490 mergeLists((*ita
).second
->elementsNotInThisSet
,
1491 (*itb
).second
->elementsNotInThisSet
);
1493 /* sets containing this element */
1494 // pushToSettermPropagationQueue( b, (*ita).second->setsContainingThisElement, true);
1495 // pushToSettermPropagationQueue( b, (*ita).second->setsNotContainingThisElement, false);
1496 pushToSettermPropagationQueue( a
, (*itb
).second
->setsNotContainingThisElement
, false);
1497 pushToSettermPropagationQueue( a
, (*itb
).second
->setsContainingThisElement
, true);
1498 mergeLists( (*ita
).second
->setsContainingThisElement
,
1499 (*itb
).second
->setsContainingThisElement
);
1500 mergeLists( (*ita
).second
->setsNotContainingThisElement
,
1501 (*itb
).second
->setsNotContainingThisElement
);
1503 d_theory
.d_modelCache
.clear();
1506 Node
TheorySetsPrivate::TermInfoManager::getModelValue(TNode n
)
1508 if(d_terms
.find(n
) == d_terms
.end()) {
1511 Assert(n
.getType().isSet());
1512 set
<Node
> elements
, elements_const
;
1513 Node S
= d_eqEngine
->getRepresentative(n
);
1514 typeof(d_theory
.d_modelCache
.begin()) it
= d_theory
.d_modelCache
.find(S
);
1515 if(it
!= d_theory
.d_modelCache
.end()) {
1516 return (*it
).second
;
1518 const CDTNodeList
* l
= getMembers(S
);
1519 for(typeof(l
->begin()) it
= l
->begin(); it
!= l
->end(); ++it
) {
1521 elements
.insert(d_eqEngine
->getRepresentative(n
));
1523 BOOST_FOREACH(TNode e
, elements
) {
1525 elements_const
.insert(e
);
1527 elements_const
.insert(d_theory
.d_external
.d_valuation
.getModelValue(e
));
1530 Node v
= d_theory
.elementsToShape(elements_const
, n
.getType());
1531 d_theory
.d_modelCache
[n
] = v
;
1535 }/* CVC4::theory::sets namespace */
1536 }/* CVC4::theory namespace */
1537 }/* CVC4 namespace */