; this file names the clauses in classify (set-option :produce-unsat-cores true) (declare-datatypes () ((Triangle EQUILATERAL ISOSCELES ACUTE OBTUSE RIGHT ILLEGAL))) (declare-const a Int) (assert (= a 2)) ; a, b, c are the failing input (declare-const b Int) (assert (= b 2)) ; this input was computed during (declare-const c Int) (assert (= c 1)) ; verification (assert (! (= ISOSCELES ; this is the expected output (if (and (>= a b) (>= b c)) ; the name a2 appears to be ignored by Z3 so we need to break ; this big assert into smaller ones. Z3 supports named asserts ; on top level only, using the construct (assert (! (EXPR) :named NAME)) (if (! (or (= a c) (= b c)) :named a2) (if (! (and (= a b) (= a c)) :named a3) EQUILATERAL ISOSCELES) (if (not (= (* a a) (+ (* b b) (* c c)))) (if (< (* a a) (+ (* b b) (* c c))) ACUTE OBTUSE) RIGHT)) ILLEGAL)) :named a1)) (check-sat) (get-unsat-core) ; Notes: The full unsat-core formula is pre(x) => S(x,y) /\ post(x,y), ; where x is the failing input. Note we are not including pre(x) in our ; formula becasue we believe that our failing input x is a valid input. ; Similarly, post(x,y) is simplified to the comparison with the expected ; output, ISOSCELES.