javaz3openjml

Reasoning about reals


I am experimenting with OpenJML in combination with Z3, and I'm trying to reason about double or float values:

class Test {

  //@ requires b > 0;
  void a(double b) {
  }

  void b() {
    a(2.4);
  }
}

I have already found out OpenJML uses AUFLIA as the default logic, which doesn't support reals. I am now using AUFNIRA.

Unfortunately, the tool is unable to prove this class:

→ java -jar openjml.jar -esc -prover z3_4_3 -exec ./z3 Test.java -noInternalSpecs -logic AUFNIRA

Test.java:8: warning: The prover cannot establish an assertion (Precondition: Test.java:3: ) in method b
    a(2.4);
     ^
Test.java:3: warning: Associated declaration: Test.java:8: 
  //@ requires b > 0;
      ^
2 warnings

Why is this?


Solution

  • The SMT translation (used as input for z3) appears to be faulty when doubles are involved. In Program B below, which uses doubles instead of ints, the constants for either the call or the pre-condition never get translated into SMT.

    This is a fault of openjml, not z3 - since z3 would need something of the form (define-fun _JML__tmp3 () Real 2345.0) to work with (see verbose output of Program A), but openjml never generates it. In general, floating point support seems to be buggy.

    Program A (with ints):

    class Test {
        //@ requires b > 1234;
        void a(int b) { }
        void z() { a(2345); }
    }
    

    Output (running with -verbose | grep 234, to search for mentions of 1234 or 2345 in the verbose output):

      // requires b > 1234; 
    Pre_1 = b > 1234;
        // requires b > 1234; 
        assume Assignment Pre_1_0_21___4 == b_55 > 1234;
    (assert (= BL_58bodyBegin_2 (=> (= _JML___exception_49_49___1 NULL) (=> (= _JML___termination_49_49___2 0) (=> (distinct THIS NULL) (=> (or (= THIS NULL) (and (and (distinct THIS NULL) (javaSubType (javaTypeOf THIS) T_Test)) (jmlSubType (jmlTypeOf THIS) JMLT_Test))) (=> (and (<= (- 2147483648) b_55) (<= b_55 2147483647)) (=> (select _isalloc___0 THIS) (=> (= (select _alloc___0 THIS) 0) (=> (= Pre_1_0_21___3 false) (=> (= Pre_1_0_21___4 (> b_55 1234)) (=> Pre_1_0_21___4 BL_49_AfterLabel_3))))))))))))
    a(2345);
        // a(2345)
        int _JML__tmp3 = 2345;
        boolean _JML__tmp6 = _JML__tmp3 > 1234;
        // a(2345)
        int _JML__tmp3 = 2345
        boolean _JML__tmp6 = _JML__tmp3 > 1234
    (define-fun _JML__tmp3 () Int 2345)
    (define-fun _JML__tmp6 () Bool (> _JML__tmp3 1234))
    

    Result:

    EXECUTION
    Proof result is unsat
    Method checked OK
    [total 427ms]    
    

    Program B (with doubles):

    class Test {
        //@ requires b > 1234.0;
        void a(double b) { }
        void z() { a(2345.0); }
    }
    

    Output (running with -verbose | grep 234, to search for mentions of 1234.0 or 2345.0 in the verbose output):

    // requires b > 1234.0; 
    Pre_1 = b > 1234.0;
        // requires b > 1234.0; 
        assume Assignment Pre_1_0_29___4 == b_72 > 1234.0;
    a(2345.0);
        // a(2345.0)
        double _JML__tmp3 = 2345.0;
        boolean _JML__tmp6 = _JML__tmp3 > 1234.0;
        // a(2345.0)
        double _JML__tmp3 = 2345.0
        boolean _JML__tmp6 = _JML__tmp3 > 1234.0
            void z() { a(2345.0); }
            //@ requires b > 1234.0;
    Test.java:4:    a(2345.0)
                VALUE: 2345.0    === 0.0
    

    Result:

    EXECUTION
    Proof result is sat
    Some assertion is not valid
    Test.java:4: warning: The prover cannot establish an assertion (Precondition: Test.java:2: ) in method z
            void z() { a(2345.0); }
                        ^
    Test.java:2: warning: Associated declaration: Test.java:4: 
            //@ requires b > 1234.0;
                ^