moonlight-planar-1.1.0.0: bench/power/Moonlight/Planar/PowerMassBench.hs
-- | Preparation and repeated observation are separate measured workloads.
-- This inspectable three-site fixture is a microbenchmark, not a production
-- speed claim. Reconstruction shares the canonical power-site encoding.
module Moonlight.Planar.PowerMassBench (prepareBenchmarks) where
import BenchMeasure (requireRight)
import Control.DeepSeq (force)
import Control.Exception (evaluate)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Map.Strict as Map
import Moonlight.Planar.Convex (convexPolygon, convexPolygonPoints, retainConvexPolygon)
import Moonlight.Planar.Exact (ExactPoint, ExactRational, exactPoint, exactPointCross, exactRational)
import Moonlight.Planar.PowerDiagram
( PowerCellDisposition (..)
, PowerDiagramError
, PowerMassError
, PowerSite
, boundedPowerDiagram
, evaluatePowerMasses
, powerCellDispositions
, powerSite
, powerSiteLabel
, powerSitePosition
, powerWeightFromExact
, preparePowerMassSection
)
import Moonlight.Planar.Point (Point (..))
import Test.Tasty.Bench (Benchmark, bench, bgroup, nf)
prepareBenchmarks :: IO [Benchmark]
prepareBenchmarks = do
window <- requireRight
(convexPolygon (exactPoint (-2) (-2) :| [exactPoint 2 (-2), exactPoint 2 2, exactPoint (-2) 2]))
sites <- requireRight
(traverse (\(label, position) -> powerSite label position (powerWeightFromExact 0))
((0 :: Int, Point (-1) (-1)) :| [(1, Point 1 (-1)), (2, Point 0 1)]))
let trajectories = NonEmpty.zip sites (1 :| [0, 0])
direction = Map.fromList (fmap (\(site, rate) -> (powerSiteLabel site, rate)) (NonEmpty.toList trajectories))
prepare = preparePowerMassSection window sites
section <- requireRight (prepare direction) >>= evaluate . force
parameters <- requireRight (traverse (`exactRational` 16) [-112 .. 64])
half <- requireRight (exactRational 1 2)
expiryBenchmarks <- prepareExpiryBenchmarks
retentionBenchmarks <- traverse prepareRetentionBenchmark [4, 32, 128]
let observations :: [ExactRational] -> Either (PowerMassError Int) [Map.Map Int ExactRational]
observations queryParameters = traverse (`evaluatePowerMasses` section) queryParameters
prepareAndObserve
:: (Map.Map Int ExactRational, [ExactRational])
-> Either (PowerMassError Int) [Map.Map Int ExactRational]
prepareAndObserve (queryDirection, queryParameters) = do
prepared <- prepare queryDirection
traverse (`evaluatePowerMasses` prepared) queryParameters
reconstruction parameter = do
reweighted <- traverse
(\(site, rate) -> powerSite (powerSiteLabel site) (powerSitePosition site) (powerWeightFromExact (parameter * rate)))
trajectories
(diagram, _) <- boundedPowerDiagram window reweighted
pure (Map.fromList (fmap (\(label, cell) -> (label, cellArea cell)) (powerCellDispositions diagram)))
cellArea :: PowerCellDisposition Int -> ExactRational
cellArea disposition = case disposition of
PublishedPowerCell polygon ->
let points@(initial :| remaining) = convexPolygonPoints polygon
in half * sum (zipWith exactPointCross (NonEmpty.toList points) (remaining <> [initial]))
LowerDimensionalPowerCell _ -> 0
EmptyPowerCell -> 0
CoincidentEquivalentTo _ -> 0
CoincidentDominatedBy _ -> 0
amortizedBenchmarks queryCount =
let queryParameters = take queryCount parameters
in bgroup ("queries-" <> show queryCount)
[ bench "prepare-and-evaluate" (nf prepareAndObserve (direction, queryParameters))
, bench "reconstruct" (nf (traverse reconstruction) queryParameters)
]
pure
([ bgroup "certified power mass/three-site"
( [ bench "prepare" (nf prepare direction)
, bench "reuse-only-177-exact-parameters" (nf observations parameters)
]
<> fmap amortizedBenchmarks [1, 2, 8, 32, 128]
)
, expiryBenchmarks
] <> retentionBenchmarks)
-- The admitted window is fixture cost. This measures only its conversion into
-- retained affine boundaries, over the same exact convex family at each size.
prepareRetentionBenchmark :: Int -> IO Benchmark
prepareRetentionBenchmark count = do
let pointAt :: Int -> ExactPoint
pointAt index = exactPoint (fromIntegral index) (fromIntegral (index * index))
window <- requireRight (convexPolygon (pointAt 0 :| fmap pointAt [1 .. count - 1])) >>= evaluate . force
pure (bench ("convex-retention/" <> show count)
(nf retainConvexPolygon window))
-- The next seed is an explicitly supplied exact interior value, not an
-- epsilon-derived event transition. The benchmark includes the refusal at
-- the old endpoint and complete preparation at the new seed.
prepareExpiryBenchmarks :: IO Benchmark
prepareExpiryBenchmarks = do
window <- requireRight
(convexPolygon (exactPoint (-1) (-1) :| [exactPoint 1 (-1), exactPoint 1 1, exactPoint (-1) 1]))
let siteAt :: Int -> Point -> ExactRational -> Either (PowerDiagramError Int) (PowerSite Int)
siteAt label position weight = powerSite label position (powerWeightFromExact weight)
direction = Map.fromList [(0 :: Int, 0), (1, 4)]
firstSite <- requireRight (siteAt 0 (Point 0 0) 0)
hiddenSite <- requireRight (siteAt 1 (Point 2 0) (-4))
visibleSite <- requireRight (siteAt 1 (Point 2 0) 2)
initial <- requireRight (preparePowerMassSection window (firstSite :| [hiddenSite]) direction) >>= evaluate . force
let expireAndRecertify (parameter, updatedSites) =
( evaluatePowerMasses parameter initial
, preparePowerMassSection window updatedSites direction
)
pure (bench "certified power mass/window-contact/expiry-and-recertify-at-3-over-2"
(nf expireAndRecertify (1, firstSite :| [visibleSite])))