Theory of Bags 
  1 /******************************************************************************
  2  * Top contributors (to current version):
  3  *   Mudathir Mohamed
  4  *
  5  * This file is part of the cvc5 project.
  6  *
  7  * Copyright (c) 2009-2022 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 
 20 using namespace std;
 21 using namespace cvc5;
 22 
 23 int main()
 24 {
 25   Solver slv;
 26   slv.setLogic("ALL");
 27   // Produce models
 28   slv.setOption("produce-models", "true");
 29   slv.setOption("incremental", "true");
 30 
 31   Sort bag = slv.mkBagSort(slv.getStringSort());
 32   Term A = slv.mkConst(bag, "A");
 33   Term B = slv.mkConst(bag, "B");
 34   Term C = slv.mkConst(bag, "C");
 35   Term x = slv.mkConst(slv.getStringSort(), "x");
 36 
 37   Term intersectionAC = slv.mkTerm(BAG_INTER_MIN, {A, C});
 38   Term intersectionBC = slv.mkTerm(BAG_INTER_MIN, {B, C});
 39 
 40   // union disjoint does not distribute over intersection
 41   {
 42     Term unionDisjointAB = slv.mkTerm(BAG_UNION_DISJOINT, {A, B});
 43     Term lhs = slv.mkTerm(BAG_INTER_MIN, {unionDisjointAB, C});
 44     Term rhs = slv.mkTerm(BAG_UNION_DISJOINT, {intersectionAC, intersectionBC});
 45     Term guess = slv.mkTerm(EQUAL, {lhs, rhs});
 46     cout << "cvc5 reports: " << guess.notTerm() << " is "
 47          << slv.checkSatAssuming(guess.notTerm()) << "." << endl;
 48 
 49     cout << A << ": " << slv.getValue(A) << endl;
 50     cout << B << ": " << slv.getValue(B) << endl;
 51     cout << C << ": " << slv.getValue(C) << endl;
 52     cout << lhs << ": " << slv.getValue(lhs) << endl;
 53     cout << rhs << ": " << slv.getValue(rhs) << endl;
 54   }
 55 
 56   // union max distributes over intersection
 57   {
 58     Term unionMaxAB = slv.mkTerm(BAG_UNION_MAX, {A, B});
 59     Term lhs = slv.mkTerm(BAG_INTER_MIN, {unionMaxAB, C});
 60     Term rhs = slv.mkTerm(BAG_UNION_MAX, {intersectionAC, intersectionBC});
 61     Term theorem = slv.mkTerm(EQUAL, {lhs, rhs});
 62     cout << "cvc5 reports: " << theorem.notTerm() << " is "
 63          << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
 64   }
 65 
 66   // Verify emptbag is a subbag of any bag
 67   {
 68     Term emptybag = slv.mkEmptyBag(bag);
 69     Term theorem = slv.mkTerm(BAG_SUBBAG, {emptybag, A});
 70 
 71     cout << "cvc5 reports: " << theorem.notTerm() << " is "
 72          << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
 73   }
 74 
 75   // find an element with multiplicity 4 in the disjoint union of
 76   // ; {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
 77 
 78   {
 79     Term one = slv.mkInteger(1);
 80     Term two = slv.mkInteger(2);
 81     Term three = slv.mkInteger(3);
 82     Term four = slv.mkInteger(4);
 83     Term a = slv.mkString("a");
 84     Term b = slv.mkString("b");
 85     Term c = slv.mkString("c");
 86 
 87     Term bag_a_2 = slv.mkTerm(BAG_MAKE, {a, two});
 88     Term bag_b_3 = slv.mkTerm(BAG_MAKE, {b, three});
 89     Term bag_b_1 = slv.mkTerm(BAG_MAKE, {b, one});
 90     Term bag_c_2 = slv.mkTerm(BAG_MAKE, {c, two});
 91     Term bag_a_2_b_3 = slv.mkTerm(BAG_UNION_DISJOINT, {bag_a_2, bag_b_3});
 92     Term bag_b_1_c_2 = slv.mkTerm(BAG_UNION_DISJOINT, {bag_b_1, bag_c_2});
 93     Term union_disjoint =
 94         slv.mkTerm(BAG_UNION_DISJOINT, {bag_a_2_b_3, bag_b_1_c_2});
 95 
 96     Term count_x = slv.mkTerm(BAG_COUNT, {x, union_disjoint});
 97     Term e = slv.mkTerm(EQUAL, {four, count_x});
 98     Result result = slv.checkSatAssuming(e);
 99 
100     cout << "cvc5 reports: " << e << " is " << result << "." << endl;
101     if (result.isSat())
102     {
103       cout << x << ": " << slv.getValue(x) << endl;
104     }
105   }
106 }
              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-2022 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 
 16 import static io.github.cvc5.Kind.*;
 17 
 18 import io.github.cvc5.*;
 19 
 20 public class Bags
 21 {
 22   public static void main(String args[]) throws CVC5ApiException
 23 
 24   {
 25     try (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   }
112 }
             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-2022 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 
17 import cvc5
18 from cvc5 import Kind
19 
20 if __name__ == "__main__":
21     slv = cvc5.Solver()
22     slv.setLogic("ALL")
23 
24     # Produce models
25     slv.setOption("produce-models", "true")
26     slv.setOption("incremental", "true")
27 
28     bag = slv.mkBagSort(slv.getStringSort())
29     A = slv.mkConst(bag, "A")
30     B = slv.mkConst(bag, "B")
31     C = slv.mkConst(bag, "C")
32     x = slv.mkConst(slv.getStringSort(), "x")
33 
34     intersectionAC = slv.mkTerm(Kind.BAG_INTER_MIN, A, C)
35     intersectionBC = slv.mkTerm(Kind.BAG_INTER_MIN, B, C)
36 
37     # union disjoint does not distribute over intersection
38     unionDisjointAB = slv.mkTerm(Kind.BAG_UNION_DISJOINT, A, B)
39     lhs = slv.mkTerm(Kind.BAG_INTER_MIN, unionDisjointAB, C)
40     rhs = slv.mkTerm(Kind.BAG_UNION_DISJOINT, intersectionAC, intersectionBC)
41     guess = slv.mkTerm(Kind.EQUAL, lhs, rhs)
42     print("cvc5 reports: {} is {}".format(
43         guess.notTerm(), slv.checkSatAssuming(guess.notTerm())))
44 
45     print("{}: {}".format(A, slv.getValue(A)))
46     print("{}: {}".format(B, slv.getValue(B)))
47     print("{}: {}".format(C, slv.getValue(C)))
48     print("{}: {}".format(lhs, slv.getValue(lhs)))
49     print("{}: {}".format(rhs, slv.getValue(rhs)))
50 
51     # union max distributes over intersection
52     unionMaxAB = slv.mkTerm(Kind.BAG_UNION_MAX, A, B)
53     lhs = slv.mkTerm(Kind.BAG_INTER_MIN, unionMaxAB, C)
54     rhs = slv.mkTerm(Kind.BAG_UNION_MAX, intersectionAC, intersectionBC)
55     theorem = slv.mkTerm(Kind.EQUAL, lhs, rhs)
56     print("cvc5 reports: {} is {}.".format(
57         theorem.notTerm(), slv.checkSatAssuming(theorem.notTerm())))
58 
59     # Verify emptbag is a subbag of any bag
60     emptybag = slv.mkEmptyBag(bag)
61     theorem = slv.mkTerm(Kind.BAG_SUBBAG, emptybag, A)
62     print("cvc5 reports: {} is {}.".format(
63         theorem.notTerm(), slv.checkSatAssuming(theorem.notTerm())))
64 
65     # find an element with multiplicity 4 in the disjoint union of
66     #  {|"a", "a", "b", "b", "b"|} and {|"b", "c", "c"|}
67     one = slv.mkInteger(1)
68     two = slv.mkInteger(2)
69     three = slv.mkInteger(3)
70     four = slv.mkInteger(4)
71     a = slv.mkString("a")
72     b = slv.mkString("b")
73     c = slv.mkString("c")
74 
75     bag_a_2 = slv.mkTerm(Kind.BAG_MAKE, a, two)
76     bag_b_3 = slv.mkTerm(Kind.BAG_MAKE, b, three)
77     bag_b_1 = slv.mkTerm(Kind.BAG_MAKE, b, one)
78     bag_c_2 = slv.mkTerm(Kind.BAG_MAKE, c, two)
79     bag_a_2_b_3 = slv.mkTerm(Kind.BAG_UNION_DISJOINT, bag_a_2, bag_b_3)
80     bag_b_1_c_2 = slv.mkTerm(Kind.BAG_UNION_DISJOINT, bag_b_1, bag_c_2)
81     UnionDisjoint = slv.mkTerm(
82             Kind.BAG_UNION_DISJOINT, bag_a_2_b_3, bag_b_1_c_2)
83 
84     count_x = slv.mkTerm(Kind.BAG_COUNT, x, UnionDisjoint)
85     e = slv.mkTerm(Kind.EQUAL, four, count_x)
86     result = slv.checkSatAssuming(e)
87 
88     print("cvc5 reports: {} is {}.".format(e, result))
89     if result.isSat():
90         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))