2020-02-25 11:47:24 -06:00
|
|
|
/********************* */
|
|
|
|
|
/*! \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)
|
|
|
|
|
*/
|
|
|
|
|
|
2020-06-08 21:20:25 -07:00
|
|
|
public class Relations {
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
System.loadLibrary("cvc4jni");
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2020-06-08 21:20:25 -07:00
|
|
|
// (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);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
// (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);
|
2020-06-08 21:20:25 -07:00
|
|
|
Expr parentIsFatherOrMother =
|
|
|
|
|
manager.mkExpr(Kind.EQUAL, parent, unionFatherMother);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
// (assert (= parent (union father mother)))
|
|
|
|
|
Expr transitiveClosure = manager.mkExpr(Kind.TCLOSURE, parent);
|
2020-06-08 21:20:25 -07:00
|
|
|
Expr descendantFormula =
|
|
|
|
|
manager.mkExpr(Kind.EQUAL, descendant, transitiveClosure);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
// (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);
|
2020-06-08 21:20:25 -07:00
|
|
|
Expr noSelfAncestor =
|
|
|
|
|
manager.mkExpr(Kind.FORALL, quantifiedVariables, notMember);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
// formulas
|
|
|
|
|
Expr formula1 = manager.mkExpr(Kind.AND,
|
2020-06-08 21:20:25 -07:00
|
|
|
peopleAreTheUniverse,
|
|
|
|
|
maleSetIsNotEmpty,
|
|
|
|
|
femaleSetIsNotEmpty,
|
|
|
|
|
malesAndFemalesAreDisjoint);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
Expr formula2 = manager.mkExpr(Kind.AND,
|
2020-06-08 21:20:25 -07:00
|
|
|
formula1,
|
|
|
|
|
fatherIsNotEmpty,
|
|
|
|
|
motherIsNotEmpty,
|
|
|
|
|
fathersAreMales,
|
|
|
|
|
mothersAreFemales);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
Expr formula3 = manager.mkExpr(Kind.AND,
|
2020-06-08 21:20:25 -07:00
|
|
|
formula2,
|
|
|
|
|
parentIsFatherOrMother,
|
|
|
|
|
descendantFormula,
|
|
|
|
|
ancestorFormula,
|
|
|
|
|
noSelfAncestor);
|
2020-02-25 11:47:24 -06:00
|
|
|
|
|
|
|
|
// 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));
|
|
|
|
|
}
|
|
|
|
|
}
|