Changes in version 2.0.0 (2026-03-19) Breaking Changes - All solvers now return solver_result objects (class vector: c("solver_result", "mle_fit_numerical", "mle_fit")). Per-solver subclasses (mle_gradient_ascent, mle_bfgs, etc.) are removed. - Solver metadata moved to $solver_info nested list. Access solver name via result$solver_info$name, iterations via result$solver_info$iterations, trace data via result$solver_info$trace_data. - Composition metadata moved to $solver_info$composition. Access strategy via result$solver_info$composition$strategy, chain results via result$solver_info$composition$chain, etc. - Solver-specific diagnostics moved to $solver_info$diagnostics (e.g., $diagnostics$final_temp for sim_anneal, $diagnostics$cycles for coordinate_ascent). - is_mle_numerical() replaced by is_solver_result(). - compose() removed from exports — use chain() instead (superset with early_stop). - mle_problem() is now an S3 generic dispatching on its first argument. - Requires algebraic.mle >= 2.0.0. New Features - mle_problem.likelihood_model(): Bridge to the likelihood.model package. Pass a likelihood_model object and data to auto-extract loglik/score/fisher. - fisher_scoring() now correctly reports "fisher_scoring" as solver name (previously reported "newton_raphson"). - coordinate_ascent() gains learning_rate parameter for non-line-search mode. - grid_search() now errors if the grid would exceed 1 million points. - race() warns when parallel = TRUE but future is not installed. Bug Fixes - sim_anneal() now correctly reports convergence based on temperature cooling (previously always reported converged = TRUE). - coordinate_ascent() non-line-search mode uses scaled gradient step instead of hardcoded 0.1 step. - print.mle_trace_data() no longer accesses vector elements before null-check. - print.mle_problem() correctly detects default (unconstrained) problems. Changes in version 1.0.0 CRAN Release - First CRAN release - Moved algebraic.mle from Imports to Depends so that generics (params(), se(), confint(), loglik_val(), aic(), nparams(), vcov()) are available immediately when the package is loaded - Converted \dontrun{} to \donttest{} in examples (CRAN policy) - Added hypothesize to Suggests - Added CI via GitHub Actions Changes in version 0.2.0 New Features - Simulated annealing solver (sim_anneal()) - Coordinate ascent solver (coordinate_ascent()) - race() function for explicit parallel solver racing with future support - chain() function for sequential composition with early stopping - Convergence diagnostics: plot.mle_numerical() and optimization_path() - Derivative caching in mle_problem() to avoid redundant computation - Verbose/progress output via cli for long-running solvers - Trace aggregation with merge_traces() across composed solvers Documentation - Four vignettes: getting-started, theory-and-intuition, case-studies, strategy-design - pkgdown site at https://queelius.github.io/compositional.mle/ Bug Fixes - Fixed R CMD check issues (missing imports, example errors) - Fixed LICENSE copyright holder Changes in version 0.1.0 - Initial release with core solver factories and composition operators - Solvers: gradient_ascent, newton_raphson, bfgs, lbfgsb, nelder_mead, grid_search, random_search - Composition: %>>% (sequential), %|% (racing), with_restarts(), unless_converged() - Problem specification with mle_problem() and constraint support - Tracing system for optimization iteration recording - Penalty/regularization transformers (L1, L2, elastic net)