File: Relations.java

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 (153 lines) | stat: -rw-r--r-- 6,466 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
/******************************************************************************
 * Top contributors (to current version):
 *   Mudathir Mohamed, Daniel Larraz, Andres Noetzli
 *
 * 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 with cvc5 via Java API.
 */

import static io.github.cvc5.Kind.*;

import io.github.cvc5.*;

public class Relations
{
  public static void main(String[] args) throws CVC5ApiException
  {
    TermManager tm = new TermManager();
    Solver solver = new Solver(tm);
    {
      // Set the logic
      solver.setLogic("ALL");

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

      // (declare-sort Person 0)
      Sort personSort = tm.mkUninterpretedSort("Person");

      // (Tuple Person)
      Sort tupleArity1 = tm.mkTupleSort(new Sort[] {personSort});
      // (Relation Person)
      Sort relationArity1 = tm.mkSetSort(tupleArity1);

      // (Tuple Person Person)
      Sort tupleArity2 = tm.mkTupleSort(new Sort[] {personSort, personSort});
      // (Relation Person Person)
      Sort relationArity2 = tm.mkSetSort(tupleArity2);

      // empty set
      Term emptySetTerm = tm.mkEmptySet(relationArity1);

      // empty relation
      Term emptyRelationTerm = tm.mkEmptySet(relationArity2);

      // universe set
      Term universeSet = tm.mkUniverseSet(relationArity1);

      // variables
      Term people = tm.mkConst(relationArity1, "people");
      Term males = tm.mkConst(relationArity1, "males");
      Term females = tm.mkConst(relationArity1, "females");
      Term father = tm.mkConst(relationArity2, "father");
      Term mother = tm.mkConst(relationArity2, "mother");
      Term parent = tm.mkConst(relationArity2, "parent");
      Term ancestor = tm.mkConst(relationArity2, "ancestor");
      Term descendant = tm.mkConst(relationArity2, "descendant");

      Term isEmpty1 = tm.mkTerm(EQUAL, males, emptySetTerm);
      Term isEmpty2 = tm.mkTerm(EQUAL, females, emptySetTerm);

      // (assert (= people (as set.universe (Relation Person))))
      Term peopleAreTheUniverse = tm.mkTerm(EQUAL, people, universeSet);
      // (assert (not (= males (as set.empty (Relation Person)))))
      Term maleSetIsNotEmpty = tm.mkTerm(NOT, isEmpty1);
      // (assert (not (= females (as set.empty (Relation Person)))))
      Term femaleSetIsNotEmpty = tm.mkTerm(NOT, isEmpty2);

      // (assert (= (set.inter males females)
      //            (as set.empty (Relation Person))))
      Term malesFemalesIntersection = tm.mkTerm(SET_INTER, males, females);
      Term malesAndFemalesAreDisjoint = tm.mkTerm(EQUAL, malesFemalesIntersection, emptySetTerm);

      // (assert (not (= father (as set.empty (Relation Person Person)))))
      // (assert (not (= mother (as set.empty (Relation Person Person)))))
      Term isEmpty3 = tm.mkTerm(EQUAL, father, emptyRelationTerm);
      Term isEmpty4 = tm.mkTerm(EQUAL, mother, emptyRelationTerm);
      Term fatherIsNotEmpty = tm.mkTerm(NOT, isEmpty3);
      Term motherIsNotEmpty = tm.mkTerm(NOT, isEmpty4);

      // fathers are males
      // (assert (set.subset (rel.join father people) males))
      Term fathers = tm.mkTerm(RELATION_JOIN, father, people);
      Term fathersAreMales = tm.mkTerm(SET_SUBSET, fathers, males);

      // mothers are females
      // (assert (set.subset (rel.join mother people) females))
      Term mothers = tm.mkTerm(RELATION_JOIN, mother, people);
      Term mothersAreFemales = tm.mkTerm(SET_SUBSET, mothers, females);

      // (assert (= parent (set.union father mother)))
      Term unionFatherMother = tm.mkTerm(SET_UNION, father, mother);
      Term parentIsFatherOrMother = tm.mkTerm(EQUAL, parent, unionFatherMother);

      // (assert (= ancestor (rel.tclosure parent)))
      Term transitiveClosure = tm.mkTerm(RELATION_TCLOSURE, parent);
      Term ancestorFormula = tm.mkTerm(EQUAL, ancestor, transitiveClosure);

      // (assert (= descendant (rel.transpose ancestor)))
      Term transpose = tm.mkTerm(RELATION_TRANSPOSE, ancestor);
      Term descendantFormula = tm.mkTerm(EQUAL, descendant, transpose);

      // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
      Term x = tm.mkVar(personSort, "x");
      Term xxTuple = tm.mkTuple(new Term[] {x, x});
      Term member = tm.mkTerm(SET_MEMBER, xxTuple, ancestor);
      Term notMember = tm.mkTerm(NOT, member);

      Term quantifiedVariables = tm.mkTerm(VARIABLE_LIST, x);
      Term noSelfAncestor = tm.mkTerm(FORALL, quantifiedVariables, notMember);

      // formulas
      solver.assertFormula(peopleAreTheUniverse);
      solver.assertFormula(maleSetIsNotEmpty);
      solver.assertFormula(femaleSetIsNotEmpty);
      solver.assertFormula(malesAndFemalesAreDisjoint);
      solver.assertFormula(fatherIsNotEmpty);
      solver.assertFormula(motherIsNotEmpty);
      solver.assertFormula(fathersAreMales);
      solver.assertFormula(mothersAreFemales);
      solver.assertFormula(parentIsFatherOrMother);
      solver.assertFormula(descendantFormula);
      solver.assertFormula(ancestorFormula);
      solver.assertFormula(noSelfAncestor);

      // check sat
      Result result = solver.checkSat();

      // output
      System.out.println("Result     = " + result);
      System.out.println("people     = " + solver.getValue(people));
      System.out.println("males      = " + solver.getValue(males));
      System.out.println("females    = " + solver.getValue(females));
      System.out.println("father     = " + solver.getValue(father));
      System.out.println("mother     = " + solver.getValue(mother));
      System.out.println("parent     = " + solver.getValue(parent));
      System.out.println("descendant = " + solver.getValue(descendant));
      System.out.println("ancestor   = " + solver.getValue(ancestor));
    }
    Context.deletePointers();
  }
}