File: relations.c

package info (click to toggle)
cvc5 1.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 87,260 kB
  • sloc: cpp: 383,850; java: 12,207; python: 12,090; sh: 5,679; ansic: 4,729; lisp: 763; perl: 208; makefile: 38
file content (202 lines) | stat: -rw-r--r-- 7,701 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/******************************************************************************
 * Top contributors (to current version):
 *   Aina Niemetz, Mudathir Mohamed, Andrew Reynolds
 *
 * This file is part of the cvc5 project.
 *
 * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
 * in the top-level source directory and their institutional affiliations.
 * All rights reserved.  See the file COPYING in the top-level source
 * directory for licensing information.
 * ****************************************************************************
 *
 * A simple demonstration of reasoning about relations via the C API.
 */

#include <cvc5/c/cvc5.h>
#include <stdio.h>

int main()
{
  Cvc5TermManager* tm = cvc5_term_manager_new();
  Cvc5* slv = cvc5_new(tm);

  // Set the logic
  cvc5_set_logic(slv, "ALL");

  // options
  cvc5_set_option(slv, "produce-models", "true");
  // we need finite model finding to answer sat problems with universal
  // quantified formulas
  cvc5_set_option(slv, "finite-model-find", "true");
  // we need sets extension to support set.universe operator
  cvc5_set_option(slv, "sets-exp", "true");

  // (declare-sort Person 0)
  Cvc5Sort person_sort = cvc5_mk_uninterpreted_sort(tm, "Person");

  // (Tuple Person)
  Cvc5Sort sorts1[1] = {person_sort};
  Cvc5Sort tuple_arity1 = cvc5_mk_tuple_sort(tm, 1, sorts1);
  // (Relation Person)
  Cvc5Sort rel_arity1 = cvc5_mk_set_sort(tm, tuple_arity1);

  // (Tuple Person Person)
  Cvc5Sort sorts2[2] = {person_sort, person_sort};
  Cvc5Sort tuple_arity2 = cvc5_mk_tuple_sort(tm, 2, sorts2);
  // (Relation Person Person)
  Cvc5Sort rel_arity2 = cvc5_mk_set_sort(tm, tuple_arity2);

  // empty set
  Cvc5Term empty_set = cvc5_mk_empty_set(tm, rel_arity1);

  // empty relation
  Cvc5Term empty_rel = cvc5_mk_empty_set(tm, rel_arity2);

  // universe set
  Cvc5Term universe_set = cvc5_mk_universe_set(tm, rel_arity1);

  // variables
  Cvc5Term people = cvc5_mk_const(tm, rel_arity1, "people");
  Cvc5Term males = cvc5_mk_const(tm, rel_arity1, "males");
  Cvc5Term females = cvc5_mk_const(tm, rel_arity1, "females");
  Cvc5Term father = cvc5_mk_const(tm, rel_arity2, "father");
  Cvc5Term mother = cvc5_mk_const(tm, rel_arity2, "mother");
  Cvc5Term parent = cvc5_mk_const(tm, rel_arity2, "parent");
  Cvc5Term ancestor = cvc5_mk_const(tm, rel_arity2, "ancestor");
  Cvc5Term descendant = cvc5_mk_const(tm, rel_arity2, "descendant");

  Cvc5Term args2[2] = {males, empty_set};
  Cvc5Term is_empty1 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
  args2[0] = females;
  Cvc5Term is_empty2 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);

  // (assert (= people (as set.universe (Relation Person))))
  args2[0] = people;
  args2[1] = universe_set;
  Cvc5Term people_universe = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
  // (assert (not (= males (as set.empty (Relation Person)))))
  Cvc5Term args1[1] = {is_empty1};
  Cvc5Term male_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
  // (assert (not (= females (as set.empty (Relation Person)))))
  args1[0] = is_empty2;
  Cvc5Term female_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);

  // (assert (= (set.inter males females)
  //            (as set.empty (Relation Person))))
  args2[0] = males;
  args2[1] = females;
  Cvc5Term inter_males_females =
      cvc5_mk_term(tm, CVC5_KIND_SET_INTER, 2, args2);
  args2[0] = inter_males_females;
  args2[1] = empty_set;
  Cvc5Term disjoint_males_females = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);

  // (assert (not (= father (as set.empty (Relation Person Person)))))
  // (assert (not (= mother (as set.empty (Relation Person Person)))))
  args2[0] = father;
  args2[1] = empty_rel;
  Cvc5Term is_empty3 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
  args2[0] = mother;
  args2[1] = empty_rel;
  Cvc5Term is_empty4 = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);
  args1[0] = is_empty3;
  Cvc5Term father_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);
  args1[0] = is_empty4;
  Cvc5Term mother_not_empty = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);

  // fathers are males
  // (assert (set.subset (rel.join father people) males))
  args2[0] = father;
  args2[1] = people;
  Cvc5Term fathers = cvc5_mk_term(tm, CVC5_KIND_RELATION_JOIN, 2, args2);
  args2[0] = fathers;
  args2[1] = males;
  Cvc5Term fathers_are_males = cvc5_mk_term(tm, CVC5_KIND_SET_SUBSET, 2, args2);

  // mothers are females
  // (assert (set.subset (rel.join mother people) females))
  args2[0] = mother;
  args2[1] = people;
  Cvc5Term mothers = cvc5_mk_term(tm, CVC5_KIND_RELATION_JOIN, 2, args2);
  args2[0] = mothers;
  args2[1] = females;
  Cvc5Term mothers_are_females =
      cvc5_mk_term(tm, CVC5_KIND_SET_SUBSET, 2, args2);

  // (assert (= parent (set.union father mother)))
  args2[0] = father;
  args2[1] = mother;
  Cvc5Term union_father_mother =
      cvc5_mk_term(tm, CVC5_KIND_SET_UNION, 2, args2);
  args2[0] = parent;
  args2[1] = union_father_mother;
  Cvc5Term parent_is_father_or_mother =
      cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);

  // (assert (= ancestor (rel.tclosure parent)))
  args1[0] = parent;
  Cvc5Term trans_closure =
      cvc5_mk_term(tm, CVC5_KIND_RELATION_TCLOSURE, 1, args1);
  args2[0] = ancestor;
  args2[1] = trans_closure;
  Cvc5Term ancestor_formula = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);

  // (assert (= descendant (rel.transpose descendant)))
  args1[0] = ancestor;
  Cvc5Term transpose = cvc5_mk_term(tm, CVC5_KIND_RELATION_TRANSPOSE, 1, args1);
  args2[0] = descendant;
  args2[1] = transpose;
  Cvc5Term descendant_formula = cvc5_mk_term(tm, CVC5_KIND_EQUAL, 2, args2);

  // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
  Cvc5Term x = cvc5_mk_var(tm, person_sort, "x");
  args2[0] = x;
  args2[1] = x;
  Cvc5Term xx_tuple = cvc5_mk_tuple(tm, 2, args2);
  args2[0] = xx_tuple;
  args2[1] = ancestor;
  Cvc5Term member = cvc5_mk_term(tm, CVC5_KIND_SET_MEMBER, 2, args2);
  args1[0] = member;
  Cvc5Term not_member = cvc5_mk_term(tm, CVC5_KIND_NOT, 1, args1);

  args1[0] = x;
  Cvc5Term vars = cvc5_mk_term(tm, CVC5_KIND_VARIABLE_LIST, 1, args1);
  args2[0] = vars;
  args2[1] = not_member;
  Cvc5Term not_self_ancestor = cvc5_mk_term(tm, CVC5_KIND_FORALL, 2, args2);

  // formulas
  cvc5_assert_formula(slv, people_universe);
  cvc5_assert_formula(slv, male_not_empty);
  cvc5_assert_formula(slv, female_not_empty);
  cvc5_assert_formula(slv, disjoint_males_females);
  cvc5_assert_formula(slv, father_not_empty);
  cvc5_assert_formula(slv, mother_not_empty);
  cvc5_assert_formula(slv, fathers_are_males);
  cvc5_assert_formula(slv, mothers_are_females);
  cvc5_assert_formula(slv, parent_is_father_or_mother);
  cvc5_assert_formula(slv, descendant_formula);
  cvc5_assert_formula(slv, ancestor_formula);
  cvc5_assert_formula(slv, not_self_ancestor);

  // check sat
  Cvc5Result result = cvc5_check_sat(slv);

  // output
  printf("Result     = %s\n", cvc5_result_to_string(result));
  printf("people     = %s\n", cvc5_term_to_string(cvc5_get_value(slv, people)));
  printf("males      = %s\n", cvc5_term_to_string(cvc5_get_value(slv, males)));
  printf("females    = %s\n",
         cvc5_term_to_string(cvc5_get_value(slv, females)));
  printf("father     = %s\n", cvc5_term_to_string(cvc5_get_value(slv, father)));
  printf("mother     = %s\n", cvc5_term_to_string(cvc5_get_value(slv, mother)));
  printf("parent     = %s\n", cvc5_term_to_string(cvc5_get_value(slv, parent)));
  printf("descendant = %s\n",
         cvc5_term_to_string(cvc5_get_value(slv, descendant)));
  printf("ancestor   = %s\n",
         cvc5_term_to_string(cvc5_get_value(slv, ancestor)));

  cvc5_delete(slv);
  cvc5_term_manager_delete(tm);
}