Theory of Sets

examples/api/cpp/sets.cpp

 1/******************************************************************************
 2 * This file is part of the cvc5 project.
 3 *
 4 * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
 5 * in the top-level source directory and their institutional affiliations.
 6 * All rights reserved.  See the file COPYING in the top-level source
 7 * directory for licensing information.
 8 * ****************************************************************************
 9 *
10 * A simple demonstration of reasoning about sets via the C++ API.
11 */
12
13#include <cvc5/cvc5.h>
14
15#include <iostream>
16
17using namespace std;
18using namespace cvc5;
19
20int main()
21{
22  TermManager tm;
23  Solver slv(tm);
24
25  // Optionally, set the logic. We need at least UF for equality predicate,
26  // integers (LIA) and sets (FS).
27  slv.setLogic("QF_UFLIAFS");
28
29  // Produce models
30  slv.setOption("produce-models", "true");
31
32  Sort integer = tm.getIntegerSort();
33  Sort set = tm.mkSetSort(integer);
34
35  // Verify union distributions over intersection
36  // (A union B) intersection C = (A intersection C) union (B intersection C)
37  {
38    Term A = tm.mkConst(set, "A");
39    Term B = tm.mkConst(set, "B");
40    Term C = tm.mkConst(set, "C");
41
42    Term unionAB = tm.mkTerm(Kind::SET_UNION, {A, B});
43    Term lhs = tm.mkTerm(Kind::SET_INTER, {unionAB, C});
44
45    Term intersectionAC = tm.mkTerm(Kind::SET_INTER, {A, C});
46    Term intersectionBC = tm.mkTerm(Kind::SET_INTER, {B, C});
47    Term rhs = tm.mkTerm(Kind::SET_UNION, {intersectionAC, intersectionBC});
48
49    Term theorem = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
50
51    cout << "cvc5 reports: " << theorem << " is "
52         << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
53  }
54
55  // Verify emptset is a subset of any set
56  {
57    Term A = tm.mkConst(set, "A");
58    Term emptyset = tm.mkEmptySet(set);
59
60    Term theorem = tm.mkTerm(Kind::SET_SUBSET, {emptyset, A});
61
62    cout << "cvc5 reports: " << theorem << " is "
63         << slv.checkSatAssuming(theorem.notTerm()) << "." << endl;
64  }
65
66  // Find me an element in {1, 2} intersection {2, 3}, if there is one.
67  {
68    Term one = tm.mkInteger(1);
69    Term two = tm.mkInteger(2);
70    Term three = tm.mkInteger(3);
71
72    Term singleton_one = tm.mkTerm(Kind::SET_SINGLETON, {one});
73    Term singleton_two = tm.mkTerm(Kind::SET_SINGLETON, {two});
74    Term singleton_three = tm.mkTerm(Kind::SET_SINGLETON, {three});
75    Term one_two = tm.mkTerm(Kind::SET_UNION, {singleton_one, singleton_two});
76    Term two_three =
77        tm.mkTerm(Kind::SET_UNION, {singleton_two, singleton_three});
78    Term intersection = tm.mkTerm(Kind::SET_INTER, {one_two, two_three});
79
80    Term x = tm.mkConst(integer, "x");
81
82    Term e = tm.mkTerm(Kind::SET_MEMBER, {x, intersection});
83
84    Result result = slv.checkSatAssuming(e);
85    cout << "cvc5 reports: " << e << " is " << result << "." << endl;
86
87    if (result.isSat())
88    {
89      cout << "For instance, " << slv.getValue(x) << " is a member." << endl;
90    }
91  }
92}