Skip to content

Commit 5adcc6d

Browse files
Move simplifyConjunctionByAssumption to Condition simplifier (#2170)
* WIP move simplifyConjunctionByAssumption to Pattern simplifier * Refactor + fix * Refactor * Remove Changed * Test.Integration.sortMatching: reorder ands * Test.Integration.map-like simplification: reorder ands * Integration test issue-2095: renegerate golden * Test.Simplification.Equals: fix tests add pattern simplifier checks as well * Move local function evaluation tests to Test.Simplification.Pattern * Move tests from Simplification.And to Simplification.Pattern * Remove tests * Check for equivalence of claims in Test.Simplify.Rule * Add a Proven branch to tests in OnePathStrategy. Is this right? * Add definedness condition to stuck configuration. Is this right? * Pattern.simplify: clean-up * Update kore/src/Kore/Step/Simplification/Pattern.hs Co-authored-by: Thomas Tuegel <[email protected]> * Update kore/src/Kore/Step/ClaimPattern.hs Co-authored-by: Thomas Tuegel <[email protected]> * lensPredicate: move to Internal.MultiAnd * Address review comment: move ClaimPattern.areEquivalent to test suite * MultiAnd: sorted version of toPredicate * Use Pattern simplifier in checkImplication and in applyRemainder * Step.applyRemainder: simplifyCondition and then simplifyConjunctions * simplifyConjunctions: move to condition simplifier * simplifyConjunctions: set simplified based on whether the predicate changed * test-issue-2095: regenerate golden * Condition.simplify: simplify conjunctions at the end, continue if predicate changed * Revert "Test.Integration.sortMatching: reorder ands" This reverts commit 2521e12. * Revert "Test.Integration.map-like simplification: reorder ands" This reverts commit e63d5ee. * test-issue-2095: regenerate golden * Update kore/src/Kore/Reachability/Claim.hs Co-authored-by: Thomas Tuegel <[email protected]> * Address review comments * Address review comment Co-authored-by: Thomas Tuegel <[email protected]>
1 parent dc259a5 commit 5adcc6d

File tree

11 files changed

+771
-496
lines changed

11 files changed

+771
-496
lines changed

kore/src/Kore/Internal/MultiAnd.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Kore.Internal.MultiAnd
1616
, top
1717
, make
1818
, toPredicate
19+
, toPredicateSorted
1920
, fromPredicate
2021
, fromTermLike
2122
, singleton
@@ -44,10 +45,12 @@ import Kore.Internal.Predicate
4445
( Predicate
4546
, getMultiAndPredicate
4647
, makeAndPredicate
48+
, makeTruePredicate
4749
, makeTruePredicate_
4850
)
4951
import Kore.Internal.TermLike
50-
( TermLike
52+
( Sort
53+
, TermLike
5154
, TermLikeF (..)
5255
)
5356
import Kore.Internal.Variable
@@ -207,6 +210,16 @@ toPredicate (MultiAnd predicates) =
207210
[] -> makeTruePredicate_
208211
_ -> foldr1 makeAndPredicate predicates
209212

213+
toPredicateSorted
214+
:: InternalVariable variable
215+
=> Sort
216+
-> MultiAnd (Predicate variable)
217+
-> Predicate variable
218+
toPredicateSorted sort (MultiAnd predicates) =
219+
case predicates of
220+
[] -> makeTruePredicate sort
221+
_ -> foldr1 makeAndPredicate predicates
222+
210223
fromPredicate
211224
:: Ord variable
212225
=> Predicate variable

kore/src/Kore/Reachability/Claim.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ import Logic
162162
, MonadLogic
163163
)
164164
import qualified Logic
165+
import Pretty
166+
( Pretty (..)
167+
)
165168
import qualified Pretty
166169

167170
class Claim claim where
@@ -410,6 +413,19 @@ data CheckImplicationResult a
410413
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
411414
deriving anyclass (Debug, Diff)
412415

416+
instance Pretty a => Pretty (CheckImplicationResult a) where
417+
pretty Implied = "implied"
418+
pretty (NotImplied a) =
419+
Pretty.vsep
420+
[ "not implied:"
421+
, Pretty.indent 4 $ pretty a
422+
]
423+
pretty (NotImpliedStuck a) =
424+
Pretty.vsep
425+
[ "stuck:"
426+
, Pretty.indent 4 $ pretty a
427+
]
428+
413429
-- | Remove the destination of the claim.
414430
checkImplication'
415431
:: forall claim m
@@ -513,6 +529,8 @@ checkImplicationWorker (ClaimPattern.refreshExistentials -> claimPattern) =
513529
stuck <-
514530
simplifyConditionsWithSmt sideCondition configs'
515531
>>= Logic.scatter
532+
>>= Pattern.simplify sideCondition
533+
>>= Logic.scatter
516534
pure (examine anyUnified stuck)
517535
& elseImplied
518536
where

kore/src/Kore/Step/Simplification/And.hs

Lines changed: 6 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,22 @@ import Prelude.Kore
1616
import Control.Error
1717
( runMaybeT
1818
)
19-
import Control.Monad.State.Strict
20-
( StateT
21-
, evalStateT
22-
)
23-
import qualified Control.Monad.State.Strict as State
2419
import Data.Bifunctor
2520
( bimap
2621
)
2722
import qualified Data.Foldable as Foldable
28-
import qualified Data.Functor.Foldable as Recursive
29-
import Data.HashMap.Strict
30-
( HashMap
31-
)
32-
import qualified Data.HashMap.Strict as HashMap
3323
import Data.List
3424
( foldl1'
35-
, sortOn
3625
)
3726
import Data.Set
3827
( Set
3928
)
4029
import qualified Data.Set as Set
41-
import Data.Traversable
42-
( for
43-
)
4430
import Kore.Internal.MultiAnd
4531
( MultiAnd
4632
)
4733
import qualified Kore.Internal.MultiAnd as MultiAnd
4834

49-
import Changed
50-
import Kore.Attribute.Synthetic
51-
( synthesize
52-
)
5335
import qualified Kore.Internal.Conditional as Conditional
5436
import Kore.Internal.OrPattern
5537
( OrPattern
@@ -58,36 +40,19 @@ import qualified Kore.Internal.OrPattern as OrPattern
5840
import Kore.Internal.Pattern as Pattern
5941
import Kore.Internal.Predicate
6042
( Predicate
61-
, makePredicate
6243
)
6344
import qualified Kore.Internal.Predicate as Predicate
6445
import Kore.Internal.SideCondition
6546
( SideCondition
6647
)
67-
import Kore.Internal.Symbol
68-
( isConstructor
69-
, isFunction
70-
)
7148
import Kore.Internal.TermLike
7249
( And (..)
7350
, pattern And_
74-
, pattern App_
75-
, pattern Builtin_
76-
, pattern Equals_
77-
, pattern Exists_
78-
, pattern Forall_
79-
, pattern Inj_
80-
, pattern Mu_
8151
, pattern Not_
82-
, pattern Nu_
8352
, TermLike
84-
, Variable (..)
8553
, mkAnd
86-
, mkBottom
8754
, mkBottom_
8855
, mkNot
89-
, mkTop
90-
, termLikeSort
9156
)
9257
import qualified Kore.Internal.TermLike as TermLike
9358
import Kore.Step.Simplification.AndTerms
@@ -100,12 +65,7 @@ import Kore.Unification.UnifierT
10065
( UnifierT (..)
10166
, runUnifierT
10267
)
103-
import Kore.Unparser
104-
( unparse
105-
)
10668
import Logic
107-
import Pair
108-
import qualified Pretty
10969

11070
{- | Simplify a conjunction of 'OrPattern'.
11171
@@ -200,182 +160,22 @@ makeEvaluateNonBool notSimplifier sideCondition patterns = do
200160
from @_ @(Condition _) substitutions
201161
& Substitution.normalize sideCondition
202162
let substitution = Pattern.substitution normalized
203-
predicates :: Changed (MultiAnd (Predicate variable))
163+
predicates :: MultiAnd (Predicate variable)
204164
predicates =
205165
mconcat
206166
[ MultiAnd.fromPredicate (predicate unified)
207167
, MultiAnd.fromPredicate (predicate normalized)
208168
, foldMap (from @(Predicate _) . predicate) patterns
209169
]
210-
& simplifyConjunctionByAssumption
211170
term =
212171
applyAndIdempotenceAndFindContradictions
213172
(Conditional.term unified)
214-
case predicates of
215-
Unchanged unchanged ->
216-
Pattern.withCondition term (from substitution <> from predicate)
173+
let predicate =
174+
MultiAnd.toPredicate predicates
175+
& Predicate.setSimplified simplified
176+
simplified = foldMap Predicate.simplifiedAttribute predicates
177+
in Pattern.withCondition term (from substitution <> from predicate)
217178
& return
218-
where
219-
predicate =
220-
MultiAnd.toPredicate unchanged
221-
& Predicate.setSimplified simplified
222-
simplified = foldMap Predicate.simplifiedAttribute unchanged
223-
Changed changed ->
224-
Pattern.withCondition term (from substitution <> from predicate)
225-
& simplifyCondition sideCondition
226-
where
227-
predicate = MultiAnd.toPredicate changed
228-
229-
{- | Simplify the conjunction of 'Predicate' clauses by assuming each is true.
230-
231-
The conjunction is simplified by the identity:
232-
233-
@
234-
A ∧ P(A) = A ∧ P(⊤)
235-
@
236-
237-
-}
238-
simplifyConjunctionByAssumption
239-
:: forall variable
240-
. InternalVariable variable
241-
=> MultiAnd (Predicate variable)
242-
-> Changed (MultiAnd (Predicate variable))
243-
simplifyConjunctionByAssumption (Foldable.toList -> andPredicates) =
244-
fmap MultiAnd.make
245-
$ flip evalStateT HashMap.empty
246-
$ for (sortBySize andPredicates)
247-
$ \predicate' -> do
248-
let original = Predicate.unwrapPredicate predicate'
249-
result <- applyAssumptions original
250-
assume result
251-
return result
252-
where
253-
-- Sorting by size ensures that every clause is considered before any clause
254-
-- which could contain it, because the containing clause is necessarily
255-
-- larger.
256-
sortBySize :: [Predicate variable] -> [Predicate variable]
257-
sortBySize = sortOn (size . from)
258-
259-
size :: TermLike variable -> Int
260-
size =
261-
Recursive.fold $ \(_ :< termLikeF) ->
262-
case termLikeF of
263-
TermLike.EvaluatedF evaluated -> TermLike.getEvaluated evaluated
264-
TermLike.DefinedF defined -> TermLike.getDefined defined
265-
_ -> 1 + Foldable.sum termLikeF
266-
267-
assume
268-
:: Predicate variable
269-
-> StateT (HashMap (TermLike variable) (TermLike variable)) Changed ()
270-
assume predicate1 =
271-
State.modify' (assumeEqualTerms . assumePredicate)
272-
where
273-
assumePredicate =
274-
case termLike of
275-
Not_ _ notChild ->
276-
-- Infer that the predicate is \bottom.
277-
HashMap.insert notChild (mkBottom sort)
278-
_ ->
279-
-- Infer that the predicate is \top.
280-
HashMap.insert termLike (mkTop sort)
281-
assumeEqualTerms =
282-
case retractLocalFunction termLike of
283-
Just (Pair term1 term2) -> HashMap.insert term1 term2
284-
_ -> id
285-
286-
termLike = Predicate.unwrapPredicate predicate1
287-
sort = termLikeSort termLike
288-
289-
applyAssumptions
290-
:: TermLike variable
291-
-> StateT (HashMap (TermLike variable) (TermLike variable)) Changed
292-
(Predicate variable)
293-
applyAssumptions replaceIn = do
294-
assumptions <- State.get
295-
lift $ fmap
296-
(unsafeMakePredicate assumptions replaceIn)
297-
(applyAssumptionsWorker assumptions replaceIn)
298-
299-
unsafeMakePredicate replacements original result =
300-
case makePredicate result of
301-
-- TODO (ttuegel): https://github.com/kframework/kore/issues/1442
302-
-- should make it impossible to have an error here.
303-
Left err ->
304-
(error . show . Pretty.vsep . map (either id (Pretty.indent 4)))
305-
[ Left "Replacing"
306-
, Right (Pretty.vsep (unparse <$> HashMap.keys replacements))
307-
, Left "in"
308-
, Right (unparse original)
309-
, Right (Pretty.pretty err)
310-
]
311-
Right p -> p
312-
313-
applyAssumptionsWorker
314-
:: HashMap (TermLike variable) (TermLike variable)
315-
-> TermLike variable
316-
-> Changed (TermLike variable)
317-
applyAssumptionsWorker assumptions original
318-
| Just result <- HashMap.lookup original assumptions = Changed result
319-
320-
| HashMap.null assumptions' = Unchanged original
321-
322-
| otherwise =
323-
traverse (applyAssumptionsWorker assumptions') replaceIn
324-
& getChanged
325-
-- The next line ensures that if the result is Unchanged, any allocation
326-
-- performed while computing that result is collected.
327-
& maybe (Unchanged original) (Changed . synthesize)
328-
329-
where
330-
_ :< replaceIn = Recursive.project original
331-
332-
assumptions'
333-
| Exists_ _ var _ <- original = restrictAssumptions (inject var)
334-
| Forall_ _ var _ <- original = restrictAssumptions (inject var)
335-
| Mu_ var _ <- original = restrictAssumptions (inject var)
336-
| Nu_ var _ <- original = restrictAssumptions (inject var)
337-
| otherwise = assumptions
338-
339-
restrictAssumptions Variable { variableName } =
340-
HashMap.filterWithKey
341-
(\termLike _ -> wouldNotCapture termLike)
342-
assumptions
343-
where
344-
wouldNotCapture = not . TermLike.hasFreeVariable variableName
345-
346-
{- | Get a local function definition from a 'TermLike'.
347-
348-
A local function definition is a predicate that we can use to evaluate a
349-
function locally (based on the side conditions) when none of the functions
350-
global definitions (axioms) apply. We are looking for a 'TermLike' of the form
351-
352-
@
353-
\equals(f(...), C(...))
354-
@
355-
356-
where @f@ is a function and @C@ is a constructor, sort injection or builtin.
357-
@retractLocalFunction@ will match an @\equals@ predicate with its arguments
358-
in either order, but the function pattern is always returned first in the
359-
'Pair'.
360-
361-
-}
362-
retractLocalFunction
363-
:: TermLike variable
364-
-> Maybe (Pair (TermLike variable))
365-
retractLocalFunction =
366-
\case
367-
Equals_ _ _ term1 term2 -> go term1 term2 <|> go term2 term1
368-
_ -> Nothing
369-
where
370-
go term1@(App_ symbol1 _) term2
371-
| isFunction symbol1 =
372-
case term2 of
373-
App_ symbol2 _
374-
| isConstructor symbol2 -> Just (Pair term1 term2)
375-
Inj_ _ -> Just (Pair term1 term2)
376-
Builtin_ _ -> Just (Pair term1 term2)
377-
_ -> Nothing
378-
go _ _ = Nothing
379179

380180
applyAndIdempotenceAndFindContradictions
381181
:: InternalVariable variable

0 commit comments

Comments
 (0)