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