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
,
32 : TheoryState(c
, u
, val
), d_parent(p
), d_proxy(u
), d_proxy_to_term(u
)
34 d_true
= NodeManager::currentNM()->mkConst(true);
35 d_false
= NodeManager::currentNM()->mkConst(false);
38 void SolverState::reset()
41 d_eqc_emptyset
.clear();
42 d_eqc_univset
.clear();
43 d_eqc_singleton
.clear();
48 d_pol_mems
[0].clear();
49 d_pol_mems
[1].clear();
50 d_members_index
.clear();
51 d_singleton_index
.clear();
54 d_allCompSets
.clear();
57 void SolverState::registerEqc(TypeNode tn
, Node r
)
61 d_set_eqc
.push_back(r
);
65 void SolverState::registerTerm(Node r
, TypeNode tnn
, Node n
)
67 Kind nk
= n
.getKind();
72 Node s
= d_ee
->getRepresentative(n
[1]);
73 Node x
= d_ee
->getRepresentative(n
[0]);
74 int pindex
= r
== d_true
? 0 : (r
== d_false
? 1 : -1);
77 if (d_pol_mems
[pindex
][s
].find(x
) == d_pol_mems
[pindex
][s
].end())
79 d_pol_mems
[pindex
][s
][x
] = n
;
80 Trace("sets-debug2") << "Membership[" << x
<< "][" << s
<< "] : " << n
81 << ", pindex = " << pindex
<< std::endl
;
83 if (d_members_index
[s
].find(x
) == d_members_index
[s
].end())
85 d_members_index
[s
][x
] = n
;
86 d_op_list
[MEMBER
].push_back(n
);
95 else if (nk
== SINGLETON
|| nk
== UNION
|| nk
== INTERSECTION
96 || nk
== SETMINUS
|| nk
== EMPTYSET
|| nk
== UNIVERSE_SET
)
102 Node re
= d_ee
->getRepresentative(n
[0]);
103 if (d_singleton_index
.find(re
) == d_singleton_index
.end())
105 d_singleton_index
[re
] = n
;
106 d_eqc_singleton
[r
] = n
;
107 d_op_list
[SINGLETON
].push_back(n
);
111 d_congruent
[n
] = d_singleton_index
[re
];
114 else if (nk
== EMPTYSET
)
116 d_eqc_emptyset
[tnn
] = r
;
118 else if (nk
== UNIVERSE_SET
)
120 Assert(options::setsExt());
121 d_eqc_univset
[tnn
] = r
;
125 Node r1
= d_ee
->getRepresentative(n
[0]);
126 Node r2
= d_ee
->getRepresentative(n
[1]);
127 std::map
<Node
, Node
>& binr1
= d_bop_index
[nk
][r1
];
128 std::map
<Node
, Node
>::iterator itb
= binr1
.find(r2
);
129 if (itb
== binr1
.end())
132 d_op_list
[nk
].push_back(n
);
136 d_congruent
[n
] = itb
->second
;
139 d_nvar_sets
[r
].push_back(n
);
140 Trace("sets-debug2") << "Non-var-set[" << r
<< "] : " << n
<< std::endl
;
142 else if (nk
== COMPREHENSION
)
144 d_compSets
[r
].push_back(n
);
145 d_allCompSets
.push_back(n
);
146 Trace("sets-debug2") << "Comp-set[" << r
<< "] : " << n
<< std::endl
;
148 else if (n
.isVar() && !d_skCache
.isSkolem(n
))
150 // it is important that we check it is a variable, but not an internally
151 // introduced skolem, due to the semantics of the universe set.
154 if (d_var_set
.find(r
) == d_var_set
.end())
157 Trace("sets-debug2") << "var-set[" << r
<< "] : " << n
<< std::endl
;
163 Trace("sets-debug2") << "Unknown-set[" << r
<< "] : " << n
<< std::endl
;
167 void SolverState::addEqualityToExp(Node a
, Node b
, std::vector
<Node
>& exp
) const
171 Assert(areEqual(a
, b
));
172 exp
.push_back(a
.eqNode(b
));
176 Node
SolverState::getEmptySetEqClass(TypeNode tn
) const
178 std::map
<TypeNode
, Node
>::const_iterator it
= d_eqc_emptyset
.find(tn
);
179 if (it
!= d_eqc_emptyset
.end())
186 Node
SolverState::getUnivSetEqClass(TypeNode tn
) const
188 std::map
<TypeNode
, Node
>::const_iterator it
= d_univset
.find(tn
);
189 if (it
!= d_univset
.end())
196 Node
SolverState::getSingletonEqClass(Node r
) const
198 std::map
<Node
, Node
>::const_iterator it
= d_eqc_singleton
.find(r
);
199 if (it
!= d_eqc_singleton
.end())
206 Node
SolverState::getBinaryOpTerm(Kind k
, Node r1
, Node r2
) const
208 std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >::const_iterator itk
=
210 if (itk
== d_bop_index
.end())
214 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it1
=
215 itk
->second
.find(r1
);
216 if (it1
== itk
->second
.end())
220 std::map
<Node
, Node
>::const_iterator it2
= it1
->second
.find(r2
);
221 if (it2
== it1
->second
.end())
228 bool SolverState::isEntailed(Node n
, bool polarity
) const
230 if (n
.getKind() == NOT
)
232 return isEntailed(n
[0], !polarity
);
234 else if (n
.getKind() == EQUAL
)
238 return areEqual(n
[0], n
[1]);
240 return areDisequal(n
[0], n
[1]);
242 else if (n
.getKind() == MEMBER
)
244 if (areEqual(n
, polarity
? d_true
: d_false
))
248 // check members cache
249 if (polarity
&& d_ee
->hasTerm(n
[1]))
251 Node r
= d_ee
->getRepresentative(n
[1]);
252 if (d_parent
.isMember(n
[0], r
))
258 else if (n
.getKind() == AND
|| n
.getKind() == OR
)
260 bool conj
= (n
.getKind() == AND
) == polarity
;
261 for (const Node
& nc
: n
)
263 bool isEnt
= isEntailed(nc
, polarity
);
271 else if (n
.isConst())
273 return (polarity
&& n
== d_true
) || (!polarity
&& n
== d_false
);
278 bool SolverState::isSetDisequalityEntailed(Node r1
, Node r2
) const
280 Assert(d_ee
->hasTerm(r1
) && d_ee
->getRepresentative(r1
) == r1
);
281 Assert(d_ee
->hasTerm(r2
) && d_ee
->getRepresentative(r2
) == r2
);
282 TypeNode tn
= r1
.getType();
283 Node re
= getEmptySetEqClass(tn
);
284 for (unsigned e
= 0; e
< 2; e
++)
286 Node a
= e
== 0 ? r1
: r2
;
287 Node b
= e
== 0 ? r2
: r1
;
288 if (isSetDisequalityEntailedInternal(a
, b
, re
))
296 bool SolverState::isSetDisequalityEntailedInternal(Node a
,
300 // if there are members in a
301 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpma
=
302 d_pol_mems
[0].find(a
);
303 if (itpma
== d_pol_mems
[0].end())
305 // no positive members, continue
311 if (!itpma
->second
.empty())
313 Trace("sets-deq") << "Disequality is satisfied because members are in "
314 << a
<< " and " << b
<< " is empty" << std::endl
;
319 // a should not be singleton
320 Assert(d_eqc_singleton
.find(a
) == d_eqc_singleton
.end());
324 std::map
<Node
, Node
>::const_iterator itsb
= d_eqc_singleton
.find(b
);
325 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itpmb
=
326 d_pol_mems
[1].find(b
);
327 std::vector
<Node
> prev
;
328 for (const std::pair
<const Node
, Node
>& itm
: itpma
->second
)
330 // if b is a singleton
331 if (itsb
!= d_eqc_singleton
.end())
333 if (areDisequal(itm
.first
, itsb
->second
[0]))
335 Trace("sets-deq") << "Disequality is satisfied because of "
336 << itm
.second
<< ", singleton eq " << itsb
->second
[0]
340 // or disequal with another member
341 for (const Node
& p
: prev
)
343 if (areDisequal(itm
.first
, p
))
346 << "Disequality is satisfied because of disequal members "
347 << itm
.first
<< " " << p
<< ", singleton eq " << std::endl
;
351 // if a has positive member that is negative member in b
353 else if (itpmb
!= d_pol_mems
[1].end())
355 for (const std::pair
<const Node
, Node
>& itnm
: itpmb
->second
)
357 if (areEqual(itm
.first
, itnm
.first
))
359 Trace("sets-deq") << "Disequality is satisfied because of "
360 << itm
.second
<< " " << itnm
.second
<< std::endl
;
365 prev
.push_back(itm
.first
);
370 Node
SolverState::getProxy(Node n
)
372 Kind nk
= n
.getKind();
373 if (nk
!= EMPTYSET
&& nk
!= SINGLETON
&& nk
!= INTERSECTION
&& nk
!= SETMINUS
374 && nk
!= UNION
&& nk
!= UNIVERSE_SET
)
378 NodeMap::const_iterator it
= d_proxy
.find(n
);
379 if (it
!= d_proxy
.end())
383 NodeManager
* nm
= NodeManager::currentNM();
384 Node k
= d_skCache
.mkTypedSkolemCached(
385 n
.getType(), n
, SkolemCache::SK_PURIFY
, "sp");
387 d_proxy_to_term
[k
] = n
;
388 Node eq
= k
.eqNode(n
);
389 Trace("sets-lemma") << "Sets::Lemma : " << eq
<< " by proxy" << std::endl
;
390 d_parent
.getOutputChannel()->lemma(eq
);
393 Node slem
= nm
->mkNode(MEMBER
, n
[0], k
);
394 Trace("sets-lemma") << "Sets::Lemma : " << slem
<< " by singleton"
396 d_parent
.getOutputChannel()->lemma(slem
);
401 Node
SolverState::getCongruent(Node n
) const
403 Assert(d_ee
->hasTerm(n
));
404 std::map
<Node
, Node
>::const_iterator it
= d_congruent
.find(n
);
405 if (it
== d_congruent
.end())
411 bool SolverState::isCongruent(Node n
) const
413 return d_congruent
.find(n
) != d_congruent
.end();
416 Node
SolverState::getEmptySet(TypeNode tn
)
418 std::map
<TypeNode
, Node
>::iterator it
= d_emptyset
.find(tn
);
419 if (it
!= d_emptyset
.end())
423 Node n
= NodeManager::currentNM()->mkConst(EmptySet(tn
));
427 Node
SolverState::getUnivSet(TypeNode tn
)
429 std::map
<TypeNode
, Node
>::iterator it
= d_univset
.find(tn
);
430 if (it
!= d_univset
.end())
434 NodeManager
* nm
= NodeManager::currentNM();
435 Node n
= nm
->mkNullaryOperator(tn
, UNIVERSE_SET
);
436 for (it
= d_univset
.begin(); it
!= d_univset
.end(); ++it
)
440 if (tn
.isSubtypeOf(it
->first
))
445 else if (it
->first
.isSubtypeOf(tn
))
452 Node ulem
= nm
->mkNode(SUBSET
, n1
, n2
);
453 Trace("sets-lemma") << "Sets::Lemma : " << ulem
<< " by univ-type"
455 d_parent
.getOutputChannel()->lemma(ulem
);
462 Node
SolverState::getTypeConstraintSkolem(Node n
, TypeNode tn
)
464 std::map
<TypeNode
, Node
>::iterator it
= d_tc_skolem
[n
].find(tn
);
465 if (it
== d_tc_skolem
[n
].end())
467 Node k
= NodeManager::currentNM()->mkSkolem("tc_k", tn
);
468 d_tc_skolem
[n
][tn
] = k
;
474 const std::vector
<Node
>& SolverState::getNonVariableSets(Node r
) const
476 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_nvar_sets
.find(r
);
477 if (it
== d_nvar_sets
.end())
484 Node
SolverState::getVariableSet(Node r
) const
486 std::map
<Node
, Node
>::const_iterator it
= d_var_set
.find(r
);
487 if (it
!= d_var_set
.end())
494 const std::vector
<Node
>& SolverState::getComprehensionSets(Node r
) const
496 std::map
<Node
, std::vector
<Node
> >::const_iterator it
= d_compSets
.find(r
);
497 if (it
== d_compSets
.end())
504 const std::map
<Node
, Node
>& SolverState::getMembers(Node r
) const
506 return getMembersInternal(r
, 0);
508 const std::map
<Node
, Node
>& SolverState::getNegativeMembers(Node r
) const
510 return getMembersInternal(r
, 1);
512 const std::map
<Node
, Node
>& SolverState::getMembersInternal(Node r
,
515 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator itp
=
516 d_pol_mems
[i
].find(r
);
517 if (itp
== d_pol_mems
[i
].end())
524 bool SolverState::hasMembers(Node r
) const
526 std::map
<Node
, std::map
<Node
, Node
> >::const_iterator it
=
527 d_pol_mems
[0].find(r
);
528 if (it
== d_pol_mems
[0].end())
532 return !it
->second
.empty();
534 const std::map
<Kind
, std::map
<Node
, std::map
<Node
, Node
> > >&
535 SolverState::getBinaryOpIndex() const
539 const std::map
<Kind
, std::vector
<Node
> >& SolverState::getOperatorList() const
544 const std::vector
<Node
>& SolverState::getComprehensionSets() const
546 return d_allCompSets
;
549 void SolverState::debugPrintSet(Node s
, const char* c
) const
551 if (s
.getNumChildren() == 0)
553 NodeMap::const_iterator it
= d_proxy_to_term
.find(s
);
554 if (it
!= d_proxy_to_term
.end())
556 debugPrintSet((*it
).second
, c
);
565 Trace(c
) << "(" << s
.getOperator();
566 for (const Node
& sc
: s
)
569 debugPrintSet(sc
, c
);
575 const vector
<Node
> SolverState::getSetsEqClasses(const TypeNode
& t
) const
577 vector
<Node
> representatives
;
578 for (const Node
& eqc
: getSetsEqClasses())
580 if (eqc
.getType().getSetElementType() == t
)
582 representatives
.push_back(eqc
);
585 return representatives
;
589 } // namespace theory