-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bit-vector optimization algorithm and example
- Loading branch information
1 parent
585c9d5
commit 1292075
Showing
3 changed files
with
133 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
----------------------------------------------------------------------------- | ||
-- | | ||
-- Module : Data.SBV.Tools.BVOptimize | ||
-- Copyright : (c) Levent Erkok | ||
-- License : BSD3 | ||
-- Maintainer: [email protected] | ||
-- Stability : experimental | ||
-- | ||
-- Bit-vector optimization based on linear scan of the bits. The optimization | ||
-- engines are usually not incremental, and they perform poorly for optimizing | ||
-- bit-vector values in the presence of complicated constraints. We implement | ||
-- a simple optimizer by scanning the bits from top-to-bottom to minimize/maximize | ||
-- unsigned bit vector quantities, using the regular (i.e., incremental) solver. | ||
-- This can lead to better performance for this class of problems. | ||
-- | ||
-- This implementation is based on an idea by Nikolaj Bjorner, see <https://github.com/Z3Prover/z3/issues/7156>. | ||
----------------------------------------------------------------------------- | ||
|
||
{-# OPTIONS_GHC -Wall -Werror #-} | ||
|
||
module Data.SBV.Tools.BVOptimize ( | ||
-- ** Maximizing bit-vectors | ||
-- $maxBVEx | ||
maxBV, maxBVWith | ||
-- ** Minimizing bit-vectors | ||
-- $minBVEx | ||
, minBV, minBVWith | ||
) where | ||
|
||
import Control.Monad | ||
|
||
import Data.SBV | ||
import Data.SBV.Control | ||
|
||
-- $setup | ||
-- >>> -- For doctest purposes only: | ||
-- >>> :set -XDataKinds | ||
-- >>> import Data.SBV | ||
|
||
{- $maxBVEx | ||
Here is a simple example of maximizing a bit-vector value: | ||
>>> :{ | ||
runSMT $ do x :: SWord 32 <- free "x" | ||
constrain $ x .> 5 | ||
constrain $ x .< 27 | ||
maxBV False x | ||
:} | ||
Satisfiable. Model: | ||
x = 26 :: Word32 | ||
-} | ||
|
||
-- | Maximize the value of an unsigned bit-vector value, using the default solver. | ||
maxBV :: SFiniteBits a | ||
=> Bool -- ^ Do we want unsat-cores if unsatisfiable? | ||
-> SBV a -- ^ Value to maximize | ||
-> Symbolic SatResult | ||
maxBV = maxBVWith defaultSMTCfg | ||
|
||
-- | Maximize the value of an unsigned bit-vector value, using the given solver. | ||
maxBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult | ||
maxBVWith = minMaxBV True | ||
|
||
{- $minBVEx | ||
Here is a simple example of minimizing a bit-vector value: | ||
>>> :{ | ||
runSMT $ do x :: SWord 32 <- free "x" | ||
constrain $ x .> 5 | ||
constrain $ x .< 27 | ||
minBV False x | ||
:} | ||
Satisfiable. Model: | ||
x = 6 :: Word32 | ||
-} | ||
|
||
-- | Minimize the value of an unsigned bit-vector value, using the default solver. | ||
minBV :: SFiniteBits a | ||
=> Bool -- ^ Do we want unsat-cores if unsatisfiable? | ||
-> SBV a -- ^ Value to minimize | ||
-> Symbolic SatResult | ||
minBV = minBVWith defaultSMTCfg | ||
|
||
-- | Minimize the value of an unsigned bit-vector value, using the given solver. | ||
minBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult | ||
minBVWith = minMaxBV False | ||
|
||
-- | min/max a given unsigned bit-vector. We walk down the bits in an incremental | ||
-- fashion. If we are maximizing, we try to make the bits set as we go down, otherwise | ||
-- we try to unset them. We keep adding the constraints so long as they are satisfiable, | ||
-- and at the end, get the optimal value produced. | ||
minMaxBV :: SFiniteBits a => Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult | ||
minMaxBV isMax cfg getUC v | ||
| hasSign v | ||
= error $ "minMaxBV works on unsigned bitvectors, received: " ++ show (kindOf v) | ||
| True | ||
= do when getUC $ setOption $ ProduceUnsatCores True | ||
query $ go (blastBE v) | ||
where uc | getUC = Just <$> getUnsatCore | ||
| True = pure Nothing | ||
|
||
rSat = SatResult . Satisfiable cfg <$> getModel | ||
rUnk = SatResult . Unknown cfg <$> getUnknownReason | ||
rUnsat = SatResult . Unsatisfiable cfg <$> uc | ||
|
||
go :: [SBool] -> Query SatResult | ||
go [] = do r <- checkSat | ||
case r of | ||
Sat -> rSat | ||
Unsat -> rUnsat | ||
Unk -> rUnk | ||
DSat {} -> error "minMaxBV: Unexpected DSat result" | ||
go (b:bs) = do push 1 | ||
if isMax then constrain b | ||
else constrain $ sNot b | ||
r <- checkSat | ||
case r of | ||
Sat -> go bs >>= \res -> pop 1 >> return res | ||
Unsat -> pop 1 >> go bs | ||
Unk -> pop 1 >> rUnk | ||
DSat{} -> error "minMaxBV: Unexpected DSat result" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters