Model generation
Alt-Ergo can generate best-effort models (also known as counter-examples in the program verification community) in the case it cannot conclude the unsatisfiability of the context.
Model generation is supported in all input languages, but more functionality is available when using the SMT-LIB input language.
Note
Generated models are always displayed using SMT-LIB syntax, even when using the native input language.
Activation
Model generation is disabled by default and needs to be enabled before being used. There are multiple ways to enable model generation:
With the SMT-LIB language, using either
(set-option :produce-models true)
in a script, or with the--produce-model
option. This enables the use of the(check-sat)
command defined in the SMT-LIB standard.With the native language, using the
--dump-models
option. This will cause Alt-Ergo to automatically (try to) produce a model after eachcheck_sat
statement that returnsI don't know
, and a counter-example after eachgoal
statement that cannot be provenValid
.
Correctness of model generation
Alt-ergo’s model generation procedure is incomplete in the presence of quantifiers, and hence Alt-ergo only ever produces candidate models that are not guaranteed to satisfy all the assertions in the problem. Ground assertions (i.e. assertions that do not involve quantifiers) are guaranteed to hold in the models generated by Alt-ergo as long as they only include the following constructs:
Boolean connectives;
Algebraic data types (including records and enumerated types in the native language)
The following integer and real primitives: addition, subtraction, multiplication, division, modulo, comparisons, and exponentiations with an integer exponent
Bit-vector primitives (concatenation, extraction,
bvadd
,bvand
,bvule
, etc.), includingbv2nat
andint2bv
Completeness for the following constructs is only guaranteed with certain command-line flags:
Conversions operators from integers to reals
real_of_int
andreal_is_int
require the--enable-theories ria
flagFloating-point primitives (
ae.round
,ae.float32
etc. in the SMT-LIB language;float
,float32
andfloat64
in the native language) require the--enable-theories fpa
flag
Model generation is known to be sometimes incomplete in the presence of arrays,
and is incomplete for the integer_round
function.
Examples
Using the native language in the input file
INPUT.ae
:
logic a, b, c : int
axiom A : a <> c
check_sat c1: a = b + c
check_sat c2: a <> b
and the command alt-ergo --dump-models INPUT.ae
, Alt-Ergo produces the
output models:
; Model for c1
(
(define-fun a () Int 2)
(define-fun b () Int 2)
(define-fun c () Int 0)
)
I don't known
; Model for c2
(
(define-fun a () Int 2)
(define-fun b () Int 0)
(define-fun c () Int 0)
)
I don't known
Note
In this example the model for the statement check_sat c2
is not a
model for the statement check_sat c1
since check_sat
are independent in
the native language. The same goes for goals
.
Using the SMT-LIB language in the input file
INPUT.smt2
:
(set-logic ALL)
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(assert (= a (+ b c)))
(check-sat)
(get-model)
(assert (distinct a b))
(check-sat)
and the command alt-ergo --produce-models INPUT.smt2
produces the output
unknown
(
(define-fun a () Int 0)
(define-fun b () Int 0)
(define-fun c () Int 0)
)
unknown
Note
There is no model printed after the second (check-sat)
since we
don’t demand it with the statement (get-model)
.
Alternatively, using the statement
(set-option :produce-models true)
(set-logic ALL)
(set-option :produce-models true)
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(assert (= a (+ b c)))
(check-sat)
(get-model)
and the command alt-ergo INPUT.smt2
produces
the output model
unknown
(
(define-fun a () Int 0)
(define-fun b () Int 0)
(define-fun c () Int 0)
)
As a more didactic example, let us imagine while checking the loop invariant in the pseudocode below:
while i < 5
invariant i < 5
do
i := i + 1
done
we got the SMT-LIB file INPUT.smt2
:
(set-logic ALL)
(declare-const i Int)
(assert (and (< i 5) (not (< (+ i 1) 5))))
(check-sat)
(get-model)
Execute the command
alt-ergo --produce-models INPUT.smt2
We got the output
; File "INPUT.smt2", line 4, characters 1-12: I don't know (0.6689) (2 steps) (goal g_1)
unknown
(
(define-fun i () Int 4)
)
Alt-Ergo tells us that the (check-sat)
could succeed with i = 4
. Indeed,
the loop invariant isn’t preserved during the last iteration of the loop and
the context is satisfiable. Let’s fix our specification as follows:
while i < 5
invariant 0 <= i <= 5
do
i := i + 1
end
and fix our SMT-LIB input accordingly:
(set-logic ALL)
(declare-const i Int)
(assert (and (< i 5) (not (<= (+ i 1) 5))))
(check-sat)
(get-model)
Running the very same command, we got the expected output:
; File "INPUT.smt2", line 4, characters 1-12: Valid (0.5347) (1 steps) (goal g_1)
unsat
(error "No model produced.")
Our invariant is valid!