packages feed

srtree 3.0.0.4 → 3.0.0.5

raw patch · 4 files changed

+26/−8 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,5 +1,19 @@ # Changelog for srtree +## 3.0.0.5++- **Fix NLopt re-entered thousands of times per fit** (`NonlinearOpt` + `SearchSR`):+  - `minimizeNLLWith` no longer `{-# INLINE #-}` and forces the NLopt result+    once (`t_opt `seq` nEvs `seq` ...`), so the optimization is not re-run at+    every use site. Previously GHC duplicated the lazy `where` thunk, re-entering+    NLopt ~tens of thousands of times for a single fit of expressions with a+    parameter in a division/log denominator (e.g. `t1/(x0+t1)`).+  - `fitnessFun` now `DeepSeq.force`s the `minimizeNLL'` result, so the parallel+    fit's forcing of both the fitness and the theta does not re-trigger the+    unshared optimization.+  - Effect: previously-hanging eggp fits (e.g. `gen=6, nPop=30`) now complete in+    ~1-9 s.+ ## 3.0.0.4  - **Export `createLoss`**: expose compiled loss function for external use
src/Algorithm/EqSat/SearchSR.hs view
@@ -122,7 +122,10 @@     else (val, theta)   where     nParams       = countParamsUniq tree + if loss == NLL ROXY then 3 else if loss == NLL Gaussian then 1 else 0-    (theta, lossVal, _) = minimizeNLL' VAR1 backend loss mYErr nIter x y tree thetaOrig+    -- force the NLopt result once so the parallel fit's `DeepSeq.force` of both+    -- the fitness and the theta never re-runs the optimization (which otherwise+    -- re-entered NLopt thousands of times for degenerate expressions).+    (theta, lossVal, _) = DeepSeq.force (minimizeNLL' VAR1 backend loss mYErr nIter x y tree thetaOrig)     evalF a b c   = negate $ compileLoss a (buildLoss loss (fromIntegral (V.length b)) tree) b c $ if nParams == 0 then thetaOrig else theta     -- at folds=1 the validation split is the training data itself, so the     -- train loss returned by minimizeNLL' already is the val loss; skipping
src/Algorithm/SRTree/NonlinearOpt.hs view
@@ -41,7 +41,11 @@ minimizeNLLWith funAndGrad alg niter t0   | niter == 0 = (t0, f, 0)   | n == 0     = (t0, f, 0)-  | otherwise  = (t_opt', fst (funAndGrad t_opt), nEvs)+  | otherwise  = let (t_opt, nEvs) = case minimizeLocal problem t0' of+                                        Right sol -> (solutionParams sol, nEvals sol)+                                        Left e    -> (t0', 0)+                     t_opt'        = G.convert t_opt+                 in t_opt `seq` nEvs `seq` (t_opt', fst (funAndGrad t_opt), nEvs)   where     t0'        = G.convert t0     n          = V.length t0@@ -51,11 +55,8 @@     algorithm  = alg funAndGrad (Just $ VectorStorage $ fromIntegral n)     stop       = ObjectiveRelativeTolerance 1e-6 :| [ObjectiveAbsoluteTolerance 1e-6, MaximumEvaluations (fromIntegral niter)]     problem    = LocalProblem (fromIntegral n) stop algorithm-    (t_opt, nEvs) = case minimizeLocal problem t0' of-                      Right sol -> (solutionParams sol, nEvals sol)-                      Left e    -> (t0', 0)-    t_opt'      = G.convert t_opt-{-# INLINE minimizeNLLWith #-}+-- no INLINE: inlining duplicated the lazy `where` thunk so the NLopt call was+-- re-evaluated thousands of times per fit.  -- | Compile the loss function and gradient for a tree, returning a reusable -- closure. Use this when you need to optimize the same expression with
srtree.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:               srtree-version:            3.0.0.4+version:            3.0.0.5 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