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.
Files changed (48) hide show
  1. ssfortran-0.1.0/.gitignore +10 -0
  2. ssfortran-0.1.0/CMakeLists.txt +56 -0
  3. ssfortran-0.1.0/LICENSE +21 -0
  4. ssfortran-0.1.0/PKG-INFO +137 -0
  5. ssfortran-0.1.0/README.md +113 -0
  6. ssfortran-0.1.0/THIRD_PARTY_NOTICES.md +93 -0
  7. ssfortran-0.1.0/fpm.toml +27 -0
  8. ssfortran-0.1.0/pyproject.toml +77 -0
  9. ssfortran-0.1.0/python/src/ssfortran/__init__.py +60 -0
  10. ssfortran-0.1.0/python/src/ssfortran/_lib.py +222 -0
  11. ssfortran-0.1.0/python/src/ssfortran/diagnostics.py +112 -0
  12. ssfortran-0.1.0/python/src/ssfortran/models.py +1437 -0
  13. ssfortran-0.1.0/python/src/ssfortran/representation.py +1347 -0
  14. ssfortran-0.1.0/src/statespace.f90 +27 -0
  15. ssfortran-0.1.0/src/statespace_arima.f90 +247 -0
  16. ssfortran-0.1.0/src/statespace_augmented.f90 +174 -0
  17. ssfortran-0.1.0/src/statespace_callback.f90 +116 -0
  18. ssfortran-0.1.0/src/statespace_capi.f90 +763 -0
  19. ssfortran-0.1.0/src/statespace_capi_extras.f90 +680 -0
  20. ssfortran-0.1.0/src/statespace_capi_models.f90 +941 -0
  21. ssfortran-0.1.0/src/statespace_collapse.f90 +95 -0
  22. ssfortran-0.1.0/src/statespace_components.f90 +412 -0
  23. ssfortran-0.1.0/src/statespace_dense.f90 +117 -0
  24. ssfortran-0.1.0/src/statespace_diagnostics.f90 +338 -0
  25. ssfortran-0.1.0/src/statespace_em.f90 +125 -0
  26. ssfortran-0.1.0/src/statespace_filter.f90 +1021 -0
  27. ssfortran-0.1.0/src/statespace_forecast.f90 +78 -0
  28. ssfortran-0.1.0/src/statespace_kinds.f90 +20 -0
  29. ssfortran-0.1.0/src/statespace_linalg.f90 +431 -0
  30. ssfortran-0.1.0/src/statespace_mapped.f90 +245 -0
  31. ssfortran-0.1.0/src/statespace_mle.f90 +451 -0
  32. ssfortran-0.1.0/src/statespace_model.f90 +234 -0
  33. ssfortran-0.1.0/src/statespace_rep.f90 +370 -0
  34. ssfortran-0.1.0/src/statespace_restrict.f90 +60 -0
  35. ssfortran-0.1.0/src/statespace_score.f90 +262 -0
  36. ssfortran-0.1.0/src/statespace_simsmooth.f90 +282 -0
  37. ssfortran-0.1.0/src/statespace_smoother.f90 +484 -0
  38. ssfortran-0.1.0/src/statespace_smoothing.f90 +750 -0
  39. ssfortran-0.1.0/src/statespace_special.f90 +158 -0
  40. ssfortran-0.1.0/src/statespace_sqrt.f90 +196 -0
  41. ssfortran-0.1.0/src/statespace_structural.f90 +922 -0
  42. ssfortran-0.1.0/third_party/lbfgsb/License.txt +71 -0
  43. ssfortran-0.1.0/third_party/lbfgsb/README.md +11 -0
  44. ssfortran-0.1.0/third_party/lbfgsb/fpm.toml +14 -0
  45. ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb.f90 +3420 -0
  46. ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_blas_module.F90 +284 -0
  47. ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_kinds_module.F90 +40 -0
  48. ssfortran-0.1.0/third_party/lbfgsb/src/lbfgsb_linpack_module.f90 +167 -0
@@ -0,0 +1,10 @@
1
+ build/
2
+ .venv/
3
+ __pycache__/
4
+ ref/
5
+ PLAN.md
6
+ private/
7
+ data/seatbelts.csv
8
+ data/wwwusage.csv
9
+ data/mcycle.csv
10
+ docs/reference/python/generated/
@@ -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()
@@ -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.
@@ -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.
@@ -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
+ ]