Theory of Sets

examples/api/cpp/sets.cpp

 1/******************************************************************************
 2 * Top contributors (to current version):
 3 *   Aina Niemetz, Kshitij Bansal, Andrew Reynolds
 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 sets with cvc5.
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
28  // Optionally, set the logic. We need at least UF for equality predicate,
29  // integers (LIA) and sets (FS).
30  slv.setLogic("QF_UFLIAFS");
31
32  // Produce models
33  slv.setOption("produce-models", "true");
34  slv.setOption("output-language", "smt2");
35
36  Sort integer = tm.getIntegerSort();
37  Sort set = tm.mkSetSort(integer);
38
39  // Verify union distributions over intersection
40  // (A union B) intersection C = (A intersection C) union (B intersection C)
41  {
42    Term A = tm.mkConst(set, "A");
43    Term B = tm.mkConst(set, "B");
44    Term C = tm.mkConst(set, "C");
45
46    Term unionAB = tm.mkTerm(Kind::SET_UNION, {A, B});
47    Term lhs = tm.mkTerm(Kind::SET_INTER, {unionAB, C});
48
49    Term intersectionAC = tm.mkTerm(Kind::SET_INTER, {A, C});
50    Term intersectionBC = tm.mkTerm(Kind::SET_INTER, {B, C});
51    Term rhs = tm.mkTerm(Kind::SET_UNION, {intersectionAC, intersectionBC});
52
53    Term theorem = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
54
55    cout << "cvc5 reports: " << theorem << " is "
56         << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
57  }
58
59  // Verify emptset is a subset of any set
60  {
61    Term A = tm.mkConst(set, "A");
62    Term emptyset = tm.mkEmptySet(set);
63
64    Term theorem = tm.mkTerm(Kind::SET_SUBSET, {emptyset, A});
65
66    cout << "cvc5 reports: " << theorem << " is "
67         << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
68  }
69
70  // Find me an element in {1, 2} intersection {2, 3}, if there is one.
71  {
72    Term one = tm.mkInteger(1);
73    Term two = tm.mkInteger(2);
74    Term three = tm.mkInteger(3);
75
76    Term singleton_one = tm.mkTerm(Kind::SET_SINGLETON, {one});
77    Term singleton_two = tm.mkTerm(Kind::SET_SINGLETON, {two});
78    Term singleton_three = tm.mkTerm(Kind::SET_SINGLETON, {three});
79    Term one_two = tm.mkTerm(Kind::SET_UNION, {singleton_one, singleton_two});
80    Term two_three =
81        tm.mkTerm(Kind::SET_UNION, {singleton_two, singleton_three});
82    Term intersection = tm.mkTerm(Kind::SET_INTER, {one_two, two_three});
83
84    Term x = tm.mkConst(integer, "x");
85
86    Term e = tm.mkTerm(Kind::SET_MEMBER, {x, intersection});
87
88    Result result = slv.checkSatAssuming(e);
89    cout << "cvc5 reports: " << e << " is " << result << "." << endl;
90
91    if (result.isSat())
92    {
93      cout << "For instance, " << slv.getValue(x) << " is a member." << endl;
94    }
95  }
96}