2021-04-12 12:31:43 -07:00
|
|
|
/******************************************************************************
|
|
|
|
|
* Top contributors (to current version):
|
2022-04-05 13:38:57 -07:00
|
|
|
* Mudathir Mohamed, Andres Noetzli, Aina Niemetz
|
2021-04-12 12:31:43 -07:00
|
|
|
*
|
|
|
|
|
* This file is part of the cvc5 project.
|
|
|
|
|
*
|
2024-03-12 09:35:09 -07:00
|
|
|
* Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
|
2021-04-12 12:31:43 -07:00
|
|
|
* 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.
|
|
|
|
|
* ****************************************************************************
|
|
|
|
|
*
|
2021-10-01 18:21:02 -05:00
|
|
|
* An example of solving floating-point problems with cvc5's Java API
|
2021-04-12 12:31:43 -07:00
|
|
|
*
|
2021-10-01 18:21:02 -05:00
|
|
|
* This example shows to create floating-point types, variables and expressions,
|
|
|
|
|
* and how to create rounding mode constants by solving toy problems. The
|
|
|
|
|
* example also shows making special values (such as NaN and +oo) and converting
|
|
|
|
|
* an IEEE 754-2008 bit-vector to a floating-point number.
|
2021-04-12 12:31:43 -07:00
|
|
|
*/
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2022-03-30 21:09:03 -07:00
|
|
|
import static io.github.cvc5.Kind.*;
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2022-03-30 21:09:03 -07:00
|
|
|
import io.github.cvc5.*;
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2021-10-01 18:21:02 -05:00
|
|
|
public class FloatingPointArith
|
|
|
|
|
{
|
|
|
|
|
public static void main(String[] args) throws CVC5ApiException
|
|
|
|
|
{
|
2024-06-21 14:32:07 -07:00
|
|
|
TermManager tm = new TermManager();
|
|
|
|
|
Solver solver = new Solver(tm);
|
2021-11-03 16:32:10 -05:00
|
|
|
{
|
2024-06-21 14:32:07 -07:00
|
|
|
solver.setOption("incremental", "true");
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.setOption("produce-models", "true");
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2021-11-03 16:32:10 -05:00
|
|
|
// Make single precision floating-point variables
|
2024-06-21 14:32:07 -07:00
|
|
|
Sort fpt32 = tm.mkFloatingPointSort(8, 24);
|
|
|
|
|
Term a = tm.mkConst(fpt32, "a");
|
|
|
|
|
Term b = tm.mkConst(fpt32, "b");
|
|
|
|
|
Term c = tm.mkConst(fpt32, "c");
|
|
|
|
|
Term d = tm.mkConst(fpt32, "d");
|
|
|
|
|
Term e = tm.mkConst(fpt32, "e");
|
|
|
|
|
// Rounding mode
|
|
|
|
|
Term rm = tm.mkRoundingMode(RoundingMode.ROUND_NEAREST_TIES_TO_EVEN);
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Show that fused multiplication and addition `(fp.fma RM a b c)`");
|
|
|
|
|
System.out.println("is different from `(fp.add RM (fp.mul a b) c)`:");
|
|
|
|
|
solver.push(1);
|
|
|
|
|
Term fma = tm.mkTerm(Kind.FLOATINGPOINT_FMA, new Term[] {rm, a, b, c});
|
|
|
|
|
Term mul = tm.mkTerm(Kind.FLOATINGPOINT_MULT, rm, a, b);
|
|
|
|
|
Term add = tm.mkTerm(Kind.FLOATINGPOINT_ADD, rm, mul, c);
|
|
|
|
|
solver.assertFormula(tm.mkTerm(Kind.DISTINCT, fma, add));
|
2021-11-03 16:32:10 -05:00
|
|
|
Result r = solver.checkSat(); // result is sat
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Expect sat: " + r);
|
|
|
|
|
System.out.println("Value of `a`: " + solver.getValue(a));
|
|
|
|
|
System.out.println("Value of `b`: " + solver.getValue(b));
|
|
|
|
|
System.out.println("Value of `c`: " + solver.getValue(c));
|
|
|
|
|
System.out.println("Value of `(fp.fma RNE a b c)`: " + solver.getValue(fma));
|
|
|
|
|
System.out.println("Value of `(fp.add RNE (fp.mul a b) c)`: " + solver.getValue(add));
|
|
|
|
|
System.out.println();
|
|
|
|
|
solver.pop(1);
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Show that floating-point addition is not associative:");
|
|
|
|
|
System.out.println("(a + (b + c)) != ((a + b) + c)");
|
|
|
|
|
Term lhs =
|
|
|
|
|
tm.mkTerm(Kind.FLOATINGPOINT_ADD, rm, a, tm.mkTerm(Kind.FLOATINGPOINT_ADD, rm, b, c));
|
|
|
|
|
Term rhs =
|
|
|
|
|
tm.mkTerm(Kind.FLOATINGPOINT_ADD, rm, tm.mkTerm(Kind.FLOATINGPOINT_ADD, rm, a, b), c);
|
|
|
|
|
solver.assertFormula(tm.mkTerm(Kind.NOT, tm.mkTerm(Kind.EQUAL, a, b)));
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2021-11-03 16:32:10 -05:00
|
|
|
r = solver.checkSat(); // result is sat
|
|
|
|
|
assert r.isSat();
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Value of `a`: " + solver.getValue(a));
|
|
|
|
|
System.out.println("Value of `b`: " + solver.getValue(b));
|
|
|
|
|
System.out.println("Value of `c`: " + solver.getValue(c));
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Now, restrict `a` to be either NaN or positive infinity:");
|
|
|
|
|
Term nan = tm.mkFloatingPointNaN(8, 24);
|
|
|
|
|
Term inf = tm.mkFloatingPointPosInf(8, 24);
|
|
|
|
|
solver.assertFormula(
|
|
|
|
|
tm.mkTerm(Kind.OR, tm.mkTerm(Kind.EQUAL, a, inf), tm.mkTerm(Kind.EQUAL, a, nan)));
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2021-11-03 16:32:10 -05:00
|
|
|
r = solver.checkSat(); // result is sat
|
|
|
|
|
assert r.isSat();
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Value of `a`: " + solver.getValue(a));
|
|
|
|
|
System.out.println("Value of `b`: " + solver.getValue(b));
|
|
|
|
|
System.out.println("Value of `c`: " + solver.getValue(c));
|
|
|
|
|
|
|
|
|
|
System.out.println("Now, try to find a (normal) floating-point number that rounds");
|
|
|
|
|
System.out.println("to different integer values for different rounding modes:");
|
|
|
|
|
Term rtp = tm.mkRoundingMode(RoundingMode.ROUND_TOWARD_POSITIVE);
|
|
|
|
|
Term rtn = tm.mkRoundingMode(RoundingMode.ROUND_TOWARD_NEGATIVE);
|
|
|
|
|
Op op = tm.mkOp(Kind.FLOATINGPOINT_TO_UBV, 16); // (_ fp.to_ubv 16)
|
|
|
|
|
lhs = tm.mkTerm(op, rtp, d);
|
|
|
|
|
rhs = tm.mkTerm(op, rtn, d);
|
|
|
|
|
solver.assertFormula(tm.mkTerm(Kind.FLOATINGPOINT_IS_NORMAL, d));
|
|
|
|
|
solver.assertFormula(tm.mkTerm(Kind.NOT, tm.mkTerm(Kind.EQUAL, lhs, rhs)));
|
|
|
|
|
|
|
|
|
|
r = solver.checkSat(); // result is sat
|
|
|
|
|
assert r.isSat();
|
|
|
|
|
|
|
|
|
|
System.out.println("Get value of `d` as floating-point, bit-vector and real:");
|
2021-11-03 16:32:10 -05:00
|
|
|
Term val = solver.getValue(d);
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Value of `d`: " + val);
|
|
|
|
|
System.out.println("Value of `((_ fp.to_ubv 16) RTP d)`: " + solver.getValue(lhs));
|
|
|
|
|
System.out.println("Value of `((_ fp.to_ubv 16) RTN d)`: " + solver.getValue(rhs));
|
|
|
|
|
System.out.println("Value of `(fp.to_real d)`: "
|
|
|
|
|
+ solver.getValue(tm.mkTerm(Kind.FLOATINGPOINT_TO_REAL, val)));
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2024-06-21 14:32:07 -07:00
|
|
|
System.out.println("Finally, try to find a floating-point number between positive");
|
|
|
|
|
System.out.println("zero and the smallest positive floating-point number:");
|
|
|
|
|
Term zero = tm.mkFloatingPointPosZero(8, 24);
|
|
|
|
|
Term smallest = tm.mkFloatingPoint(8, 24, tm.mkBitVector(32, 0b001));
|
|
|
|
|
solver.assertFormula(tm.mkTerm(Kind.AND,
|
|
|
|
|
tm.mkTerm(Kind.FLOATINGPOINT_LT, zero, e),
|
|
|
|
|
tm.mkTerm(Kind.FLOATINGPOINT_LT, e, smallest)));
|
2019-06-21 22:29:01 -07:00
|
|
|
|
2021-11-03 16:32:10 -05:00
|
|
|
r = solver.checkSat(); // result is unsat
|
|
|
|
|
assert !r.isSat();
|
|
|
|
|
}
|
2023-10-02 01:20:26 -05:00
|
|
|
Context.deletePointers();
|
2019-06-21 22:29:01 -07:00
|
|
|
}
|
|
|
|
|
}
|