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

4059 ensures substitution #4060

Merged
merged 36 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5481f26
Make substitution part of Pattern
geo2a Oct 15, 2024
1e7ce61
Do not invalidate cache twice when ensuring conditions
geo2a Oct 15, 2024
b491b85
Extract substitution items from ensured conditions
geo2a Oct 15, 2024
f98f4b5
Include ensured substitution when externalising pattern
geo2a Oct 15, 2024
b4502f9
Update integration test output
geo2a Oct 16, 2024
aee79b7
Add substitution conversion helpers
geo2a Oct 16, 2024
0f6ccf5
Build existential substitution together with the matching one
geo2a Oct 16, 2024
7c7a4ba
Fix imports
geo2a Oct 16, 2024
82f0955
Move partitionPredicates to Booster.Pattern.Bool
geo2a Oct 16, 2024
20c10ef
Consider substitution as constraints in evaluatePattern
geo2a Oct 16, 2024
8b6fbfd
Delete obsolete booster-dev responses
geo2a Oct 16, 2024
ac825e6
Include input substitution into the pattern
geo2a Oct 16, 2024
a6c7808
Extend Unknown type, abort on unsafe unknown ensures
geo2a Oct 17, 2024
ffc4035
Include substitution when pretty-printing Pattern
geo2a Oct 17, 2024
32a8418
Fix substitution externalisation
geo2a Oct 17, 2024
7da0911
Do not simplify substitution when normalising it
geo2a Oct 17, 2024
9f11343
Kill redundant patterns
geo2a Oct 17, 2024
9e47e06
Move substitution-related stuff into a separate module
geo2a Oct 17, 2024
ef7ea92
Tweak substitution naming in applyRule
geo2a Oct 17, 2024
2f3017f
Rename rule pattern internalisation function
geo2a Oct 17, 2024
b72baf9
Format with fourmolu
invalid-email-address Oct 17, 2024
a6f2dd9
Float mbSubstitution out, make pure
geo2a Oct 18, 2024
a08f937
Reuse substitution internalisation code
geo2a Oct 18, 2024
900e13d
Do not override with old substitution when externalising
geo2a Oct 22, 2024
b4a3599
Update test-substitution
geo2a Oct 22, 2024
3b2b7d5
Update test-questionmark-vars
geo2a Oct 22, 2024
598c8a4
Update test-a-to-f
geo2a Oct 22, 2024
bc72188
Remove dead code
geo2a Oct 22, 2024
b2ea0f8
Use substitution in Implies
geo2a Oct 22, 2024
f8f956f
Handle input substitution as part of Pattern
geo2a Oct 22, 2024
c73a2c9
Handle substitution better when simplifying standalone predicates
geo2a Oct 22, 2024
cc808a2
Remove unused function modifyVariables
geo2a Oct 23, 2024
f9f0d51
Fix typo
geo2a Oct 23, 2024
c974346
Refactor extractSubstitution
geo2a Oct 23, 2024
9bcdc52
Bind the known constraints expressin
geo2a Oct 23, 2024
58f6402
Substitute in the internalisation functions directly
geo2a Oct 23, 2024
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
64 changes: 33 additions & 31 deletions booster/library/Booster/JsonRpc.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import Booster.Definition.Base qualified as Definition (RewriteRule (..))
import Booster.LLVM as LLVM (API)
import Booster.Log
import Booster.Pattern.ApplyEquations qualified as ApplyEquations
import Booster.Pattern.Base (Pattern (..), Sort (SortApp), Term, Variable)
import Booster.Pattern.Base (Pattern (..), Sort (SortApp))
import Booster.Pattern.Base qualified as Pattern
import Booster.Pattern.Implies (runImplies)
import Booster.Pattern.Pretty
Expand All @@ -55,12 +55,11 @@ import Booster.Pattern.Rewrite (
RewriteTrace (..),
performRewrite,
)
import Booster.Pattern.Substitution qualified as Substitution
import Booster.Pattern.Util (
freeVariables,
sortOfPattern,
sortOfTerm,
substituteInPredicate,
substituteInTerm,
)
import Booster.Prettyprinter (renderText)
import Booster.SMT.Interface qualified as SMT
Expand All @@ -69,6 +68,7 @@ import Booster.Syntax.Json.Externalise
import Booster.Syntax.Json.Internalise (
InternalisedPredicates (..),
TermOrPredicates (..),
extractSubsitution,
internalisePattern,
internaliseTermOrPredicate,
logPatternError,
Expand Down Expand Up @@ -134,9 +134,10 @@ respond stateVar request =
-- apply the given substitution before doing anything else
let substPat =
Pattern
{ term = substituteInTerm substitution term
, constraints = Set.fromList $ map (substituteInPredicate substitution) preds
{ term = Substitution.substituteInTerm substitution term
, constraints = Set.fromList $ map (Substitution.substituteInPredicate substitution) preds
, ceilConditions = ceils
, substitution
}
-- remember all variables used in the substitutions
substVars =
Expand Down Expand Up @@ -166,7 +167,7 @@ respond stateVar request =
result <-
performRewrite rewriteConfig substPat
SMT.finaliseSolver solver
pure $ execResponse req result substitution unsupported
pure $ execResponse req result unsupported
RpcTypes.AddModule RpcTypes.AddModuleRequest{_module, nameAsId = nameAsId'} -> Booster.Log.withContext CtxAddModule $ runExceptT $ do
-- block other request executions while modifying the server state
state <- liftIO $ takeMVar stateVar
Expand Down Expand Up @@ -244,20 +245,21 @@ respond stateVar request =
RpcError.CouldNotVerifyPattern $
map patternErrorToRpcError patternErrors
-- term and predicate (pattern)
Right (TermAndPredicates pat substitution unsupported) -> do
Right (TermAndPredicates pat unsupported) -> do
unless (null unsupported) $ do
withKorePatternContext (KoreJson.KJAnd (externaliseSort $ sortOfPattern pat) unsupported) $ do
logMessage ("ignoring unsupported predicate parts" :: Text)
-- apply the given substitution before doing anything else
let substPat =
Pattern
{ term = substituteInTerm substitution pat.term
, constraints = Set.map (substituteInPredicate substitution) pat.constraints
{ term = Substitution.substituteInTerm pat.substitution pat.term
, constraints = Set.map (Substitution.substituteInPredicate pat.substitution) pat.constraints
, ceilConditions = pat.ceilConditions
, substitution = pat.substitution
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While reading through here, I thought that internaliseTermOrPredicates, and any internalisation that may return a Pattern as a whole, should maybe already apply the substitution before returning the result (somewhat "normalising" the pattern before it is returned).
The internalisePattern, in contrast, returns the parts separately and leaves it to the caller to piece them back together. This is because we use it a lot in the definition internalisation where we need the parts separately.
This is more of a stylistic preference, and IDK how much fall-out it will have, so it is not necessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good point. I'll try putting this change in.

ApplyEquations.evaluatePattern def mLlvmLibrary solver mempty substPat >>= \case
(Right newPattern, _) -> do
let (term, mbPredicate, mbSubstitution) = externalisePattern newPattern substitution
let (term, mbPredicate, mbSubstitution) = externalisePattern newPattern
tSort = externaliseSort (sortOfPattern newPattern)
result = case catMaybes (mbPredicate : mbSubstitution : map Just unsupported) of
[] -> term
Expand All @@ -281,23 +283,24 @@ respond stateVar request =
withKorePatternContext (KoreJson.KJAnd (externaliseSort $ SortApp "SortBool" []) ps.unsupported) $ do
logMessage ("ignoring unsupported predicate parts" :: Text)
-- apply the given substitution before doing anything else
let predicates = map (substituteInPredicate ps.substitution) ps.boolPredicates
let predicates = map (Substitution.substituteInPredicate ps.substitution) ps.boolPredicates
withContext CtxConstraint $
ApplyEquations.simplifyConstraints
def
mLlvmLibrary
solver
mempty
predicates
(predicates <> Substitution.asEquations ps.substitution)
>>= \case
(Right newPreds, _) -> do
(Right simplified, _) -> do
let predicateSort =
fromMaybe (error "not a predicate") $
sortOfJson req.state.term
(simplifiedSubstitution, simplifiedPredicates) = extractSubsitution simplified
result =
map (externalisePredicate predicateSort) newPreds
map (externalisePredicate predicateSort) (Set.toList simplifiedPredicates)
<> map (externaliseCeil predicateSort) ps.ceilPredicates
<> map (uncurry $ externaliseSubstitution predicateSort) (Map.toList ps.substitution)
<> map (uncurry $ externaliseSubstitution predicateSort) (Map.assocs simplifiedSubstitution)
<> ps.unsupported

pure $ Right (addHeader $ Syntax.KJAnd predicateSort result)
Expand Down Expand Up @@ -332,7 +335,7 @@ respond stateVar request =
-- term and predicates were sent. Only work on predicates
(boolPs, suppliedSubst) <-
case things of
TermAndPredicates pat substitution unsupported -> do
TermAndPredicates pat unsupported -> do
withContext CtxGetModel $
logMessage' ("ignoring supplied terms and only checking predicates" :: Text)

Expand All @@ -341,7 +344,7 @@ respond stateVar request =
logMessage' ("ignoring unsupported predicates" :: Text)
withContext CtxDetail $
logMessage (Text.unwords $ map prettyPattern unsupported)
pure (Set.toList pat.constraints, substitution)
pure (Set.toList pat.constraints, pat.substitution)
Predicates ps -> do
unless (null ps.ceilPredicates && null ps.unsupported) $ do
withContext CtxGetModel $ do
Expand Down Expand Up @@ -472,21 +475,20 @@ execStateToKoreJson RpcTypes.ExecuteState{term = t, substitution, predicate} =
execResponse ::
RpcTypes.ExecuteRequest ->
(Natural, Seq (RewriteTrace ()), RewriteResult Pattern) ->
Map Variable Term ->
[Syntax.KorePattern] ->
Either ErrorObj (RpcTypes.API 'RpcTypes.Res)
execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
execResponse req (d, traces, rr) unsupported = case rr of
RewriteBranch p nexts ->
Right $
RpcTypes.Execute
RpcTypes.ExecuteResult
{ reason = RpcTypes.Branching
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates =
Just $
map (\(_, muid, p') -> toExecState p' originalSubstitution unsupported (Just muid)) $
map (\(_, muid, p') -> toExecState p' unsupported (Just muid)) $
toList nexts
, rule = Nothing
, unknownPredicate = Nothing
Expand All @@ -498,7 +500,7 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
{ reason = RpcTypes.Stuck
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates = Nothing
, rule = Nothing
, unknownPredicate = Nothing
Expand All @@ -510,7 +512,7 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
{ reason = RpcTypes.Vacuous
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates = Nothing
, rule = Nothing
, unknownPredicate = Nothing
Expand All @@ -522,8 +524,8 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
{ reason = RpcTypes.CutPointRule
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, nextStates = Just [toExecState next originalSubstitution unsupported Nothing]
, state = toExecState p unsupported Nothing
, nextStates = Just [toExecState next unsupported Nothing]
, rule = Just lbl
, unknownPredicate = Nothing
}
Expand All @@ -534,7 +536,7 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
{ reason = RpcTypes.TerminalRule
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates = Nothing
, rule = Just lbl
, unknownPredicate = Nothing
Expand All @@ -546,7 +548,7 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
{ reason = RpcTypes.DepthBound
, depth
, logs
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates = Nothing
, rule = Nothing
, unknownPredicate = Nothing
Expand All @@ -563,7 +565,7 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
(logSuccessfulRewrites, logFailedRewrites)
(RewriteStepFailed failure)
in logs <|> abortRewriteLog
, state = toExecState p originalSubstitution unsupported Nothing
, state = toExecState p unsupported Nothing
, nextStates = Nothing
, rule = Nothing
, unknownPredicate = Nothing
Expand All @@ -586,8 +588,8 @@ execResponse req (d, traces, rr) originalSubstitution unsupported = case rr of
xs@(_ : _) -> Just xs

toExecState ::
Pattern -> Map Variable Term -> [Syntax.KorePattern] -> Maybe UniqueId -> RpcTypes.ExecuteState
toExecState pat sub unsupported muid =
Pattern -> [Syntax.KorePattern] -> Maybe UniqueId -> RpcTypes.ExecuteState
toExecState pat unsupported muid =
RpcTypes.ExecuteState
{ term = addHeader t
, predicate = addHeader <$> addUnsupported p
Expand All @@ -597,7 +599,7 @@ toExecState pat sub unsupported muid =
, ruleId = getUniqueId <$> muid
}
where
(t, p, s) = externalisePattern pat sub
(t, p, s) = externalisePattern pat
termSort = externaliseSort $ sortOfPattern pat
allUnsupported = Syntax.KJAnd termSort unsupported
addUnsupported
Expand Down
11 changes: 1 addition & 10 deletions booster/library/Booster/JsonRpc/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,9 @@ diffBy def pat1 pat2 =
<> if null ps.unsupported
then ""
else BS.unlines ("Unsupported parts:" : map Json.encode ps.unsupported)
renderBS (TermAndPredicates p m u) =
renderBS (TermAndPredicates p u) =
( BS.pack . renderDefault $
pretty (PrettyWithModifiers @['Decoded, 'Truncated] p)
<+> vsep
( map
( \(k, v) ->
pretty (PrettyWithModifiers @['Decoded, 'Truncated] k)
<+> "="
<+> pretty (PrettyWithModifiers @['Decoded, 'Truncated] v)
)
(Map.toList m)
)
)
<> if null u then "" else BS.unlines ("Unsupported parts: " : map Json.encode u)
internalise =
Expand Down
5 changes: 3 additions & 2 deletions booster/library/Booster/Log.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import Booster.Pattern.Base (
pattern AndTerm,
)
import Booster.Pattern.Pretty
import Booster.Pattern.Substitution (asEquations)
import Booster.Prettyprinter (renderOneLineText)
import Booster.Syntax.Json (KorePattern, addHeader, prettyPattern)
import Booster.Syntax.Json.Externalise (externaliseTerm)
Expand Down Expand Up @@ -185,8 +186,8 @@ withTermContext t@(Term attrs _) m =
m

withPatternContext :: LoggerMIO m => Pattern -> m a -> m a
withPatternContext Pattern{term, constraints} m =
let t' = foldl' AndTerm term $ Set.toList $ Set.map coerce constraints -- FIXME
withPatternContext Pattern{term, constraints, substitution} m =
let t' = foldl' AndTerm term . map coerce $ Set.toList constraints <> asEquations substitution
Comment on lines -188 to +190
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That FIXME was referring to the fact that the t' :: Term is not well-sorted. Probably good enough for logging, though... just that nobody should use the json version of it as input directly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we make it well-sorted? Replace AndTerm with _andBool_?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no, there's a term there...

in withTermContext t' m

instance ToLogFormat KorePattern where
Expand Down
27 changes: 25 additions & 2 deletions booster/library/Booster/Pattern/ApplyEquations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ import Booster.Pattern.Bool
import Booster.Pattern.Index qualified as Idx
import Booster.Pattern.Match
import Booster.Pattern.Pretty
import Booster.Pattern.Substitution
import Booster.Pattern.Util
import Booster.Prettyprinter (renderOneLineText)
import Booster.SMT.Interface qualified as SMT
import Booster.Syntax.Json.Externalise (externaliseTerm)
import Booster.Syntax.Json.Internalise (extractSubsitution)
import Booster.Util (Bound (..))
import Kore.JsonRpc.Types.ContextLog (CLContext (CLWithId), IdContext (CtxCached))
import Kore.Util (showHashHex)
Expand Down Expand Up @@ -455,7 +457,15 @@ evaluatePattern ::
Pattern ->
io (Either EquationFailure Pattern, SimplifierCache)
evaluatePattern def mLlvmLibrary smtSolver cache pat =
runEquationT def mLlvmLibrary smtSolver cache pat.constraints . evaluatePattern' $ pat
runEquationT
def
mLlvmLibrary
smtSolver
cache
-- interpret substitution as additional known constraints
(pat.constraints <> (Set.fromList . asEquations $ pat.substitution))
. evaluatePattern'
$ pat

-- version for internal nested evaluation
evaluatePattern' ::
Expand All @@ -469,7 +479,20 @@ evaluatePattern' pat@Pattern{term, ceilConditions} = withPatternContext pat $ do
traverse_ simplifyAssumedPredicate . predicates =<< getState
-- this may yield additional new constraints, left unevaluated
evaluatedConstraints <- predicates <$> getState
pure Pattern{constraints = evaluatedConstraints, term = newTerm, ceilConditions}
-- The interface-level evaluatePattern puts pat.substitution together with pat.constraints
-- into the simplifier state as known truth. Here the substitution will bubble-up as part of
-- evaluatedConstraints. To avoid duplicating constraints (i.e. having equivalent entities
-- in pat.predicate and pat.substitution), we discard the old substitution here
-- and extract a possible simplified one from evaluatedConstraints.
let (simplifiedSubsitution, simplifiedConstraints) = extractSubsitution (Set.toList evaluatedConstraints)

pure
Pattern
{ constraints = simplifiedConstraints
, term = newTerm
, ceilConditions
, substitution = simplifiedSubsitution
}
where
-- when TooManyIterations exception occurred while evaluating the top-level term,
-- i.e. not in a recursive evaluation of a side-condition,
Expand Down
8 changes: 6 additions & 2 deletions booster/library/Booster/Pattern/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import Data.Functor.Foldable
import Data.Hashable (Hashable)
import Data.Hashable qualified as Hashable
import Data.List as List (foldl', foldl1', sort)
import Data.Map.Strict (Map)
import Data.Set (Set)
import Data.Set qualified as Set
import GHC.Generics (Generic)
Expand Down Expand Up @@ -761,19 +762,22 @@ pattern KSeq sort a =

--------------------

type Substitution = Map Variable Term

-- | A term (configuration) constrained by a number of predicates.
data Pattern = Pattern
{ term :: Term
, constraints :: !(Set Predicate)
, substitution :: Substitution
, ceilConditions :: ![Ceil]
}
deriving stock (Eq, Ord, Show, Generic, Data)
deriving anyclass (NFData)

pattern Pattern_ :: Term -> Pattern
pattern Pattern_ t <- Pattern t _ _
pattern Pattern_ t <- Pattern t _ _ _
where
Pattern_ t = Pattern t mempty mempty
Pattern_ t = Pattern t mempty mempty mempty

pattern ConsApplication :: Symbol -> [Sort] -> [Term] -> Term
pattern ConsApplication sym sorts args <-
Expand Down
2 changes: 1 addition & 1 deletion booster/library/Booster/Pattern/Binary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ decodePattern mDef = do
preds <- forM preds' $ \case
BPredicate pIdx -> Predicate <$> getTerm pIdx
_ -> fail "Expecting a predicate"
pure $ Pattern trm (Set.fromList preds) mempty
pure $ Pattern trm (Set.fromList preds) mempty mempty
_ -> fail "Expecting a term on the top of the stack"

encodeMagicHeaderAndVersion :: Version -> Put
Expand Down
3 changes: 1 addition & 2 deletions booster/library/Booster/Pattern/Bool.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ import Booster.Definition.Attributes.Base (
pattern IsNotMacroOrAlias,
)
import Booster.Pattern.Base (
Pattern,
Pattern (..),
Predicate (..),
Symbol (Symbol),
Term,
constraints,
pattern DomainValue,
pattern SortBool,
pattern SortInt,
Expand Down
Loading
Loading