Theory of Relations
This simple example demonstrates the combined theory of finite sets and finite relations using a family tree. Relations are defined as sets of tuples with arity \(\geq 1\) . The example includes the unary relations \(people, males,\) and \(females\) and the binary relations \(father, mother, parent, ancestor\) , and \(descendant\) .
We have the following list of constraints:
-
All relations are nonempty.
-
People is the universe set.
-
Males and females are disjoint sets (i.e., \(males \cap females = \phi\) ).
-
Fathers are males (i.e., \(father \bowtie people \subseteq males\) ) [ * ] .
-
Mothers are females (i.e., \(mother \bowtie people \subseteq females\) ).
-
A parent is a father or a mother (i.e., \(parent = father \cup mother\) ).
-
Ancestor relation is the transitive closure of parent (i.e., \(ancestor = parent^{+}\) ).
-
Descendant relation is the transpose of ancestor (i.e., \(descendant = ancestor^{-1}\) ).
-
No self ancestor (i.e., \(\forall x: Person. \langle x, x \rangle \not\in ancestor\) ).
examples/api/cpp/relations.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 relations via the C++ API.
11 */
12
13#include <cvc5/cvc5.h>
14
15#include <iostream>
16
17using namespace cvc5;
18
19int main()
20{
21 TermManager tm;
22 Solver solver(tm);
23
24 // Set the logic
25 solver.setLogic("ALL");
26
27 // options
28 solver.setOption("produce-models", "true");
29 // we need finite model finding to answer sat problems with universal
30 // quantified formulas
31 solver.setOption("finite-model-find", "true");
32 // we need sets extension to support set.universe operator
33 solver.setOption("sets-exp", "true");
34
35 // (declare-sort Person 0)
36 Sort personSort = tm.mkUninterpretedSort("Person");
37
38 // (Tuple Person)
39 Sort tupleArity1 = tm.mkTupleSort({personSort});
40 // (Relation Person)
41 Sort relationArity1 = tm.mkSetSort(tupleArity1);
42
43 // (Tuple Person Person)
44 Sort tupleArity2 = tm.mkTupleSort({personSort, personSort});
45 // (Relation Person Person)
46 Sort relationArity2 = tm.mkSetSort(tupleArity2);
47
48 // empty set
49 Term emptySetTerm = tm.mkEmptySet(relationArity1);
50
51 // empty relation
52 Term emptyRelationTerm = tm.mkEmptySet(relationArity2);
53
54 // universe set
55 Term universeSet = tm.mkUniverseSet(relationArity1);
56
57 // variables
58 Term people = tm.mkConst(relationArity1, "people");
59 Term males = tm.mkConst(relationArity1, "males");
60 Term females = tm.mkConst(relationArity1, "females");
61 Term father = tm.mkConst(relationArity2, "father");
62 Term mother = tm.mkConst(relationArity2, "mother");
63 Term parent = tm.mkConst(relationArity2, "parent");
64 Term ancestor = tm.mkConst(relationArity2, "ancestor");
65 Term descendant = tm.mkConst(relationArity2, "descendant");
66
67 Term isEmpty1 = tm.mkTerm(Kind::EQUAL, {males, emptySetTerm});
68 Term isEmpty2 = tm.mkTerm(Kind::EQUAL, {females, emptySetTerm});
69
70 // (assert (= people (as set.universe (Relation Person))))
71 Term peopleAreTheUniverse = tm.mkTerm(Kind::EQUAL, {people, universeSet});
72 // (assert (not (= males (as set.empty (Relation Person)))))
73 Term maleSetIsNotEmpty = tm.mkTerm(Kind::NOT, {isEmpty1});
74 // (assert (not (= females (as set.empty (Relation Person)))))
75 Term femaleSetIsNotEmpty = tm.mkTerm(Kind::NOT, {isEmpty2});
76
77 // (assert (= (set.inter males females)
78 // (as set.empty (Relation Person))))
79 Term malesFemalesIntersection = tm.mkTerm(Kind::SET_INTER, {males, females});
80 Term malesAndFemalesAreDisjoint =
81 tm.mkTerm(Kind::EQUAL, {malesFemalesIntersection, emptySetTerm});
82
83 // (assert (not (= father (as set.empty (Relation Person Person)))))
84 // (assert (not (= mother (as set.empty (Relation Person Person)))))
85 Term isEmpty3 = tm.mkTerm(Kind::EQUAL, {father, emptyRelationTerm});
86 Term isEmpty4 = tm.mkTerm(Kind::EQUAL, {mother, emptyRelationTerm});
87 Term fatherIsNotEmpty = tm.mkTerm(Kind::NOT, {isEmpty3});
88 Term motherIsNotEmpty = tm.mkTerm(Kind::NOT, {isEmpty4});
89
90 // fathers are males
91 // (assert (set.subset (rel.join father people) males))
92 Term fathers = tm.mkTerm(Kind::RELATION_JOIN, {father, people});
93 Term fathersAreMales = tm.mkTerm(Kind::SET_SUBSET, {fathers, males});
94
95 // mothers are females
96 // (assert (set.subset (rel.join mother people) females))
97 Term mothers = tm.mkTerm(Kind::RELATION_JOIN, {mother, people});
98 Term mothersAreFemales = tm.mkTerm(Kind::SET_SUBSET, {mothers, females});
99
100 // (assert (= parent (set.union father mother)))
101 Term unionFatherMother = tm.mkTerm(Kind::SET_UNION, {father, mother});
102 Term parentIsFatherOrMother =
103 tm.mkTerm(Kind::EQUAL, {parent, unionFatherMother});
104
105 // (assert (= ancestor (rel.tclosure parent)))
106 Term transitiveClosure = tm.mkTerm(Kind::RELATION_TCLOSURE, {parent});
107 Term ancestorFormula = tm.mkTerm(Kind::EQUAL, {ancestor, transitiveClosure});
108
109 // (assert (= descendant (rel.transpose descendant)))
110 Term transpose = tm.mkTerm(Kind::RELATION_TRANSPOSE, {ancestor});
111 Term descendantFormula = tm.mkTerm(Kind::EQUAL, {descendant, transpose});
112
113 // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
114 Term x = tm.mkVar(personSort, "x");
115 Term xxTuple = tm.mkTuple({x, x});
116 Term member = tm.mkTerm(Kind::SET_MEMBER, {xxTuple, ancestor});
117 Term notMember = tm.mkTerm(Kind::NOT, {member});
118
119 Term quantifiedVariables = tm.mkTerm(Kind::VARIABLE_LIST, {x});
120 Term noSelfAncestor =
121 tm.mkTerm(Kind::FORALL, {quantifiedVariables, notMember});
122
123 // formulas
124 solver.assertFormula(peopleAreTheUniverse);
125 solver.assertFormula(maleSetIsNotEmpty);
126 solver.assertFormula(femaleSetIsNotEmpty);
127 solver.assertFormula(malesAndFemalesAreDisjoint);
128 solver.assertFormula(fatherIsNotEmpty);
129 solver.assertFormula(motherIsNotEmpty);
130 solver.assertFormula(fathersAreMales);
131 solver.assertFormula(mothersAreFemales);
132 solver.assertFormula(parentIsFatherOrMother);
133 solver.assertFormula(descendantFormula);
134 solver.assertFormula(ancestorFormula);
135 solver.assertFormula(noSelfAncestor);
136
137 // check sat
138 Result result = solver.checkSat();
139
140 // output
141 std::cout << "Result = " << result << std::endl;
142 std::cout << "people = " << solver.getValue(people) << std::endl;
143 std::cout << "males = " << solver.getValue(males) << std::endl;
144 std::cout << "females = " << solver.getValue(females) << std::endl;
145 std::cout << "father = " << solver.getValue(father) << std::endl;
146 std::cout << "mother = " << solver.getValue(mother) << std::endl;
147 std::cout << "parent = " << solver.getValue(parent) << std::endl;
148 std::cout << "descendant = " << solver.getValue(descendant) << std::endl;
149 std::cout << "ancestor = " << solver.getValue(ancestor) << std::endl;
150}
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 relations via the C API.
11 */
12
13#include <cvc5/c/cvc5.h>
14#include <stdio.h>
15
16int main()
17{
18 Cvc5TermManager* tm = cvc5_term_manager_new();
19 Cvc5* slv = cvc5_new(tm);
20
21 // Set the logic
22 cvc5_set_logic(slv, "ALL");
23
24 // options
25 cvc5_set_option(slv, "produce-models", "true");
26 // we need finite model finding to answer sat problems with universal
27 // quantified formulas
28 cvc5_set_option(slv, "finite-model-find", "true");
29 // we need sets extension to support set.universe operator
30 cvc5_set_option(slv, "sets-exp", "true");
31
32 // (declare-sort Person 0)
33 Cvc5Sort person_sort = cvc5_mk_uninterpreted_sort(tm, "Person");
34
35 // (Tuple Person)
36 Cvc5Sort sorts1[1] = {person_sort};
37 Cvc5Sort tuple_arity1 = cvc5_mk_tuple_sort(tm, 1, sorts1);
38 // (Relation Person)
39 Cvc5Sort rel_arity1 = cvc5_mk_set_sort(tm, tuple_arity1);
40
41 // (Tuple Person Person)
42 Cvc5Sort sorts2[2] = {person_sort, person_sort};
43 Cvc5Sort tuple_arity2 = cvc5_mk_tuple_sort(tm, 2, sorts2);
44 // (Relation Person Person)
45 Cvc5Sort rel_arity2 = cvc5_mk_set_sort(tm, tuple_arity2);
46
47 // empty set
48 Cvc5Term empty_set = cvc5_mk_empty_set(tm, rel_arity1);
49
50 // empty relation
51 Cvc5Term empty_rel = cvc5_mk_empty_set(tm, rel_arity2);
52
53 // universe set
54 Cvc5Term universe_set = cvc5_mk_universe_set(tm, rel_arity1);
55
56 // variables
57 Cvc5Term people = cvc5_mk_const(tm, rel_arity1, "people");
58 Cvc5Term males = cvc5_mk_const(tm, rel_arity1, "males");
59 Cvc5Term females = cvc5_mk_const(tm, rel_arity1, "females");
60 Cvc5Term father = cvc5_mk_const(tm, rel_arity2, "father");
61 Cvc5Term mother = cvc5_mk_const(tm, rel_arity2, "mother");
62 Cvc5Term parent = cvc5_mk_const(tm, rel_arity2, "parent");
63 Cvc5Term ancestor = cvc5_mk_const(tm, rel_arity2, "ancestor");
64 Cvc5Term descendant = cvc5_mk_const(tm, rel_arity2, "descendant");
65
66 Cvc5Term args2[2] = {males, empty_set};
67 Cvc5Term is_empty1 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
68 args2[0] = females;
69 Cvc5Term is_empty2 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
70
71 // (assert (= people (as set.universe (Relation Person))))
72 args2[0] = people;
73 args2[1] = universe_set;
74 Cvc5Term people_universe = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
75 // (assert (not (= males (as set.empty (Relation Person)))))
76 Cvc5Term args1[1] = {is_empty1};
77 Cvc5Term male_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
78 // (assert (not (= females (as set.empty (Relation Person)))))
79 args1[0] = is_empty2;
80 Cvc5Term female_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
81
82 // (assert (= (set.inter males females)
83 // (as set.empty (Relation Person))))
84 args2[0] = males;
85 args2[1] = females;
86 Cvc5Term inter_males_females =
87 cvc5_mk_term(tm, CVC5_KIND_SET_INTER, 2, args2);
88 args2[0] = inter_males_females;
89 args2[1] = empty_set;
90 Cvc5Term disjoint_males_females = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
91
92 // (assert (not (= father (as set.empty (Relation Person Person)))))
93 // (assert (not (= mother (as set.empty (Relation Person Person)))))
94 args2[0] = father;
95 args2[1] = empty_rel;
96 Cvc5Term is_empty3 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
97 args2[0] = mother;
98 args2[1] = empty_rel;
99 Cvc5Term is_empty4 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
100 args1[0] = is_empty3;
101 Cvc5Term father_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
102 args1[0] = is_empty4;
103 Cvc5Term mother_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
104
105 // fathers are males
106 // (assert (set.subset (rel.join father people) males))
107 args2[0] = father;
108 args2[1] = people;
109 Cvc5Term fathers = cvc5_mk_term(tm, CVC5_KIND_RELATION_JOIN, 2, args2);
110 args2[0] = fathers;
111 args2[1] = males;
112 Cvc5Term fathers_are_males = cvc5_mk_term(tm, CVC5_KIND_SET_SUBSET, 2, args2);
113
114 // mothers are females
115 // (assert (set.subset (rel.join mother people) females))
116 args2[0] = mother;
117 args2[1] = people;
118 Cvc5Term mothers = cvc5_mk_term(tm, CVC5_KIND_RELATION_JOIN, 2, args2);
119 args2[0] = mothers;
120 args2[1] = females;
121 Cvc5Term mothers_are_females =
122 cvc5_mk_term(tm, CVC5_KIND_SET_SUBSET, 2, args2);
123
124 // (assert (= parent (set.union father mother)))
125 args2[0] = father;
126 args2[1] = mother;
127 Cvc5Term union_father_mother =
128 cvc5_mk_term(tm, CVC5_KIND_SET_UNION, 2, args2);
129 args2[0] = parent;
130 args2[1] = union_father_mother;
131 Cvc5Term parent_is_father_or_mother =
132 cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
133
134 // (assert (= ancestor (rel.tclosure parent)))
135 args1[0] = parent;
136 Cvc5Term trans_closure =
137 cvc5_mk_term(tm, CVC5_KIND_RELATION_TCLOSURE, 1, args1);
138 args2[0] = ancestor;
139 args2[1] = trans_closure;
140 Cvc5Term ancestor_formula = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
141
142 // (assert (= descendant (rel.transpose descendant)))
143 args1[0] = ancestor;
144 Cvc5Term transpose = cvc5_mk_term(tm, CVC5_KIND_RELATION_TRANSPOSE, 1, args1);
145 args2[0] = descendant;
146 args2[1] = transpose;
147 Cvc5Term descendant_formula = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
148
149 // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
150 Cvc5Term x = cvc5_mk_var(tm, person_sort, "x");
151 args2[0] = x;
152 args2[1] = x;
153 Cvc5Term xx_tuple = cvc5_mk_tuple(tm, 2, args2);
154 args2[0] = xx_tuple;
155 args2[1] = ancestor;
156 Cvc5Term member = cvc5_mk_term(tm, CVC5_KIND_SET_MEMBER, 2, args2);
157 args1[0] = member;
158 Cvc5Term not_member = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
159
160 args1[0] = x;
161 Cvc5Term vars = cvc5_mk_term(tm, CVC5_KIND_VARIABLE_LIST, 1, args1);
162 args2[0] = vars;
163 args2[1] = not_member;
164 Cvc5Term not_self_ancestor = cvc5_mk_term(tm, CVC5_KIND_FORALL, 2, args2);
165
166 // formulas
167 cvc5_assert_formula(slv, people_universe);
168 cvc5_assert_formula(slv, male_not_empty);
169 cvc5_assert_formula(slv, female_not_empty);
170 cvc5_assert_formula(slv, disjoint_males_females);
171 cvc5_assert_formula(slv, father_not_empty);
172 cvc5_assert_formula(slv, mother_not_empty);
173 cvc5_assert_formula(slv, fathers_are_males);
174 cvc5_assert_formula(slv, mothers_are_females);
175 cvc5_assert_formula(slv, parent_is_father_or_mother);
176 cvc5_assert_formula(slv, descendant_formula);
177 cvc5_assert_formula(slv, ancestor_formula);
178 cvc5_assert_formula(slv, not_self_ancestor);
179
180 // check sat
181 Cvc5Result result = cvc5_check_sat(slv);
182
183 // output
184 printf("Result = %s\n", cvc5_result_to_string(result));
185 printf("people = %s\n", cvc5_term_to_string(cvc5_get_value(slv, people)));
186 printf("males = %s\n", cvc5_term_to_string(cvc5_get_value(slv, males)));
187 printf("females = %s\n",
188 cvc5_term_to_string(cvc5_get_value(slv, females)));
189 printf("father = %s\n", cvc5_term_to_string(cvc5_get_value(slv, father)));
190 printf("mother = %s\n", cvc5_term_to_string(cvc5_get_value(slv, mother)));
191 printf("parent = %s\n", cvc5_term_to_string(cvc5_get_value(slv, parent)));
192 printf("descendant = %s\n",
193 cvc5_term_to_string(cvc5_get_value(slv, descendant)));
194 printf("ancestor = %s\n",
195 cvc5_term_to_string(cvc5_get_value(slv, ancestor)));
196
197 cvc5_delete(slv);
198 cvc5_term_manager_delete(tm);
199}
examples/api/java/Relations.java
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 relations with cvc5 via Java API.
11 */
12
13import static io.github.cvc5.Kind.*;
14
15import io.github.cvc5.*;
16
17public class Relations
18{
19 public static void main(String[] args) throws CVC5ApiException
20 {
21 TermManager tm = new TermManager();
22 Solver solver = new Solver(tm);
23 {
24 // Set the logic
25 solver.setLogic("ALL");
26
27 // options
28 solver.setOption("produce-models", "true");
29 // we need finite model finding to answer sat problems with universal
30 // quantified formulas
31 solver.setOption("finite-model-find", "true");
32 // we need sets extension to support set.universe operator
33 solver.setOption("sets-exp", "true");
34
35 // (declare-sort Person 0)
36 Sort personSort = tm.mkUninterpretedSort("Person");
37
38 // (Tuple Person)
39 Sort tupleArity1 = tm.mkTupleSort(new Sort[] {personSort});
40 // (Relation Person)
41 Sort relationArity1 = tm.mkSetSort(tupleArity1);
42
43 // (Tuple Person Person)
44 Sort tupleArity2 = tm.mkTupleSort(new Sort[] {personSort, personSort});
45 // (Relation Person Person)
46 Sort relationArity2 = tm.mkSetSort(tupleArity2);
47
48 // empty set
49 Term emptySetTerm = tm.mkEmptySet(relationArity1);
50
51 // empty relation
52 Term emptyRelationTerm = tm.mkEmptySet(relationArity2);
53
54 // universe set
55 Term universeSet = tm.mkUniverseSet(relationArity1);
56
57 // variables
58 Term people = tm.mkConst(relationArity1, "people");
59 Term males = tm.mkConst(relationArity1, "males");
60 Term females = tm.mkConst(relationArity1, "females");
61 Term father = tm.mkConst(relationArity2, "father");
62 Term mother = tm.mkConst(relationArity2, "mother");
63 Term parent = tm.mkConst(relationArity2, "parent");
64 Term ancestor = tm.mkConst(relationArity2, "ancestor");
65 Term descendant = tm.mkConst(relationArity2, "descendant");
66
67 Term isEmpty1 = tm.mkTerm(EQUAL, males, emptySetTerm);
68 Term isEmpty2 = tm.mkTerm(EQUAL, females, emptySetTerm);
69
70 // (assert (= people (as set.universe (Relation Person))))
71 Term peopleAreTheUniverse = tm.mkTerm(EQUAL, people, universeSet);
72 // (assert (not (= males (as set.empty (Relation Person)))))
73 Term maleSetIsNotEmpty = tm.mkTerm(NOT, isEmpty1);
74 // (assert (not (= females (as set.empty (Relation Person)))))
75 Term femaleSetIsNotEmpty = tm.mkTerm(NOT, isEmpty2);
76
77 // (assert (= (set.inter males females)
78 // (as set.empty (Relation Person))))
79 Term malesFemalesIntersection = tm.mkTerm(SET_INTER, males, females);
80 Term malesAndFemalesAreDisjoint = tm.mkTerm(EQUAL, malesFemalesIntersection, emptySetTerm);
81
82 // (assert (not (= father (as set.empty (Relation Person Person)))))
83 // (assert (not (= mother (as set.empty (Relation Person Person)))))
84 Term isEmpty3 = tm.mkTerm(EQUAL, father, emptyRelationTerm);
85 Term isEmpty4 = tm.mkTerm(EQUAL, mother, emptyRelationTerm);
86 Term fatherIsNotEmpty = tm.mkTerm(NOT, isEmpty3);
87 Term motherIsNotEmpty = tm.mkTerm(NOT, isEmpty4);
88
89 // fathers are males
90 // (assert (set.subset (rel.join father people) males))
91 Term fathers = tm.mkTerm(RELATION_JOIN, father, people);
92 Term fathersAreMales = tm.mkTerm(SET_SUBSET, fathers, males);
93
94 // mothers are females
95 // (assert (set.subset (rel.join mother people) females))
96 Term mothers = tm.mkTerm(RELATION_JOIN, mother, people);
97 Term mothersAreFemales = tm.mkTerm(SET_SUBSET, mothers, females);
98
99 // (assert (= parent (set.union father mother)))
100 Term unionFatherMother = tm.mkTerm(SET_UNION, father, mother);
101 Term parentIsFatherOrMother = tm.mkTerm(EQUAL, parent, unionFatherMother);
102
103 // (assert (= ancestor (rel.tclosure parent)))
104 Term transitiveClosure = tm.mkTerm(RELATION_TCLOSURE, parent);
105 Term ancestorFormula = tm.mkTerm(EQUAL, ancestor, transitiveClosure);
106
107 // (assert (= descendant (rel.transpose ancestor)))
108 Term transpose = tm.mkTerm(RELATION_TRANSPOSE, ancestor);
109 Term descendantFormula = tm.mkTerm(EQUAL, descendant, transpose);
110
111 // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
112 Term x = tm.mkVar(personSort, "x");
113 Term xxTuple = tm.mkTuple(new Term[] {x, x});
114 Term member = tm.mkTerm(SET_MEMBER, xxTuple, ancestor);
115 Term notMember = tm.mkTerm(NOT, member);
116
117 Term quantifiedVariables = tm.mkTerm(VARIABLE_LIST, x);
118 Term noSelfAncestor = tm.mkTerm(FORALL, quantifiedVariables, notMember);
119
120 // formulas
121 solver.assertFormula(peopleAreTheUniverse);
122 solver.assertFormula(maleSetIsNotEmpty);
123 solver.assertFormula(femaleSetIsNotEmpty);
124 solver.assertFormula(malesAndFemalesAreDisjoint);
125 solver.assertFormula(fatherIsNotEmpty);
126 solver.assertFormula(motherIsNotEmpty);
127 solver.assertFormula(fathersAreMales);
128 solver.assertFormula(mothersAreFemales);
129 solver.assertFormula(parentIsFatherOrMother);
130 solver.assertFormula(descendantFormula);
131 solver.assertFormula(ancestorFormula);
132 solver.assertFormula(noSelfAncestor);
133
134 // check sat
135 Result result = solver.checkSat();
136
137 // output
138 System.out.println("Result = " + result);
139 System.out.println("people = " + solver.getValue(people));
140 System.out.println("males = " + solver.getValue(males));
141 System.out.println("females = " + solver.getValue(females));
142 System.out.println("father = " + solver.getValue(father));
143 System.out.println("mother = " + solver.getValue(mother));
144 System.out.println("parent = " + solver.getValue(parent));
145 System.out.println("descendant = " + solver.getValue(descendant));
146 System.out.println("ancestor = " + solver.getValue(ancestor));
147 }
148 Context.deletePointers();
149 }
150}
examples/api/python/relations.py
1#!/usr/bin/env python
2###############################################################################
3# This file is part of the cvc5 project.
4#
5# Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
6# in the top-level source directory and their institutional affiliations.
7# All rights reserved. See the file COPYING in the top-level source
8# directory for licensing information.
9# #############################################################################
10#
11# A simple demonstration of the solving capabilities of the cvc5 relations solver
12# through the Python API. This is a direct translation of relations.cpp.
13##
14
15import cvc5
16from cvc5 import Kind
17
18if __name__ == "__main__":
19 tm = cvc5.TermManager()
20 solver = cvc5.Solver(tm)
21
22 # Set the logic
23 solver.setLogic("ALL")
24
25 # options
26 solver.setOption("produce-models", "true")
27 # we need finite model finding to answer sat problems with universal
28 # quantified formulas
29 solver.setOption("finite-model-find", "true")
30 # we need sets extension to support set.universe operator
31 solver.setOption("sets-exp", "true")
32
33 integer = tm.getIntegerSort()
34 set_ = tm.mkSetSort(integer)
35
36 # Verify union distributions over intersection
37 # (A union B) intersection C = (A intersection C) union (B intersection C)
38
39 # (declare-sort Person 0)
40 personSort = tm.mkUninterpretedSort("Person")
41
42 # (Tuple Person)
43 tupleArity1 = tm.mkTupleSort(personSort)
44 # (Relation Person)
45 relationArity1 = tm.mkSetSort(tupleArity1)
46
47 # (Tuple Person Person)
48 tupleArity2 = tm.mkTupleSort(personSort, personSort)
49 # (Relation Person Person)
50 relationArity2 = tm.mkSetSort(tupleArity2)
51
52 # empty set
53 emptySetTerm = tm.mkEmptySet(relationArity1)
54
55 # empty relation
56 emptyRelationTerm = tm.mkEmptySet(relationArity2)
57
58 # universe set
59 universeSet = tm.mkUniverseSet(relationArity1)
60
61 # variables
62 people = tm.mkConst(relationArity1, "people")
63 males = tm.mkConst(relationArity1, "males")
64 females = tm.mkConst(relationArity1, "females")
65 father = tm.mkConst(relationArity2, "father")
66 mother = tm.mkConst(relationArity2, "mother")
67 parent = tm.mkConst(relationArity2, "parent")
68 ancestor = tm.mkConst(relationArity2, "ancestor")
69 descendant = tm.mkConst(relationArity2, "descendant")
70
71 isEmpty1 = tm.mkTerm(Kind.EQUAL, males, emptySetTerm)
72 isEmpty2 = tm.mkTerm(Kind.EQUAL, females, emptySetTerm)
73
74 # (assert (= people (as set.universe (Relation Person))))
75 peopleAreTheUniverse = tm.mkTerm(Kind.EQUAL, people, universeSet)
76 # (assert (not (= males (as set.empty (Relation Person)))))
77 maleSetIsNotEmpty = tm.mkTerm(Kind.NOT, isEmpty1)
78 # (assert (not (= females (as set.empty (Relation Person)))))
79 femaleSetIsNotEmpty = tm.mkTerm(Kind.NOT, isEmpty2)
80
81 # (assert (= (set.inter males females)
82 # (as set.empty (Relation Person))))
83 malesFemalesIntersection = tm.mkTerm(Kind.SET_INTER, males, females)
84 malesAndFemalesAreDisjoint = \
85 tm.mkTerm(Kind.EQUAL, malesFemalesIntersection, emptySetTerm)
86
87 # (assert (not (= father (as set.empty (Relation Person Person)))))
88 # (assert (not (= mother (as set.empty (Relation Person Person)))))
89 isEmpty3 = tm.mkTerm(Kind.EQUAL, father, emptyRelationTerm)
90 isEmpty4 = tm.mkTerm(Kind.EQUAL, mother, emptyRelationTerm)
91 fatherIsNotEmpty = tm.mkTerm(Kind.NOT, isEmpty3)
92 motherIsNotEmpty = tm.mkTerm(Kind.NOT, isEmpty4)
93
94 # fathers are males
95 # (assert (set.subset (rel.join father people) males))
96 fathers = tm.mkTerm(Kind.RELATION_JOIN, father, people)
97 fathersAreMales = tm.mkTerm(Kind.SET_SUBSET, fathers, males)
98
99 # mothers are females
100 # (assert (set.subset (rel.join mother people) females))
101 mothers = tm.mkTerm(Kind.RELATION_JOIN, mother, people)
102 mothersAreFemales = tm.mkTerm(Kind.SET_SUBSET, mothers, females)
103
104 # (assert (= parent (set.union father mother)))
105 unionFatherMother = tm.mkTerm(Kind.SET_UNION, father, mother)
106 parentIsFatherOrMother = \
107 tm.mkTerm(Kind.EQUAL, parent, unionFatherMother)
108
109 # (assert (= ancestor (rel.tclosure parent)))
110 transitiveClosure = tm.mkTerm(Kind.RELATION_TCLOSURE, parent)
111 ancestorFormula = tm.mkTerm(Kind.EQUAL, ancestor, transitiveClosure)
112
113 # (assert (= descendant (rel.transpose ancestor)))
114 transpose = tm.mkTerm(Kind.RELATION_TRANSPOSE, ancestor)
115 descendantFormula = tm.mkTerm(Kind.EQUAL, descendant, transpose)
116
117 # (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
118 x = tm.mkVar(personSort, "x")
119 xxTuple = tm.mkTuple([x, x])
120 member = tm.mkTerm(Kind.SET_MEMBER, xxTuple, ancestor)
121 notMember = tm.mkTerm(Kind.NOT, member)
122
123 quantifiedVariables = tm.mkTerm(Kind.VARIABLE_LIST, x)
124 noSelfAncestor = tm.mkTerm(Kind.FORALL, quantifiedVariables, notMember)
125
126 # formulas
127 solver.assertFormula(peopleAreTheUniverse)
128 solver.assertFormula(maleSetIsNotEmpty)
129 solver.assertFormula(femaleSetIsNotEmpty)
130 solver.assertFormula(malesAndFemalesAreDisjoint)
131 solver.assertFormula(fatherIsNotEmpty)
132 solver.assertFormula(motherIsNotEmpty)
133 solver.assertFormula(fathersAreMales)
134 solver.assertFormula(mothersAreFemales)
135 solver.assertFormula(parentIsFatherOrMother)
136 solver.assertFormula(descendantFormula)
137 solver.assertFormula(ancestorFormula)
138 solver.assertFormula(noSelfAncestor)
139
140 # check sat
141 result = solver.checkSat()
142
143 # output
144 print("Result = {}".format(result))
145 print("people = {}".format(solver.getValue(people)))
146 print("males = {}".format(solver.getValue(males)))
147 print("females = {}".format(solver.getValue(females)))
148 print("father = {}".format(solver.getValue(father)))
149 print("mother = {}".format(solver.getValue(mother)))
150 print("parent = {}".format(solver.getValue(parent)))
151 print("descendant = {}".format(solver.getValue(descendant)))
152 print("ancestor = {}".format(solver.getValue(ancestor)))
examples/api/smtlib/relations.smt2
1(set-logic ALL)
2
3(set-option :produce-models true)
4; we need finite model finding to answer sat problems with universal
5; quantified formulas
6(set-option :finite-model-find true)
7; we need sets extension to support set.universe operator
8(set-option :sets-exp true)
9
10(declare-sort Person 0)
11
12(declare-fun people () (Relation Person))
13(declare-fun males () (Relation Person))
14(declare-fun females () (Relation Person))
15(declare-fun father () (Relation Person Person))
16(declare-fun mother () (Relation Person Person))
17(declare-fun parent () (Relation Person Person))
18(declare-fun ancestor () (Relation Person Person))
19(declare-fun descendant () (Relation Person Person))
20
21(assert (= people (as set.universe (Relation Person))))
22(assert (not (= males (as set.empty (Relation Person)))))
23(assert (not (= females (as set.empty (Relation Person)))))
24(assert (= (set.inter males females) (as set.empty (Relation Person))))
25
26; father relation is not empty
27(assert (not (= father (as set.empty (Relation Person Person)))))
28; mother relation is not empty
29(assert (not (= mother (as set.empty (Relation Person Person)))))
30; fathers are males
31(assert (set.subset (rel.join father people) males))
32; mothers are females
33(assert (set.subset (rel.join mother people) females))
34; parent
35(assert (= parent (set.union father mother)))
36; no self ancestor
37(assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
38; ancestor
39(assert (= ancestor (rel.tclosure parent)))
40; ancestor
41(assert (= descendant (rel.transpose ancestor)))
42
43(check-sat)
44(get-model)