You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,19 @@ All notable changes to RegressionLab are documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [1.1.0] - 2026-03-01
9
+
10
+
### Changed
11
+
12
+
-**Equation lookups (Performance)**: `get_equation_format_for_function()` and `get_equation_param_names_for_function()` now use O(1) reverse-lookup dicts (`_FUNCTION_TO_EQUATION`, `_FORMAT_TO_FORMULA`) instead of scanning the entire `EQUATIONS` dict on every call. The formula lookup in `generic_fit` also uses the same O(1) dict. Affects every `fit_*` call.
13
+
-**Regex compilation (Performance)**: The ~40 regex patterns in `MATH_FUNCTION_REPLACEMENTS` are now pre-compiled at module load (`MATH_FUNCTION_REPLACEMENTS_COMPILED`). `custom_function_evaluator._prepare_formula()` uses the compiled patterns, avoiding recompilation on every custom formula evaluation.
14
+
-**Residuals reuse (Performance/Readability)**: In `generic_fit`, `(y - y_fitted) ** 2` is now computed once as `residuals_sq` and reused for both R² and RMSE calculations.
15
+
-**Formatting cleanup (Readability)**: In `fitting_utils.py`, nested `.format()` calls for parameter text replaced with direct f-strings; `merge_initial_guess` now uses `zip(computed, override)` instead of `range(len(computed))`.
16
+
-**Transform dispatch (Performance/Maintainability)**: `_apply_to_column` in `transforms.py` refactored from a ~200-line if/elif chain to a dispatch dict (`_TRANSFORM_DISPATCH`) mapping transform IDs to small handler functions. Adding a new transform now requires only writing the handler and adding one dict entry.
17
+
-**Simplified `_base.py` re-exports (Maintainability)**: `fitting/functions/_base.py` now uses standard `from module import name` imports instead of manual tuple-assignment. Reduces update points when adding new estimators or utilities.
18
+
-**Walsh-Hadamard Transform (Performance)**: Replaced the O(n²) dense matrix approach (`scipy.linalg.hadamard(n2)`) with a vectorized in-place Fast Walsh-Hadamard Transform (FWHT) using only NumPy — O(n log n) time, O(n) memory. Removed `scipy.linalg.hadamard` dependency from transforms.
19
+
-**3D plot fallback (Performance)**: The nearest-neighbor fallback in `plot_utils.py` (used when scipy is unavailable) now processes grid points in chunks, bounding peak memory to ~10M floats instead of allocating a full `(grid_size² × n_points)` distance matrix.
20
+
8
21
## [1.0.0] - 2026-02-14
9
22
10
23
### Added
@@ -180,6 +193,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
180
193
181
194
Initial 0.8.x release. See repository history and documentation for features and changes prior to 0.8.1.
Copy file name to clipboardExpand all lines: docs/customization.md
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,15 +67,17 @@ def generic_fit(func, x, y, uy=None, p0=None):
67
67
# Calculate fitted values
68
68
y_fitted = func(x, *popt)
69
69
70
-
# Calculate R²
71
-
ss_res = np.sum((y - y_fitted) **2)
70
+
# Calculate R² and RMSE (residuals computed once and reused)
71
+
residuals_sq = (y - y_fitted) **2
72
+
ss_res = np.sum(residuals_sq)
72
73
ss_tot = np.sum((y - np.mean(y)) **2)
73
74
r_squared =1- (ss_res / ss_tot)
74
-
75
+
rmse =float(np.sqrt(np.mean(residuals_sq)))
76
+
75
77
return popt, y_fitted, r_squared
76
78
```
77
79
78
-
This function is the **single point of control** for the optimization backend.
80
+
This function is the **single point of control** for the optimization backend. Equation lookups (`get_equation_format_for_function`, `get_equation_param_names_for_function`) use O(1) reverse dicts built at module load, so there is no performance cost when resolving equations by function name.
-**Return**: Your wrapper can return `(text, y_fitted, equation)` or the full 4-tuple from `generic_fit`: `(text, y_fitted, equation, fit_info)`. R² is included in `text`. Callers (e.g. Streamlit) use the first three values.
102
102
103
-
Use `get_equation_param_names_for_function('fit_<name>')` and `get_equation_format_for_function('fit_<name>')` so parameter names and the equation format live only in `equations.yaml`. That way you define them once in config.
103
+
Use `get_equation_param_names_for_function('fit_<name>')` and `get_equation_format_for_function('fit_<name>')` so parameter names and the equation format live only in `equations.yaml`. That way you define them once in config. These lookups are O(1) via pre-built reverse dicts (`_FUNCTION_TO_EQUATION` in `constants.py`).
0 commit comments