/********************* */ /*! \file Relations.java ** \verbatim ** Top contributors (to current version): ** Mudathir Mahgoub ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 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.\endverbatim ** ** \brief Reasoning about relations with CVC4 via Java API. ** ** A simple demonstration of reasoning about strings with CVC4 via Jave API. **/ import edu.stanford.CVC4.*; /* This file uses the API to make a sat call equivalent to the following benchmark: (set-logic ALL) (set-option :finite-model-find true) (set-option :produce-models true) (set-option :sets-ext true) (set-option :output-language "smt2") (declare-sort Person 0) (declare-fun people () (Set (Tuple Person))) (declare-fun males () (Set (Tuple Person))) (declare-fun females() (Set (Tuple Person))) (declare-fun father () (Set (Tuple Person Person))) (declare-fun mother () (Set (Tuple Person Person))) (declare-fun parent () (Set (Tuple Person Person))) (declare-fun ancestor () (Set (Tuple Person Person))) (declare-fun descendant () (Set (Tuple Person Person))) (assert (= people (as univset (Set (Tuple Person))))) (assert (not (= males (as emptyset (Set (Tuple Person)))))) (assert (not (= females (as emptyset (Set (Tuple Person)))))) (assert (= (intersection males females) (as emptyset (Set (Tuple Person))))) ; father relation is not empty (assert (not (= father (as emptyset (Set (Tuple Person Person)))))) ; mother relation is not empty (assert (not (= mother (as emptyset (Set (Tuple Person Person)))))) ; fathers are males (assert (subset (join father people) males)) ; mothers are females (assert (subset (join mother people) females)) ; parent (assert (= parent (union father mother))) ; no self ancestor (assert (forall ((x Person)) (not (member (mkTuple x x) ancestor)))) ; descendant (assert (= descendant (tclosure parent))) ; ancestor (assert (= ancestor (transpose descendant))) (check-sat) (get-model) */ public class Relations { public static void main(String[] args) { System.load("/usr/local/lib/libcvc4jni.so"); ExprManager manager = new ExprManager(); SmtEngine smtEngine = new SmtEngine(manager); // Set the logic smtEngine.setLogic("ALL"); // options smtEngine.setOption("produce-models", new SExpr(true)); smtEngine.setOption("finite-model-find", new SExpr(true)); smtEngine.setOption("sets-ext", new SExpr(true)); smtEngine.setOption("output-language", new SExpr("smt2")); // (declare-sort Person 0) Type personType = manager.mkSort("Person", 0); vectorType vector1 = new vectorType(); vector1.add(personType); // (Tuple Person) Type tupleArity1 = manager.mkTupleType(vector1); // (Set (Tuple Person)) SetType relationArity1 = manager.mkSetType(tupleArity1); vectorType vector2 = new vectorType(); vector2.add(personType); vector2.add(personType); // (Tuple Person Person) DatatypeType tupleArity2 = manager.mkTupleType(vector2); // (Set (Tuple Person Person)) SetType relationArity2 = manager.mkSetType(tupleArity2); // empty set EmptySet emptySet = new EmptySet(relationArity1); Expr emptySetExpr = manager.mkConst(emptySet); // empty relation EmptySet emptyRelation = new EmptySet(relationArity2); Expr emptyRelationExpr = manager.mkConst(emptyRelation); // universe set Expr universeSet = manager.mkNullaryOperator(relationArity1, Kind.UNIVERSE_SET); // variables Expr people = manager.mkVar("people", relationArity1); Expr males = manager.mkVar("males", relationArity1); Expr females = manager.mkVar("females", relationArity1); Expr father = manager.mkVar("father", relationArity2); Expr mother = manager.mkVar("mother", relationArity2); Expr parent = manager.mkVar("parent", relationArity2); Expr ancestor = manager.mkVar("ancestor", relationArity2); Expr descendant = manager.mkVar("descendant", relationArity2); Expr isEmpty1 = manager.mkExpr(Kind.EQUAL, males, emptySetExpr); Expr isEmpty2 = manager.mkExpr(Kind.EQUAL, females, emptySetExpr); // (assert (= people (as univset (Set (Tuple Person))))) Expr peopleAreTheUniverse = manager.mkExpr(Kind.EQUAL, people, universeSet); // (assert (not (= males (as emptyset (Set (Tuple Person)))))) Expr maleSetIsNotEmpty = manager.mkExpr(Kind.NOT, isEmpty1); // (assert (not (= females (as emptyset (Set (Tuple Person)))))) Expr femaleSetIsNotEmpty = manager.mkExpr(Kind.NOT, isEmpty2); // (assert (= (intersection males females) (as emptyset (Set (Tuple Person))))) Expr malesFemalesIntersection = manager.mkExpr(Kind.INTERSECTION, males, females); Expr malesAndFemalesAreDisjoint = manager.mkExpr(Kind.EQUAL, malesFemalesIntersection, emptySetExpr); // (assert (not (= father (as emptyset (Set (Tuple Person Person)))))) // (assert (not (= mother (as emptyset (Set (Tuple Person Person)))))) Expr isEmpty3 = manager.mkExpr(Kind.EQUAL, father, emptyRelationExpr); Expr isEmpty4 = manager.mkExpr(Kind.EQUAL, mother, emptyRelationExpr); Expr fatherIsNotEmpty = manager.mkExpr(Kind.NOT, isEmpty3); Expr motherIsNotEmpty = manager.mkExpr(Kind.NOT, isEmpty4); // fathers are males // (assert (subset (join father people) males)) Expr fathers = manager.mkExpr(Kind.JOIN, father, people); Expr fathersAreMales = manager.mkExpr(Kind.SUBSET, fathers, males); // mothers are females // (assert (subset (join mother people) females)) Expr mothers = manager.mkExpr(Kind.JOIN, mother, people); Expr mothersAreFemales = manager.mkExpr(Kind.SUBSET, mothers, females); // (assert (= parent (union father mother))) Expr unionFatherMother = manager.mkExpr(Kind.UNION, father, mother); Expr parentIsFatherOrMother = manager.mkExpr(Kind.EQUAL, parent, unionFatherMother); // (assert (= parent (union father mother))) Expr transitiveClosure = manager.mkExpr(Kind.TCLOSURE, parent); Expr descendantFormula = manager.mkExpr(Kind.EQUAL, descendant, transitiveClosure); // (assert (= parent (union father mother))) Expr transpose = manager.mkExpr(Kind.TRANSPOSE, descendant); Expr ancestorFormula = manager.mkExpr(Kind.EQUAL, ancestor, transpose); // (assert (forall ((x Person)) (not (member (mkTuple x x) ancestor)))) Expr x = manager.mkBoundVar("x", personType); Expr constructor = tupleArity2.getDatatype().get(0).getConstructor(); Expr xxTuple = manager.mkExpr(Kind.APPLY_CONSTRUCTOR, constructor, x, x); Expr member = manager.mkExpr(Kind.MEMBER, xxTuple, ancestor); Expr notMember = manager.mkExpr(Kind.NOT, member); vectorExpr vectorExpr = new vectorExpr(); vectorExpr.add(x); Expr quantifiedVariables = manager.mkExpr(Kind.BOUND_VAR_LIST, x); Expr noSelfAncestor = manager.mkExpr(Kind.FORALL, quantifiedVariables, notMember); // formulas Expr formula1 = manager.mkExpr(Kind.AND, peopleAreTheUniverse, maleSetIsNotEmpty, femaleSetIsNotEmpty, malesAndFemalesAreDisjoint); Expr formula2 = manager.mkExpr(Kind.AND, formula1, fatherIsNotEmpty, motherIsNotEmpty, fathersAreMales, mothersAreFemales); Expr formula3 = manager.mkExpr(Kind.AND, formula2, parentIsFatherOrMother, descendantFormula, ancestorFormula, noSelfAncestor); // check sat Result result = smtEngine.checkSat(formula3); // output System.out.println("CVC4 reports: " + formula3 + " is " + result + "."); System.out.println("people = " + smtEngine.getValue(people)); System.out.println("males = " + smtEngine.getValue(males)); System.out.println("females = " + smtEngine.getValue(females)); System.out.println("father = " + smtEngine.getValue(father)); System.out.println("mother = " + smtEngine.getValue(mother)); System.out.println("parent = " + smtEngine.getValue(parent)); System.out.println("descendant = " + smtEngine.getValue(descendant)); System.out.println("ancestor = " + smtEngine.getValue(ancestor)); } }