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(context::Context
* c
,
29 context::UserContext
* u
,
31 : TheoryState(c
, u
, val
), d_parent(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::setParent(TheorySetsPrivate
* p
) { d_parent
= p
; }
39 void SolverState::reset()
42 d_eqc_emptyset
.clear();
43 d_eqc_univset
.clear();
44 d_eqc_singleton
.clear();
49 d_pol_mems
[0].clear();
50 d_pol_mems
[1].clear();
51 d_members_index
.clear();
52 d_singleton_index
.clear();
55 d_allCompSets
.clear();
58 void SolverState::registerEqc(TypeNode tn
, Node r
)
62 d_set_eqc
.push_back(r
);
66 void SolverState::registerTerm(Node r
, TypeNode tnn
, Node n
)
68 Kind nk
= n
.getKind();
73 Node s
= d_ee
->getRepresentative(n
[1]);
74 Node x
= d_ee
->getRepresentative(n
[0]);
75 int pindex
= r
== d_true
? 0 : (r
== d_false
? 1 : -1);
78 if (d_pol_mems
[pindex
][s
].find(x
) == d_pol_mems
[pindex
][s
].end())
80 d_pol_mems
[pindex
][s
][x
] = n
;
81 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
82 << ", pindex = " << pindex
<< std::endl
;
84 if (d_members_index
[s
].find(x
) == d_members_index
[s
].end())
86 d_members_index
[s
][x
] = n
;
87 d_op_list
[MEMBER
].push_back(n
);
96 else if (nk
== SINGLETON
|| nk
== UNION
|| nk
== INTERSECTION
97 || nk
== SETMINUS
|| nk
== EMPTYSET
|| nk
== UNIVERSE_SET
)
103 Node re
= d_ee
->getRepresentative(n
[0]);
104 if (d_singleton_index
.find(re
) == d_singleton_index
.end())
106 d_singleton_index
[re
] = n
;
107 d_eqc_singleton
[r
] = n
;
108 d_op_list
[SINGLETON
].push_back(n
);
112 d_congruent
[n
] = d_singleton_index
[re
];
115 else if (nk
== EMPTYSET
)
117 d_eqc_emptyset
[tnn
] = r
;
119 else if (nk
== UNIVERSE_SET
)
121 Assert(options::setsExt());
122 d_eqc_univset
[tnn
] = r
;
126 Node r1
= d_ee
->getRepresentative(n
[0]);
127 Node r2
= d_ee
->getRepresentative(n
[1]);
128 std::map
<Node
, Node
>& binr1
= d_bop_index
[nk
][r1
];
129 std::map
<Node
, Node
>::iterator itb
= binr1
.find(r2
);
130 if (itb
== binr1
.end())
133 d_op_list
[nk
].push_back(n
);
137 d_congruent
[n
] = itb
->second
;
140 d_nvar_sets
[r
].push_back(n
);
141 Trace("sets-debug2") << "Non-var-set[" << r
<< "] : " << n
<< std::endl
;
143 else if (nk
== COMPREHENSION
)
145 d_compSets
[r
].push_back(n
);
146 d_allCompSets
.push_back(n
);
147 Trace("sets-debug2") << "Comp-set[" << r
<< "] : " << n
<< std::endl
;
149 else if (n
.isVar() && !d_skCache
.isSkolem(n
))
151 // it is important that we check it is a variable, but not an internally
152 // introduced skolem, due to the semantics of the universe set.
155 if (d_var_set
.find(r
) == d_var_set
.end())
158 Trace("sets-debug2") << "var-set[" << r
<< "] : " << n
<< std::endl
;
164 Trace("sets-debug2") << "Unknown-set[" << r
<< "] : " << n
<< std::endl
;
168 void SolverState::addEqualityToExp(Node a
, Node b
, std::vector
<Node
>& exp
) const
172 Assert(areEqual(a
, b
));
173 exp
.push_back(a
.eqNode(b
));
177 Node
SolverState::getEmptySetEqClass(TypeNode tn
) const
179 std::map
<TypeNode
, Node
>::const_iterator it
= d_eqc_emptyset
.find(tn
);
180 if (it
!= d_eqc_emptyset
.end())
187 Node
SolverState::getUnivSetEqClass(TypeNode tn
) const
189 std::map
<TypeNode
, Node
>::const_iterator it
= d_univset
.find(tn
);
190 if (it
!= d_univset
.end())
197 Node
SolverState::getSingletonEqClass(Node r
) const
199 std::map
<Node
, Node
>::const_iterator it
= d_eqc_singleton
.find(r
);
200 if (it
!= d_eqc_singleton
.end())
207 Node
SolverState::getBinaryOpTerm(Kind k
, Node r1
, Node r2
) const
209 std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >::const_iterator itk
=
211 if (itk
== d_bop_index
.end())
215 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it1
=
216 itk
->second
.find(r1
);
217 if (it1
== itk
->second
.end())
221 std::map
<Node
, Node
>::const_iterator it2
= it1
->second
.find(r2
);
222 if (it2
== it1
->second
.end())
229 bool SolverState::isEntailed(Node n
, bool polarity
) const
231 if (n
.getKind() == NOT
)
233 return isEntailed(n
[0], !polarity
);
235 else if (n
.getKind() == EQUAL
)
239 return areEqual(n
[0], n
[1]);
241 return areDisequal(n
[0], n
[1]);
243 else if (n
.getKind() == MEMBER
)
245 if (areEqual(n
, polarity
? d_true
: d_false
))
249 // check members cache
250 if (polarity
&& d_ee
->hasTerm(n
[1]))
252 Node r
= d_ee
->getRepresentative(n
[1]);
253 if (d_parent
->isMember(n
[0], r
))
259 else if (n
.getKind() == AND
|| n
.getKind() == OR
)
261 bool conj
= (n
.getKind() == AND
) == polarity
;
262 for (const Node
& nc
: n
)
264 bool isEnt
= isEntailed(nc
, polarity
);
272 else if (n
.isConst())
274 return (polarity
&& n
== d_true
) || (!polarity
&& n
== d_false
);
279 bool SolverState::isSetDisequalityEntailed(Node r1
, Node r2
) const
281 Assert(d_ee
->hasTerm(r1
) && d_ee
->getRepresentative(r1
) == r1
);
282 Assert(d_ee
->hasTerm(r2
) && d_ee
->getRepresentative(r2
) == r2
);
283 TypeNode tn
= r1
.getType();
284 Node re
= getEmptySetEqClass(tn
);
285 for (unsigned e
= 0; e
< 2; e
++)
287 Node a
= e
== 0 ? r1
: r2
;
288 Node b
= e
== 0 ? r2
: r1
;
289 if (isSetDisequalityEntailedInternal(a
, b
, re
))
297 bool SolverState::isSetDisequalityEntailedInternal(Node a
,
301 // if there are members in a
302 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpma
=
303 d_pol_mems
[0].find(a
);
304 if (itpma
== d_pol_mems
[0].end())
306 // no positive members, continue
312 if (!itpma
->second
.empty())
314 Trace("sets-deq") << "Disequality is satisfied because members are in "
315 << a
<< " and " << b
<< " is empty" << std::endl
;
320 // a should not be singleton
321 Assert(d_eqc_singleton
.find(a
) == d_eqc_singleton
.end());
325 std::map
<Node
, Node
>::const_iterator itsb
= d_eqc_singleton
.find(b
);
326 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpmb
=
327 d_pol_mems
[1].find(b
);
328 std::vector
<Node
> prev
;
329 for (const std::pair
<const Node
, Node
>& itm
: itpma
->second
)
331 // if b is a singleton
332 if (itsb
!= d_eqc_singleton
.end())
334 if (areDisequal(itm
.first
, itsb
->second
[0]))
336 Trace("sets-deq") << "Disequality is satisfied because of "
337 << itm
.second
<< ", singleton eq " << itsb
->second
[0]
341 // or disequal with another member
342 for (const Node
& p
: prev
)
344 if (areDisequal(itm
.first
, p
))
347 << "Disequality is satisfied because of disequal members "
348 << itm
.first
<< " " << p
<< ", singleton eq " << std::endl
;
352 // if a has positive member that is negative member in b
354 else if (itpmb
!= d_pol_mems
[1].end())
356 for (const std::pair
<const Node
, Node
>& itnm
: itpmb
->second
)
358 if (areEqual(itm
.first
, itnm
.first
))
360 Trace("sets-deq") << "Disequality is satisfied because of "
361 << itm
.second
<< " " << itnm
.second
<< std::endl
;
366 prev
.push_back(itm
.first
);
371 Node
SolverState::getProxy(Node n
)
373 Kind nk
= n
.getKind();
374 if (nk
!= EMPTYSET
&& nk
!= SINGLETON
&& nk
!= INTERSECTION
&& nk
!= SETMINUS
375 && nk
!= UNION
&& nk
!= UNIVERSE_SET
)
379 NodeMap::const_iterator it
= d_proxy
.find(n
);
380 if (it
!= d_proxy
.end())
384 NodeManager
* nm
= NodeManager::currentNM();
385 Node k
= d_skCache
.mkTypedSkolemCached(
386 n
.getType(), n
, SkolemCache::SK_PURIFY
, "sp");
388 d_proxy_to_term
[k
] = n
;
389 Node eq
= k
.eqNode(n
);
390 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
391 d_parent
->getOutputChannel()->lemma(eq
);
394 Node slem
= nm
->mkNode(MEMBER
, n
[0], k
);
395 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton"
397 d_parent
->getOutputChannel()->lemma(slem
);
402 Node
SolverState::getCongruent(Node n
) const
404 Assert(d_ee
->hasTerm(n
));
405 std::map
<Node
, Node
>::const_iterator it
= d_congruent
.find(n
);
406 if (it
== d_congruent
.end())
412 bool SolverState::isCongruent(Node n
) const
414 return d_congruent
.find(n
) != d_congruent
.end();
417 Node
SolverState::getEmptySet(TypeNode tn
)
419 std::map
<TypeNode
, Node
>::iterator it
= d_emptyset
.find(tn
);
420 if (it
!= d_emptyset
.end())
424 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
));
428 Node
SolverState::getUnivSet(TypeNode tn
)
430 std::map
<TypeNode
, Node
>::iterator it
= d_univset
.find(tn
);
431 if (it
!= d_univset
.end())
435 NodeManager
* nm
= NodeManager::currentNM();
436 Node n
= nm
->mkNullaryOperator(tn
, UNIVERSE_SET
);
437 for (it
= d_univset
.begin(); it
!= d_univset
.end(); ++it
)
441 if (tn
.isSubtypeOf(it
->first
))
446 else if (it
->first
.isSubtypeOf(tn
))
453 Node ulem
= nm
->mkNode(SUBSET
, n1
, n2
);
454 Trace("sets-lemma") << "Sets::Lemma : " << ulem
<< " by univ-type"
456 d_parent
->getOutputChannel()->lemma(ulem
);
463 Node
SolverState::getTypeConstraintSkolem(Node n
, TypeNode tn
)
465 std::map
<TypeNode
, Node
>::iterator it
= d_tc_skolem
[n
].find(tn
);
466 if (it
== d_tc_skolem
[n
].end())
468 Node k
= NodeManager::currentNM()->mkSkolem("tc_k", tn
);
469 d_tc_skolem
[n
][tn
] = k
;
475 const std::vector
<Node
>& SolverState::getNonVariableSets(Node r
) const
477 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_nvar_sets
.find(r
);
478 if (it
== d_nvar_sets
.end())
485 Node
SolverState::getVariableSet(Node r
) const
487 std::map
<Node
, Node
>::const_iterator it
= d_var_set
.find(r
);
488 if (it
!= d_var_set
.end())
495 const std::vector
<Node
>& SolverState::getComprehensionSets(Node r
) const
497 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_compSets
.find(r
);
498 if (it
== d_compSets
.end())
505 const std::map
<Node
, Node
>& SolverState::getMembers(Node r
) const
507 return getMembersInternal(r
, 0);
509 const std::map
<Node
, Node
>& SolverState::getNegativeMembers(Node r
) const
511 return getMembersInternal(r
, 1);
513 const std::map
<Node
, Node
>& SolverState::getMembersInternal(Node r
,
516 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itp
=
517 d_pol_mems
[i
].find(r
);
518 if (itp
== d_pol_mems
[i
].end())
525 bool SolverState::hasMembers(Node r
) const
527 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it
=
528 d_pol_mems
[0].find(r
);
529 if (it
== d_pol_mems
[0].end())
533 return !it
->second
.empty();
535 const std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >&
536 SolverState::getBinaryOpIndex() const
540 const std::map
<Kind
, std::vector
<Node
> >& SolverState::getOperatorList() const
545 const std::vector
<Node
>& SolverState::getComprehensionSets() const
547 return d_allCompSets
;
550 void SolverState::debugPrintSet(Node s
, const char* c
) const
552 if (s
.getNumChildren() == 0)
554 NodeMap::const_iterator it
= d_proxy_to_term
.find(s
);
555 if (it
!= d_proxy_to_term
.end())
557 debugPrintSet((*it
).second
, c
);
566 Trace(c
) << "(" << s
.getOperator();
567 for (const Node
& sc
: s
)
570 debugPrintSet(sc
, c
);
576 const vector
<Node
> SolverState::getSetsEqClasses(const TypeNode
& t
) const
578 vector
<Node
> representatives
;
579 for (const Node
& eqc
: getSetsEqClasses())
581 if (eqc
.getType().getSetElementType() == t
)
583 representatives
.push_back(eqc
);
586 return representatives
;
590 } // namespace theory