/****************************************************************************** * Top contributors (to current version): * Aina Niemetz, Mudathir Mohamed, 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. * **************************************************************************** * * An example of solving floating-point problems with cvc5's Java API * * 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. */ import static io.github.cvc5.Kind.*; import io.github.cvc5.*; public class FloatingPointArith { public static void main(String[] args) throws CVC5ApiException { TermManager tm = new TermManager(); Solver solver = new Solver(tm); { solver.setOption("incremental", "true"); solver.setOption("produce-models", "true"); // Make single precision floating-point variables 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); 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)); Result r = solver.checkSat(); // result is sat 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); 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))); r = solver.checkSat(); // result is sat assert r.isSat(); 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, 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))); r = solver.checkSat(); // result is sat assert r.isSat(); 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:"); Term val = solver.getValue(d); 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))); 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))); r = solver.checkSat(); // result is unsat assert !r.isSat(); } Context.deletePointers(); } }