LeventErkok / sbv

SMT Based Verification in Haskell. Express properties about Haskell programs and automatically prove them using SMT solvers.
https://github.com/LeventErkok/sbv
Other
239 stars 33 forks source link

Bizarre output from observe #667

Closed LeventErkok closed 1 year ago

LeventErkok commented 1 year ago
Prelude Data.SBV> proveWith z3{verbose=True,validateModel=True} $ \x ->  (x::SInteger) .== 1
** Calling: z3 -nw -in -smt2
[GOOD] ; Automatically generated by SBV. Do not edit.
[GOOD] (set-option :print-success true)
[GOOD] (set-option :global-declarations true)
[GOOD] (set-option :smtlib2_compliant true)
[GOOD] (set-option :diagnostic-output-channel "stdout")
[GOOD] (set-option :produce-models true)
[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
[GOOD] ; --- uninterpreted sorts ---
[GOOD] ; --- tuples ---
[GOOD] ; --- sums ---
[GOOD] ; --- literal constants ---
[GOOD] (define-fun s1 () Int 1)
[GOOD] ; --- top level inputs ---
[GOOD] (declare-fun s0 () Int)
[GOOD] ; --- constant tables ---
[GOOD] ; --- non-constant tables ---
[GOOD] ; --- arrays ---
[GOOD] ; --- uninterpreted constants ---
[GOOD] ; --- user defined functions ---
[GOOD] ; --- assignments ---
[GOOD] (define-fun s2 () Bool (= s0 s1))
[GOOD] ; --- arrayDelayeds ---
[GOOD] ; --- arraySetups ---
[GOOD] ; --- delayedEqualities ---
[GOOD] ; --- formula ---
[GOOD] (assert (not s2))
[SEND] (check-sat)
[RECV] sat
[SEND] (get-value (s0))
[RECV] ((s0 2))
*** Solver   : Z3
*** Exit code: ExitSuccess
[VALIDATE] Validating the model. Assignment:
[VALIDATE]       s0 = 2 :: Integer
[VALIDATE] There are no constraints to check.
[VALIDATE] Validating outputs.
[VALIDATE] Counterexample is validated.
Falsifiable. Counter-example:
  s0 = 2 :: Integer

BUT

Prelude Data.SBV> proveWith z3{verbose=True,validateModel=True} $ \x ->  (x::SInteger) .== observe "r" 1
** Calling: z3 -nw -in -smt2
[GOOD] ; Automatically generated by SBV. Do not edit.
[GOOD] (set-option :print-success true)
[GOOD] (set-option :global-declarations true)
[GOOD] (set-option :smtlib2_compliant true)
[GOOD] (set-option :diagnostic-output-channel "stdout")
[GOOD] (set-option :produce-models true)
[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
[GOOD] ; --- uninterpreted sorts ---
[GOOD] ; --- tuples ---
[GOOD] ; --- sums ---
[GOOD] ; --- literal constants ---
[GOOD] (define-fun s1 () Int 1)
[GOOD] ; --- top level inputs ---
[GOOD] (declare-fun s0 () Int)
[GOOD] ; --- constant tables ---
[GOOD] ; --- non-constant tables ---
[GOOD] ; --- arrays ---
[GOOD] ; --- uninterpreted constants ---
[GOOD] ; --- user defined functions ---
[GOOD] ; --- assignments ---
[GOOD] (define-fun s2 () Bool (= s0 s1))
[GOOD] ; --- arrayDelayeds ---
[GOOD] ; --- arraySetups ---
[GOOD] ; --- delayedEqualities ---
[GOOD] ; --- formula ---
[GOOD] (assert (not s2))
[SEND] (check-sat)
[RECV] sat
[SEND] (get-value (s1))
[RECV] ((s1 1))
[SEND] (get-value (s0))
[RECV] ((s0 2))
*** Solver   : Z3
*** Exit code: ExitSuccess
[VALIDATE] Validating the model. Assignment:
[VALIDATE]       s0 = 2 :: Integer
[VALIDATE] There are no constraints to check.
[VALIDATE] Validating outputs.
*** Data.SBV: Cannot validate the model, since s3 is not concretely computable.
***
*** Assignment:
***
***       s0 = 2 :: Integer
***
*** SBV's model validator is incomplete, and cannot handle this particular case.
*** Please report this as a feature request or possibly a bug!
***
*** Alleged model:
***
*** Falsifiable. Counter-example:
***   r  = 1 :: Integer
***   s0 = 2 :: Integer

There isn't even a value s3 in the program generated. What's going on?

LeventErkok commented 1 year ago

Oops, this is because "observe" never constant folds! And when you don't constant fold, you can't validate, since it's not a constant during evaluation.

Why does observe never constant fold? Because, arguably, if someone put an observe call, they really want to see that value printed: It could be a complicated expression, reducing to a constant. So, let's err on the side of the original decision of keeping observe variables unfodable. Though I did print out a better error message so as not to get confused in the future.