probability-polynomial 1.0.0.1 → 1.0.1.0
raw patch · 9 files changed
+153/−42 lines, 9 filesdep ~QuickChecknew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: QuickCheck
API changes (from Hackage documentation)
+ Numeric.Measure.Discrete: after :: (Ord a, Num a) => a -> Discrete a -> Discrete a
+ Numeric.Measure.Discrete: beforeOrAt :: (Ord a, Num a) => a -> Discrete a -> Discrete a
+ Numeric.Measure.Finite.Mixed: after :: (Ord a, Num a) => a -> Measure a -> Measure a
+ Numeric.Measure.Finite.Mixed: beforeOrAt :: (Ord a, Num a) => a -> Measure a -> Measure a
- Numeric.Polynomial.Simple: euclidianDivision :: forall a. (Fractional a, Eq a, Ord a) => Poly a -> Poly a -> (Poly a, Poly a)
+ Numeric.Polynomial.Simple: euclidianDivision :: (Fractional a, Eq a, Ord a) => Poly a -> Poly a -> (Poly a, Poly a)
- Numeric.Polynomial.Simple: translate :: forall a. (Fractional a, Eq a, Num a) => a -> Poly a -> Poly a
+ Numeric.Polynomial.Simple: translate :: (Fractional a, Eq a, Num a) => a -> Poly a -> Poly a
Files
- CHANGELOG.md +16/−6
- probability-polynomial.cabal +21/−31
- src/Numeric/Function/Piecewise.hs +7/−2
- src/Numeric/Measure/Discrete.hs +16/−0
- src/Numeric/Measure/Finite/Mixed.hs +36/−1
- src/Numeric/Polynomial/Simple.hs +2/−2
- test/Numeric/Function/PiecewiseSpec.hs +4/−0
- test/Numeric/Measure/DiscreteSpec.hs +11/−0
- test/Numeric/Measure/Finite/MixedSpec.hs +40/−0
CHANGELOG.md view
@@ -1,14 +1,24 @@ # Revision history for `probability-polynomial` +## 1.0.1.0 — 2025-09-26++### Added++* Add `beforeOrAt` and `after` for mixed measures+* Add `beforeOrAt` and `after` for discrete measures+* Add `instance Functor Moments`+* Allow `containers-0.8`, `QuickCheck-2.16`++## 1.0.0.1 — 2025-01-17++### Fixed ++* Improved implementation of `findRoot` to handle repeated roots+* Added test to check repeated roots handled correctly+ ## 1.0.0.0 — 2024-12-23 * Initial release * Polynomials * Finite, signed measures on the number line * Probability measures--## 1.0.0.1 - 2025-01-17--* Minor version update- * Improved inmplementation of findRoot to handle repeated roots- * Added test to check repeated roots handled correctly
probability-polynomial.cabal view
@@ -2,10 +2,10 @@ name: probability-polynomial -- Package Versioning Policy: https://pvp.haskell.org--- PVP summary: +-+------- breaking API changes--- | | +----- non-breaking API additions--- | | | +--- code changes with no API change-version: 1.0.0.1+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 1.0.1.0 synopsis: Probability distributions via piecewise polynomials description: Package for manipulating finite probability distributions.@@ -20,37 +20,32 @@ homepage: https://github.com/DeltaQ-SD/deltaq license: BSD-3-Clause license-file: LICENSE-copyright: Predictable Network Solutions Ltd., 2020-2024+copyright: Predictable Network Solutions Ltd., 2020-2025 author: Peter W. Thompson, Heinrich Apfelmus maintainer: peter.thompson@pnsol.com- extra-doc-files: CHANGELOG.md README.md -tested-with:- , GHC == 9.10.1- , GHC == 9.6.6- , GHC == 8.10.7+tested-with: GHC ==8.10.7 || ==9.6.7 || ==9.10.3 common warnings ghc-options: -Wall source-repository head type: git- location: git://github.com/DeltaQ-SD/deltaq.git+ location: https://github.com/DeltaQ-SD/deltaq.git subdir: lib/probability-polynomial library import: warnings hs-source-dirs: src default-language: Haskell2010- build-depends:- , base >= 4.14.3.0 && < 5- , containers >= 0.6 && < 0.8- , deepseq >= 1.4.4.0 && < 1.6- , exact-combinatorics >= 0.2 && < 0.3+ , base >=4.14.3.0 && <5+ , containers >=0.6 && <0.9+ , deepseq >=1.4.4.0 && <1.6+ , exact-combinatorics >=0.2 && <0.3 exposed-modules: Data.Function.Class@@ -62,23 +57,19 @@ Numeric.Probability.Moments test-suite test- import: warnings- type: exitcode-stdio-1.0- hs-source-dirs: test- default-language: Haskell2010-+ import: warnings+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ default-language: Haskell2010 build-tool-depends: hspec-discover:hspec-discover- build-depends: , base , containers+ , hspec >=2.11.0 && <2.12 , probability-polynomial- , hspec >= 2.11.0 && < 2.12- , QuickCheck >= 2.14 && < 2.16- - main-is:- Spec.hs- + , QuickCheck >=2.14 && <2.17++ main-is: Spec.hs other-modules: Numeric.Function.PiecewiseSpec Numeric.Measure.DiscreteSpec@@ -92,9 +83,8 @@ hs-source-dirs: benchmark default-language: Haskell2010 main-is: Main.hs- build-depends: , base- , probability-polynomial- , criterion >= 1.6 && < 1.7+ , criterion >=1.6 && <1.7 , deepseq+ , probability-polynomial
src/Numeric/Function/Piecewise.hs view
@@ -111,12 +111,17 @@ -- | @fromInterval (x1,x2) o@ creates a 'Piecewise' function -- from a single function @o@ by restricting it to the--- to half-open interval @x1 <= x < x2@.+-- to half-open interval @y1 <= x < y2@+-- where @y1 = min x1 x2@ and @y2 = max x1 x2@.+-- -- The result is zero outside this interval.+-- As a special case, the result is 'zero' when @x1 == x2@. fromInterval :: (Ord (Fun.Domain o), Num o) => (Fun.Domain o, Fun.Domain o) -> o -> Piecewise o-fromInterval (x,y) o = Pieces [Piece start o, Piece end 0]+fromInterval (x,y) o+ | start < end = Pieces [Piece start o, Piece end 0]+ | otherwise = zero where start = min x y end = max x y
src/Numeric/Measure/Discrete.hs view
@@ -20,6 +20,8 @@ , add , scale , translate+ , beforeOrAt+ , after , convolve ) where @@ -129,6 +131,20 @@ -- > = eval (distribution m) (x - y) translate :: (Ord a, Num a) => a -> Discrete a -> Discrete a translate y (Discrete m) = Discrete $ Map.mapKeys (y +) m++-- | Intersect a measure with the interval @(-∞, x]@.+--+-- The measure of the interval @(-∞, t]@ with @beforeOrAt x m@ is the same as+-- the measure of the intersection @(-∞, t] ∩ (-∞, x]@ with @m@. +beforeOrAt :: (Ord a, Num a) => a -> Discrete a -> Discrete a+beforeOrAt x (Discrete m) = Discrete $ Map.filterWithKey (\t _ -> t <= x) m++-- | Intersect a measure with the interval @(x, +∞)@.+--+-- The measure of the interval @(-∞, t]@ with @after x m@ is the same as+-- the measure of the intersection @(-∞, t] ∩ (x, +∞)@ with @m@. +after :: (Ord a, Num a) => a -> Discrete a -> Discrete a+after x (Discrete m) = Discrete $ Map.filterWithKey (\t _ -> x < t) m -- | Additive convolution of two measures. --
src/Numeric/Measure/Finite/Mixed.hs view
@@ -24,6 +24,8 @@ , add , scale , translate+ , beforeOrAt+ , after , convolve ) where @@ -41,6 +43,7 @@ ) import Numeric.Polynomial.Simple ( Poly+ , constant ) import qualified Data.Map.Strict as Map@@ -80,7 +83,7 @@ | isEventuallyConstant pieces = Just $ Measure $ trim pieces | otherwise = Nothing --- | Test whether a piecewise polynomial is consant as x -> ∞.+-- | Test whether a piecewise polynomial is constant as x -> ∞. isEventuallyConstant :: (Ord a, Num a) => Piecewise (Poly a) -> Bool isEventuallyConstant pieces | null xpolys = True@@ -192,6 +195,38 @@ translate :: (Ord a, Num a, Fractional a) => a -> Measure a -> Measure a translate y (Measure m) = Measure $ Piecewise.translateWith Poly.translate y m++{-----------------------------------------------------------------------------+ Operations+ Intersection+------------------------------------------------------------------------------}+-- | Intersect a measure with the interval @(-∞, x]@.+--+-- The measure of the interval @(-∞, t]@ with @beforeOrAt x m@ is the same as+-- the measure of the intersection @(-∞, t] ∩ (-∞, x]@ with @m@. +beforeOrAt :: (Ord a, Num a) => a -> Measure a -> Measure a+beforeOrAt x (Measure m) =+ case Piecewise.toAscPieces m of+ [] -> zero+ ((x1, _):_) ->+ let indicatorToX = Piecewise.fromInterval (x1,x) 1+ scaledIndicatorAfterX v =+ Piecewise.fromAscPieces [(x, constant v)]+ in Measure+ $ trim+ $ indicatorToX * m + scaledIndicatorAfterX (eval m x)++-- | Intersect a measure with the interval @(x, +∞)@.+--+-- The measure of the interval @(-∞, t]@ with @after x m@ is the same as+-- the measure of the intersection @(-∞, t] ∩ (x, +∞)@ with @m@. +after :: (Ord a, Num a) => a -> Measure a -> Measure a+after x (Measure m) =+ let scaledIndicatorAfterX v = Piecewise.fromAscPieces [(x, constant v)]+ in Measure+ $ trim+ $ scaledIndicatorAfterX 1 * m+ - scaledIndicatorAfterX (eval m x) {----------------------------------------------------------------------------- Operations
src/Numeric/Polynomial/Simple.hs view
@@ -677,8 +677,8 @@ d1 = (diffP `divide` g0) - differentiate c1 divide x y = fst (euclidianDivision x y) go c d- | c == constant 1 = [] -- terminate the recursion- | a' == constant 1 = go c' d' -- skip over the constant polynomial+ | degree c == 0 = [] -- terminate the recursion+ | degree a' == 0 = go c' d' -- skip over constant polynomials | otherwise = a' : go c' d' where a' = gcdPoly c d
test/Numeric/Function/PiecewiseSpec.hs view
@@ -67,6 +67,10 @@ member z (intersect x y) === (member z x && member z y) describe "fromInterval" $ do+ it "zero" $ property $+ \(x :: Rational) (o :: Constant) ->+ eval (fromInterval (x, x) o) x === 0+ it "intervals" $ property $ \(x :: Rational) (Positive d) (o :: Constant) -> let y = x + d
test/Numeric/Measure/DiscreteSpec.hs view
@@ -17,6 +17,8 @@ import Numeric.Measure.Discrete ( Discrete , add+ , after+ , beforeOrAt , convolve , dirac , distribution@@ -101,6 +103,15 @@ \(m :: Discrete Rational) y x -> eval (distribution (translate y m)) x === eval (distribution m) (x - y)++ describe "beforeOrAt and after" $ do+ it "add beforeOrAt after" $ property $+ \(mx :: Discrete Rational) t ->+ add (beforeOrAt t mx) (after t mx) === mx++ it "eval distribution after" $ property $+ \(mx :: Discrete Rational) t ->+ eval (distribution (after t mx)) t === 0 describe "convolve" $ do it "dirac" $ property $
test/Numeric/Measure/Finite/MixedSpec.hs view
@@ -21,6 +21,8 @@ import Numeric.Measure.Finite.Mixed ( Measure , add+ , after+ , beforeOrAt , convolve , dirac , distribution@@ -195,6 +197,44 @@ let f = Poly.fromCoefficients [0,1] in integrate f (scale a mx) === a * integrate f mx++ describe "beforeOrAt and after" $ do+ it "add beforeOrAt after" $ property $+ \(mx :: Measure Rational) t ->+ add (beforeOrAt t mx) (after t mx) === mx++ it "support after" $ property $+ \(mx :: Measure Rational) t ->+ let isAfterOrAt Nothing = True+ isAfterOrAt (Just (x1, _)) = x1 >= t+ in isAfterOrAt (support (after t mx))++ it "support beforeOrAt" $ property $+ \(mx :: Measure Rational) t ->+ let isBeforeOrAt Nothing = True+ isBeforeOrAt (Just (_, x2)) = x2 <= t+ in isBeforeOrAt (support (beforeOrAt t mx))++ it "eval distribution after" $ property $+ \(mx :: Measure Rational) t ->+ eval (distribution (after t mx)) t === 0++ it "after support" $ property $+ \(mx :: Measure Rational) ->+ case support mx of+ Nothing -> property True+ Just (_, x2) ->+ cover 70 True "non-trivial" $+ after x2 mx === zero++ it "beforeOrAt support" $ property $+ \(mx :: Measure Rational) ->+ case support mx of+ Nothing -> property True+ Just (x1, _) ->+ let value1 = eval (distribution mx) x1+ in cover 70 True "non-trivial" $+ beforeOrAt x1 mx === scale value1 (dirac x1) {----------------------------------------------------------------------------- Random generators