1 /********************* */
2 /*! \file solver_state.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Mudathir Mohamed
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
8 ** in the top-level source directory) and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief Implementation of sets state object
15 #include "theory/sets/solver_state.h"
17 #include "expr/emptyset.h"
18 #include "options/sets_options.h"
19 #include "theory/sets/theory_sets_private.h"
22 using namespace CVC4::kind
;
28 SolverState::SolverState(TheorySetsPrivate
& p
,
30 context::UserContext
* u
)
31 : d_conflict(c
), d_parent(p
), d_ee(nullptr), d_proxy(u
), d_proxy_to_term(u
)
33 d_true
= NodeManager::currentNM()->mkConst(true);
34 d_false
= NodeManager::currentNM()->mkConst(false);
37 void SolverState::finishInit(eq::EqualityEngine
* ee
)
39 Assert(ee
!= nullptr);
43 void SolverState::reset()
46 d_eqc_emptyset
.clear();
47 d_eqc_univset
.clear();
48 d_eqc_singleton
.clear();
53 d_pol_mems
[0].clear();
54 d_pol_mems
[1].clear();
55 d_members_index
.clear();
56 d_singleton_index
.clear();
59 d_allCompSets
.clear();
62 void SolverState::registerEqc(TypeNode tn
, Node r
)
66 d_set_eqc
.push_back(r
);
70 void SolverState::registerTerm(Node r
, TypeNode tnn
, Node n
)
72 Kind nk
= n
.getKind();
77 Node s
= d_ee
->getRepresentative(n
[1]);
78 Node x
= d_ee
->getRepresentative(n
[0]);
79 int pindex
= r
== d_true
? 0 : (r
== d_false
? 1 : -1);
82 if (d_pol_mems
[pindex
][s
].find(x
) == d_pol_mems
[pindex
][s
].end())
84 d_pol_mems
[pindex
][s
][x
] = n
;
85 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
86 << ", pindex = " << pindex
<< std::endl
;
88 if (d_members_index
[s
].find(x
) == d_members_index
[s
].end())
90 d_members_index
[s
][x
] = n
;
91 d_op_list
[MEMBER
].push_back(n
);
100 else if (nk
== SINGLETON
|| nk
== UNION
|| nk
== INTERSECTION
101 || nk
== SETMINUS
|| nk
== EMPTYSET
|| nk
== UNIVERSE_SET
)
107 Node re
= d_ee
->getRepresentative(n
[0]);
108 if (d_singleton_index
.find(re
) == d_singleton_index
.end())
110 d_singleton_index
[re
] = n
;
111 d_eqc_singleton
[r
] = n
;
112 d_op_list
[SINGLETON
].push_back(n
);
116 d_congruent
[n
] = d_singleton_index
[re
];
119 else if (nk
== EMPTYSET
)
121 d_eqc_emptyset
[tnn
] = r
;
123 else if (nk
== UNIVERSE_SET
)
125 Assert(options::setsExt());
126 d_eqc_univset
[tnn
] = r
;
130 Node r1
= d_ee
->getRepresentative(n
[0]);
131 Node r2
= d_ee
->getRepresentative(n
[1]);
132 std::map
<Node
, Node
>& binr1
= d_bop_index
[nk
][r1
];
133 std::map
<Node
, Node
>::iterator itb
= binr1
.find(r2
);
134 if (itb
== binr1
.end())
137 d_op_list
[nk
].push_back(n
);
141 d_congruent
[n
] = itb
->second
;
144 d_nvar_sets
[r
].push_back(n
);
145 Trace("sets-debug2") << "Non-var-set[" << r
<< "] : " << n
<< std::endl
;
147 else if (nk
== COMPREHENSION
)
149 d_compSets
[r
].push_back(n
);
150 d_allCompSets
.push_back(n
);
151 Trace("sets-debug2") << "Comp-set[" << r
<< "] : " << n
<< std::endl
;
153 else if (n
.isVar() && !d_skCache
.isSkolem(n
))
155 // it is important that we check it is a variable, but not an internally
156 // introduced skolem, due to the semantics of the universe set.
159 if (d_var_set
.find(r
) == d_var_set
.end())
162 Trace("sets-debug2") << "var-set[" << r
<< "] : " << n
<< std::endl
;
168 Trace("sets-debug2") << "Unknown-set[" << r
<< "] : " << n
<< std::endl
;
172 Node
SolverState::getRepresentative(Node a
) const
174 if (d_ee
->hasTerm(a
))
176 return d_ee
->getRepresentative(a
);
181 bool SolverState::hasTerm(Node a
) const { return d_ee
->hasTerm(a
); }
183 bool SolverState::areEqual(Node a
, Node b
) const
189 if (d_ee
->hasTerm(a
) && d_ee
->hasTerm(b
))
191 return d_ee
->areEqual(a
, b
);
196 bool SolverState::areDisequal(Node a
, Node b
) const
202 else if (d_ee
->hasTerm(a
) && d_ee
->hasTerm(b
))
204 return d_ee
->areDisequal(a
, b
, false);
206 return a
.isConst() && b
.isConst();
209 eq::EqualityEngine
* SolverState::getEqualityEngine() const { return d_ee
; }
211 void SolverState::setConflict() { d_conflict
= true; }
212 void SolverState::setConflict(Node conf
)
214 d_parent
.getOutputChannel()->conflict(conf
);
218 void SolverState::addEqualityToExp(Node a
, Node b
, std::vector
<Node
>& exp
) const
222 Assert(areEqual(a
, b
));
223 exp
.push_back(a
.eqNode(b
));
227 Node
SolverState::getEmptySetEqClass(TypeNode tn
) const
229 std::map
<TypeNode
, Node
>::const_iterator it
= d_eqc_emptyset
.find(tn
);
230 if (it
!= d_eqc_emptyset
.end())
237 Node
SolverState::getUnivSetEqClass(TypeNode tn
) const
239 std::map
<TypeNode
, Node
>::const_iterator it
= d_univset
.find(tn
);
240 if (it
!= d_univset
.end())
247 Node
SolverState::getSingletonEqClass(Node r
) const
249 std::map
<Node
, Node
>::const_iterator it
= d_eqc_singleton
.find(r
);
250 if (it
!= d_eqc_singleton
.end())
257 Node
SolverState::getBinaryOpTerm(Kind k
, Node r1
, Node r2
) const
259 std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >::const_iterator itk
=
261 if (itk
== d_bop_index
.end())
265 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it1
=
266 itk
->second
.find(r1
);
267 if (it1
== itk
->second
.end())
271 std::map
<Node
, Node
>::const_iterator it2
= it1
->second
.find(r2
);
272 if (it2
== it1
->second
.end())
279 bool SolverState::isEntailed(Node n
, bool polarity
) const
281 if (n
.getKind() == NOT
)
283 return isEntailed(n
[0], !polarity
);
285 else if (n
.getKind() == EQUAL
)
289 return areEqual(n
[0], n
[1]);
291 return areDisequal(n
[0], n
[1]);
293 else if (n
.getKind() == MEMBER
)
295 if (areEqual(n
, polarity
? d_true
: d_false
))
299 // check members cache
300 if (polarity
&& d_ee
->hasTerm(n
[1]))
302 Node r
= d_ee
->getRepresentative(n
[1]);
303 if (d_parent
.isMember(n
[0], r
))
309 else if (n
.getKind() == AND
|| n
.getKind() == OR
)
311 bool conj
= (n
.getKind() == AND
) == polarity
;
312 for (const Node
& nc
: n
)
314 bool isEnt
= isEntailed(nc
, polarity
);
322 else if (n
.isConst())
324 return (polarity
&& n
== d_true
) || (!polarity
&& n
== d_false
);
329 bool SolverState::isSetDisequalityEntailed(Node r1
, Node r2
) const
331 Assert(d_ee
->hasTerm(r1
) && d_ee
->getRepresentative(r1
) == r1
);
332 Assert(d_ee
->hasTerm(r2
) && d_ee
->getRepresentative(r2
) == r2
);
333 TypeNode tn
= r1
.getType();
334 Node re
= getEmptySetEqClass(tn
);
335 for (unsigned e
= 0; e
< 2; e
++)
337 Node a
= e
== 0 ? r1
: r2
;
338 Node b
= e
== 0 ? r2
: r1
;
339 if (isSetDisequalityEntailedInternal(a
, b
, re
))
347 bool SolverState::isSetDisequalityEntailedInternal(Node a
,
351 // if there are members in a
352 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpma
=
353 d_pol_mems
[0].find(a
);
354 if (itpma
== d_pol_mems
[0].end())
356 // no positive members, continue
362 if (!itpma
->second
.empty())
364 Trace("sets-deq") << "Disequality is satisfied because members are in "
365 << a
<< " and " << b
<< " is empty" << std::endl
;
370 // a should not be singleton
371 Assert(d_eqc_singleton
.find(a
) == d_eqc_singleton
.end());
375 std::map
<Node
, Node
>::const_iterator itsb
= d_eqc_singleton
.find(b
);
376 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpmb
=
377 d_pol_mems
[1].find(b
);
378 std::vector
<Node
> prev
;
379 for (const std::pair
<const Node
, Node
>& itm
: itpma
->second
)
381 // if b is a singleton
382 if (itsb
!= d_eqc_singleton
.end())
384 if (areDisequal(itm
.first
, itsb
->second
[0]))
386 Trace("sets-deq") << "Disequality is satisfied because of "
387 << itm
.second
<< ", singleton eq " << itsb
->second
[0]
391 // or disequal with another member
392 for (const Node
& p
: prev
)
394 if (areDisequal(itm
.first
, p
))
397 << "Disequality is satisfied because of disequal members "
398 << itm
.first
<< " " << p
<< ", singleton eq " << std::endl
;
402 // if a has positive member that is negative member in b
404 else if (itpmb
!= d_pol_mems
[1].end())
406 for (const std::pair
<const Node
, Node
>& itnm
: itpmb
->second
)
408 if (areEqual(itm
.first
, itnm
.first
))
410 Trace("sets-deq") << "Disequality is satisfied because of "
411 << itm
.second
<< " " << itnm
.second
<< std::endl
;
416 prev
.push_back(itm
.first
);
421 Node
SolverState::getProxy(Node n
)
423 Kind nk
= n
.getKind();
424 if (nk
!= EMPTYSET
&& nk
!= SINGLETON
&& nk
!= INTERSECTION
&& nk
!= SETMINUS
425 && nk
!= UNION
&& nk
!= UNIVERSE_SET
)
429 NodeMap::const_iterator it
= d_proxy
.find(n
);
430 if (it
!= d_proxy
.end())
434 NodeManager
* nm
= NodeManager::currentNM();
435 Node k
= d_skCache
.mkTypedSkolemCached(
436 n
.getType(), n
, SkolemCache::SK_PURIFY
, "sp");
438 d_proxy_to_term
[k
] = n
;
439 Node eq
= k
.eqNode(n
);
440 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
441 d_parent
.getOutputChannel()->lemma(eq
);
444 Node slem
= nm
->mkNode(MEMBER
, n
[0], k
);
445 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton"
447 d_parent
.getOutputChannel()->lemma(slem
);
452 Node
SolverState::getCongruent(Node n
) const
454 Assert(d_ee
->hasTerm(n
));
455 std::map
<Node
, Node
>::const_iterator it
= d_congruent
.find(n
);
456 if (it
== d_congruent
.end())
462 bool SolverState::isCongruent(Node n
) const
464 return d_congruent
.find(n
) != d_congruent
.end();
467 Node
SolverState::getEmptySet(TypeNode tn
)
469 std::map
<TypeNode
, Node
>::iterator it
= d_emptyset
.find(tn
);
470 if (it
!= d_emptyset
.end())
474 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
));
478 Node
SolverState::getUnivSet(TypeNode tn
)
480 std::map
<TypeNode
, Node
>::iterator it
= d_univset
.find(tn
);
481 if (it
!= d_univset
.end())
485 NodeManager
* nm
= NodeManager::currentNM();
486 Node n
= nm
->mkNullaryOperator(tn
, UNIVERSE_SET
);
487 for (it
= d_univset
.begin(); it
!= d_univset
.end(); ++it
)
491 if (tn
.isSubtypeOf(it
->first
))
496 else if (it
->first
.isSubtypeOf(tn
))
503 Node ulem
= nm
->mkNode(SUBSET
, n1
, n2
);
504 Trace("sets-lemma") << "Sets::Lemma : " << ulem
<< " by univ-type"
506 d_parent
.getOutputChannel()->lemma(ulem
);
513 Node
SolverState::getTypeConstraintSkolem(Node n
, TypeNode tn
)
515 std::map
<TypeNode
, Node
>::iterator it
= d_tc_skolem
[n
].find(tn
);
516 if (it
== d_tc_skolem
[n
].end())
518 Node k
= NodeManager::currentNM()->mkSkolem("tc_k", tn
);
519 d_tc_skolem
[n
][tn
] = k
;
525 const std::vector
<Node
>& SolverState::getNonVariableSets(Node r
) const
527 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_nvar_sets
.find(r
);
528 if (it
== d_nvar_sets
.end())
535 Node
SolverState::getVariableSet(Node r
) const
537 std::map
<Node
, Node
>::const_iterator it
= d_var_set
.find(r
);
538 if (it
!= d_var_set
.end())
545 const std::vector
<Node
>& SolverState::getComprehensionSets(Node r
) const
547 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_compSets
.find(r
);
548 if (it
== d_compSets
.end())
555 const std::map
<Node
, Node
>& SolverState::getMembers(Node r
) const
557 return getMembersInternal(r
, 0);
559 const std::map
<Node
, Node
>& SolverState::getNegativeMembers(Node r
) const
561 return getMembersInternal(r
, 1);
563 const std::map
<Node
, Node
>& SolverState::getMembersInternal(Node r
,
566 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itp
=
567 d_pol_mems
[i
].find(r
);
568 if (itp
== d_pol_mems
[i
].end())
575 bool SolverState::hasMembers(Node r
) const
577 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it
=
578 d_pol_mems
[0].find(r
);
579 if (it
== d_pol_mems
[0].end())
583 return !it
->second
.empty();
585 const std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >&
586 SolverState::getBinaryOpIndex() const
590 const std::map
<Kind
, std::vector
<Node
> >& SolverState::getOperatorList() const
595 const std::vector
<Node
>& SolverState::getComprehensionSets() const
597 return d_allCompSets
;
600 void SolverState::debugPrintSet(Node s
, const char* c
) const
602 if (s
.getNumChildren() == 0)
604 NodeMap::const_iterator it
= d_proxy_to_term
.find(s
);
605 if (it
!= d_proxy_to_term
.end())
607 debugPrintSet((*it
).second
, c
);
616 Trace(c
) << "(" << s
.getOperator();
617 for (const Node
& sc
: s
)
620 debugPrintSet(sc
, c
);
626 const vector
<Node
> SolverState::getSetsEqClasses(const TypeNode
& t
) const
628 vector
<Node
> representatives
;
629 for (const Node
& eqc
: getSetsEqClasses())
631 if (eqc
.getType().getSetElementType() == t
)
633 representatives
.push_back(eqc
);
636 return representatives
;
640 } // namespace theory