Theory of Bags
1/******************************************************************************
2 * Top contributors (to current version):
3 * Mudathir Mohamed, Aina Niemetz
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2024 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 * ****************************************************************************
12 *
13 * A simple demonstration of reasoning about bags.
14 */
15
16#include <cvc5/cvc5.h>
17
18#include <iostream>
19
20using namespace std;
21using namespace cvc5;
22
23int main()
24{
25 TermManager tm;
26 Solver slv(tm);
27 slv.setLogic("ALL");
28 // Produce models
29 slv.setOption("produce-models", "true");
30 slv.setOption("incremental", "true");
31
32 Sort bag = tm.mkBagSort(tm.getStringSort());
33 Term A = tm.mkConst(bag, "A");
34 Term B = tm.mkConst(bag, "B");
35 Term C = tm.mkConst(bag, "C");
36 Term x = tm.mkConst(tm.getStringSort(), "x");
37
38 Term intersectionAC = tm.mkTerm(Kind::BAG_INTER_MIN, {A, C});
39 Term intersectionBC = tm.mkTerm(Kind::BAG_INTER_MIN, {B, C});
40
41 // union disjoint does not distribute over intersection
42 {
43 Term unionDisjointAB = tm.mkTerm(Kind::BAG_UNION_DISJOINT, {A, B});
44 Term lhs = tm.mkTerm(Kind::BAG_INTER_MIN, {unionDisjointAB, C});
45 Term rhs =
46 tm.mkTerm(Kind::BAG_UNION_DISJOINT, {intersectionAC, intersectionBC});
47 Term guess = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
48 cout << "cvc5 reports: " << guess.notTerm() << " is "
49 << slv.checkSatAssuming(guess.notTerm()) << "." << endl;
50
51 cout << A << ": " << slv.getValue(A) << endl;
52 cout << B << ": " << slv.getValue(B) << endl;
53 cout << C << ": " << slv.getValue(C) << endl;
54 cout << lhs << ": " << slv.getValue(lhs) << endl;
55 cout << rhs << ": " << slv.getValue(rhs) << endl;
56 }
57
58 // union max distributes over intersection
59 {
60 Term unionMaxAB = tm.mkTerm(Kind::BAG_UNION_MAX, {A, B});
61 Term lhs = tm.mkTerm(Kind::BAG_INTER_MIN, {unionMaxAB, C});
62 Term rhs = tm.mkTerm(Kind::BAG_UNION_MAX, {intersectionAC, intersectionBC});
63 Term theorem = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
64 cout << "cvc5 reports: " << theorem.notTerm() << " is "
65 << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
66 }
67
68 // Verify emptbag is a subbag of any bag
69 {
70 Term emptybag = tm.mkEmptyBag(bag);
71 Term theorem = tm.mkTerm(Kind::BAG_SUBBAG, {emptybag, A});
72
73 cout << "cvc5 reports: " << theorem.notTerm() << " is "
74 << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
75 }
76
77 // find an element with multiplicity 4 in the disjoint union of
78 // ; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
79
80 {
81 Term one = tm.mkInteger(1);
82 Term two = tm.mkInteger(2);
83 Term three = tm.mkInteger(3);
84 Term four = tm.mkInteger(4);
85 Term a = tm.mkString("a");
86 Term b = tm.mkString("b");
87 Term c = tm.mkString("c");
88
89 Term bag_a_2 = tm.mkTerm(Kind::BAG_MAKE, {a, two});
90 Term bag_b_3 = tm.mkTerm(Kind::BAG_MAKE, {b, three});
91 Term bag_b_1 = tm.mkTerm(Kind::BAG_MAKE, {b, one});
92 Term bag_c_2 = tm.mkTerm(Kind::BAG_MAKE, {c, two});
93 Term bag_a_2_b_3 = tm.mkTerm(Kind::BAG_UNION_DISJOINT, {bag_a_2, bag_b_3});
94 Term bag_b_1_c_2 = tm.mkTerm(Kind::BAG_UNION_DISJOINT, {bag_b_1, bag_c_2});
95 Term union_disjoint =
96 tm.mkTerm(Kind::BAG_UNION_DISJOINT, {bag_a_2_b_3, bag_b_1_c_2});
97
98 Term count_x = tm.mkTerm(Kind::BAG_COUNT, {x, union_disjoint});
99 Term e = tm.mkTerm(Kind::EQUAL, {four, count_x});
100 Result result = slv.checkSatAssuming(e);
101
102 cout << "cvc5 reports: " << e << " is " << result << "." << endl;
103 if (result.isSat())
104 {
105 cout << x << ": " << slv.getValue(x) << endl;
106 }
107 }
108}
1/******************************************************************************
2 * Top contributors (to current version):
3 * Aina Niemetz
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2024 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 * ****************************************************************************
12 *
13 * A simple demonstration of reasoning about bags.
14 */
15
16#include <cvc5/c/cvc5.h>
17#include <stdio.h>
18
19int main()
20{
21 Cvc5TermManager* tm = cvc5_term_manager_new();
22 Cvc5* slv = cvc5_new(tm);
23 cvc5_set_logic(slv, "ALL");
24 // Produce models
25 cvc5_set_option(slv, "produce-models", "true");
26 cvc5_set_option(slv, "incremental", "true");
27
28 Cvc5Sort bag = cvc5_mk_bag_sort(tm, cvc5_get_string_sort(tm));
29 Cvc5Term A = cvc5_mk_const(tm, bag, "A");
30 Cvc5Term B = cvc5_mk_const(tm, bag, "B");
31 Cvc5Term C = cvc5_mk_const(tm, bag, "C");
32 Cvc5Term x = cvc5_mk_const(tm, cvc5_get_string_sort(tm), "x");
33
34 Cvc5Term args[2];
35
36 args[0] = A;
37 args[1] = C;
38 Cvc5Term interAC = cvc5_mk_term(tm, CVC5_KIND_BAG_INTER_MIN, 2, args);
39 args[0] = B;
40 args[1] = C;
41 Cvc5Term interBC = cvc5_mk_term(tm, CVC5_KIND_BAG_INTER_MIN, 2, args);
42
43 // union disjoint does not distribute over intersection
44 {
45 args[0] = A;
46 args[1] = B;
47 Cvc5Term union_disAB =
48 cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_DISJOINT, 2, args);
49
50 args[0] = union_disAB;
51 args[1] = C;
52 Cvc5Term lhs = cvc5_mk_term(tm, CVC5_KIND_BAG_INTER_MIN, 2, args);
53
54 args[0] = interAC;
55 args[1] = interBC;
56 Cvc5Term rhs = cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_DISJOINT, 2, args);
57
58 args[0] = lhs;
59 args[1] = rhs;
60 Cvc5Term guess = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args);
61
62 Cvc5Term args_not[1] = {guess};
63 Cvc5Term not_guess = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args_not);
64
65 Cvc5Term assumptions[1] = {not_guess};
66 printf("cvc5 reports: %s is %s.\n",
67 cvc5_term_to_string(not_guess),
68 cvc5_result_to_string(cvc5_check_sat_assuming(slv, 1, assumptions)));
69
70 // Note: The const char* returned by cvc5_term_to_string is only valid
71 // until the next call to cvc5_term_to_string. Thus, we cannot
72 // chain calls to this function like this:
73 // printf("%s: %s\n",
74 // cvc5_term_to_string(A),
75 // cvc5_term_to_string(cvc5_get_value(slv, A)));
76 // Instead, we have to split such printf calls into two.
77 printf("%s: ", cvc5_term_to_string(A));
78 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, A)));
79
80 printf("%s: ", cvc5_term_to_string(B));
81 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, B)));
82
83 printf("%s: ", cvc5_term_to_string(C));
84 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, C)));
85
86 printf("%s: ", cvc5_term_to_string(lhs));
87 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, lhs)));
88
89 printf("%s: ", cvc5_term_to_string(rhs));
90 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, rhs)));
91 }
92
93 // union max distributes over intersection
94 {
95 args[0] = A;
96 args[1] = B;
97 Cvc5Term union_maxAB = cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_MAX, 2, args);
98
99 args[0] = union_maxAB;
100 args[1] = C;
101 Cvc5Term lhs = cvc5_mk_term(tm, CVC5_KIND_BAG_INTER_MIN, 2, args);
102
103 args[0] = interAC;
104 args[1] = interBC;
105 Cvc5Term rhs = cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_MAX, 2, args);
106
107 args[0] = lhs;
108 args[1] = rhs;
109 Cvc5Term theorem = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args);
110
111 Cvc5Term not_args[1] = {theorem};
112 Cvc5Term not_theorem = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, not_args);
113 Cvc5Term assumptions[1] = {not_theorem};
114 printf("cvc5 reports: %s is %s.\n",
115 cvc5_term_to_string(not_theorem),
116 cvc5_result_to_string(cvc5_check_sat_assuming(slv, 1, assumptions)));
117 }
118
119 // Verify emptbag is a subbag of any bag
120 {
121 Cvc5Term empty_bag = cvc5_mk_empty_bag(tm, bag);
122 args[0] = empty_bag;
123 args[1] = A;
124 Cvc5Term theorem = cvc5_mk_term(tm, CVC5_KIND_BAG_SUBBAG, 2, args);
125
126 Cvc5Term not_args[1] = {theorem};
127 Cvc5Term not_theorem = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, not_args);
128 Cvc5Term assumptions[1] = {not_theorem};
129 printf("cvc5 reports: %s is %s.\n",
130 cvc5_term_to_string(not_theorem),
131 cvc5_result_to_string(cvc5_check_sat_assuming(slv, 1, assumptions)));
132 }
133
134 // find an element with multiplicity 4 in the disjoint union of
135 // ; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
136
137 {
138 Cvc5Term one = cvc5_mk_integer_int64(tm, 1);
139 Cvc5Term two = cvc5_mk_integer_int64(tm, 2);
140 Cvc5Term three = cvc5_mk_integer_int64(tm, 3);
141 Cvc5Term four = cvc5_mk_integer_int64(tm, 4);
142
143 Cvc5Term a = cvc5_mk_string(tm, "a", false);
144 Cvc5Term b = cvc5_mk_string(tm, "b", false);
145 Cvc5Term c = cvc5_mk_string(tm, "c", false);
146
147 args[0] = a;
148 args[1] = two;
149 Cvc5Term bag_a_2 = cvc5_mk_term(tm, CVC5_KIND_BAG_MAKE, 2, args);
150
151 args[0] = b;
152 args[1] = three;
153 Cvc5Term bag_b_3 = cvc5_mk_term(tm, CVC5_KIND_BAG_MAKE, 2, args);
154
155 args[0] = b;
156 args[1] = one;
157 Cvc5Term bag_b_1 = cvc5_mk_term(tm, CVC5_KIND_BAG_MAKE, 2, args);
158
159 args[0] = c;
160 args[1] = two;
161 Cvc5Term bag_c_2 = cvc5_mk_term(tm, CVC5_KIND_BAG_MAKE, 2, args);
162
163 args[0] = bag_a_2;
164 args[1] = bag_b_3;
165 Cvc5Term bag_a_2_b_3 =
166 cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_DISJOINT, 2, args);
167
168 args[0] = bag_b_1;
169 args[1] = bag_c_2;
170 Cvc5Term bag_b_1_c_2 =
171 cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_DISJOINT, 2, args);
172
173 args[0] = bag_a_2_b_3;
174 args[1] = bag_b_1_c_2;
175 Cvc5Term union_disjoint =
176 cvc5_mk_term(tm, CVC5_KIND_BAG_UNION_DISJOINT, 2, args);
177
178 args[0] = x;
179 args[1] = union_disjoint;
180 Cvc5Term count_x = cvc5_mk_term(tm, CVC5_KIND_BAG_COUNT, 2, args);
181
182 args[0] = four;
183 args[1] = count_x;
184 Cvc5Term e = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args);
185
186 Cvc5Term assumptions[1] = {e};
187 Cvc5Result result = cvc5_check_sat_assuming(slv, 1, assumptions);
188
189 printf("cvc5 reports: %s is %s.\n",
190 cvc5_term_to_string(e),
191 cvc5_result_to_string(result));
192
193 if (cvc5_result_is_sat(result))
194 {
195 printf("%s: ", cvc5_term_to_string(x));
196 printf("%s\n", cvc5_term_to_string(cvc5_get_value(slv, x)));
197 }
198 }
199
200 cvc5_delete(slv);
201 cvc5_term_manager_delete(tm);
202}
1/******************************************************************************
2 * Top contributors (to current version):
3 * Mudathir Mohamed, Andres Noetzli
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2024 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 * ****************************************************************************
12 *
13 * A simple demonstration of reasoning about bags with cvc5.
14 */
15
16import static io.github.cvc5.Kind.*;
17
18import io.github.cvc5.*;
19
20public class Bags
21{
22 public static void main(String args[]) throws CVC5ApiException
23
24 {
25 Solver slv = new Solver();
26 {
27 slv.setLogic("ALL");
28
29 // Produce models
30 slv.setOption("produce-models", "true");
31 slv.setOption("incremental", "true");
32
33 Sort bag = slv.mkBagSort(slv.getStringSort());
34 Term A = slv.mkConst(bag, "A");
35 Term B = slv.mkConst(bag, "B");
36 Term C = slv.mkConst(bag, "C");
37 Term x = slv.mkConst(slv.getStringSort(), "x");
38
39 Term intersectionAC = slv.mkTerm(BAG_INTER_MIN, new Term[] {A, C});
40 Term intersectionBC = slv.mkTerm(BAG_INTER_MIN, new Term[] {B, C});
41
42 // union disjoint does not distribute over intersection
43 {
44 Term unionDisjointAB = slv.mkTerm(BAG_UNION_DISJOINT, new Term[] {A, B});
45 Term lhs = slv.mkTerm(BAG_INTER_MIN, new Term[] {unionDisjointAB, C});
46 Term rhs = slv.mkTerm(BAG_UNION_DISJOINT, new Term[] {intersectionAC, intersectionBC});
47 Term guess = slv.mkTerm(EQUAL, new Term[] {lhs, rhs});
48
49 System.out.println("cvc5 reports: " + guess.notTerm() + " is "
50 + slv.checkSatAssuming(guess.notTerm()) + ".");
51
52 System.out.println(A + ": " + slv.getValue(A));
53 System.out.println(B + ": " + slv.getValue(B));
54 System.out.println(C + ": " + slv.getValue(C));
55 System.out.println(lhs + ": " + slv.getValue(lhs));
56 System.out.println(rhs + ": " + slv.getValue(rhs));
57 }
58
59 // union max distributes over intersection
60 {
61 Term unionMaxAB = slv.mkTerm(BAG_UNION_MAX, new Term[] {A, B});
62 Term lhs = slv.mkTerm(BAG_INTER_MIN, new Term[] {unionMaxAB, C});
63 Term rhs = slv.mkTerm(BAG_UNION_MAX, new Term[] {intersectionAC, intersectionBC});
64 Term theorem = slv.mkTerm(EQUAL, new Term[] {lhs, rhs});
65 System.out.println("cvc5 reports: " + theorem.notTerm() + " is "
66 + slv.checkSatAssuming(theorem.notTerm()) + ".");
67 }
68
69 // Verify emptbag is a subbag of any bag
70 {
71 Term emptybag = slv.mkEmptyBag(bag);
72 Term theorem = slv.mkTerm(BAG_SUBBAG, new Term[] {emptybag, A});
73
74 System.out.println("cvc5 reports: " + theorem.notTerm() + " is "
75 + slv.checkSatAssuming(theorem.notTerm()) + ".");
76 }
77
78 // find an element with multiplicity 4 in the disjoint union of
79 // ; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
80 {
81 Term one = slv.mkInteger(1);
82 Term two = slv.mkInteger(2);
83 Term three = slv.mkInteger(3);
84 Term four = slv.mkInteger(4);
85 Term a = slv.mkString("a");
86 Term b = slv.mkString("b");
87 Term c = slv.mkString("c");
88
89 Term bag_a_2 = slv.mkTerm(BAG_MAKE, new Term[] {a, two});
90 Term bag_b_3 = slv.mkTerm(BAG_MAKE, new Term[] {b, three});
91 Term bag_b_1 = slv.mkTerm(BAG_MAKE, new Term[] {b, one});
92 Term bag_c_2 = slv.mkTerm(BAG_MAKE, new Term[] {c, two});
93
94 Term bag_a_2_b_3 = slv.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_a_2, bag_b_3});
95
96 Term bag_b_1_c_2 = slv.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_b_1, bag_c_2});
97
98 Term union_disjoint = slv.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_a_2_b_3, bag_b_1_c_2});
99
100 Term count_x = slv.mkTerm(BAG_COUNT, new Term[] {x, union_disjoint});
101 Term e = slv.mkTerm(EQUAL, new Term[] {four, count_x});
102 Result result = slv.checkSatAssuming(e);
103
104 System.out.println("cvc5 reports: " + e + " is " + result + ".");
105 if (result.isSat())
106 {
107 System.out.println(x + ": " + slv.getValue(x));
108 }
109 }
110 }
111 Context.deletePointers();
112 }
113}
1#!/usr/bin/env python
2###############################################################################
3# Top contributors (to current version):
4# Mudathir Mohamed, Aina Niemetz
5#
6# This file is part of the cvc5 project.
7#
8# Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
9# in the top-level source directory and their institutional affiliations.
10# All rights reserved. See the file COPYING in the top-level source
11# directory for licensing information.
12# #############################################################################
13#
14# A simple demonstration of reasoning about bags.
15##
16
17import cvc5
18from cvc5 import Kind
19
20if __name__ == "__main__":
21 tm = cvc5.TermManager()
22 slv = cvc5.Solver(tm)
23 slv.setLogic("ALL")
24
25 # Produce models
26 slv.setOption("produce-models", "true")
27 slv.setOption("incremental", "true")
28
29 bag = tm.mkBagSort(tm.getStringSort())
30 A = tm.mkConst(bag, "A")
31 B = tm.mkConst(bag, "B")
32 C = tm.mkConst(bag, "C")
33 x = tm.mkConst(tm.getStringSort(), "x")
34
35 intersectionAC = tm.mkTerm(Kind.BAG_INTER_MIN, A, C)
36 intersectionBC = tm.mkTerm(Kind.BAG_INTER_MIN, B, C)
37
38 # union disjoint does not distribute over intersection
39 unionDisjointAB = tm.mkTerm(Kind.BAG_UNION_DISJOINT, A, B)
40 lhs = tm.mkTerm(Kind.BAG_INTER_MIN, unionDisjointAB, C)
41 rhs = tm.mkTerm(Kind.BAG_UNION_DISJOINT, intersectionAC, intersectionBC)
42 guess = tm.mkTerm(Kind.EQUAL, lhs, rhs)
43 print("cvc5 reports: {} is {}".format(
44 guess.notTerm(), slv.checkSatAssuming(guess.notTerm())))
45
46 print("{}: {}".format(A, slv.getValue(A)))
47 print("{}: {}".format(B, slv.getValue(B)))
48 print("{}: {}".format(C, slv.getValue(C)))
49 print("{}: {}".format(lhs, slv.getValue(lhs)))
50 print("{}: {}".format(rhs, slv.getValue(rhs)))
51
52 # union max distributes over intersection
53 unionMaxAB = tm.mkTerm(Kind.BAG_UNION_MAX, A, B)
54 lhs = tm.mkTerm(Kind.BAG_INTER_MIN, unionMaxAB, C)
55 rhs = tm.mkTerm(Kind.BAG_UNION_MAX, intersectionAC, intersectionBC)
56 theorem = tm.mkTerm(Kind.EQUAL, lhs, rhs)
57 print("cvc5 reports: {} is {}.".format(
58 theorem.notTerm(), slv.checkSatAssuming(theorem.notTerm())))
59
60 # Verify emptbag is a subbag of any bag
61 emptybag = tm.mkEmptyBag(bag)
62 theorem = tm.mkTerm(Kind.BAG_SUBBAG, emptybag, A)
63 print("cvc5 reports: {} is {}.".format(
64 theorem.notTerm(), slv.checkSatAssuming(theorem.notTerm())))
65
66 # find an element with multiplicity 4 in the disjoint union of
67 # {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
68 one = tm.mkInteger(1)
69 two = tm.mkInteger(2)
70 three = tm.mkInteger(3)
71 four = tm.mkInteger(4)
72 a = tm.mkString("a")
73 b = tm.mkString("b")
74 c = tm.mkString("c")
75
76 bag_a_2 = tm.mkTerm(Kind.BAG_MAKE, a, two)
77 bag_b_3 = tm.mkTerm(Kind.BAG_MAKE, b, three)
78 bag_b_1 = tm.mkTerm(Kind.BAG_MAKE, b, one)
79 bag_c_2 = tm.mkTerm(Kind.BAG_MAKE, c, two)
80 bag_a_2_b_3 = tm.mkTerm(Kind.BAG_UNION_DISJOINT, bag_a_2, bag_b_3)
81 bag_b_1_c_2 = tm.mkTerm(Kind.BAG_UNION_DISJOINT, bag_b_1, bag_c_2)
82 UnionDisjoint = tm.mkTerm(
83 Kind.BAG_UNION_DISJOINT, bag_a_2_b_3, bag_b_1_c_2)
84
85 count_x = tm.mkTerm(Kind.BAG_COUNT, x, UnionDisjoint)
86 e = tm.mkTerm(Kind.EQUAL, four, count_x)
87 result = slv.checkSatAssuming(e)
88
89 print("cvc5 reports: {} is {}.".format(e, result))
90 if result.isSat():
91 print("{}: {} ".format(x, slv.getValue(x)))
1(set-logic ALL)
2
3(set-option :produce-models true)
4(set-option :incremental true)
5
6(declare-const A (Bag String))
7(declare-const B (Bag String))
8(declare-const C (Bag String))
9(declare-const x String)
10
11; union disjoint does not distribute over intersection
12; sat
13(check-sat-assuming
14 ((distinct
15 (bag.inter_min (bag.union_disjoint A B) C)
16 (bag.union_disjoint (bag.inter_min A C) (bag.inter_min B C)))))
17
18
19(get-value (A))
20(get-value (B))
21(get-value (C))
22(get-value ((bag.inter_min (bag.union_disjoint A B) C)))
23(get-value ((bag.union_disjoint (bag.inter_min A C) (bag.inter_min B C))))
24
25; union max distributes over intersection
26; unsat
27(check-sat-assuming
28 ((distinct
29 (bag.inter_min (bag.union_max A B) C)
30 (bag.union_max (bag.inter_min A C) (bag.inter_min B C)))))
31
32; Verify emptbag is a subbag of any bag
33; unsat
34(check-sat-assuming
35 ((not (bag.subbag (as bag.empty (Bag String)) A))))
36
37; find an element with multiplicity 4 in the disjoint union of
38; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
39(check-sat-assuming
40 ((= 4
41 (bag.count x
42 (bag.union_disjoint
43 (bag.union_disjoint (bag "a" 2) (bag "b" 3))
44 (bag.union_disjoint (bag "b" 1) (bag "c" 2)))))))
45
46; x is "b"
47(get-value (x))