Skip to content

Commit deaf0af

Browse files
Keep set of defined terms in SideCondition (#2354)
Co-authored-by: Thomas Tuegel <[email protected]>
1 parent e87dac7 commit deaf0af

File tree

7 files changed

+1121
-157
lines changed

7 files changed

+1121
-157
lines changed

kore/src/Debug.hs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import Data.HashMap.Strict
4141
( HashMap
4242
)
4343
import qualified Data.HashMap.Strict as HashMap
44+
import Data.HashSet
45+
( HashSet
46+
)
47+
import qualified Data.HashSet as HashSet
4448
import Data.Int
4549
import Data.Map.Strict
4650
( Map
@@ -346,6 +350,11 @@ instance Debug a => Debug (Set a) where
346350
(parens (precOut >= 10) . Pretty.sep)
347351
["Data.Set.fromList", debug (Set.toList as)]
348352

353+
instance Debug a => Debug (HashSet a) where
354+
debugPrec as precOut =
355+
(parens (precOut >= 10) . Pretty.sep)
356+
["Data.HashSet.fromList", debug (HashSet.toList as)]
357+
349358
instance Debug a => Debug (Seq a) where
350359
debugPrec as precOut =
351360
(parens (precOut >= 10) . Pretty.sep)
@@ -620,6 +629,13 @@ instance (Debug a, Diff a) => Diff (Set a) where
620629
wrapFromList diff' precOut =
621630
parens (precOut >= 10) $ "Data.Set.fromList" <+> diff' 10
622631

632+
instance (Debug a, Diff a) => Diff (HashSet a) where
633+
diffPrec as bs =
634+
fmap wrapFromList $ diffPrec (HashSet.toList as) (HashSet.toList bs)
635+
where
636+
wrapFromList diff' precOut =
637+
parens (precOut >= 10) $ "Data.HashSet.fromList" <+> diff' 10
638+
623639
instance Diff ExitCode
624640

625641
instance (Debug a, Debug b, Diff a, Diff b) => Diff (Either a b)

kore/src/Kore/Builtin/AssocComm/CeilSimplifier.hs

Lines changed: 106 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@ import Prelude.Kore
1717
import Control.Error
1818
( MaybeT
1919
)
20-
import qualified Control.Lens as Lens
21-
import Control.Monad
22-
( zipWithM
23-
)
2420
import Control.Monad.Reader
2521
( MonadReader
2622
)
2723
import qualified Control.Monad.Reader as Reader
28-
import qualified Data.List as List
24+
import qualified Data.Bifunctor as Bifunctor
2925
import qualified Data.Map.Strict as Map
3026

3127
import Kore.Attribute.Pattern.FreeVariables
@@ -175,6 +171,8 @@ generalizeMapElement freeVariables' element =
175171
newBuiltinAssocCommCeilSimplifier
176172
:: forall normalized variable simplifier
177173
. InternalVariable variable
174+
=> Ord (Element normalized (TermLike variable))
175+
=> Ord (Value normalized (TermLike variable))
178176
=> MonadReader (SideCondition variable) simplifier
179177
=> MonadSimplify simplifier
180178
=> Traversable (Value normalized)
@@ -188,112 +186,95 @@ newBuiltinAssocCommCeilSimplifier mkBuiltin mkNotMember =
188186
CeilSimplifier $ \Ceil { ceilChild } -> do
189187
let internalAc@InternalAc { builtinAcChild } = ceilChild
190188
sideCondition <- Reader.ask
191-
let normalizedAc :: NormalizedAc normalized Key (TermLike variable)
192-
normalizedAc = unwrapAc builtinAcChild
193-
NormalizedAc
194-
{ elementsWithVariables = abstractElements
195-
, concreteElements
196-
, opaque
197-
}
198-
= normalizedAc
199-
200-
let defineOpaquePair
201-
:: TermLike variable
202-
-> TermLike variable
203-
-> MultiAnd (OrCondition variable)
204-
defineOpaquePair opaque1 opaque2 =
205-
internalAc
206-
{ builtinAcChild =
207-
wrapAc
208-
emptyNormalizedAc { opaque = [opaque1, opaque2] }
209-
}
210-
& mkBuiltin
211-
& makeCeilPredicate
212-
-- TODO (thomas.tuegel): Do not mark this simplified.
213-
-- Marking here may prevent user-defined axioms from applying.
214-
-- At present, we wouldn't apply such an axiom, anyway.
215-
& Predicate.markSimplifiedMaybeConditional Nothing
216-
& OrCondition.fromPredicate
217-
& MultiAnd.singleton
218-
219-
defineOpaquePairs
220-
:: TermLike variable
221-
-> [TermLike variable]
222-
-> MultiAnd (OrCondition variable)
223-
defineOpaquePairs this others =
224-
foldMap (defineOpaquePair this) others
225-
226-
definedOpaquePairs :: MultiAnd (OrCondition variable)
227-
definedOpaquePairs =
228-
mconcat
229-
$ zipWith defineOpaquePairs opaque
230-
$ tail $ List.tails opaque
231-
232-
let abstractKeys, concreteKeys
233-
:: [TermLike variable]
234-
abstractValues, concreteValues, allValues
235-
:: [Value normalized (TermLike variable)]
236-
(abstractKeys, abstractValues) =
237-
unzip (unwrapElement <$> abstractElements)
238-
concreteKeys = from @Key <$> Map.keys concreteElements
239-
concreteValues = Map.elems concreteElements
240-
allValues = concreteValues <> abstractValues
241-
242-
let makeEvaluateTerm, defineAbstractKey, defineOpaque
243-
:: TermLike variable -> MaybeT simplifier (OrCondition variable)
244-
makeEvaluateTerm = makeEvaluateTermCeil sideCondition
245-
defineAbstractKey = makeEvaluateTerm
246-
defineOpaque = makeEvaluateTerm
247-
248-
defineValue
249-
:: Value normalized (TermLike variable)
250-
-> MaybeT simplifier (MultiAnd (OrCondition variable))
251-
defineValue = foldlM worker mempty
252-
where
253-
worker multiAnd termLike = do
254-
evaluated <- makeEvaluateTerm termLike
255-
return (multiAnd <> MultiAnd.singleton evaluated)
256-
257-
TermLike.assertConstructorLikeKeys concreteKeys $ return ()
258-
259-
-- concreteKeys are defined by assumption
260-
definedKeys <- traverse defineAbstractKey abstractKeys
261-
definedOpaque <- traverse defineOpaque opaque
262-
definedValues <- traverse defineValue allValues
263-
-- concreteKeys are distinct by assumption
264-
distinctConcreteKeys <-
265-
traverse (flip distinctKey concreteKeys) abstractKeys
266-
distinctAbstractKeys <-
267-
zipWithM distinctKey
268-
abstractKeys
269-
(tail $ List.tails abstractKeys)
270-
let conditions :: MultiAnd (OrCondition variable)
271-
conditions =
272-
mconcat
273-
[ MultiAnd.make definedKeys
274-
, MultiAnd.make definedOpaque
275-
, mconcat definedValues
276-
, mconcat distinctConcreteKeys
277-
, mconcat distinctAbstractKeys
278-
, foldMap (notMembers normalizedAc) opaque
279-
, definedOpaquePairs
280-
]
281-
189+
let symbolicKeys = getSymbolicKeysOfAc builtinAcChild
190+
symbolicValues = getSymbolicValuesOfAc builtinAcChild
191+
concreteValues = getConcreteValuesOfAc builtinAcChild
192+
opaqueElements = opaque . unwrapAc $ builtinAcChild
193+
definedKeysAndOpaque <-
194+
traverse
195+
(makeEvaluateTermCeil sideCondition)
196+
(symbolicKeys <> opaqueElements)
197+
& fmap MultiAnd.make
198+
definedValues <-
199+
traverse
200+
(defineValue sideCondition)
201+
(symbolicValues <> concreteValues)
202+
& fmap mconcat
203+
definedSubCollections <-
204+
definePairWiseElements mkBuiltin mkNotMember internalAc
205+
. generatePairWiseElements
206+
$ builtinAcChild
207+
let conditions =
208+
definedKeysAndOpaque
209+
<> definedValues
210+
<> definedSubCollections
282211
And.simplifyEvaluatedMultiPredicate sideCondition conditions
283212
where
213+
defineValue
214+
:: SideCondition variable
215+
-> Value normalized (TermLike variable)
216+
-> MaybeT simplifier (MultiAnd (OrCondition variable))
217+
defineValue sideCondition = foldlM worker mempty
218+
where
219+
worker multiAnd termLike = do
220+
evaluated <- makeEvaluateTermCeil sideCondition termLike
221+
return (multiAnd <> MultiAnd.singleton evaluated)
284222

285-
distinctKey
286-
:: TermLike variable
287-
-> [TermLike variable]
288-
-> MaybeT simplifier (MultiAnd (OrCondition variable))
289-
distinctKey thisKey otherKeys =
290-
MultiAnd.make <$> traverse (notEquals thisKey) otherKeys
223+
definePairWiseElements
224+
:: forall variable normalized simplifier
225+
. MonadSimplify simplifier
226+
=> InternalVariable variable
227+
=> MonadReader (SideCondition variable) simplifier
228+
=> AcWrapper normalized
229+
=> MkBuiltinAssocComm normalized variable
230+
-> MkNotMember normalized variable
231+
-> InternalAc Key normalized (TermLike variable)
232+
-> PairWiseElements normalized Key (TermLike variable)
233+
-> MaybeT simplifier (MultiAnd (OrCondition variable))
234+
definePairWiseElements mkBuiltin mkNotMember internalAc pairWiseElements = do
235+
definedKeyPairs <-
236+
traverse
237+
distinctKey
238+
(symbolicKeyPairs <> symbolicConcreteKeyPairs)
239+
& fmap MultiAnd.make
240+
let definedElementOpaquePairs =
241+
foldMap
242+
notMember
243+
(symbolicOpaquePairs <> concreteOpaquePairs')
244+
definedOpaquePairs =
245+
foldMap defineOpaquePair opaquePairs
246+
return . fold $
247+
[ definedKeyPairs
248+
, definedElementOpaquePairs
249+
, definedOpaquePairs
250+
]
251+
where
252+
PairWiseElements
253+
{ symbolicPairs
254+
, opaquePairs
255+
, symbolicConcretePairs
256+
, symbolicOpaquePairs
257+
, concreteOpaquePairs
258+
} = pairWiseElements
259+
symbolicKeyPairs =
260+
Bifunctor.bimap
261+
(fst . unwrapElement)
262+
(fst . unwrapElement)
263+
<$> symbolicPairs
264+
symbolicConcreteKeyPairs =
265+
Bifunctor.bimap
266+
(fst . unwrapElement)
267+
(from @Key @(TermLike variable) . fst)
268+
<$> symbolicConcretePairs
269+
concreteOpaquePairs' =
270+
Bifunctor.first
271+
wrapConcreteElement
272+
<$> concreteOpaquePairs
291273

292-
notEquals
293-
:: TermLike variable
294-
-> TermLike variable
295-
-> MaybeT simplifier (OrCondition variable)
296-
notEquals t1 t2 = do
274+
distinctKey
275+
:: (TermLike variable, TermLike variable)
276+
-> MaybeT simplifier (OrCondition variable)
277+
distinctKey (t1, t2) = do
297278
sideCondition <- Reader.ask
298279
Equals.makeEvaluateTermsToPredicate tMin tMax sideCondition
299280
>>= Not.simplifyEvaluatedPredicate
@@ -302,37 +283,30 @@ newBuiltinAssocCommCeilSimplifier mkBuiltin mkNotMember =
302283
(tMin, tMax) = minMax t1 t2
303284

304285
notMember
305-
:: TermLike variable
306-
-> Element normalized (TermLike variable)
286+
:: (Element normalized (TermLike variable), TermLike variable)
307287
-> MultiAnd (OrCondition variable)
308-
notMember termLike element =
288+
notMember (element, termLike) =
309289
mkNotMember element termLike
310290
& OrCondition.fromPredicate
311291
& MultiAnd.singleton
312292

313-
notMembers
314-
:: NormalizedAc normalized Key (TermLike variable)
315-
-> TermLike variable
293+
defineOpaquePair
294+
:: (TermLike variable, TermLike variable)
316295
-> MultiAnd (OrCondition variable)
317-
notMembers normalizedAc termLike =
318-
Lens.foldMapOf foldElements (notMember termLike) normalizedAc
319-
320-
foldElements
321-
:: AcWrapper collection
322-
=> InternalVariable variable
323-
=> Lens.Fold
324-
(NormalizedAc collection Key (TermLike variable))
325-
(Element collection (TermLike variable))
326-
foldElements =
327-
Lens.folding $ \normalizedAc ->
328-
let
329-
concreteElements' =
330-
concreteElements normalizedAc
331-
& Map.toList
332-
& map wrapConcreteElement
333-
symbolicElements' = elementsWithVariables normalizedAc
334-
in
335-
concreteElements' <> symbolicElements'
296+
defineOpaquePair (opaque1, opaque2) =
297+
internalAc
298+
{ builtinAcChild =
299+
wrapAc
300+
emptyNormalizedAc { opaque = [opaque1, opaque2] }
301+
}
302+
& mkBuiltin
303+
& makeCeilPredicate
304+
-- TODO (thomas.tuegel): Do not mark this simplified.
305+
-- Marking here may prevent user-defined axioms from applying.
306+
-- At present, we wouldn't apply such an axiom, anyway.
307+
& Predicate.markSimplifiedMaybeConditional Nothing
308+
& OrCondition.fromPredicate
309+
& MultiAnd.singleton
336310

337311
fromElement
338312
:: AcWrapper normalized

kore/src/Kore/Internal/NormalizedAc.hs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ module Kore.Internal.NormalizedAc
2828
, normalizedAcConstructorLike
2929
, normalizedAcFunctional
3030
, unparseInternalAc
31+
, PairWiseElements (..)
32+
, generatePairWiseElements
3133
) where
3234

3335
import Prelude.Kore
@@ -39,6 +41,9 @@ import Control.Lens.Iso
3941
import Data.Kind
4042
( Type
4143
)
44+
import Data.List.Extra
45+
( nubOrdBy
46+
)
4247
import Data.Map.Strict
4348
( Map
4449
)
@@ -489,3 +494,54 @@ normalizedAcConstructorLike ac@(NormalizedAc _ _ _) =
489494
pairIsConstructorLike (key, value) =
490495
assertConstructorLike "" key $ isConstructorLike value
491496
_ -> ConstructorLike Nothing
497+
498+
-- | 'PairWiseElements' is a representation of the elements of all subcollections
499+
-- necessary for proving the definedness of a collection.
500+
data PairWiseElements normalized key child =
501+
PairWiseElements
502+
{ symbolicPairs
503+
:: [(Element normalized child, Element normalized child)]
504+
, concretePairs
505+
:: [((key, Value normalized child), (key, Value normalized child))]
506+
, opaquePairs
507+
:: [(child, child)]
508+
, symbolicConcretePairs
509+
:: [(Element normalized child, (key, Value normalized child))]
510+
, symbolicOpaquePairs
511+
:: [(Element normalized child, child)]
512+
, concreteOpaquePairs
513+
:: [((key, Value normalized child), child)]
514+
}
515+
516+
-- | Generates the 'PairWiseElements' for a 'AcWrapper' collection.
517+
generatePairWiseElements
518+
:: AcWrapper normalized
519+
=> Ord key
520+
=> Ord child
521+
=> Ord (Element normalized child)
522+
=> Ord (Value normalized child)
523+
=> normalized key child
524+
-> PairWiseElements normalized key child
525+
generatePairWiseElements (unwrapAc -> normalized) =
526+
PairWiseElements
527+
{ symbolicPairs = pairWiseElemsOfSameType symbolicElems
528+
, concretePairs = pairWiseElemsOfSameType concreteElems
529+
, opaquePairs = pairWiseElemsOfSameType opaqueElems
530+
, symbolicConcretePairs =
531+
(,) <$> symbolicElems <*> concreteElems
532+
, symbolicOpaquePairs =
533+
(,) <$> symbolicElems <*> opaqueElems
534+
, concreteOpaquePairs =
535+
(,) <$> concreteElems <*> opaqueElems
536+
}
537+
where
538+
symbolicElems = elementsWithVariables normalized
539+
concreteElems = Map.toList . concreteElements $ normalized
540+
opaqueElems = opaque normalized
541+
pairWiseElemsOfSameType elems =
542+
[ (x, y) | x <- elems, y <- elems, x /= y ]
543+
& nubOrdBy applyComm
544+
applyComm p1 p2
545+
| p1 == p2 = EQ
546+
| swap p1 == p2 = EQ
547+
| otherwise = compare p1 p2

0 commit comments

Comments
 (0)