moonlight-pale-0.1.0.0: test/diagnostic/CohomologySpec.hs
module CohomologySpec
( tests,
)
where
import Moonlight.Pale.Diagnostic.Views.Rewrite
( RewriteOutcomeSummary (..),
summarizeSaturationTrace,
)
import Moonlight.Pale.Diagnostic.Summary.Structural
( GrothendieckStructuralSummary (..),
StructuralSummary (..),
)
import Moonlight.Pale.Diagnostic.Local.Rewrite
( RewriteOutcomeStat (..),
RuleTrace (..),
)
import Moonlight.Pale.Diagnostic.Local.Saturation
( SaturationIterationTrace (..),
SaturationTrace (..),
)
import Moonlight.Pale.Diagnostic.Topology.Cohomology
( CoboundaryNilpotenceEvidence (..),
evidenceNilpotent,
)
import Moonlight.Pale.Diagnostic.Topology.Homotopy (NerveHomotopyProfile (..))
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertEqual, testCase)
data RuleId
= RuleFold
| RuleInline
| RuleSimplify
deriving stock (Eq, Ord, Show)
tests :: TestTree
tests =
testGroup
"pale.diagnostic.cohomology"
[ testCase "cohomology evidence distinguishes single-context nilpotence from multi-context obstruction" $ do
assertEqual
"single-context nilpotent constructor"
SingleContextNilpotent
knownSingleContextEvidence
assertEqual
"multi-context non-nilpotent constructor"
MultiContextNonNilpotent
knownMultiContextEvidence
assertEqual
"single-context nilpotence predicate"
True
(evidenceNilpotent knownSingleContextEvidence)
assertEqual
"multi-context obstruction predicate"
False
(evidenceNilpotent knownMultiContextEvidence),
testCase "global structural summary folds cohomology and homotopy evidence into record shape" $
assertEqual
"structural summary shape"
expectedStructuralSummary
(structuralSummaryFromGrothendieck knownGrothendieckSummary),
testCase "derived rewrite summary ranks worked trace structure" $
assertEqual
"rewrite rule rank"
[RuleInline, RuleFold, RuleSimplify]
(rosRuleId <$> rosRuleStats workedRewriteSummary)
]
knownSingleContextEvidence :: CoboundaryNilpotenceEvidence
knownSingleContextEvidence =
SingleContextNilpotent
knownMultiContextEvidence :: CoboundaryNilpotenceEvidence
knownMultiContextEvidence =
MultiContextNonNilpotent
knownHomotopyProfile :: NerveHomotopyProfile
knownHomotopyProfile =
NerveHomotopyProfile
{ nhpConnectedComponents = 1,
nhpBettiVector = [1, 0]
}
knownGrothendieckSummary :: GrothendieckStructuralSummary
knownGrothendieckSummary =
GrothendieckStructuralSummary
{ gssHomotopyProfile = knownHomotopyProfile,
gssCellCount = 4,
gssFaceCount = 3,
gssObjectCount = 2,
gssMorphismCount = 5,
gssCrossContextMorphismCount = 2,
gssVerticalMorphismCount = 2,
gssDiagonalMorphismCount = 1,
gssCoboundaryNilpotenceEvidence = knownSingleContextEvidence
}
expectedStructuralSummary :: StructuralSummary
expectedStructuralSummary =
StructuralSummary
{ ssConnectedComponents = 1,
ssBettiNumbers = [1, 0],
ssCellCount = 4,
ssRestrictionCount = 5,
ssCoboundaryNilpotent = True,
ssMicrosupportSize = Just 2,
ssCriticalCellCount = Just 2,
ssNoncriticalFraction = Nothing
}
structuralSummaryFromGrothendieck :: GrothendieckStructuralSummary -> StructuralSummary
structuralSummaryFromGrothendieck summary =
StructuralSummary
{ ssConnectedComponents = nhpConnectedComponents (gssHomotopyProfile summary),
ssBettiNumbers = nhpBettiVector (gssHomotopyProfile summary),
ssCellCount = gssCellCount summary,
ssRestrictionCount = gssMorphismCount summary,
ssCoboundaryNilpotent = evidenceNilpotent (gssCoboundaryNilpotenceEvidence summary),
ssMicrosupportSize = Just (gssObjectCount summary),
ssCriticalCellCount = Just (gssCrossContextMorphismCount summary),
ssNoncriticalFraction = Nothing
}
workedTrace :: SaturationTrace RuleId
workedTrace =
SaturationTrace
{ stIterations =
[ firstIterationTrace,
secondIterationTrace
]
}
workedRewriteSummary :: RewriteOutcomeSummary RuleId
workedRewriteSummary =
summarizeSaturationTrace workedTrace
firstIterationTrace :: SaturationIterationTrace RuleId
firstIterationTrace =
SaturationIterationTrace
{ sitIteration = 0,
sitNodeCountBefore = 2,
sitNodeCountAfter = 4,
sitBaseEligibleCount = 3,
sitContextEligibleCount = 2,
sitAggregatedEligibleCount = 3,
sitGuidedCount = 2,
sitScheduledCount = 4,
sitFactsChanged = True,
sitFactRoundCount = 1,
sitContextRevision = 0,
sitRuleTraces =
[ foldTraceInitial,
inlineTraceInitial
]
}
secondIterationTrace :: SaturationIterationTrace RuleId
secondIterationTrace =
SaturationIterationTrace
{ sitIteration = 1,
sitNodeCountBefore = 4,
sitNodeCountAfter = 5,
sitBaseEligibleCount = 2,
sitContextEligibleCount = 2,
sitAggregatedEligibleCount = 2,
sitGuidedCount = 1,
sitScheduledCount = 4,
sitFactsChanged = False,
sitFactRoundCount = 2,
sitContextRevision = 1,
sitRuleTraces =
[ inlineTraceFollowup,
simplifyTraceFiltered,
foldTraceBanned
]
}
foldTraceInitial :: RuleTrace RuleId
foldTraceInitial =
RuleTrace
{ rtRuleId = RuleFold,
rtMatchedCount = 5,
rtFilteredCount = 1,
rtScheduledCount = 3,
rtSkippedByScheduler = False,
rtBannedUntil = Nothing
}
inlineTraceInitial :: RuleTrace RuleId
inlineTraceInitial =
RuleTrace
{ rtRuleId = RuleInline,
rtMatchedCount = 2,
rtFilteredCount = 1,
rtScheduledCount = 1,
rtSkippedByScheduler = False,
rtBannedUntil = Nothing
}
inlineTraceFollowup :: RuleTrace RuleId
inlineTraceFollowup =
RuleTrace
{ rtRuleId = RuleInline,
rtMatchedCount = 4,
rtFilteredCount = 0,
rtScheduledCount = 4,
rtSkippedByScheduler = False,
rtBannedUntil = Nothing
}
simplifyTraceFiltered :: RuleTrace RuleId
simplifyTraceFiltered =
RuleTrace
{ rtRuleId = RuleSimplify,
rtMatchedCount = 3,
rtFilteredCount = 3,
rtScheduledCount = 0,
rtSkippedByScheduler = False,
rtBannedUntil = Nothing
}
foldTraceBanned :: RuleTrace RuleId
foldTraceBanned =
RuleTrace
{ rtRuleId = RuleFold,
rtMatchedCount = 1,
rtFilteredCount = 1,
rtScheduledCount = 0,
rtSkippedByScheduler = True,
rtBannedUntil = Just 3
}