1 /******************************************************************************
2 * Top contributors (to current version):
3 * Mudathir Mohamed, Andrew Reynolds, Gereon Kremer
5 * This file is part of the cvc5 project.
7 * Copyright (c) 2009-2021 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.
11 * ****************************************************************************
13 * Inference generator utility.
16 #include "inference_generator.h"
18 #include "expr/attribute.h"
19 #include "expr/bound_var_manager.h"
20 #include "expr/dtype_cons.h"
21 #include "expr/emptybag.h"
22 #include "expr/skolem_manager.h"
23 #include "theory/bags/bags_utils.h"
24 #include "theory/bags/inference_manager.h"
25 #include "theory/bags/solver_state.h"
26 #include "theory/datatypes/tuple_utils.h"
27 #include "theory/quantifiers/fmf/bounded_integers.h"
28 #include "theory/uf/equality_engine.h"
29 #include "util/rational.h"
31 using namespace cvc5::kind
;
32 using namespace cvc5::theory::datatypes
;
38 InferenceGenerator::InferenceGenerator(SolverState
* state
, InferenceManager
* im
)
39 : d_state(state
), d_im(im
)
41 d_nm
= NodeManager::currentNM();
42 d_sm
= d_nm
->getSkolemManager();
43 d_true
= d_nm
->mkConst(true);
44 d_zero
= d_nm
->mkConstInt(Rational(0));
45 d_one
= d_nm
->mkConstInt(Rational(1));
48 InferInfo
InferenceGenerator::nonNegativeCount(Node n
, Node e
)
50 Assert(n
.getType().isBag());
51 Assert(e
.getType().isSubtypeOf(n
.getType().getBagElementType()));
53 InferInfo
inferInfo(d_im
, InferenceId::BAGS_NON_NEGATIVE_COUNT
);
54 Node count
= d_nm
->mkNode(BAG_COUNT
, e
, n
);
55 Node gte
= d_nm
->mkNode(GEQ
, count
, d_zero
);
56 inferInfo
.d_conclusion
= gte
;
60 InferInfo
InferenceGenerator::nonNegativeCardinality(Node n
)
62 InferInfo
inferInfo(d_im
, InferenceId::BAGS_NON_NEGATIVE_COUNT
);
63 Node gte
= d_nm
->mkNode(GEQ
, n
, d_zero
);
64 inferInfo
.d_conclusion
= gte
;
68 InferInfo
InferenceGenerator::bagMake(Node n
)
70 Assert(n
.getKind() == BAG_MAKE
);
73 * (and (< c 1) (= (bag x c) (as bag.empty (Bag E))))
74 * (and (>= c 1) (not (= (bag x c) (as bag.empty (Bag E))))
78 InferInfo
inferInfo(d_im
, InferenceId::BAGS_BAG_MAKE_SPLIT
);
79 Node empty
= d_nm
->mkConst(EmptyBag(n
.getType()));
80 Node equal
= d_nm
->mkNode(EQUAL
, n
, empty
);
81 Node geq
= d_nm
->mkNode(GEQ
, c
, d_one
);
82 Node isEmpty
= geq
.notNode().andNode(equal
);
83 Node isNotEmpty
= geq
.andNode(equal
.notNode());
84 Node orNode
= isEmpty
.orNode(isNotEmpty
);
85 inferInfo
.d_conclusion
= orNode
;
89 InferInfo
InferenceGenerator::bagMake(Node n
, Node e
)
91 Assert(n
.getKind() == BAG_MAKE
);
92 Assert(e
.getType().isSubtypeOf(n
.getType().getBagElementType()));
95 * (ite (and (= e x) (>= c 1))
96 * (= (bag.count e skolem) c)
97 * (= (bag.count e skolem) 0))
101 InferInfo
inferInfo(d_im
, InferenceId::BAGS_BAG_MAKE
);
102 Node same
= d_nm
->mkNode(EQUAL
, e
, x
);
103 Node geq
= d_nm
->mkNode(GEQ
, c
, d_one
);
104 Node andNode
= same
.andNode(geq
);
105 Node skolem
= getSkolem(n
, inferInfo
);
106 Node count
= getMultiplicityTerm(e
, skolem
);
107 Node equalC
= d_nm
->mkNode(EQUAL
, count
, c
);
108 Node equalZero
= d_nm
->mkNode(EQUAL
, count
, d_zero
);
109 Node ite
= d_nm
->mkNode(ITE
, andNode
, equalC
, equalZero
);
110 inferInfo
.d_conclusion
= ite
;
115 * A bound variable corresponding to the universally quantified integer
116 * variable used to range over the distinct elements in a bag, used
117 * for axiomatizing the behavior of some term.
119 struct FirstIndexVarAttributeId
122 typedef expr::Attribute
<FirstIndexVarAttributeId
, Node
> FirstIndexVarAttribute
;
125 * A bound variable corresponding to the universally quantified integer
126 * variable used to range over the distinct elements in a bag, used
127 * for axiomatizing the behavior of some term.
129 struct SecondIndexVarAttributeId
132 typedef expr::Attribute
<SecondIndexVarAttributeId
, Node
>
133 SecondIndexVarAttribute
;
135 struct BagsDeqAttributeId
138 typedef expr::Attribute
<BagsDeqAttributeId
, Node
> BagsDeqAttribute
;
140 InferInfo
InferenceGenerator::bagDisequality(Node n
)
142 Assert(n
.getKind() == EQUAL
&& n
[0].getType().isBag());
147 InferInfo
inferInfo(d_im
, InferenceId::BAGS_DISEQUALITY
);
149 TypeNode elementType
= A
.getType().getBagElementType();
150 BoundVarManager
* bvm
= d_nm
->getBoundVarManager();
151 Node element
= bvm
->mkBoundVar
<BagsDeqAttribute
>(n
, elementType
);
153 d_sm
->mkSkolem(element
,
156 "an extensional lemma for disequality of two bags");
158 Node countA
= getMultiplicityTerm(skolem
, A
);
159 Node countB
= getMultiplicityTerm(skolem
, B
);
161 Node disEqual
= countA
.eqNode(countB
).notNode();
163 inferInfo
.d_premises
.push_back(n
.notNode());
164 inferInfo
.d_conclusion
= disEqual
;
168 Node
InferenceGenerator::getSkolem(Node
& n
, InferInfo
& inferInfo
)
170 Node skolem
= d_sm
->mkPurifySkolem(n
, "skolem_bag", "skolem bag");
171 inferInfo
.d_skolems
[n
] = skolem
;
175 InferInfo
InferenceGenerator::empty(Node n
, Node e
)
177 Assert(n
.getKind() == BAG_EMPTY
);
178 Assert(e
.getType() == n
.getType().getBagElementType());
180 InferInfo
inferInfo(d_im
, InferenceId::BAGS_EMPTY
);
181 Node skolem
= getSkolem(n
, inferInfo
);
182 Node count
= getMultiplicityTerm(e
, skolem
);
184 Node equal
= count
.eqNode(d_zero
);
185 inferInfo
.d_conclusion
= equal
;
189 InferInfo
InferenceGenerator::unionDisjoint(Node n
, Node e
)
191 Assert(n
.getKind() == BAG_UNION_DISJOINT
&& n
[0].getType().isBag());
192 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
196 InferInfo
inferInfo(d_im
, InferenceId::BAGS_UNION_DISJOINT
);
198 Node countA
= getMultiplicityTerm(e
, A
);
199 Node countB
= getMultiplicityTerm(e
, B
);
201 Node skolem
= getSkolem(n
, inferInfo
);
202 Node count
= getMultiplicityTerm(e
, skolem
);
204 Node sum
= d_nm
->mkNode(ADD
, countA
, countB
);
205 Node equal
= count
.eqNode(sum
);
207 inferInfo
.d_conclusion
= equal
;
211 InferInfo
InferenceGenerator::unionMax(Node n
, Node e
)
213 Assert(n
.getKind() == BAG_UNION_MAX
&& n
[0].getType().isBag());
214 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
218 InferInfo
inferInfo(d_im
, InferenceId::BAGS_UNION_MAX
);
220 Node countA
= getMultiplicityTerm(e
, A
);
221 Node countB
= getMultiplicityTerm(e
, B
);
223 Node skolem
= getSkolem(n
, inferInfo
);
224 Node count
= getMultiplicityTerm(e
, skolem
);
226 Node gt
= d_nm
->mkNode(GT
, countA
, countB
);
227 Node max
= d_nm
->mkNode(ITE
, gt
, countA
, countB
);
228 Node equal
= count
.eqNode(max
);
230 inferInfo
.d_conclusion
= equal
;
234 InferInfo
InferenceGenerator::intersection(Node n
, Node e
)
236 Assert(n
.getKind() == BAG_INTER_MIN
&& n
[0].getType().isBag());
237 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
241 InferInfo
inferInfo(d_im
, InferenceId::BAGS_INTERSECTION_MIN
);
243 Node countA
= getMultiplicityTerm(e
, A
);
244 Node countB
= getMultiplicityTerm(e
, B
);
245 Node skolem
= getSkolem(n
, inferInfo
);
246 Node count
= getMultiplicityTerm(e
, skolem
);
248 Node lt
= d_nm
->mkNode(LT
, countA
, countB
);
249 Node min
= d_nm
->mkNode(ITE
, lt
, countA
, countB
);
250 Node equal
= count
.eqNode(min
);
251 inferInfo
.d_conclusion
= equal
;
255 InferInfo
InferenceGenerator::differenceSubtract(Node n
, Node e
)
257 Assert(n
.getKind() == BAG_DIFFERENCE_SUBTRACT
&& n
[0].getType().isBag());
258 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
262 InferInfo
inferInfo(d_im
, InferenceId::BAGS_DIFFERENCE_SUBTRACT
);
264 Node countA
= getMultiplicityTerm(e
, A
);
265 Node countB
= getMultiplicityTerm(e
, B
);
266 Node skolem
= getSkolem(n
, inferInfo
);
267 Node count
= getMultiplicityTerm(e
, skolem
);
269 Node subtract
= d_nm
->mkNode(SUB
, countA
, countB
);
270 Node gte
= d_nm
->mkNode(GEQ
, countA
, countB
);
271 Node difference
= d_nm
->mkNode(ITE
, gte
, subtract
, d_zero
);
272 Node equal
= count
.eqNode(difference
);
273 inferInfo
.d_conclusion
= equal
;
277 InferInfo
InferenceGenerator::differenceRemove(Node n
, Node e
)
279 Assert(n
.getKind() == BAG_DIFFERENCE_REMOVE
&& n
[0].getType().isBag());
280 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
284 InferInfo
inferInfo(d_im
, InferenceId::BAGS_DIFFERENCE_REMOVE
);
286 Node countA
= getMultiplicityTerm(e
, A
);
287 Node countB
= getMultiplicityTerm(e
, B
);
289 Node skolem
= getSkolem(n
, inferInfo
);
290 Node count
= getMultiplicityTerm(e
, skolem
);
292 Node notInB
= d_nm
->mkNode(LEQ
, countB
, d_zero
);
293 Node difference
= d_nm
->mkNode(ITE
, notInB
, countA
, d_zero
);
294 Node equal
= count
.eqNode(difference
);
295 inferInfo
.d_conclusion
= equal
;
299 InferInfo
InferenceGenerator::duplicateRemoval(Node n
, Node e
)
301 Assert(n
.getKind() == BAG_DUPLICATE_REMOVAL
&& n
[0].getType().isBag());
302 Assert(e
.getType().isSubtypeOf(n
[0].getType().getBagElementType()));
305 InferInfo
inferInfo(d_im
, InferenceId::BAGS_DUPLICATE_REMOVAL
);
307 Node countA
= getMultiplicityTerm(e
, A
);
308 Node skolem
= getSkolem(n
, inferInfo
);
309 Node count
= getMultiplicityTerm(e
, skolem
);
311 Node gte
= d_nm
->mkNode(GEQ
, countA
, d_one
);
312 Node ite
= d_nm
->mkNode(ITE
, gte
, d_one
, d_zero
);
313 Node equal
= count
.eqNode(ite
);
314 inferInfo
.d_conclusion
= equal
;
318 InferInfo
InferenceGenerator::cardEmpty(const std::pair
<Node
, Node
>& pair
,
321 Assert(pair
.first
.getKind() == BAG_CARD
);
322 Assert(n
.getKind() == BAG_EMPTY
&& n
.getType() == pair
.first
[0].getType());
323 InferInfo
inferInfo(d_im
, InferenceId::BAGS_CARD
);
324 Node premise
= pair
.first
[0].eqNode(n
);
325 Node conclusion
= pair
.second
.eqNode(d_zero
);
326 inferInfo
.d_conclusion
= premise
.notNode().orNode(conclusion
);
330 InferInfo
InferenceGenerator::cardBagMake(const std::pair
<Node
, Node
>& pair
,
333 Assert(pair
.first
.getKind() == BAG_CARD
);
334 Assert(n
.getKind() == BAG_MAKE
&& n
.getType() == pair
.first
[0].getType());
336 // (and (= A (bag x c)) (>= 0 c))
337 // (= (bag.card A) c))
339 InferInfo
inferInfo(d_im
, InferenceId::BAGS_CARD
);
340 Node nonNegative
= d_nm
->mkNode(GEQ
, c
, d_zero
);
341 Node premise
= pair
.first
[0].eqNode(n
).andNode(nonNegative
);
342 Node conclusion
= pair
.second
.eqNode(c
);
343 inferInfo
.d_conclusion
= premise
.notNode().orNode(conclusion
);
347 InferInfo
InferenceGenerator::cardUnionDisjoint(Node premise
,
349 const std::set
<Node
>& children
)
351 Assert(premise
.getType().isBoolean());
352 Assert(!children
.empty());
353 InferInfo
inferInfo(d_im
, InferenceId::BAGS_CARD
);
355 std::set
<Node
>::iterator it
= children
.begin();
357 d_state
->registerBag(child
);
358 Node unionDisjoints
= child
;
359 Node card
= d_nm
->mkNode(BAG_CARD
, child
);
360 std::vector
<Node
> lemmas
;
361 lemmas
.push_back(d_state
->registerCardinalityTerm(card
));
362 Node sum
= d_state
->getCardinalitySkolem(card
);
364 while (it
!= children
.end())
367 d_state
->registerBag(child
);
369 d_nm
->mkNode(kind::BAG_UNION_DISJOINT
, unionDisjoints
, child
);
370 card
= d_nm
->mkNode(BAG_CARD
, child
);
371 lemmas
.push_back(d_state
->registerCardinalityTerm(card
));
372 d_state
->getCardinalitySkolem(card
);
373 Node skolem
= d_state
->getCardinalitySkolem(card
);
374 sum
= d_nm
->mkNode(ADD
, sum
, skolem
);
377 Node parentCard
= d_nm
->mkNode(BAG_CARD
, parent
);
378 lemmas
.push_back(d_state
->registerCardinalityTerm(parentCard
));
379 Node parentSkolem
= d_state
->getCardinalitySkolem(parentCard
);
381 Node bags
= parent
.eqNode(unionDisjoints
);
382 lemmas
.push_back(bags
);
383 Node cards
= parentSkolem
.eqNode(sum
);
384 lemmas
.push_back(cards
);
385 Node conclusion
= d_nm
->mkNode(AND
, lemmas
);
386 inferInfo
.d_conclusion
= premise
.notNode().orNode(conclusion
);
390 Node
InferenceGenerator::getMultiplicityTerm(Node element
, Node bag
)
392 Node count
= d_nm
->mkNode(BAG_COUNT
, element
, bag
);
396 std::tuple
<InferInfo
, Node
, Node
> InferenceGenerator::mapDownwards(Node n
,
399 Assert(n
.getKind() == BAG_MAP
&& n
[1].getType().isBag());
400 Assert(n
[0].getType().isFunction()
401 && n
[0].getType().getArgTypes().size() == 1);
402 Assert(e
.getType() == n
[0].getType().getRangeType());
404 InferInfo
inferInfo(d_im
, InferenceId::BAGS_MAP
);
408 // declare an uninterpreted function uf: Int -> T
409 TypeNode domainType
= f
.getType().getArgTypes()[0];
410 TypeNode ufType
= d_nm
->mkFunctionType(d_nm
->integerType(), domainType
);
412 d_sm
->mkSkolemFunction(SkolemFunId::BAGS_MAP_PREIMAGE
, ufType
, {n
, e
});
414 // declare uninterpreted function sum: Int -> Int
416 d_nm
->mkFunctionType(d_nm
->integerType(), d_nm
->integerType());
417 Node sum
= d_sm
->mkSkolemFunction(SkolemFunId::BAGS_MAP_SUM
, sumType
, {n
, e
});
420 Node sum_zero
= d_nm
->mkNode(APPLY_UF
, sum
, d_zero
);
421 Node baseCase
= d_nm
->mkNode(EQUAL
, sum_zero
, d_zero
);
423 // guess the size of the preimage of e
424 Node preImageSize
= d_sm
->mkDummySkolem("preImageSize", d_nm
->integerType());
426 // (= (sum preImageSize) (bag.count e skolem))
427 Node mapSkolem
= getSkolem(n
, inferInfo
);
428 Node countE
= getMultiplicityTerm(e
, mapSkolem
);
429 Node totalSum
= d_nm
->mkNode(APPLY_UF
, sum
, preImageSize
);
430 Node totalSumEqualCountE
= d_nm
->mkNode(EQUAL
, totalSum
, countE
);
433 // (let ((uf_i (uf i)))
434 // (let ((count_uf_i (bag.count uf_i A)))
436 // (and (>= i 1) (<= i preImageSize))
440 // (= (sum i) (+ (sum (- i 1)) count_uf_i))
443 // (and (< i j) (<= j preImageSize))
444 // (not (= (uf i) (uf j))))))
447 BoundVarManager
* bvm
= d_nm
->getBoundVarManager();
448 Node i
= bvm
->mkBoundVar
<FirstIndexVarAttribute
>(n
, "i", d_nm
->integerType());
450 bvm
->mkBoundVar
<SecondIndexVarAttribute
>(n
, "j", d_nm
->integerType());
451 Node iList
= d_nm
->mkNode(BOUND_VAR_LIST
, i
);
452 Node jList
= d_nm
->mkNode(BOUND_VAR_LIST
, j
);
453 Node iPlusOne
= d_nm
->mkNode(ADD
, i
, d_one
);
454 Node iMinusOne
= d_nm
->mkNode(SUB
, i
, d_one
);
455 Node uf_i
= d_nm
->mkNode(APPLY_UF
, uf
, i
);
456 Node uf_j
= d_nm
->mkNode(APPLY_UF
, uf
, j
);
457 Node f_uf_i
= d_nm
->mkNode(APPLY_UF
, f
, uf_i
);
458 Node uf_iPlusOne
= d_nm
->mkNode(APPLY_UF
, uf
, iPlusOne
);
459 Node uf_iMinusOne
= d_nm
->mkNode(APPLY_UF
, uf
, iMinusOne
);
460 Node interval_i
= d_nm
->mkNode(
461 AND
, d_nm
->mkNode(GEQ
, i
, d_one
), d_nm
->mkNode(LEQ
, i
, preImageSize
));
462 Node sum_i
= d_nm
->mkNode(APPLY_UF
, sum
, i
);
463 Node sum_iPlusOne
= d_nm
->mkNode(APPLY_UF
, sum
, iPlusOne
);
464 Node sum_iMinusOne
= d_nm
->mkNode(APPLY_UF
, sum
, iMinusOne
);
465 Node count_iMinusOne
= d_nm
->mkNode(BAG_COUNT
, uf_iMinusOne
, A
);
466 Node count_uf_i
= d_nm
->mkNode(BAG_COUNT
, uf_i
, A
);
468 d_nm
->mkNode(EQUAL
, sum_i
, d_nm
->mkNode(ADD
, sum_iMinusOne
, count_uf_i
));
469 Node f_iEqualE
= d_nm
->mkNode(EQUAL
, f_uf_i
, e
);
470 Node geqOne
= d_nm
->mkNode(GEQ
, count_uf_i
, d_one
);
472 // i < j <= preImageSize
473 Node interval_j
= d_nm
->mkNode(
474 AND
, d_nm
->mkNode(LT
, i
, j
), d_nm
->mkNode(LEQ
, j
, preImageSize
));
476 Node uf_i_equals_uf_j
= d_nm
->mkNode(EQUAL
, uf_i
, uf_j
);
477 Node notEqual
= d_nm
->mkNode(EQUAL
, uf_i
, uf_j
).negate();
478 Node body_j
= d_nm
->mkNode(OR
, interval_j
.negate(), notEqual
);
479 Node forAll_j
= quantifiers::BoundedIntegers::mkBoundedForall(jList
, body_j
);
481 d_nm
->mkNode(AND
, {f_iEqualE
, geqOne
, inductiveCase
, forAll_j
});
482 Node body_i
= d_nm
->mkNode(OR
, interval_i
.negate(), andNode
);
483 Node forAll_i
= quantifiers::BoundedIntegers::mkBoundedForall(iList
, body_i
);
484 Node preImageGTE_zero
= d_nm
->mkNode(GEQ
, preImageSize
, d_zero
);
485 Node conclusion
= d_nm
->mkNode(
486 AND
, {baseCase
, totalSumEqualCountE
, forAll_i
, preImageGTE_zero
});
487 inferInfo
.d_conclusion
= conclusion
;
489 std::map
<Node
, Node
> m
;
491 Trace("bags::InferenceGenerator::mapDownwards")
492 << "conclusion: " << inferInfo
.d_conclusion
<< std::endl
;
493 return std::tuple(inferInfo
, uf
, preImageSize
);
496 InferInfo
InferenceGenerator::mapUpwards(
497 Node n
, Node uf
, Node preImageSize
, Node y
, Node x
)
499 Assert(n
.getKind() == BAG_MAP
&& n
[1].getType().isBag());
500 Assert(n
[0].getType().isFunction()
501 && n
[0].getType().getArgTypes().size() == 1);
503 InferInfo
inferInfo(d_im
, InferenceId::BAGS_MAP
);
507 Node countA
= getMultiplicityTerm(x
, A
);
508 Node xInA
= d_nm
->mkNode(GEQ
, countA
, d_one
);
509 Node notEqual
= d_nm
->mkNode(EQUAL
, d_nm
->mkNode(APPLY_UF
, f
, x
), y
).negate();
511 Node k
= d_sm
->mkDummySkolem("k", d_nm
->integerType());
512 Node inRange
= d_nm
->mkNode(
513 AND
, d_nm
->mkNode(GEQ
, k
, d_one
), d_nm
->mkNode(LEQ
, k
, preImageSize
));
514 Node equal
= d_nm
->mkNode(EQUAL
, d_nm
->mkNode(APPLY_UF
, uf
, k
), x
);
515 Node andNode
= d_nm
->mkNode(AND
, inRange
, equal
);
516 Node orNode
= d_nm
->mkNode(OR
, notEqual
, andNode
);
517 Node implies
= d_nm
->mkNode(IMPLIES
, xInA
, orNode
);
518 inferInfo
.d_conclusion
= implies
;
519 Trace("bags::InferenceGenerator::mapUpwards")
520 << "conclusion: " << inferInfo
.d_conclusion
<< std::endl
;
524 InferInfo
InferenceGenerator::filterDownwards(Node n
, Node e
)
526 Assert(n
.getKind() == BAG_FILTER
&& n
[1].getType().isBag());
527 Assert(e
.getType().isSubtypeOf(n
[1].getType().getBagElementType()));
531 InferInfo
inferInfo(d_im
, InferenceId::BAGS_FILTER_DOWN
);
533 Node countA
= getMultiplicityTerm(e
, A
);
534 Node skolem
= getSkolem(n
, inferInfo
);
535 Node count
= getMultiplicityTerm(e
, skolem
);
537 Node member
= d_nm
->mkNode(GEQ
, count
, d_one
);
538 Node pOfe
= d_nm
->mkNode(APPLY_UF
, P
, e
);
539 Node equal
= count
.eqNode(countA
);
541 inferInfo
.d_conclusion
= pOfe
.andNode(equal
);
542 inferInfo
.d_premises
.push_back(member
);
546 InferInfo
InferenceGenerator::filterUpwards(Node n
, Node e
)
548 Assert(n
.getKind() == BAG_FILTER
&& n
[1].getType().isBag());
549 Assert(e
.getType().isSubtypeOf(n
[1].getType().getBagElementType()));
553 InferInfo
inferInfo(d_im
, InferenceId::BAGS_FILTER_UP
);
555 Node countA
= getMultiplicityTerm(e
, A
);
556 Node skolem
= getSkolem(n
, inferInfo
);
557 Node count
= getMultiplicityTerm(e
, skolem
);
559 Node member
= d_nm
->mkNode(GEQ
, countA
, d_one
);
560 Node pOfe
= d_nm
->mkNode(APPLY_UF
, P
, e
);
561 Node equal
= count
.eqNode(countA
);
562 Node included
= pOfe
.andNode(equal
);
563 Node equalZero
= count
.eqNode(d_zero
);
564 Node excluded
= pOfe
.notNode().andNode(equalZero
);
565 inferInfo
.d_conclusion
= included
.orNode(excluded
);
566 inferInfo
.d_premises
.push_back(member
);
570 InferInfo
InferenceGenerator::productUp(Node n
, Node e1
, Node e2
)
572 Assert(n
.getKind() == TABLE_PRODUCT
);
575 Node tuple
= BagsUtils::constructProductTuple(n
, e1
, e2
);
577 InferInfo
inferInfo(d_im
, InferenceId::TABLES_PRODUCT_UP
);
579 Node countA
= getMultiplicityTerm(e1
, A
);
580 Node countB
= getMultiplicityTerm(e2
, B
);
582 Node skolem
= getSkolem(n
, inferInfo
);
583 Node count
= getMultiplicityTerm(tuple
, skolem
);
585 Node multiply
= d_nm
->mkNode(MULT
, countA
, countB
);
586 inferInfo
.d_conclusion
= count
.eqNode(multiply
);
591 InferInfo
InferenceGenerator::productDown(Node n
, Node e
)
593 Assert(n
.getKind() == TABLE_PRODUCT
);
594 Assert(e
.getType().isSubtypeOf(n
.getType().getBagElementType()));
599 TypeNode tupleBType
= B
.getType().getBagElementType();
600 TypeNode tupleAType
= A
.getType().getBagElementType();
601 size_t tupleALength
= tupleAType
.getTupleLength();
602 size_t productTupleLength
= n
.getType().getBagElementType().getTupleLength();
604 std::vector
<Node
> elements
= TupleUtils::getTupleElements(e
);
605 Node a
= TupleUtils::constructTupleFromElements(
606 tupleAType
, elements
, 0, tupleALength
- 1);
607 Node b
= TupleUtils::constructTupleFromElements(
608 tupleBType
, elements
, tupleALength
, productTupleLength
- 1);
610 InferInfo
inferInfo(d_im
, InferenceId::TABLES_PRODUCT_DOWN
);
612 Node countA
= getMultiplicityTerm(a
, A
);
613 Node countB
= getMultiplicityTerm(b
, B
);
615 Node skolem
= getSkolem(n
, inferInfo
);
616 Node count
= getMultiplicityTerm(e
, skolem
);
618 Node multiply
= d_nm
->mkNode(MULT
, countA
, countB
);
619 inferInfo
.d_conclusion
= count
.eqNode(multiply
);
625 } // namespace theory