Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a solver adapter for bitwuzla #124

Merged
merged 2 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/gen_matrix.pl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
solver(stp).
solver(cvc4).
solver(cvc5).
solver(bitwuzla).
solver(boolector).
solver(abc).

Expand All @@ -78,6 +79,7 @@
main_version(stp, "2_3_3").
main_version(cvc4, "1_8").
main_version(cvc5, "1_0_2").
main_version(bitwuzla, "0_3_0").
main_version(boolector, "3_2_2").
main_version(abc, "2021_12_30").

Expand Down Expand Up @@ -108,7 +110,6 @@
version(z3, "4_8_9").

version(yices, "2_6_4").
version(yices, "2_6_1").
version(yices, "2_6").

version(stp, "2_3_3").
Expand All @@ -118,6 +119,8 @@
version(cvc4, "1_8").
version(cvc5, "1_0_2").

version(bitwuzla, "0_3_0").

version(boolector, "3_2_2").
version(boolector, "3_2_1").
% n.b. boolector 3.1.0 builds fail; no reason to test it
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
echo ::set-output name=matrix::$(nix run nixpkgs#swiProlog -- .github/workflows/gen_matrix.pl)

linux:
name: GHC-${{ matrix.ghc }} Z3-${{ matrix.z3 }} Yices-${{ matrix.yices }} CVC4-${{ matrix.cvc4 }} CVC5-${{ matrix.cvc5 }} STP-${{ matrix.stp }} Boolector-${{ matrix.boolector }} ABC-${{ matrix.abc }} ${{ matrix.os }}
name: GHC-${{ matrix.ghc }} Z3-${{ matrix.z3 }} Yices-${{ matrix.yices }} CVC4-${{ matrix.cvc4 }} CVC5-${{ matrix.cvc5 }} STP-${{ matrix.stp }} Bitwuzla-${{ matrix.bitwuzla }} Boolector-${{ matrix.boolector }} ABC-${{ matrix.abc }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
needs: genmatrix
continue-on-error: false
Expand Down Expand Up @@ -164,6 +164,7 @@ jobs:
run: |
cd what4
echo ABC version $(nix eval github:GaloisInc/flakes#abc.v${{ matrix.abc }}.version)
echo Bitwuzla version $(nix run github:GaloisInc/flakes#bitwuzla.v${{ matrix.bitwuzla }} -- --version | head -n1)
echo Boolector version $(nix run github:GaloisInc/flakes#boolector.v${{ matrix.boolector }} -- --version | head -n1)
echo CVC4 version $(nix run github:GaloisInc/flakes#cvc4.v${{ matrix.cvc4 }} -- --version | head -n1)
echo CVC5 version $(nix run github:GaloisInc/flakes#cvc5.v${{ matrix.cvc5 }} -- --version | head -n1)
Expand All @@ -172,6 +173,7 @@ jobs:
echo Z3 version $(nix run github:GaloisInc/flakes#z3.v${{ matrix.z3 }} -- --version | head -n1)
$NS \
github:GaloisInc/flakes#abc.v${{ matrix.abc }} \
github:GaloisInc/flakes#bitwuzla.v${{ matrix.bitwuzla }} \
github:GaloisInc/flakes#boolector.v${{ matrix.boolector }} \
github:GaloisInc/flakes#cvc4.v${{ matrix.cvc4 }} \
github:GaloisInc/flakes#cvc5.v${{ matrix.cvc5 }} \
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ views or policies of the Department of Defense or the U.S. Government.

# Solver Compatibility

| Feature | ABC | Boolector | CVC4 | CVC5 | Dreal | STP | Yices | Z3 |
|---------------------------------------|-----|-------------|-----------|-------|-------|-------------|----------|----------------------|
| Supported | yes | >= 3.2.0, ? | >= 1.8, ? | 1.0.2 | yes | >= 2.3.3, ? | 2.6.x, ? | 4.8.8 -- 4.8.14 |
| goal timeouts | ? | yes | yes | yes | ? | yes | yes | ! (4.8.11 or 4.8.12) |
| strings with unicode and escape codes | ? | ? | >= 1.8 | yes | ? | ? | ? | >= 4.8.11 |
| Feature | ABC | Bitwuzla | Boolector | CVC4 | CVC5 | Dreal | STP | Yices | Z3 |
|---------------------------------------|-----|----------|-------------|-----------|-------|-------|-------------|----------|----------------------|
| Supported | yes | yes | >= 3.2.0, ? | >= 1.8, ? | 1.0.2 | yes | >= 2.3.3, ? | 2.6.x, ? | 4.8.8 -- 4.8.14 |
| goal timeouts | ? | yes | yes | yes | yes | ? | yes | yes | ! (4.8.11 or 4.8.12) |
| strings with unicode and escape codes | ? | no | ? | >= 1.8 | yes | ? | ? | ? | >= 4.8.11 |
4 changes: 4 additions & 0 deletions what4/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# next (TBA)

* Add support for the `bitwuzla` SMT solver.

# 1.5.1 (October 2023)

* Require building with `versions >= 6.0.2`.
Expand Down
1 change: 1 addition & 0 deletions what4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ on as wide a collection of solvers as is reasonable.
- Yices 2.6.1 and 2.6.2
- CVC4 1.7 and 1.8
- CVC5 1.0.2
- Bitwuzla 0.3.0
- Boolector 3.2.1 and 3.2.2
- STP 2.3.3
(However, note https://github.com/stp/stp/issues/363, which prevents
Expand Down
11 changes: 11 additions & 0 deletions what4/src/What4/Solver.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ module What4.Solver
, runExternalABCInOverride
, writeABCSMT2File

-- * Bitwuzla
, Bitwuzla(..)
, bitwuzlaAdapter
, bitwuzlaPath
, bitwuzlaTimeout
, runBitwuzlaInOverride
, withBitwuzla
, bitwuzlaOptions
, bitwuzlaFeatures

-- * Boolector
, Boolector(..)
, boolectorAdapter
Expand Down Expand Up @@ -107,6 +117,7 @@ module What4.Solver
) where

import What4.Solver.Adapter
import What4.Solver.Bitwuzla
import What4.Solver.Boolector
import What4.Solver.CVC4
import What4.Solver.CVC5
Expand Down
158 changes: 158 additions & 0 deletions what4/src/What4/Solver/Bitwuzla.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
------------------------------------------------------------------------
-- |
-- Module : What4.Solver.Bitwuzla
-- Description : Interface for running Bitwuzla
-- Copyright : (c) Galois, Inc 2014-2023
-- License : BSD3
-- Maintainer : Ryan Scott <rscott@galois.com>
-- Stability : provisional
--
-- This module provides an interface for running Bitwuzla and parsing
-- the results back.
------------------------------------------------------------------------
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
module What4.Solver.Bitwuzla
( Bitwuzla(..)
, bitwuzlaPath
, bitwuzlaTimeout
, bitwuzlaOptions
, bitwuzlaAdapter
, runBitwuzlaInOverride
, withBitwuzla
, bitwuzlaFeatures
) where

import Control.Monad
import Data.Bits ( (.|.) )

import What4.BaseTypes
import What4.Concrete
import What4.Config
import What4.Expr.Builder
import What4.Expr.GroundEval
import What4.Interface
import What4.ProblemFeatures
import What4.Protocol.Online
import qualified What4.Protocol.SMTLib2 as SMT2
import qualified What4.Protocol.SMTLib2.Syntax as Syntax
import What4.Protocol.SMTLib2.Response ( strictSMTParseOpt )
import What4.SatResult
import What4.Solver.Adapter
import What4.Utils.Process

data Bitwuzla = Bitwuzla deriving Show

-- | Path to bitwuzla
bitwuzlaPath :: ConfigOption (BaseStringType Unicode)
bitwuzlaPath = configOption knownRepr "solver.bitwuzla.path"

-- | Per-check timeout, in milliseconds (zero is none)
bitwuzlaTimeout :: ConfigOption BaseIntegerType
bitwuzlaTimeout = configOption knownRepr "solver.bitwuzla.timeout"

-- | Control strict parsing for Bitwuzla solver responses (defaults
-- to solver.strict-parsing option setting).
bitwuzlaStrictParsing :: ConfigOption BaseBoolType
bitwuzlaStrictParsing = configOption knownRepr "solver.bitwuzla.strict_parsing"

bitwuzlaOptions :: [ConfigDesc]
bitwuzlaOptions =
let bpOpt co = mkOpt
co
executablePathOptSty
(Just "Path to bitwuzla executable")
(Just (ConcreteString "bitwuzla"))
mkTmo co = mkOpt co
integerOptSty
(Just "Per-check timeout in milliseconds (zero is none)")
(Just (ConcreteInteger 0))
bp = bpOpt bitwuzlaPath
in [ bp
, mkTmo bitwuzlaTimeout
, copyOpt (const $ configOptionText bitwuzlaStrictParsing) strictSMTParseOpt
] <> SMT2.smtlib2Options

bitwuzlaAdapter :: SolverAdapter st
bitwuzlaAdapter =
SolverAdapter
{ solver_adapter_name = "bitwuzla"
, solver_adapter_config_options = bitwuzlaOptions
, solver_adapter_check_sat = runBitwuzlaInOverride
, solver_adapter_write_smt2 =
SMT2.writeDefaultSMT2 () "Bitwuzla" defaultWriteSMTLIB2Features
(Just bitwuzlaStrictParsing)
}

instance SMT2.SMTLib2Tweaks Bitwuzla where
smtlib2tweaks = Bitwuzla

runBitwuzlaInOverride
:: ExprBuilder t st fs
-> LogData
-> [BoolExpr t]
-> (SatResult (GroundEvalFn t, Maybe (ExprRangeBindings t)) () -> IO a)
-> IO a
runBitwuzlaInOverride =
SMT2.runSolverInOverride Bitwuzla SMT2.nullAcknowledgementAction
bitwuzlaFeatures (Just bitwuzlaStrictParsing)

-- | Run Bitwuzla in a session. Bitwuzla will be configured to produce models, but
-- otherwise left with the default configuration.
withBitwuzla
:: ExprBuilder t st fs
-> FilePath
-- ^ Path to Bitwuzla executable
-> LogData
-> (SMT2.Session t Bitwuzla -> IO a)
-- ^ Action to run
-> IO a
withBitwuzla = SMT2.withSolver Bitwuzla SMT2.nullAcknowledgementAction
bitwuzlaFeatures (Just bitwuzlaStrictParsing)

bitwuzlaFeatures :: ProblemFeatures
bitwuzlaFeatures = useBitvectors
.|. useFloatingPoint
.|. useQuantifiers
.|. useSymbolicArrays
.|. useUninterpFunctions
.|. useUnsatCores
.|. useUnsatAssumptions

instance SMT2.SMTLib2GenericSolver Bitwuzla where
defaultSolverPath _ = findSolverPath bitwuzlaPath . getConfiguration
defaultSolverArgs _ sym = do
let cfg = getConfiguration sym
timeout <- getOption =<< getOptionSetting bitwuzlaTimeout cfg
let extraOpts = case timeout of
Just (ConcreteInteger n) | n > 0 -> ["-t", show n]
_ -> []
return $ ["--lang", "smt2"] ++ extraOpts
defaultFeatures _ = bitwuzlaFeatures
setDefaultLogicAndOptions writer = do
SMT2.setLogic writer Syntax.allLogic
SMT2.setProduceModels writer True

setInteractiveLogicAndOptions ::
SMT2.SMTLib2Tweaks a =>
SMT2.WriterConn t (SMT2.Writer a) ->
IO ()
setInteractiveLogicAndOptions writer = do
SMT2.setOption writer "print-success" "true"
SMT2.setOption writer "produce-models" "true"
SMT2.setOption writer "global-declarations" "true"
when (SMT2.supportedFeatures writer `hasProblemFeature` useUnsatCores) $ do
SMT2.setOption writer "produce-unsat-cores" "true"
SMT2.setLogic writer Syntax.allLogic

instance OnlineSolver (SMT2.Writer Bitwuzla) where
startSolverProcess feat mbIOh sym = do
timeout <- SolverGoalTimeout <$>
(getOpt =<< getOptionSetting bitwuzlaTimeout (getConfiguration sym))
SMT2.startSolver Bitwuzla SMT2.smtAckResult
setInteractiveLogicAndOptions
timeout
feat
(Just bitwuzlaStrictParsing) mbIOh sym
shutdownSolverProcess = SMT2.shutdownSolver Bitwuzla
3 changes: 2 additions & 1 deletion what4/test/AdapterTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ allAdapters =
, cvc5Adapter
, yicesAdapter
, z3Adapter
, bitwuzlaAdapter
, boolectorAdapter
, externalABCAdapter
#ifdef TEST_STP
Expand Down Expand Up @@ -540,7 +541,7 @@ mkConfigTests adapters =

nonlinearRealTest :: SolverAdapter EmptyExprBuilderState -> TestTree
nonlinearRealTest adpt =
let wrap = if solver_adapter_name adpt `elem` [ "ABC", "boolector", "stp" ]
let wrap = if solver_adapter_name adpt `elem` [ "ABC", "bitwuzla", "boolector", "stp" ]
then expectFailBecause
(solver_adapter_name adpt
<> " does not support this type of linear arithmetic term")
Expand Down
3 changes: 3 additions & 0 deletions what4/test/OnlineSolverTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ allOnlineSolvers =
, AnOnlineSolver @(SMT2.Writer CVC5) Proxy, cvc5Features, cvc5Options, Just cvc5Timeout)
, (SolverName "Yices"
, AnOnlineSolver @Yices.Connection Proxy, yicesDefaultFeatures, yicesOptions, Just yicesGoalTimeout)
, (SolverName "Bitwuzla"
, AnOnlineSolver @(SMT2.Writer Bitwuzla) Proxy, bitwuzlaFeatures, bitwuzlaOptions, Just bitwuzlaTimeout)
, (SolverName "Boolector"
, AnOnlineSolver @(SMT2.Writer Boolector) Proxy, boolectorFeatures, boolectorOptions, Just boolectorTimeout)
#ifdef TEST_STP
Expand Down Expand Up @@ -378,6 +380,7 @@ timeoutTests testLevel solvers =
, (SolverName "CVC4", 7.5 % Second) -- CVC4 1.8
, (SolverName "CVC5", 0.40 % Second) -- CVC5 1.0.0
, (SolverName "Yices", 2.9 % Second) -- Yices 2.6.1
, (SolverName "Bitwuzla", 0.51 % Second) -- Bitwuzla 0.3.0
, (SolverName "Boolector", 7.2 % Second) -- Boolector 3.2.1
, (SolverName "STP", 1.35 % Second) -- STP 2.3.3
]
Expand Down
3 changes: 2 additions & 1 deletion what4/what4.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Description:
What4 is a generic library for representing values as symbolic formulae which may
contain references to symbolic values, representing unknown variables.
It provides support for communicating with a variety of SAT and SMT solvers,
including Z3, CVC4, CVC5, Yices, Boolector, STP, and dReal.
including Z3, CVC4, CVC5, Yices, Bitwuzla, Boolector, STP, and dReal.

The data representation types make heavy use of GADT-style type indices
to ensure type-correct manipulation of symbolic values.
Expand Down Expand Up @@ -190,6 +190,7 @@ library

What4.Solver
What4.Solver.Adapter
What4.Solver.Bitwuzla
What4.Solver.Boolector
What4.Solver.CVC4
What4.Solver.CVC5
Expand Down
Loading