ssfortran 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ssfortran-0.1.0/.gitignore +10 -0
- ssfortran-0.1.0/CMakeLists.txt +56 -0
- ssfortran-0.1.0/LICENSE +21 -0
- ssfortran-0.1.0/PKG-INFO +137 -0
- ssfortran-0.1.0/README.md +113 -0
- ssfortran-0.1.0/THIRD_PARTY_NOTICES.md +93 -0
- ssfortran-0.1.0/fpm.toml +27 -0
- ssfortran-0.1.0/pyproject.toml +77 -0
- ssfortran-0.1.0/python/src/ssfortran/__init__.py +60 -0
- ssfortran-0.1.0/python/src/ssfortran/_lib.py +222 -0
- ssfortran-0.1.0/python/src/ssfortran/diagnostics.py +112 -0
- ssfortran-0.1.0/python/src/ssfortran/models.py +1437 -0
- ssfortran-0.1.0/python/src/ssfortran/representation.py +1347 -0
- ssfortran-0.1.0/src/statespace.f90 +27 -0
- ssfortran-0.1.0/src/statespace_arima.f90 +247 -0
- ssfortran-0.1.0/src/statespace_augmented.f90 +174 -0
- ssfortran-0.1.0/src/statespace_callback.f90 +116 -0
- ssfortran-0.1.0/src/statespace_capi.f90 +763 -0
- ssfortran-0.1.0/src/statespace_capi_extras.f90 +680 -0
- ssfortran-0.1.0/src/statespace_capi_models.f90 +941 -0
- ssfortran-0.1.0/src/statespace_collapse.f90 +95 -0
- ssfortran-0.1.0/src/statespace_components.f90 +412 -0
- ssfortran-0.1.0/src/statespace_dense.f90 +117 -0
- ssfortran-0.1.0/src/statespace_diagnostics.f90 +338 -0
- ssfortran-0.1.0/src/statespace_em.f90 +125 -0
- ssfortran-0.1.0/src/statespace_filter.f90 +1021 -0
- ssfortran-0.1.0/src/statespace_forecast.f90 +78 -0
- ssfortran-0.1.0/src/statespace_kinds.f90 +20 -0
- ssfortran-0.1.0/src/statespace_linalg.f90 +431 -0
- ssfortran-0.1.0/src/statespace_mapped.f90 +245 -0
- ssfortran-0.1.0/src/statespace_mle.f90 +451 -0
- ssfortran-0.1.0/src/statespace_model.f90 +234 -0
- ssfortran-0.1.0/src/statespace_rep.f90 +370 -0
- ssfortran-0.1.0/src/statespace_restrict.f90 +60 -0
- ssfortran-0.1.0/src/statespace_score.f90 +262 -0
- ssfortran-0.1.0/src/statespace_simsmooth.f90 +282 -0
- ssfortran-0.1.0/src/statespace_smoother.f90 +484 -0
- ssfortran-0.1.0/src/statespace_smoothing.f90 +750 -0
- ssfortran-0.1.0/src/statespace_special.f90 +158 -0
- ssfortran-0.1.0/src/statespace_sqrt.f90 +196 -0
- ssfortran-0.1.0/src/statespace_structural.f90 +922 -0
- ssfortran-0.1.0/third_party/lbfgsb/License.txt +71 -0
- ssfortran-0.1.0/third_party/lbfgsb/README.md +11 -0
- ssfortran-0.1.0/third_party/lbfgsb/fpm.toml +14 -0
- ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb.f90 +3420 -0
- ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_blas_module.F90 +284 -0
- ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_kinds_module.F90 +40 -0
- ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_linpack_module.f90 +167 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Shared library for the Python package (ssfortran) and other C callers.
|
|
2
|
+
# The Fortran-only build and the test suite use fpm (fpm.toml); this build
|
|
3
|
+
# compiles the same sources with -fPIC into libstatespace, with the bundled
|
|
4
|
+
# L-BFGS-B that fpm also uses.
|
|
5
|
+
#
|
|
6
|
+
# cmake -S . -B build/cmake -G Ninja && cmake --build build/cmake
|
|
7
|
+
#
|
|
8
|
+
# Python wheels are built through scikit-build-core (pyproject.toml).
|
|
9
|
+
cmake_minimum_required(VERSION 3.24)
|
|
10
|
+
project(statespace VERSION 0.1.0 LANGUAGES Fortran)
|
|
11
|
+
|
|
12
|
+
option(STATESPACE_OPENMP "Build fit_many with OpenMP" ON)
|
|
13
|
+
|
|
14
|
+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
15
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
16
|
+
endif()
|
|
17
|
+
|
|
18
|
+
# L-BFGS-B, bundled in third_party/lbfgsb (see its README), so the build needs
|
|
19
|
+
# no network access.
|
|
20
|
+
set(LBFGSB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/lbfgsb/src)
|
|
21
|
+
file(GLOB STATESPACE_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.f90)
|
|
22
|
+
set(LBFGSB_SOURCES
|
|
23
|
+
${LBFGSB_DIR}/lbfgsb_kinds_module.F90
|
|
24
|
+
${LBFGSB_DIR}/lbfgsb_blas_module.F90
|
|
25
|
+
${LBFGSB_DIR}/lbfgsb_linpack_module.f90
|
|
26
|
+
${LBFGSB_DIR}/lbfgsb.f90
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
add_library(statespace SHARED ${STATESPACE_SOURCES} ${LBFGSB_SOURCES})
|
|
30
|
+
set_target_properties(statespace PROPERTIES
|
|
31
|
+
POSITION_INDEPENDENT_CODE ON
|
|
32
|
+
Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules
|
|
33
|
+
)
|
|
34
|
+
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
|
35
|
+
target_compile_options(statespace PRIVATE
|
|
36
|
+
$<$<CONFIG:Release>:-O3 -funroll-loops>
|
|
37
|
+
-ffree-line-length-none
|
|
38
|
+
)
|
|
39
|
+
endif()
|
|
40
|
+
|
|
41
|
+
find_package(LAPACK REQUIRED)
|
|
42
|
+
target_link_libraries(statespace PRIVATE ${LAPACK_LIBRARIES})
|
|
43
|
+
|
|
44
|
+
if(STATESPACE_OPENMP)
|
|
45
|
+
find_package(OpenMP COMPONENTS Fortran)
|
|
46
|
+
if(OpenMP_Fortran_FOUND)
|
|
47
|
+
target_link_libraries(statespace PRIVATE OpenMP::OpenMP_Fortran)
|
|
48
|
+
endif()
|
|
49
|
+
endif()
|
|
50
|
+
|
|
51
|
+
# The wheel puts the library inside the Python package.
|
|
52
|
+
if(SKBUILD)
|
|
53
|
+
install(TARGETS statespace LIBRARY DESTINATION ssfortran RUNTIME DESTINATION ssfortran)
|
|
54
|
+
else()
|
|
55
|
+
install(TARGETS statespace)
|
|
56
|
+
endif()
|
ssfortran-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zelpuz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ssfortran-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ssfortran
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Linear Gaussian state space models (Durbin and Koopman, Part I) with a Fortran core
|
|
5
|
+
Keywords: state space,kalman filter,kalman smoother,time series,structural time series,unobserved components,durbin koopman
|
|
6
|
+
Author: zelpuz
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
10
|
+
License-File: third_party/lbfgsb/License.txt
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Fortran
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
17
|
+
Project-URL: Source, https://github.com/Zelpuz/statespace
|
|
18
|
+
Project-URL: Issues, https://github.com/Zelpuz/statespace/issues
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Provides-Extra: test
|
|
22
|
+
Requires-Dist: pytest; extra == "test"
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# statespace
|
|
26
|
+
|
|
27
|
+
Linear Gaussian state space models, following Part I of Durbin and Koopman,
|
|
28
|
+
*Time Series Analysis by State Space Methods* (2nd ed., 2012). The core is a Fortran
|
|
29
|
+
library; `ssfortran` is its Python package.
|
|
30
|
+
|
|
31
|
+
- **Filtering and smoothing:**
|
|
32
|
+
- the Kalman filter with a steady-state shortcut
|
|
33
|
+
- exact diffuse initialization, in both univariate and multivariate forms
|
|
34
|
+
- univariate treatment, including correlated and time-varying H
|
|
35
|
+
- state, disturbance, fast, classical, two-filter, fixed-point and fixed-lag smoothers
|
|
36
|
+
- augmented and square-root filters
|
|
37
|
+
- collapsing large observation vectors, and linear restrictions
|
|
38
|
+
- **Likelihood and estimation:**
|
|
39
|
+
- exact, diffuse, concentrated and marginal log likelihoods
|
|
40
|
+
- maximum likelihood with L-BFGS-B, using DK's analytic score where it applies and
|
|
41
|
+
numerical derivatives elsewhere
|
|
42
|
+
- EM for variance parameters
|
|
43
|
+
- standard errors, and the effect of parameter estimation on the smoothed states
|
|
44
|
+
- **Simulation, forecasting and diagnostics:** simulation smoothers, forecasts,
|
|
45
|
+
standardized and auxiliary residuals, and residual tests.
|
|
46
|
+
- **Built-in models (DK ch. 3):** irregular, level, trend, seasonal (dummy,
|
|
47
|
+
trigonometric, Harrison–Stevens), cycle, regression and intervention effects, ARIMA,
|
|
48
|
+
continuous-time components and splines. Components apply to one series or several
|
|
49
|
+
(SUTSE), and can load on common signals.
|
|
50
|
+
|
|
51
|
+
The documentation (user guide, examples, design notes, and Python, Fortran and C
|
|
52
|
+
references) builds with `make -C docs html`; see [docs/install.rst](docs/install.rst).
|
|
53
|
+
The illustrations of DK chapter 8 are reproduced in `example/`. Differences from
|
|
54
|
+
statsmodels' `tsa.statespace` are listed in
|
|
55
|
+
[docs/statsmodels_differences.md](docs/statsmodels_differences.md).
|
|
56
|
+
|
|
57
|
+
## Fortran
|
|
58
|
+
|
|
59
|
+
The library builds with [fpm](https://fpm.fortran-lang.org) and needs gfortran,
|
|
60
|
+
LAPACK and BLAS.
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
fpm test --profile release # the test suite
|
|
64
|
+
fpm run --profile release --example nile_mle # a model defined in Fortran
|
|
65
|
+
fpm run --profile release --example dk_8_2_seatbelt # needs data/fetch_dk_data.py first
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Models are defined by extending `ssm_model_t` (see `example/nile_mle.f90`), or
|
|
69
|
+
assembled from components with `structural_model` (see `example/dk_8_2_seatbelt.f90`).
|
|
70
|
+
`fit_many` fits independent models in parallel when built with
|
|
71
|
+
`--flag -fopenmp --link-flag -fopenmp`.
|
|
72
|
+
|
|
73
|
+
## Python
|
|
74
|
+
|
|
75
|
+
`pip` builds the shared library with CMake through scikit-build-core. It needs
|
|
76
|
+
gfortran, LAPACK and BLAS installed.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
pip install . # or: pip install .[test] && pytest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import numpy as np
|
|
84
|
+
import ssfortran as ss
|
|
85
|
+
|
|
86
|
+
y = np.loadtxt("data/nile.csv", delimiter=",", skiprows=1)[:, 1]
|
|
87
|
+
|
|
88
|
+
# Built-in components
|
|
89
|
+
mod = ss.StructuralModel(y, [ss.Irregular(), ss.Level()])
|
|
90
|
+
res = mod.fit()
|
|
91
|
+
print(res.summary())
|
|
92
|
+
smoothed = res.smooth().smoothed_state
|
|
93
|
+
|
|
94
|
+
# Matrix-level: fill the system matrices yourself
|
|
95
|
+
rep = ss.Representation(y, k_states=1)
|
|
96
|
+
rep["design"] = [[1.0]]; rep["transition"] = [[1.0]]; rep["selection"] = [[1.0]]
|
|
97
|
+
rep["obs_cov"] = [[15099.0]]; rep["state_cov"] = [[1469.1]]
|
|
98
|
+
rep.initialize_diffuse()
|
|
99
|
+
print(rep.loglike())
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Fitting results have `summary()` (estimates with z-tests and intervals, fit
|
|
103
|
+
statistics, residual tests), `fittedvalues`, `resid`, `get_forecast(steps)` with
|
|
104
|
+
`conf_int()`, `components()` and `estimation_bias()`. A `Representation` also offers:
|
|
105
|
+
- the other smoothers of DK ch. 4: fast, classical, two-filter, Whittle, fixed-point,
|
|
106
|
+
fixed-lag and updating
|
|
107
|
+
- smoothed covariances between periods, and filtering and smoothing weights
|
|
108
|
+
- the square-root and augmented filters (with the marginal likelihood)
|
|
109
|
+
- EM, collapsing, and linear state restrictions
|
|
110
|
+
- auxiliary residuals, de Jong–Penzer statistics, least squares residuals and R²_D
|
|
111
|
+
- the mean-correction and de Jong–Shephard simulation smoothers
|
|
112
|
+
|
|
113
|
+
A model with parameters can be defined in three ways:
|
|
114
|
+
|
|
115
|
+
| | How | Speed |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `StructuralModel` | built-in components | all in Fortran; works with `fit_many` |
|
|
118
|
+
| `MappedModel` | declare which matrix entries each parameter sets | all in Fortran; works with `fit_many` |
|
|
119
|
+
| `MLEModel` | subclass and write `update(params)`, as in statsmodels | calls Python for each likelihood evaluation |
|
|
120
|
+
|
|
121
|
+
For the timing comparison with statsmodels from Python, run
|
|
122
|
+
`bench/bench_python.py`. It shows 2–8× speedups for single models, and 36× for 1000
|
|
123
|
+
series with `fit_many`. `example/bench.f90` and `bench/bench_statsmodels.py` compare
|
|
124
|
+
the Fortran core directly.
|
|
125
|
+
|
|
126
|
+
To develop without installing:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
cmake -S . -B build/cmake -G Ninja && cmake --build build/cmake
|
|
130
|
+
pytest # uses python/src and build/cmake (pyproject.toml)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT (see [LICENSE](LICENSE)); third-party notices are in
|
|
136
|
+
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md), and citations in
|
|
137
|
+
[docs/references.md](docs/references.md).
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# statespace
|
|
2
|
+
|
|
3
|
+
Linear Gaussian state space models, following Part I of Durbin and Koopman,
|
|
4
|
+
*Time Series Analysis by State Space Methods* (2nd ed., 2012). The core is a Fortran
|
|
5
|
+
library; `ssfortran` is its Python package.
|
|
6
|
+
|
|
7
|
+
- **Filtering and smoothing:**
|
|
8
|
+
- the Kalman filter with a steady-state shortcut
|
|
9
|
+
- exact diffuse initialization, in both univariate and multivariate forms
|
|
10
|
+
- univariate treatment, including correlated and time-varying H
|
|
11
|
+
- state, disturbance, fast, classical, two-filter, fixed-point and fixed-lag smoothers
|
|
12
|
+
- augmented and square-root filters
|
|
13
|
+
- collapsing large observation vectors, and linear restrictions
|
|
14
|
+
- **Likelihood and estimation:**
|
|
15
|
+
- exact, diffuse, concentrated and marginal log likelihoods
|
|
16
|
+
- maximum likelihood with L-BFGS-B, using DK's analytic score where it applies and
|
|
17
|
+
numerical derivatives elsewhere
|
|
18
|
+
- EM for variance parameters
|
|
19
|
+
- standard errors, and the effect of parameter estimation on the smoothed states
|
|
20
|
+
- **Simulation, forecasting and diagnostics:** simulation smoothers, forecasts,
|
|
21
|
+
standardized and auxiliary residuals, and residual tests.
|
|
22
|
+
- **Built-in models (DK ch. 3):** irregular, level, trend, seasonal (dummy,
|
|
23
|
+
trigonometric, Harrison–Stevens), cycle, regression and intervention effects, ARIMA,
|
|
24
|
+
continuous-time components and splines. Components apply to one series or several
|
|
25
|
+
(SUTSE), and can load on common signals.
|
|
26
|
+
|
|
27
|
+
The documentation (user guide, examples, design notes, and Python, Fortran and C
|
|
28
|
+
references) builds with `make -C docs html`; see [docs/install.rst](docs/install.rst).
|
|
29
|
+
The illustrations of DK chapter 8 are reproduced in `example/`. Differences from
|
|
30
|
+
statsmodels' `tsa.statespace` are listed in
|
|
31
|
+
[docs/statsmodels_differences.md](docs/statsmodels_differences.md).
|
|
32
|
+
|
|
33
|
+
## Fortran
|
|
34
|
+
|
|
35
|
+
The library builds with [fpm](https://fpm.fortran-lang.org) and needs gfortran,
|
|
36
|
+
LAPACK and BLAS.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
fpm test --profile release # the test suite
|
|
40
|
+
fpm run --profile release --example nile_mle # a model defined in Fortran
|
|
41
|
+
fpm run --profile release --example dk_8_2_seatbelt # needs data/fetch_dk_data.py first
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Models are defined by extending `ssm_model_t` (see `example/nile_mle.f90`), or
|
|
45
|
+
assembled from components with `structural_model` (see `example/dk_8_2_seatbelt.f90`).
|
|
46
|
+
`fit_many` fits independent models in parallel when built with
|
|
47
|
+
`--flag -fopenmp --link-flag -fopenmp`.
|
|
48
|
+
|
|
49
|
+
## Python
|
|
50
|
+
|
|
51
|
+
`pip` builds the shared library with CMake through scikit-build-core. It needs
|
|
52
|
+
gfortran, LAPACK and BLAS installed.
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pip install . # or: pip install .[test] && pytest
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import numpy as np
|
|
60
|
+
import ssfortran as ss
|
|
61
|
+
|
|
62
|
+
y = np.loadtxt("data/nile.csv", delimiter=",", skiprows=1)[:, 1]
|
|
63
|
+
|
|
64
|
+
# Built-in components
|
|
65
|
+
mod = ss.StructuralModel(y, [ss.Irregular(), ss.Level()])
|
|
66
|
+
res = mod.fit()
|
|
67
|
+
print(res.summary())
|
|
68
|
+
smoothed = res.smooth().smoothed_state
|
|
69
|
+
|
|
70
|
+
# Matrix-level: fill the system matrices yourself
|
|
71
|
+
rep = ss.Representation(y, k_states=1)
|
|
72
|
+
rep["design"] = [[1.0]]; rep["transition"] = [[1.0]]; rep["selection"] = [[1.0]]
|
|
73
|
+
rep["obs_cov"] = [[15099.0]]; rep["state_cov"] = [[1469.1]]
|
|
74
|
+
rep.initialize_diffuse()
|
|
75
|
+
print(rep.loglike())
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Fitting results have `summary()` (estimates with z-tests and intervals, fit
|
|
79
|
+
statistics, residual tests), `fittedvalues`, `resid`, `get_forecast(steps)` with
|
|
80
|
+
`conf_int()`, `components()` and `estimation_bias()`. A `Representation` also offers:
|
|
81
|
+
- the other smoothers of DK ch. 4: fast, classical, two-filter, Whittle, fixed-point,
|
|
82
|
+
fixed-lag and updating
|
|
83
|
+
- smoothed covariances between periods, and filtering and smoothing weights
|
|
84
|
+
- the square-root and augmented filters (with the marginal likelihood)
|
|
85
|
+
- EM, collapsing, and linear state restrictions
|
|
86
|
+
- auxiliary residuals, de Jong–Penzer statistics, least squares residuals and R²_D
|
|
87
|
+
- the mean-correction and de Jong–Shephard simulation smoothers
|
|
88
|
+
|
|
89
|
+
A model with parameters can be defined in three ways:
|
|
90
|
+
|
|
91
|
+
| | How | Speed |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `StructuralModel` | built-in components | all in Fortran; works with `fit_many` |
|
|
94
|
+
| `MappedModel` | declare which matrix entries each parameter sets | all in Fortran; works with `fit_many` |
|
|
95
|
+
| `MLEModel` | subclass and write `update(params)`, as in statsmodels | calls Python for each likelihood evaluation |
|
|
96
|
+
|
|
97
|
+
For the timing comparison with statsmodels from Python, run
|
|
98
|
+
`bench/bench_python.py`. It shows 2–8× speedups for single models, and 36× for 1000
|
|
99
|
+
series with `fit_many`. `example/bench.f90` and `bench/bench_statsmodels.py` compare
|
|
100
|
+
the Fortran core directly.
|
|
101
|
+
|
|
102
|
+
To develop without installing:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
cmake -S . -B build/cmake -G Ninja && cmake --build build/cmake
|
|
106
|
+
pytest # uses python/src and build/cmake (pyproject.toml)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT (see [LICENSE](LICENSE)); third-party notices are in
|
|
112
|
+
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md), and citations in
|
|
113
|
+
[docs/references.md](docs/references.md).
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
This library is released under the MIT License (see `LICENSE`). It follows
|
|
4
|
+
Durbin and Koopman, *Time Series Analysis by State Space Methods* (2nd ed., 2012), and
|
|
5
|
+
the other papers cited in the source. Its code was written from those publications.
|
|
6
|
+
|
|
7
|
+
## statsmodels
|
|
8
|
+
|
|
9
|
+
We use statsmodels (`statsmodels.tsa.statespace`) as a reference:
|
|
10
|
+
|
|
11
|
+
- Some conventions follow it on purpose: output layout, diffuse tolerances, the
|
|
12
|
+
Monahan stationarity transform, optimizer defaults and AIC/BIC.
|
|
13
|
+
- The test fixtures in `test/fixtures/` are statsmodels output, generated by
|
|
14
|
+
`test/fixtures/make_fixtures.py`.
|
|
15
|
+
|
|
16
|
+
statsmodels is not part of the library and is not required to build or use it. This
|
|
17
|
+
project is not affiliated with or endorsed by the statsmodels developers. Its license:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Copyright (C) 2006, Jonathan E. Taylor
|
|
21
|
+
All rights reserved.
|
|
22
|
+
|
|
23
|
+
Copyright (c) 2006-2008 Scipy Developers.
|
|
24
|
+
All rights reserved.
|
|
25
|
+
|
|
26
|
+
Copyright (c) 2009-2018 statsmodels Developers.
|
|
27
|
+
All rights reserved.
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Redistribution and use in source and binary forms, with or without
|
|
31
|
+
modification, are permitted provided that the following conditions are met:
|
|
32
|
+
|
|
33
|
+
a. Redistributions of source code must retain the above copyright notice,
|
|
34
|
+
this list of conditions and the following disclaimer.
|
|
35
|
+
b. Redistributions in binary form must reproduce the above copyright
|
|
36
|
+
notice, this list of conditions and the following disclaimer in the
|
|
37
|
+
documentation and/or other materials provided with the distribution.
|
|
38
|
+
c. Neither the name of statsmodels nor the names of its contributors
|
|
39
|
+
may be used to endorse or promote products derived from this software
|
|
40
|
+
without specific prior written permission.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
44
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
45
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
46
|
+
ARE DISCLAIMED. IN NO EVENT SHALL STATSMODELS OR CONTRIBUTORS BE LIABLE FOR
|
|
47
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
48
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
49
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
50
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
51
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
52
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
53
|
+
DAMAGE.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## L-BFGS-B (bundled)
|
|
57
|
+
|
|
58
|
+
`third_party/lbfgsb/` holds the Fortran sources of
|
|
59
|
+
[jacobwilliams/lbfgsb](https://github.com/jacobwilliams/lbfgsb), unmodified: L-BFGS-B
|
|
60
|
+
3.0 by Ciyou Zhu, Richard Byrd, Peihuang Lu, Jorge Nocedal and Jose Luis Morales,
|
|
61
|
+
modernized by Jacob Williams. It is released under the BSD-3-Clause ("New BSD")
|
|
62
|
+
license; the text distributed with it is `third_party/lbfgsb/License.txt`, and
|
|
63
|
+
`third_party/lbfgsb/README.md` records the upstream commit. It is compiled into the
|
|
64
|
+
library and into every wheel.
|
|
65
|
+
|
|
66
|
+
## Build dependencies
|
|
67
|
+
|
|
68
|
+
These are not copied into this repository.
|
|
69
|
+
|
|
70
|
+
| Package | Use | License |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| [test-drive](https://github.com/fortran-lang/test-drive) | Tests only (fpm downloads it) | MIT or Apache-2.0 |
|
|
73
|
+
| LAPACK, BLAS (system libraries, e.g. Reference LAPACK or OpenBLAS) | Linear algebra | BSD-3-Clause (modified BSD) |
|
|
74
|
+
|
|
75
|
+
## Libraries in the binary wheels
|
|
76
|
+
|
|
77
|
+
The binary Python wheels are built by `cibuildwheel`, and `auditwheel` copies these
|
|
78
|
+
shared libraries into `ssfortran.libs/`. Their licenses apply to those copies.
|
|
79
|
+
|
|
80
|
+
| Library | License |
|
|
81
|
+
|---|---|
|
|
82
|
+
| OpenBLAS (BLAS and LAPACK) | BSD-3-Clause |
|
|
83
|
+
| libgfortran, libquadmath, libgomp (GCC runtime) | GPL-3.0 with the GCC Runtime Library Exception 3.1, which permits distribution with programs compiled by GCC under any license |
|
|
84
|
+
|
|
85
|
+
## Citations
|
|
86
|
+
|
|
87
|
+
[`docs/references.md`](docs/references.md) cites the methods, data and software,
|
|
88
|
+
including the citations these projects ask for.
|
|
89
|
+
|
|
90
|
+
## Data
|
|
91
|
+
|
|
92
|
+
See `data/README.md` for the source of each dataset and why some are downloaded
|
|
93
|
+
rather than committed.
|
ssfortran-0.1.0/fpm.toml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name = "statespace"
|
|
2
|
+
version = "0.1.0"
|
|
3
|
+
license = "MIT"
|
|
4
|
+
author = "zelpuz"
|
|
5
|
+
maintainer = "td.edwards@yahoo.com"
|
|
6
|
+
copyright = "Copyright 2026, zelpuz"
|
|
7
|
+
[build]
|
|
8
|
+
auto-executables = true
|
|
9
|
+
auto-tests = true
|
|
10
|
+
auto-examples = true
|
|
11
|
+
module-naming = false
|
|
12
|
+
link = ["lapack", "blas"]
|
|
13
|
+
[install]
|
|
14
|
+
library = false
|
|
15
|
+
[fortran]
|
|
16
|
+
implicit-typing = false
|
|
17
|
+
implicit-external = false
|
|
18
|
+
source-form = "free"
|
|
19
|
+
|
|
20
|
+
[dependencies]
|
|
21
|
+
# Modern Fortran port of L-BFGS-B 3.0 (Nocedal & Morales), BSD-3, bundled in
|
|
22
|
+
# third_party/lbfgsb at commit ce1a9322 (see its README).
|
|
23
|
+
lbfgsb.path = "third_party/lbfgsb"
|
|
24
|
+
|
|
25
|
+
[dev-dependencies]
|
|
26
|
+
test-drive.git = "https://github.com/fortran-lang/test-drive"
|
|
27
|
+
test-drive.rev = "c506771aefd594e7e372240a8027b3fd06d61264" # v0.6.1
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["scikit-build-core>=1.1"]
|
|
3
|
+
build-backend = "scikit_build_core.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ssfortran"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Linear Gaussian state space models (Durbin and Koopman, Part I) with a Fortran core"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE", "THIRD_PARTY_NOTICES.md", "third_party/lbfgsb/License.txt"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dependencies = ["numpy"]
|
|
14
|
+
authors = [{ name = "zelpuz" }]
|
|
15
|
+
keywords = ["state space", "kalman filter", "kalman smoother", "time series",
|
|
16
|
+
"structural time series", "unobserved components", "durbin koopman"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"Operating System :: POSIX :: Linux",
|
|
21
|
+
"Programming Language :: Fortran",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Source = "https://github.com/Zelpuz/statespace"
|
|
28
|
+
Issues = "https://github.com/Zelpuz/statespace/issues"
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
test = ["pytest"]
|
|
32
|
+
|
|
33
|
+
[[tool.dynamic-metadata]]
|
|
34
|
+
# The single source of the version: the string in the C interface. fpm.toml,
|
|
35
|
+
# CMakeLists.txt and docs/conf.py must agree (python/tests/test_version.py).
|
|
36
|
+
provider = "scikit_build_core.metadata.regex"
|
|
37
|
+
field = "version"
|
|
38
|
+
input = "src/statespace_capi.f90"
|
|
39
|
+
regex = 'character\(len=\*\), parameter :: version = "(?P<value>[^"]+)"'
|
|
40
|
+
|
|
41
|
+
[tool.scikit-build]
|
|
42
|
+
cmake.build-type = "Release"
|
|
43
|
+
wheel.packages = ["python/src/ssfortran"]
|
|
44
|
+
# The library is loaded with ctypes, so the wheel is Python-version
|
|
45
|
+
# independent but platform specific.
|
|
46
|
+
wheel.py-api = "py3"
|
|
47
|
+
# The source distribution holds what the build needs. Tests, fixtures (11 MB),
|
|
48
|
+
# docs, examples and data stay in the repository.
|
|
49
|
+
sdist.exclude = ["build", ".venv", "ref", "private", ".github", "docs", "test",
|
|
50
|
+
"python/tests", "python/conftest.py", "example", "bench", "data",
|
|
51
|
+
"project.md", "PLAN.md"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["python/tests", "python/src/ssfortran"]
|
|
55
|
+
# The source tree for development; to test an installed wheel instead, run
|
|
56
|
+
# pytest -o pythonpath= python/tests
|
|
57
|
+
pythonpath = ["python/src"]
|
|
58
|
+
addopts = "--doctest-modules"
|
|
59
|
+
doctest_optionflags = ["NORMALIZE_WHITESPACE", "ELLIPSIS"]
|
|
60
|
+
|
|
61
|
+
[tool.cibuildwheel]
|
|
62
|
+
# One wheel per platform serves every Python version (wheel.py-api above), so
|
|
63
|
+
# build with a single interpreter.
|
|
64
|
+
build = "cp312-*"
|
|
65
|
+
skip = "*-musllinux_*"
|
|
66
|
+
test-requires = ["pytest"]
|
|
67
|
+
# Test the installed wheel against the repository's tests and fixtures.
|
|
68
|
+
test-command = "pytest -q -o pythonpath= -o addopts= {project}/python/tests"
|
|
69
|
+
|
|
70
|
+
[tool.cibuildwheel.linux]
|
|
71
|
+
# gfortran matching the image's gcc-toolset, and OpenBLAS for BLAS and LAPACK.
|
|
72
|
+
# auditwheel then copies libgfortran, libgomp and libopenblas into the wheel.
|
|
73
|
+
before-all = [
|
|
74
|
+
"dnf install -y 'dnf-command(config-manager)'",
|
|
75
|
+
"dnf config-manager --set-enabled powertools || dnf config-manager --set-enabled crb",
|
|
76
|
+
"dnf install -y $(basename /opt/rh/gcc-toolset-*)-gcc-gfortran openblas-devel",
|
|
77
|
+
]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Linear Gaussian state space models with a Fortran core.
|
|
2
|
+
|
|
3
|
+
``ssfortran`` covers Part I of Durbin and Koopman, *Time Series Analysis by
|
|
4
|
+
State Space Methods* (2nd ed., 2012), cited as DK:
|
|
5
|
+
|
|
6
|
+
* :class:`Representation`: the model's matrices and the algorithms of DK
|
|
7
|
+
ch. 4-7 (filtering, smoothing, likelihood, simulation, forecasting,
|
|
8
|
+
diagnostics);
|
|
9
|
+
* :class:`StructuralModel`, :class:`MappedModel`, :class:`MLEModel`:
|
|
10
|
+
models with parameters, estimated by maximum likelihood;
|
|
11
|
+
* :mod:`ssfortran.diagnostics`: residual tests.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from . import diagnostics
|
|
15
|
+
from ._lib import StateSpaceError, version
|
|
16
|
+
from .models import (
|
|
17
|
+
ARIMA,
|
|
18
|
+
Cycle,
|
|
19
|
+
ContinuousLevel,
|
|
20
|
+
ContinuousTrend,
|
|
21
|
+
FitResults,
|
|
22
|
+
ForecastResults,
|
|
23
|
+
Irregular,
|
|
24
|
+
Level,
|
|
25
|
+
MappedModel,
|
|
26
|
+
MLEModel,
|
|
27
|
+
Model,
|
|
28
|
+
Regression,
|
|
29
|
+
Seasonal,
|
|
30
|
+
StructuralModel,
|
|
31
|
+
Trend,
|
|
32
|
+
fit_many,
|
|
33
|
+
)
|
|
34
|
+
from .representation import (
|
|
35
|
+
AugmentedResults,
|
|
36
|
+
DIFFUSE_MULTIVARIATE,
|
|
37
|
+
DIFFUSE_UNIVARIATE,
|
|
38
|
+
FILTER_CONVENTIONAL,
|
|
39
|
+
FILTER_UNIVARIATE,
|
|
40
|
+
INIT_APPROX_DIFFUSE,
|
|
41
|
+
INIT_DIFFUSE,
|
|
42
|
+
INIT_GENERAL,
|
|
43
|
+
INIT_KNOWN,
|
|
44
|
+
INIT_STATIONARY,
|
|
45
|
+
FilterResults,
|
|
46
|
+
Representation,
|
|
47
|
+
SmootherResults,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
__version__ = version()
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"diagnostics", "Model", "StructuralModel", "MappedModel", "MLEModel", "FitResults", "ForecastResults",
|
|
54
|
+
"fit_many",
|
|
55
|
+
"Irregular", "Level", "Trend", "Seasonal", "Cycle", "Regression", "ARIMA",
|
|
56
|
+
"ContinuousLevel", "ContinuousTrend",
|
|
57
|
+
"Representation", "AugmentedResults", "FilterResults", "SmootherResults", "StateSpaceError",
|
|
58
|
+
"INIT_KNOWN", "INIT_APPROX_DIFFUSE", "INIT_STATIONARY", "INIT_DIFFUSE", "INIT_GENERAL",
|
|
59
|
+
"FILTER_CONVENTIONAL", "FILTER_UNIVARIATE", "DIFFUSE_UNIVARIATE", "DIFFUSE_MULTIVARIATE",
|
|
60
|
+
]
|