packages feed

srtree 3.0.0.5 → 3.0.0.6

raw patch · 6 files changed

+109/−51 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Algorithm.SRTree.AD.CompiledAD: [ctMaxParam] :: CompiledTree -> Int
+ Algorithm.SRTree.AD.Unboxed: [ctMaxParam] :: CompiledTree -> Int
+ Algorithm.SRTree.ConfidenceIntervals: distExtraParams :: Distribution -> Int
+ Algorithm.SRTree.ConfidenceIntervals: maxParamOf :: Fix SRTree -> Int
- Algorithm.SRTree.AD.CompiledAD: CompiledTree :: Vector (SRTree Int) -> Int -> Vector Bool -> Vector Double -> Vector Int -> Int -> Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector (Vector Double) -> CompiledTree
+ Algorithm.SRTree.AD.CompiledAD: CompiledTree :: Vector (SRTree Int) -> Int -> Vector Bool -> Vector Double -> Vector Int -> Int -> Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector (Vector Double) -> Int -> CompiledTree
- Algorithm.SRTree.AD.Unboxed: CompiledTree :: Vector (SRTree Int) -> Int -> Vector Bool -> Vector Double -> Vector Int -> Int -> Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector (Vector Double) -> CompiledTree
+ Algorithm.SRTree.AD.Unboxed: CompiledTree :: Vector (SRTree Int) -> Int -> Vector Bool -> Vector Double -> Vector Int -> Int -> Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector Int -> Vector (Vector Double) -> Int -> CompiledTree

Files

ChangeLog.md view
@@ -1,5 +1,20 @@ # Changelog for srtree +## 3.0.0.6++- **AD theta-length guards** (`Algorithm.SRTree.AD.CompiledAD` ++  `Algorithm.SRTree.AD.Unboxed`): `CompiledTree` gains `ctMaxParam` and+  `evalGrad`/`evalGradVec`/`evalLossVec` fail soft with NaN when the theta+  vector is shorter than the tree's largest `Param` index, instead of writing+  out of bounds (which corrupted the heap).+- **Param bounds guards** (`Data.SRTree.Eval`): `compile`, `compileLoss` and+  `evalTree` return NaN for a `Param` index beyond the theta length.+- **Confidence intervals** (`Algorithm.SRTree.ConfidenceIntervals`): added+  `maxParamOf` and `distExtraParams`; `getAllProfiles` now validates theta+  against the tree's max param plus the distribution's extra parameters, and+  supports 1-parameter models (previously required >= 2). Removed a leftover+  `Debug.Trace`.+ ## 3.0.0.5  - **Fix NLopt re-entered thousands of times per fit** (`NonlinearOpt` + `SearchSR`):
src/Algorithm/SRTree/AD/CompiledAD.hs view
@@ -36,4 +36,5 @@   , ctFcode  :: !(VU.Vector Int)                     -- id -> Uni: fromEnum Function   , ctOcode  :: !(VU.Vector Int)                     -- id -> Bin: fromEnum Op   , ctVars   :: !(VB.Vector (VU.Vector Double))      -- leaf source columns xss ++ [y, yErr] (referenced, not copied)+  , ctMaxParam :: !Int                               -- largest Param index in the tree (-1 if none)   }
src/Algorithm/SRTree/AD/Unboxed.hs view
@@ -69,8 +69,21 @@ compileTree :: [VU.Vector Double] -> VU.Vector Double -> Maybe (VU.Vector Double) -> Fix SRTree -> CompiledTree compileTree xss ys mYErr tree =     CompiledTree { ctNodes = nodes, ctRoot = root, ctDyn = dynArr, ctStatic = staticArr, ctStaticBase = staticBaseArr, ctM = m, ctNPred = root + 1-                 , ctKind = kindArr, ctArg = argArr, ctArg2 = arg2Arr, ctFcode = fcodeArr, ctOcode = ocodeArr, ctVars = vars }+                 , ctKind = kindArr, ctArg = argArr, ctArg2 = arg2Arr, ctFcode = fcodeArr, ctOcode = ocodeArr, ctVars = vars+                 , ctMaxParam = maxParam }   where+    -- Largest Param index referenced by the tree (-1 when there is none).+    -- The evaluation kernels index theta by Param index, so a theta shorter+    -- than maxParam + 1 would read/write out of bounds; the eval entry points+    -- use this value to fail soft (NaN) instead of corrupting memory.+    maxParam = maximum (negate 1 : cata algP tree)+      where algP :: SRTree [Int] -> [Int]+            algP (Param ix)   = [ix]+            algP (Var _)      = []+            algP (Const _)    = []+            algP (Y _)        = []+            algP (Uni _ t)    = t+            algP (Bin _ l r)  = l <> r     -- yErr is only defined when mYErr is present (a tree referencing Var -2     -- always pairs with mYErr = Just e, see the likelihood loss wrappers). The     -- ctVars list must stay well-defined for every column even when mYErr is@@ -304,7 +317,11 @@ -- arrays) while staying in plain ST: allocation drops from O(nodes * m) -- to O(nodes + params), and the tight inner loops are all unboxed. evalGrad :: CompiledTree -> V.Vector Double -> (Double, V.Vector Double)-evalGrad ct theta = runST $ do+evalGrad ct theta+  -- theta shorter than the largest Param index would make the kernel+  -- read/write out of bounds; fail soft with NaNs (NLopt rejects NaN).+  | ctMaxParam ct >= V.length theta = (0/0, V.replicate (V.length theta) (0/0))+  | otherwise = runST $ do     fwd   <- VUM.new (root + 1)   -- node id -> forward value, current row     adj   <- VUM.new (root + 1)   -- node id -> adjoint (dL/dnode), current row     gradM <- VUM.replicate p 0    -- accumulated per-parameter gradient@@ -396,7 +413,11 @@ -- trades the O(nodes + params) scratch of the row-fused version for the -- O(nodes * m) fwd/adj columns of the massiv-style whole-column kernel. evalGradVec :: CompiledTree -> V.Vector Double -> (Double, V.Vector Double)-evalGradVec ct theta = runST $ do+evalGradVec ct theta+  -- see the note in `evalGrad`: a theta shorter than the tree's largest+  -- Param index must never reach the unsafe kernel accesses.+  | ctMaxParam ct >= V.length theta = (0/0, V.replicate (V.length theta) (0/0))+  | otherwise = runST $ do     -- Per-chunk buffers of O(stride * chunk) instead of one O(stride * m)     -- allocation per call: the fwd/adj matrices are streamed one chunk of     -- `chunk` rows at a time, so the per-call allocation drops ~m/chunk x@@ -505,7 +526,9 @@ -- but it cuts the per-call allocation ~30x so this is cheap enough for the -- val-eval hot path that runs once per explored expression. evalLossVec :: CompiledTree -> V.Vector Double -> Double-evalLossVec ct theta = runST $ do+evalLossVec ct theta+  | ctMaxParam ct >= V.length theta = 0/0+  | otherwise = runST $ do     buf <- VUM.new (stride * chunk)     go buf 0 0   where
src/Algorithm/SRTree/ConfidenceIntervals.hs view
@@ -31,7 +31,6 @@ import System.IO.Unsafe ( unsafePerformIO ) import Control.Monad.Catch ( catch, SomeException ) import Control.Exception ( evaluate )-import Debug.Trace ( trace )  -- | profile likelihood algorithms: Bates (classical), ODE (faster), Constrained (fastest) -- The Constrained approach returns only the endpoints.@@ -196,6 +195,26 @@     covMat = toRowMajor cov     stdErr = U.generate k (\ix -> sqrt $ abs (covMat U.! (ix * k + ix))) +-- | Largest `Param` index of a tree (-1 if none). Theta vectors are indexed+-- by `Param` index, so profiling requires `U.length theta > maxParamOf tree`,+-- plus the extra parameters appended by the loss (e.g. Gaussian's log-noise).+maxParamOf :: Fix SRTree -> Int+maxParamOf = maximum . (negate 1 :) . cata alg+  where alg :: SRTree [Int] -> [Int]+        alg (Param ix)  = [ix]+        alg (Var _)     = []+        alg (Const _)   = []+        alg (Y _)       = []+        alg (Uni _ t)   = t+        alg (Bin _ l r) = l <> r++-- | Extra parameters appended by 'buildDistLoss' for a distribution+-- (Gaussian: log-noise; ROXY: 3 auxiliary parameters).+distExtraParams :: Distribution -> Int+distExtraParams Gaussian = 1+distExtraParams ROXY     = 3+distExtraParams _        = 0+ -- | Calculate the profile likelihood of every parameter. -- restartLimit bounds recursive restarts when getProfileODE finds a better point mid-profile. -- For Bates, getProfile handles restarts internally and never returns Left.@@ -203,7 +222,8 @@ getAllProfiles ptype et theta stdErr estCIs alpha   -- Defensive: if theta is too short for the EvalTree's distribution,   -- return empty profiles instead of crashing (e.g. MSE loss with Gaussian dist)-  | U.length theta < 2 = pure []+  | U.null theta = pure []+  | U.length theta < maxParamOf (ctTree et) + 1 + distExtraParams (ctDist et) = pure []   | otherwise = go 0 et theta stdErr estCIs   where     restartLimit = 5 :: Int@@ -475,7 +495,6 @@     cols = getCol ix thetas     rawPairs = sortOnFirst taus cols     monoPairs = enforceMonotonicTau rawPairs-    _ = trace ("createSplines: raw=" ++ show (length rawPairs) ++ " mono=" ++ show (length monoPairs) ++ " head=" ++ show (take 3 monoPairs) ++ " last=" ++ show (reverse $ take 3 $ reverse monoPairs)) ()     tau2theta = genSplineFun monoPairs     theta2tau = genSplineFun $ enforceMonotonicTheta optTh $ sortOnFirst cols taus 
src/Data/SRTree/Eval.hs view
@@ -163,7 +163,7 @@     alg (Var (-1)) = Static y     alg (Var (-2)) = Static yErr     alg (Var i)    = Static (dataset !! i)-    alg (Param i)  = Dynamic (\th !idx -> th `V.unsafeIndex` i)+    alg (Param i)  = Dynamic (\th !idx -> if i < V.length th then th `V.unsafeIndex` i else 0/0)      -- 2. Univariate Functions     alg (Uni f (Scl c))     = Scl (evalFun f c)@@ -215,7 +215,7 @@     alg (Const c) = Scl c     alg (Var i)   = Static (dataset !! i)     -- Look at this! No more V.replicate. It just fetches the scalar directly.-    alg (Param i) = Dynamic (\th !idx -> th `V.unsafeIndex` i)+    alg (Param i) = Dynamic (\th !idx -> if i < V.length th then th `V.unsafeIndex` i else 0/0)     alg (Y i)     = undefined -- this shouldn't be called      -- 2. Univariate Functions@@ -261,7 +261,7 @@ evalTree xss params = cata $      \case         Var ix     -> xss !! ix-       Param ix   -> replicateAs xss $ params V.! ix+       Param ix   -> replicateAs xss $ if ix < V.length params then params V.! ix else 0/0        Const c    -> replicateAs xss c        Y _        -> undefined        Uni g t    -> evalFun g t
srtree.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:               srtree-version:            3.0.0.5+version:            3.0.0.6 synopsis:           A general library to work with Symbolic Regression expression trees. description:        A Symbolic Regression Tree data structure to work with mathematical expressions with support to first order derivative and simplification; license:            BSD3@@ -60,28 +60,28 @@     other-modules:           Paths_srtree     build-depends:-          async >=2.2 && <2.3+          async ==2.2.*         , attoparsec >=0.14.4 && <0.15         , attoparsec-expr >=0.1.1.2 && <0.2         , base >=4.19 && <5-        , binary >=0.8 && <0.9+        , binary ==0.8.*         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9         , deepseq >=1.4 && <1.6-        , directory >=1.3 && <1.4-        , exceptions >=0.10 && <0.11+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , hashable >=1.4 && <1.6-        , ieee754 >=0.8 && <0.9+        , ieee754 ==0.8.*         , lens >=5.0 && <6         , mtl >=2.2 && <2.4-        ,           parallel >=3.2 && <3.4+        , parallel >=3.2 && <3.4         , primitive >=0.8 && <0.10         , random >=1.2 && <1.4         , split >=0.2.5 && <0.3         , statistics >=0.15 && <0.17         , time >=1.9 && <1.15-        , unordered-containers >=0.2 && <0.3+        , unordered-containers ==0.2.*         , vector >=0.12 && <0.14         , zlib >=0.6.3 && <0.8     hs-source-dirs:@@ -99,29 +99,29 @@           apps/Bench     ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2 -fllvm -pgmlo opt-20 -pgmlc llc-20 -optlo-O3 -optlc-mcpu=native -mavx2 -mfma -fspec-constr -fmax-simplifier-iterations=20 -fexpose-all-unfoldings     build-depends:-          async >=2.2 && <2.3+          async ==2.2.*         , attoparsec >=0.14.4 && <0.15         , attoparsec-expr >=0.1.1.2 && <0.2         , base >=4.19 && <5-        , binary >=0.8 && <0.9+        , binary ==0.8.*         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9         , criterion >=1.5 && <2         , deepseq >=1.4 && <1.6-        , directory >=1.3 && <1.4-        , exceptions >=0.10 && <0.11+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , hashable >=1.4 && <1.6-        , ieee754 >=0.8 && <0.9+        , ieee754 ==0.8.*         , lens >=5.0 && <6         , mtl >=2.2 && <2.4-        ,           parallel >=3.2 && <3.4+        , parallel >=3.2 && <3.4         , primitive >=0.8 && <0.10         , random >=1.2 && <1.4         , split >=0.2.5 && <0.3         , srtree         , statistics >=0.15 && <0.17-        , unordered-containers >=0.2 && <0.3+        , unordered-containers ==0.2.*         , vector >=0.12 && <0.14         , zlib >=0.6.3 && <0.8     default-language: Haskell2010@@ -134,29 +134,29 @@           apps/BenchEqSat     ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2     build-depends:-          async >=2.2 && <2.3+          async ==2.2.*         , attoparsec >=0.14.4 && <0.15         , attoparsec-expr >=0.1.1.2 && <0.2         , base >=4.19 && <5-        , binary >=0.8 && <0.9+        , binary ==0.8.*         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9         , criterion >=1.5 && <2         , deepseq >=1.4 && <1.6-        , directory >=1.3 && <1.4-        , exceptions >=0.10 && <0.11+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , hashable >=1.4 && <1.6-        , ieee754 >=0.8 && <0.9+        , ieee754 ==0.8.*         , lens >=5.0 && <6         , mtl >=2.2 && <2.4-        ,           parallel >=3.2 && <3.4+        , parallel >=3.2 && <3.4         , primitive >=0.8 && <0.10         , random >=1.2 && <1.4         , split >=0.2.5 && <0.3         , srtree         , statistics >=0.15 && <0.17-        , unordered-containers >=0.2 && <0.3+        , unordered-containers ==0.2.*         , vector >=0.12 && <0.14         , zlib >=0.6.3 && <0.8     default-language: Haskell2010@@ -169,29 +169,29 @@           apps/Report     ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2     build-depends:-          async >=2.2 && <2.3+          async ==2.2.*         , attoparsec >=0.14.4 && <0.15         , attoparsec-expr >=0.1.1.2 && <0.2         , base >=4.19 && <5-        , binary >=0.8 && <0.9+        , binary ==0.8.*         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9         , deepseq >=1.4 && <1.6-        , directory >=1.3 && <1.4-        , exceptions >=0.10 && <0.11+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , hashable >=1.4 && <1.6-        , ieee754 >=0.8 && <0.9+        , ieee754 ==0.8.*         , lens >=5.0 && <6         , mtl >=2.2 && <2.4         , optparse-applicative >=0.16 && <0.20-        ,           parallel >=3.2 && <3.4+        , parallel >=3.2 && <3.4         , primitive >=0.8 && <0.10         , random >=1.2 && <1.4         , split >=0.2.5 && <0.3         , srtree         , statistics >=0.15 && <0.17-        , unordered-containers >=0.2 && <0.3+        , unordered-containers ==0.2.*         , vector >=0.12 && <0.14         , zlib >=0.6.3 && <0.8     default-language: Haskell2010@@ -205,14 +205,14 @@     ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2     build-depends:           base >=4.19 && <5-        , srtree         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9-        , vector >=0.12 && <0.14-        , exceptions >=0.10 && <0.11-        , directory >=1.3 && <1.4+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , random >=1.2 && <1.4+        , srtree+        , vector >=0.12 && <0.14     default-language: Haskell2010  test-suite srtree-test@@ -227,29 +227,29 @@           test     ghc-options: -threaded -rtsopts -with-rtsopts=-N     build-depends:-          HUnit >=1.6 && <1.7-        , async >=2.2 && <2.3+          HUnit ==1.6.*+        , async ==2.2.*         , attoparsec >=0.14.4 && <0.15         , attoparsec-expr >=0.1.1.2 && <0.2         , base >=4.19 && <5-        , binary >=0.8 && <0.9+        , binary ==0.8.*         , bytestring >=0.11 && <0.13         , containers >=0.6.7 && <0.9         , deepseq >=1.4 && <1.6-        , directory >=1.3 && <1.4-        , exceptions >=0.10 && <0.11+        , directory ==1.3.*+        , exceptions ==0.10.*         , filepath >=1.4.0.0 && <1.6         , hashable >=1.4 && <1.6-        , ieee754 >=0.8 && <0.9+        , ieee754 ==0.8.*         , lens >=5.0 && <6         , mtl >=2.2 && <2.4-        ,           parallel >=3.2 && <3.4+        , parallel >=3.2 && <3.4         , primitive >=0.8 && <0.10         , random >=1.2 && <1.4         , split >=0.2.5 && <0.3         , srtree         , statistics >=0.15 && <0.17-        , unordered-containers >=0.2 && <0.3+        , unordered-containers ==0.2.*         , vector >=0.12 && <0.14         , zlib >=0.6.3 && <0.8     default-language: Haskell2010