SBV (SMT Based Verification)

repository·master·Indexed 42 days ago

https://github.com/leventerkok/sbv

A Haskell library providing symbolic versions of Haskell types to express properties for automatic verification, optimization, or compilation to C using SMT solvers. It supports proving properties with `prove`, finding satisfying assignments with `sat`, and optimization via `optimize`. SBV integrates with solvers such as Z3, CVC4, and Boolector, and provides tools for theorem proving and compiling symbolic programs to C functions or static libraries.

Tokens
1.6K
Snippets
3
Records
7
Agent score
4%

What's inside SBV

  1. Understand the grounding constraint of SList

    master

    In SBV's Theorem Proving (TP) layer, SList a is mapped to the SMT Seq sort. This means SList represents finite sequences only.

    Critical Warning:

    • There is no support for ⊥ (bottom), partial lists, or infinite values within the SList type.
    • TP's induct mechanism performs finite structural induction. Therefore, any theorem proved using induct on an SList holds only for finite lists.

    Example of a false assumption: The property reverse (reverse xs) ≡ xs is provable for finite lists, but it is mathematically false for infinite lists. Do not attempt to use SList to model infinite data structures.

  2. Representing streams as index functions

    master

    If you need to reason about infinite streams (the "uniform fragment"), do not use SList. Instead, represent streams as index functions of the type Nat → a.

    This approach is the only viable method for handling infinite data in the current TP architecture because it avoids the complexities of SMT sequence theory and coinduction.

    Advantages

    • Pointwise Equality: Equality is defined as s ≅ t := ∀i. s i ≡ t i, which results in a standard first-order ∀i goal that SMT solvers handle well.
    • Trivial Uniform Laws: Operations like map become simple function compositions. For example, map f (map g s) ≅ map (f∘g) s is handled via reflexivity.
    • Arithmetic Streams: Streams produced by sEnum or enumFrom (e.g., λi. base + i·step) result in closed-form arithmetic goals that are highly efficient for solvers to process.

    Limitations

    • Uniform Fragment Only: This method is well-suited for map, zip, and enumerations.
    • Difficult Operations: Non-uniform or structural operations like filter are awkward or impossible to implement using this index-function model.
  3. How SBV symbolic types work

    master

    SBV provides symbolic versions of standard Haskell types. These symbolic types allow you to write programs that can be automatically verified, checked for satisfiability, or compiled to C.

    Supported symbolic types include:

    • Booleans: SBool
    • Integers: Unbounded (SInteger), signed/unsigned fixed-width (8, 16, 32, 64-bit), and arbitrary-width.
    • Floats: IEEE-754 floats (SFloat).
    • Other types: Reals, rationals, characters, strings, lists, tuples, sums, optionals, sets, enumerations, and algebraic data types.
  4. Quickstart with SBV

    master

    To use SBV in a REPL environment, you can load it using cabal. SBV allows you to express properties about Haskell programs and verify them using SMT solvers.

    Common tasks include:

    • Proving properties: Use prove to check if a property holds for all inputs.
    • Finding satisfying assignments: Use sat to find inputs that make a property true.
    • Optimization: Use optimize to find values that minimize or maximize a cost function subject to constraints.
    • Theorem Proving: Use runTP for inductive proofs and equational reasoning.
    $ cabal repl --build-depends sbv
    -- Proving a property (always true for unbounded integers)
    import Data.SBV
    prove $ \x -> x + 1 .> (x :: SInteger)
    
    -- Finding a satisfying model (multiplicative inverse of 3 mod 256)
    sat $ \x -> x * 3 .== (1 :: SWord8)
    
    -- Optimization example
    optimize Lexicographic $ do
        x <- sInteger "x"
        y <- sInteger "y"
        constrain $ x + y .== 20
        constrain $ x .>= 5
        constrain $ y .>= 5
        minimize "cost" $ x * y
  5. Use Algebraic Data Types with SBV

    master

    You can use user-defined algebraic data types (including enumerations, recursive, and parametric types) by making them symbolically available with mkSymbolic.

    To perform pattern matching on these symbolic types, use the sCase construct (for symbolic execution) or pCase (for proof case-splits in the theorem prover). sCase supports nested pattern matching, as-patterns, guards, and wildcards. Plain case expressions inside sCase are automatically treated as symbolic case-splits.

    {-# LANGUAGE QuasiQuotes #-}
    {-# LANGUAGE TemplateHaskell #-}
    
    import Data.SBV
    
    data Expr a = Val a
                | Add (Expr a) (Expr a)
                | Mul (Expr a) (Expr a)
                deriving Show
    
    -- Make Expr symbolically available, named SExpr
    mkSymbolic [''Expr]
    
    eval :: SymVal a => (SBV a -> SBV a -> SBV a) -> (SBV a -> SBV a -> SBV a) -> SBV (Expr a) -> SBV a
    eval add mul = smtFunction "eval" $ \e ->
        [sCase| e of
           Val v   -> v
           Add x y -> eval add mul x `add` eval add mul y
           Mul x y -> eval add mul x `mul` eval add mul y
        |]
  6. Compile symbolic programs to C

    master

    SBV can compile symbolic programs into C functions or static libraries. This includes support for recursive functions, arbitrary-width arithmetic, structured values, and bounded regex compilation.

    Key functions:

    • compileToC: Compiles to C functions.
    • compileToCLib: Compiles to static libraries.
    • genTest: Generates test vectors for the compiled code.

    Note: A legacy compiler is available via Data.SBV.Tools.CodeGen.Legacy.

  7. Configure SMT solvers in SBV

    master

    SBV communicates with SMT solvers via the SMT-Lib interface. Z3 is the default solver.

    To use a different solver, use functions like proveWith or satWith.

    Supported solvers include:

    • ABC
    • Bitwuzla
    • Boolector
    • CVC4 / CVC5
    • DReal
    • MathSAT
    • OpenSMT
    • Yices
    • Z3
    -- Example of using a specific solver
    proveWith cvc5 $ \x -> x .> 0