switch (atom.getKind())
{
case kind::BAG_CHOOSE: return expandChooseOperator(atom, lems);
+ case kind::BAG_CARD: return expandCardOperator(atom, lems);
default: return TrustNode::null();
}
}
Node ite = nm->mkNode(ITE, isEmpty, equal, geqOneAndEqual);
Node ret = sm->mkSkolem(x, ite, "kBagChoose");
lems.push_back(SkolemLemma(ret, nullptr));
+ Trace("TheoryBags::ppRewrite")
+ << "ppRewrite(" << node << ") = " << ret << std::endl;
return TrustNode::mkTrustRewrite(node, ret, nullptr);
}
+TrustNode TheoryBags::expandCardOperator(TNode n,
+ std::vector<SkolemLemma>& vector)
+{
+ if (d_env.getLogicInfo().isHigherOrder())
+ {
+ // (bag.card A) = (bag.count 1 (bag.map (lambda ((x E)) 1) A)),
+ // where E is the type of elements of A
+ NodeManager* nm = NodeManager::currentNM();
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ TypeNode type = n[0].getType().getBagElementType();
+ Node x = nm->mkBoundVar("x", type);
+ Node lambda = nm->mkNode(LAMBDA, nm->mkNode(BOUND_VAR_LIST, x), one);
+ Node map = nm->mkNode(kind::BAG_MAP, lambda, n[0]);
+ Node countOne = nm->mkNode(kind::BAG_COUNT, one, map);
+ Trace("TheoryBags::ppRewrite")
+ << "ppRewrite(" << n << ") = " << countOne << std::endl;
+ return TrustNode::mkTrustRewrite(n, countOne, nullptr);
+ }
+ return TrustNode::null();
+}
+
void TheoryBags::postCheck(Effort effort)
{
d_im.doPendingFacts();
Trace("bags::TheoryBags::preRegisterTerm") << n << std::endl;
switch (n.getKind())
{
- case BAG_CARD:
case BAG_FROM_SET:
case BAG_TO_SET:
case BAG_IS_SINGLETON:
/** expand the definition of the bag.choose operator */
TrustNode expandChooseOperator(const Node& node,
std::vector<SkolemLemma>& lems);
+ /** expand the definition of bag.card operator */
+ TrustNode expandCardOperator(TNode n, std::vector<SkolemLemma>& lems);
/** The state of the bags solver at full effort */
SolverState d_state;