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

Jb/trim booster ground truth #4038

Merged
merged 12 commits into from
Aug 21, 2024
Merged
39 changes: 35 additions & 4 deletions booster/library/Booster/SMT/Interface.hs
Original file line number Diff line number Diff line change
Expand Up @@ -434,12 +434,23 @@ checkPredicates ctxt givenPs givenSubst psToCheck
translated = SMT.runTranslator $ do
let mkSMTEquation v t =
SMT.eq <$> SMT.translateTerm (Var v) <*> SMT.translateTerm t
smtSubst <-
mapM (\(v, t) -> Assert "Substitution" <$> mkSMTEquation v t) $ Map.assocs givenSubst
smtPs <-
mapM (\(Predicate p) -> Assert (mkComment p) <$> SMT.translateTerm p) $ Set.toList givenPs
substEqs <-
mapM (uncurry mkSMTEquation) $ Map.assocs givenSubst

groundTruth <-
mapM (\(Predicate p) -> (p,) <$> SMT.translateTerm p) $ Set.toList givenPs

toCheck <-
mapM (SMT.translateTerm . coerce) $ Set.toList psToCheck

let interestingVars = mconcat $ map smtVars toCheck
filteredGroundTruth = closureOver interestingVars $ Set.fromList $ map snd groundTruth
filteredSubstEqs = closureOver interestingVars $ Set.fromList substEqs

let mkAssert (p, sexpr) = Assert (mkComment p) sexpr
smtPs = map mkAssert $ filter ((`Set.member` filteredGroundTruth) . snd) groundTruth
smtSubst = map (Assert "Substitution") $ Set.toList filteredSubstEqs

pure (smtSubst <> smtPs, toCheck)

-- Given the known truth and the expressions to check,
Expand Down Expand Up @@ -503,3 +514,23 @@ checkPredicates ctxt givenPs givenSubst psToCheck
"Given ∧ P and Given ∧ !P interpreted as "
<> pack (show (positive', negative'))
pure (positive', negative')

-- functions for filtering ground truth and substitution equations
smtVars :: SMT.SExpr -> Set SMT.SMTId
smtVars (Atom smtId@(SMTId bs))
| "SMT-" `BS.isPrefixOf` bs = Set.singleton smtId
| otherwise = mempty
smtVars (List exprs) = mconcat $ map smtVars exprs

-- filters given 'exprs' to only return those which use any of the
-- SMT 'atoms' or from other expressions that are also returned.
closureOver :: Set SMT.SMTId -> Set SMT.SExpr -> Set SMT.SExpr
closureOver atoms exprs = loop mempty exprs atoms
where
loop :: Set SMT.SExpr -> Set SMT.SExpr -> Set SMT.SMTId -> Set SMT.SExpr
loop acc exprs' currentAtoms =
let (rest, addedExprs) = Set.partition (Set.null . Set.intersection currentAtoms . smtVars) exprs'
newAtoms = Set.unions $ Set.map smtVars addedExprs
in if Set.null addedExprs
then acc
else loop (acc <> addedExprs) rest newAtoms
1 change: 1 addition & 0 deletions kore/kore.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ library
SMT
SMT.AST
SMT.SimpleSMT
SMT.Utils
SQL
SQL.ColumnDef
SQL.Key
Expand Down
33 changes: 23 additions & 10 deletions kore/src/Kore/Rewrite/SMT/Evaluator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import SMT (
)
import SMT qualified
import SMT.SimpleSMT qualified as SimpleSMT
import SMT.Utils qualified as SMT

{- | Attempt to evaluate the 'Predicate' argument with an optional side
condition using an external SMT solver.
Expand All @@ -109,11 +110,13 @@ evalPredicate onUnknown predicate sideConditionM = case predicate of
Predicate.PredicateFalse -> return $ Just False
_ -> case sideConditionM of
Nothing ->
predicate :| []
& decidePredicate onUnknown SideCondition.top
decidePredicate onUnknown SideCondition.top [] predicate
Just sideCondition ->
predicate :| [from @_ @(Predicate _) sideCondition]
& decidePredicate onUnknown sideCondition
decidePredicate
onUnknown
sideCondition
(Predicate.getMultiAndPredicate $ from @_ @(Predicate _) sideCondition)
predicate

{- | Attempt to evaluate the 'Conditional' argument with an optional side
condition using an external SMT solver.
Expand Down Expand Up @@ -164,9 +167,10 @@ decidePredicate ::
InternalVariable variable =>
OnDecidePredicateUnknown ->
SideCondition variable ->
NonEmpty (Predicate variable) ->
[Predicate variable] ->
Predicate variable ->
Simplifier (Maybe Bool)
decidePredicate onUnknown sideCondition predicates =
decidePredicate onUnknown sideCondition sideConditionPredicates predicate =
whileDebugEvaluateCondition predicates $
do
result <- query >>= whenUnknown retry
Expand All @@ -187,14 +191,23 @@ decidePredicate onUnknown sideCondition predicates =
empty
& runMaybeT
where
predicates = predicate :| sideConditionPredicates

query :: MaybeT Simplifier Result
query = onErrorUnknown $ SMT.withSolver . evalTranslator $ do
tools <- Simplifier.askMetadataTools
Morph.hoist SMT.liftSMT $ do
predicates' <-
traverse
(translatePredicate sideCondition tools)
predicates
sideConditionPredicates' <-
concatMap SMT.splitAnd
<$> traverse
(translatePredicate sideCondition tools)
sideConditionPredicates
predicate' <- SMT.splitAnd <$> translatePredicate sideCondition tools predicate
let predicates' = SMT.transitiveClosure (Set.fromList predicate') $ Set.fromList sideConditionPredicates'
-- when (Set.fromList predicate' /= predicates') $ liftIO $ do
-- putStrLn $ "predicate: " <> show (Set.fromList predicate')
-- putStrLn $ "sideConditionPredicates: " <> show sideConditionPredicates'
-- putStrLn $ "pruned to: " <> show predicates'
traverse_ SMT.assert predicates'
SMT.check >>= maybe empty return

Expand Down
30 changes: 30 additions & 0 deletions kore/src/SMT/Utils.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module SMT.Utils (module SMT.Utils) where

import Data.Set (Set)
import Data.Set qualified as Set
import Data.Text (Text, isPrefixOf, isSuffixOf)

import Prelude.Kore
import SMT qualified

splitAnd :: SMT.SExpr -> [SMT.SExpr]
splitAnd = \case
SMT.List (SMT.Atom "and" : xs) -> concatMap splitAnd xs
other -> [other]

varAtoms :: SMT.SExpr -> Set Text
varAtoms = \case
SMT.Atom a
| "<" `isPrefixOf` a && ">" `isSuffixOf` a -> Set.singleton a
| otherwise -> mempty
SMT.List xs -> mconcat $ map varAtoms xs
_ -> mempty

transitiveClosure :: Set SMT.SExpr -> Set SMT.SExpr -> Set SMT.SExpr
transitiveClosure cl' rest' = loop (Set.unions (Set.map varAtoms cl')) cl' rest'
where
loop clVars cl rest =
let (nonCommon, common) = Set.partition (null . Set.intersection clVars . varAtoms) rest
in if null common
then cl
else loop (clVars <> Set.unions (Set.map varAtoms common)) (cl <> common) nonCommon
3 changes: 2 additions & 1 deletion kore/test/Test/Kore/Rewrite/SMT/Evaluator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ assertRefuted prop = do
SMT.Evaluator.decidePredicate
(ErrorDecidePredicateUnknown $srcLoc Nothing)
SideCondition.top
(prop :| [])
[]
prop
& Test.runSimplifierSMT testEnv
assertEqual "" expect actual

Expand Down
Loading