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-2025 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-2025 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, Daniel Larraz, Andres Noetzli
  4 *
  5 * This file is part of the cvc5 project.
  6 *
  7 * Copyright (c) 2009-2025 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    TermManager tm = new TermManager();
 26    Solver slv = new Solver(tm);
 27    {
 28      slv.setLogic("ALL");
 29
 30      // Produce models
 31      slv.setOption("produce-models", "true");
 32      slv.setOption("incremental", "true");
 33
 34      Sort bag = tm.mkBagSort(tm.getStringSort());
 35      Term A = tm.mkConst(bag, "A");
 36      Term B = tm.mkConst(bag, "B");
 37      Term C = tm.mkConst(bag, "C");
 38      Term x = tm.mkConst(tm.getStringSort(), "x");
 39
 40      Term intersectionAC = tm.mkTerm(BAG_INTER_MIN, new Term[] {A, C});
 41      Term intersectionBC = tm.mkTerm(BAG_INTER_MIN, new Term[] {B, C});
 42
 43      // union disjoint does not distribute over intersection
 44      {
 45        Term unionDisjointAB = tm.mkTerm(BAG_UNION_DISJOINT, new Term[] {A, B});
 46        Term lhs = tm.mkTerm(BAG_INTER_MIN, new Term[] {unionDisjointAB, C});
 47        Term rhs = tm.mkTerm(BAG_UNION_DISJOINT, new Term[] {intersectionAC, intersectionBC});
 48        Term guess = tm.mkTerm(EQUAL, new Term[] {lhs, rhs});
 49
 50        System.out.println("cvc5 reports: " + guess.notTerm() + " is "
 51            + slv.checkSatAssuming(guess.notTerm()) + ".");
 52
 53        System.out.println(A + ": " + slv.getValue(A));
 54        System.out.println(B + ": " + slv.getValue(B));
 55        System.out.println(C + ": " + slv.getValue(C));
 56        System.out.println(lhs + ": " + slv.getValue(lhs));
 57        System.out.println(rhs + ": " + slv.getValue(rhs));
 58      }
 59
 60      // union max distributes over intersection
 61      {
 62        Term unionMaxAB = tm.mkTerm(BAG_UNION_MAX, new Term[] {A, B});
 63        Term lhs = tm.mkTerm(BAG_INTER_MIN, new Term[] {unionMaxAB, C});
 64        Term rhs = tm.mkTerm(BAG_UNION_MAX, new Term[] {intersectionAC, intersectionBC});
 65        Term theorem = tm.mkTerm(EQUAL, new Term[] {lhs, rhs});
 66        System.out.println("cvc5 reports: " + theorem.notTerm() + " is "
 67            + slv.checkSatAssuming(theorem.notTerm()) + ".");
 68      }
 69
 70      // Verify emptbag is a subbag of any bag
 71      {
 72        Term emptybag = tm.mkEmptyBag(bag);
 73        Term theorem = tm.mkTerm(BAG_SUBBAG, new Term[] {emptybag, A});
 74
 75        System.out.println("cvc5 reports: " + theorem.notTerm() + " is "
 76            + slv.checkSatAssuming(theorem.notTerm()) + ".");
 77      }
 78
 79      // find an element with multiplicity 4 in the disjoint union of
 80      // ; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
 81      {
 82        Term one = tm.mkInteger(1);
 83        Term two = tm.mkInteger(2);
 84        Term three = tm.mkInteger(3);
 85        Term four = tm.mkInteger(4);
 86        Term a = tm.mkString("a");
 87        Term b = tm.mkString("b");
 88        Term c = tm.mkString("c");
 89
 90        Term bag_a_2 = tm.mkTerm(BAG_MAKE, new Term[] {a, two});
 91        Term bag_b_3 = tm.mkTerm(BAG_MAKE, new Term[] {b, three});
 92        Term bag_b_1 = tm.mkTerm(BAG_MAKE, new Term[] {b, one});
 93        Term bag_c_2 = tm.mkTerm(BAG_MAKE, new Term[] {c, two});
 94
 95        Term bag_a_2_b_3 = tm.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_a_2, bag_b_3});
 96
 97        Term bag_b_1_c_2 = tm.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_b_1, bag_c_2});
 98
 99        Term union_disjoint = tm.mkTerm(BAG_UNION_DISJOINT, new Term[] {bag_a_2_b_3, bag_b_1_c_2});
100
101        Term count_x = tm.mkTerm(BAG_COUNT, new Term[] {x, union_disjoint});
102        Term e = tm.mkTerm(EQUAL, new Term[] {four, count_x});
103        Result result = slv.checkSatAssuming(e);
104
105        System.out.println("cvc5 reports: " + e + " is " + result + ".");
106        if (result.isSat())
107        {
108          System.out.println(x + ": " + slv.getValue(x));
109        }
110      }
111    }
112    Context.deletePointers();
113  }
114}
 1#!/usr/bin/env python
 2###############################################################################
 3# Top contributors (to current version):
 4#   Aina Niemetz, Mudathir Mohamed
 5#
 6# This file is part of the cvc5 project.
 7#
 8# Copyright (c) 2009-2025 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))