Theory of Bags

examples/api/cpp/bags.cpp

  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
 20using namespace std;
 21using namespace cvc5;
 22
 23int 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}