symident 0.9.2__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 (104) hide show
  1. symident-0.9.2/.github/workflows/wheels.yml +140 -0
  2. symident-0.9.2/.gitignore +16 -0
  3. symident-0.9.2/CMakeLists.txt +20 -0
  4. symident-0.9.2/LICENSE +21 -0
  5. symident-0.9.2/NEWS.md +44 -0
  6. symident-0.9.2/PKG-INFO +116 -0
  7. symident-0.9.2/README.md +76 -0
  8. symident-0.9.2/cpp/bindings.cpp +318 -0
  9. symident-0.9.2/cpp/kernel.cpp +2836 -0
  10. symident-0.9.2/cpp/kernel.h +48 -0
  11. symident-0.9.2/cpp/rvalue.h +233 -0
  12. symident-0.9.2/docs/api.rst +44 -0
  13. symident-0.9.2/docs/changelog.md +5 -0
  14. symident-0.9.2/docs/conf.py +38 -0
  15. symident-0.9.2/docs/guide.rst +307 -0
  16. symident-0.9.2/docs/index.rst +28 -0
  17. symident-0.9.2/docs/install.rst +42 -0
  18. symident-0.9.2/docs/method.rst +377 -0
  19. symident-0.9.2/docs/quickstart.rst +46 -0
  20. symident-0.9.2/pyproject.toml +69 -0
  21. symident-0.9.2/src/symident/__init__.py +8 -0
  22. symident-0.9.2/src/symident/api.py +337 -0
  23. symident-0.9.2/src/symident/detection/__init__.py +5 -0
  24. symident-0.9.2/src/symident/detection/classify.py +155 -0
  25. symident-0.9.2/src/symident/detection/closedform.py +102 -0
  26. symident-0.9.2/src/symident/detection/conditions.py +399 -0
  27. symident-0.9.2/src/symident/detection/core.py +636 -0
  28. symident-0.9.2/src/symident/detection/cq.py +194 -0
  29. symident-0.9.2/src/symident/detection/fields.py +526 -0
  30. symident-0.9.2/src/symident/detection/finalize.py +225 -0
  31. symident-0.9.2/src/symident/detection/forward.py +769 -0
  32. symident-0.9.2/src/symident/detection/gauge.py +192 -0
  33. symident-0.9.2/src/symident/detection/groups.py +113 -0
  34. symident-0.9.2/src/symident/detection/hybrid.py +1116 -0
  35. symident-0.9.2/src/symident/detection/interp.py +223 -0
  36. symident-0.9.2/src/symident/detection/observability/__init__.py +5 -0
  37. symident-0.9.2/src/symident/detection/observability/analysis.py +978 -0
  38. symident-0.9.2/src/symident/detection/observability/context.py +165 -0
  39. symident-0.9.2/src/symident/detection/observability/guard.py +50 -0
  40. symident-0.9.2/src/symident/detection/observability/homotopy.py +431 -0
  41. symident-0.9.2/src/symident/detection/observability/homstate.py +351 -0
  42. symident-0.9.2/src/symident/detection/observability/joint.py +655 -0
  43. symident-0.9.2/src/symident/detection/observability/narrow.py +260 -0
  44. symident-0.9.2/src/symident/detection/observability/plain.py +109 -0
  45. symident-0.9.2/src/symident/detection/observability/reconstruct.py +569 -0
  46. symident-0.9.2/src/symident/detection/observability/rest.py +321 -0
  47. symident-0.9.2/src/symident/detection/perprime.py +263 -0
  48. symident-0.9.2/src/symident/detection/rank.py +357 -0
  49. symident-0.9.2/src/symident/detection/relevance.py +120 -0
  50. symident-0.9.2/src/symident/detection/series.py +106 -0
  51. symident-0.9.2/src/symident/detection/sparse.py +264 -0
  52. symident-0.9.2/src/symident/detection/verify.py +130 -0
  53. symident-0.9.2/src/symident/gfp.py +532 -0
  54. symident-0.9.2/src/symident/install.py +146 -0
  55. symident-0.9.2/src/symident/options.py +70 -0
  56. symident-0.9.2/src/symident/par.py +53 -0
  57. symident-0.9.2/src/symident/reduction/__init__.py +5 -0
  58. symident-0.9.2/src/symident/reduction/blocks.py +377 -0
  59. symident-0.9.2/src/symident/reduction/core.py +503 -0
  60. symident-0.9.2/src/symident/reduction/darboux.py +409 -0
  61. symident-0.9.2/src/symident/reduction/expr.py +297 -0
  62. symident-0.9.2/src/symident/reduction/invariants.py +299 -0
  63. symident-0.9.2/src/symident/reduction/scaling.py +245 -0
  64. symident-0.9.2/src/symident/reduction/sections.py +586 -0
  65. symident-0.9.2/src/symident/reduction/sign.py +656 -0
  66. symident-0.9.2/src/symident/reduction/solve.py +475 -0
  67. symident-0.9.2/src/symident/reduction/zero.py +219 -0
  68. symident-0.9.2/src/symident/report.py +419 -0
  69. symident-0.9.2/src/symident/rexpr.py +223 -0
  70. symident-0.9.2/src/symident/rjson.py +110 -0
  71. symident-0.9.2/src/symident/state.py +56 -0
  72. symident-0.9.2/src/symident/sym/__init__.py +1 -0
  73. symident-0.9.2/src/symident/sym/charts.py +757 -0
  74. symident-0.9.2/src/symident/sym/continuation.py +133 -0
  75. symident-0.9.2/src/symident/sym/direction.py +215 -0
  76. symident-0.9.2/src/symident/sym/fields.py +759 -0
  77. symident-0.9.2/src/symident/sym/gfpoly.py +444 -0
  78. symident-0.9.2/src/symident/sym/invariants.py +156 -0
  79. symident-0.9.2/src/symident/sym/jets.py +172 -0
  80. symident-0.9.2/src/symident/sym/linalg.py +244 -0
  81. symident-0.9.2/src/symident/sym/modp.py +258 -0
  82. symident-0.9.2/src/symident/sym/msolve.py +230 -0
  83. symident-0.9.2/src/symident/sym/parse.py +112 -0
  84. symident-0.9.2/src/symident/sym/recast.py +1014 -0
  85. symident-0.9.2/src/symident/sym/restforward.py +389 -0
  86. symident-0.9.2/src/symident/sym/scaling.py +513 -0
  87. symident-0.9.2/src/symident/sym/steady.py +435 -0
  88. symident-0.9.2/src/symident/sym/switching.py +400 -0
  89. symident-0.9.2/src/symident/sym/symbolic.py +136 -0
  90. symident-0.9.2/src/symident/sym/tape.py +851 -0
  91. symident-0.9.2/src/symident/tools/build-msolve.sh +87 -0
  92. symident-0.9.2/tests/golden_util.py +233 -0
  93. symident-0.9.2/tests/test_detect.py +1204 -0
  94. symident-0.9.2/tests/test_exponential.py +271 -0
  95. symident-0.9.2/tests/test_golden.py +32 -0
  96. symident-0.9.2/tests/test_homotopy.py +117 -0
  97. symident-0.9.2/tests/test_install.py +142 -0
  98. symident-0.9.2/tests/test_kernel_parity.py +66 -0
  99. symident-0.9.2/tests/test_par.py +30 -0
  100. symident-0.9.2/tests/test_reduce.py +775 -0
  101. symident-0.9.2/tests/test_report.py +99 -0
  102. symident-0.9.2/tests/test_rjson.py +50 -0
  103. symident-0.9.2/tests/test_switching.py +316 -0
  104. symident-0.9.2/tests/tjson.py +43 -0
@@ -0,0 +1,140 @@
1
+ # Wheels for Linux (manylinux x86_64 and aarch64), macOS (x86_64 and arm64) and Windows,
2
+ # the sdist, tests of the Linux wheel on Fedora and Debian, and a source build on Fedora;
3
+ # uploaded to PyPI only when a release is published. Documentation goes to Pages from master.
4
+ name: wheels
5
+
6
+ on:
7
+ push:
8
+ branches: [master]
9
+ pull_request:
10
+ workflow_dispatch:
11
+ release:
12
+ types: [published]
13
+
14
+ jobs:
15
+ wheels:
16
+ name: wheels ${{ matrix.os }}
17
+ runs-on: ${{ matrix.os }}
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ os: [ubuntu-latest, ubuntu-24.04-arm, macos-15-intel, macos-latest, windows-latest]
22
+ steps:
23
+ - uses: actions/checkout@v5
24
+ - uses: pypa/cibuildwheel@v3.4.1
25
+ - uses: actions/upload-artifact@v4
26
+ with:
27
+ name: wheels-${{ matrix.os }}
28
+ path: wheelhouse/*.whl
29
+
30
+ sdist:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v5
34
+ - run: pipx run build --sdist
35
+ - uses: actions/upload-artifact@v4
36
+ with:
37
+ name: sdist
38
+ path: dist/*.tar.gz
39
+
40
+ # the manylinux wheel on the distributions' own Python; Fedora also builds msolve with
41
+ # install_msolve() and runs the tests that need it
42
+ distro:
43
+ needs: wheels
44
+ # runs when another platform's wheels failed; it needs only the ubuntu-latest wheel
45
+ if: ${{ !cancelled() }}
46
+ runs-on: ubuntu-latest
47
+ strategy:
48
+ fail-fast: false
49
+ matrix:
50
+ image: ["fedora:latest", "debian:stable"]
51
+ container: ${{ matrix.image }}
52
+ steps:
53
+ - name: Install Python and build tools
54
+ run: |
55
+ if command -v dnf >/dev/null; then
56
+ dnf install -y --setopt=install_weak_deps=False python3 python3-pip gcc make m4 curl xz tar
57
+ else
58
+ apt-get update && apt-get install -y --no-install-recommends \
59
+ python3 python3-venv ca-certificates
60
+ fi
61
+ - uses: actions/checkout@v5
62
+ - uses: actions/download-artifact@v4
63
+ with:
64
+ name: wheels-ubuntu-latest
65
+ path: wheelhouse
66
+ - name: Install the wheel
67
+ run: |
68
+ python3 -m venv /opt/venv
69
+ /opt/venv/bin/pip install --upgrade pip pytest pytest-xdist
70
+ /opt/venv/bin/pip install --only-binary=:all: --find-links wheelhouse symident
71
+ - name: Build msolve
72
+ if: startsWith(matrix.image, 'fedora')
73
+ run: /opt/venv/bin/python -c "import symident; symident.install_msolve(ask=False, jobs=4)"
74
+ - name: Tests
75
+ run: cd /tmp && /opt/venv/bin/python -m pytest -q -n auto "$GITHUB_WORKSPACE/tests"
76
+
77
+ # a source install on Fedora's own Python and compilers, as dMod2's CI installs it
78
+ fedora:
79
+ name: fedora
80
+ runs-on: ubuntu-latest
81
+ container: fedora:latest
82
+ steps:
83
+ - name: Install Python and the compilers
84
+ run: dnf install -y --setopt=install_weak_deps=False python3 python3-devel python3-pip gcc-c++ cmake
85
+ - uses: actions/checkout@v5
86
+ - name: Install from source
87
+ run: |
88
+ python3 -m venv /opt/venv
89
+ /opt/venv/bin/pip install --upgrade pip pytest pytest-xdist
90
+ /opt/venv/bin/pip install .
91
+ - name: Tests
92
+ run: cd /tmp && /opt/venv/bin/python -m pytest -q -n auto "$GITHUB_WORKSPACE/tests"
93
+
94
+ # the documentation as HTML, built on every run and deployed to Pages from master
95
+ docs:
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - uses: actions/checkout@v5
99
+ - uses: actions/setup-python@v6
100
+ with:
101
+ python-version: "3.12"
102
+ - run: pip install ".[docs]"
103
+ - run: sphinx-build -W -b html docs docs/_build/html
104
+ - uses: actions/upload-pages-artifact@v3
105
+ with:
106
+ path: docs/_build/html
107
+
108
+ pages:
109
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
110
+ needs: docs
111
+ runs-on: ubuntu-latest
112
+ permissions:
113
+ pages: write
114
+ id-token: write
115
+ environment:
116
+ name: github-pages
117
+ url: ${{ steps.deploy.outputs.page_url }}
118
+ steps:
119
+ - id: deploy
120
+ uses: actions/deploy-pages@v4
121
+
122
+ publish:
123
+ if: github.event_name == 'release' && github.event.action == 'published'
124
+ needs: [wheels, sdist, distro]
125
+ runs-on: ubuntu-latest
126
+ environment: pypi
127
+ permissions:
128
+ id-token: write
129
+ steps:
130
+ # the wheels and the sdist only, not the documentation for Pages
131
+ - uses: actions/download-artifact@v4
132
+ with:
133
+ pattern: wheels-*
134
+ path: dist
135
+ merge-multiple: true
136
+ - uses: actions/download-artifact@v4
137
+ with:
138
+ name: sdist
139
+ path: dist
140
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,16 @@
1
+ build/
2
+ *.so
3
+ __pycache__/
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .cmake/
7
+ CMakeFiles/
8
+ CMakeCache.txt
9
+ CMakeInit.txt
10
+ cmake_install.cmake
11
+ build.ninja
12
+ .ninja_*
13
+ .skbuild-info.json
14
+ .ruff_cache/
15
+ docs/_build/
16
+ docs/generated/
@@ -0,0 +1,20 @@
1
+ cmake_minimum_required(VERSION 3.18)
2
+ project(symident LANGUAGES CXX)
3
+ set(CMAKE_CXX_STANDARD 17)
4
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
5
+ if(NOT CMAKE_BUILD_TYPE)
6
+ set(CMAKE_BUILD_TYPE Release)
7
+ endif()
8
+ find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
9
+ find_package(pybind11 CONFIG REQUIRED)
10
+ find_package(OpenMP COMPONENTS CXX)
11
+ pybind11_add_module(_core cpp/bindings.cpp cpp/kernel.cpp)
12
+ if(OpenMP_CXX_FOUND)
13
+ target_link_libraries(_core PRIVATE OpenMP::OpenMP_CXX)
14
+ else()
15
+ message(WARNING "OpenMP not found: the kernel runs on one thread")
16
+ endif()
17
+ if(NOT MSVC)
18
+ target_compile_options(_core PRIVATE -O2)
19
+ endif()
20
+ install(TARGETS _core DESTINATION symident)
symident-0.9.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Simon Beyer
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.
symident-0.9.2/NEWS.md ADDED
@@ -0,0 +1,44 @@
1
+ # symident 0.9.2
2
+
3
+ * `log(x, b)` and `atan2(y, x)` parse: the commas between the arguments were dropped.
4
+ * `atanh()` of an argument whose logarithms cancel in part, such as `atanh(x/(1 + x))`,
5
+ no longer stops with a `KeyError`.
6
+
7
+ # symident 0.9.1
8
+
9
+ * Wheels for Python 3.14.
10
+ * Linux wheels are built on manylinux_2_28 and need glibc 2.28 or newer; on the older
11
+ manylinux2014 base, installing the wheel built SciPy from source.
12
+ * The tests pass on Windows: they read their data as UTF-8, and the msolve tests that run a
13
+ shell script are skipped there.
14
+
15
+ # symident 0.9.0
16
+
17
+ First release.
18
+
19
+ * `Model`, `detect()` and `reduce()`: non-identifiable directions of ODE models with
20
+ observables, conditions, events and inputs, as exact generators where they close, and the
21
+ reparametrisation that removes them.
22
+ * Observability rank over finite fields in a C++ kernel, with a certified Lie order, exact
23
+ scaling symmetries and rank proofs by scalings or invariant fields.
24
+ * Elementary functions of states (logarithms, inverse trigonometric and hyperbolic
25
+ functions, powers of sums, nested) recast into rational form; their transcendental
26
+ initial values become generic leaves.
27
+ * Steady-state constraints (`equilibrate`) through the joint resting-state system.
28
+ Directions that no sampling route closes are fitted along parameter lines through the
29
+ continued resting state, in the parameters and, where needed, the resting states
30
+ (`reconst_control(homotopy=)`).
31
+ * Switches in right-hand sides and observables: `piecewise()` in SBML order, `ifelse()`,
32
+ comparisons, `&&`, `||`, `!`, `Heaviside()`, `sign()`, `abs()`, `max()` and `min()`, and
33
+ events with a `root`. A direction is reported when the observables of every regime
34
+ that the declared signs do not exclude stay unchanged along it, it maps every surface
35
+ of a visible switch to itself and keeps the events; a switch hidden from the
36
+ observables may move. `Model(regimes=)` restricts the analysis to the regimes an
37
+ experiment visits. The rank is certified between the stacked rows of the regimes and
38
+ directions proven symbolically, and an error is raised where they do not meet.
39
+ * Reduction by scaling transversals, module reduction and invariants (monomial, polynomial,
40
+ rational, Darboux, exponential), with positivity certificates and face sections.
41
+ * `reduce()` returns the best admissible chart and lists the others under `alternatives`
42
+ (`reduce(alternatives=True)`); dependent directions are named under `dependent`.
43
+ * `install_msolve()` builds msolve, used for coupled steady states, into a per-user cache.
44
+ * `symident.rjson`: JSON interface for host languages.
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: symident
3
+ Version: 0.9.2
4
+ Summary: Structural identifiability of ODE models by Lie symmetries over finite fields
5
+ Keywords: structural identifiability,Lie symmetries,ODE models,systems biology,finite fields,reparametrisation
6
+ Author-Email: Simon Beyer <simon.beyer@fdm.uni-freiburg.de>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: Microsoft :: Windows
14
+ Classifier: Programming Language :: C++
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
23
+ Project-URL: Homepage, https://github.com/dModverse/symident
24
+ Project-URL: Documentation, https://dmodverse.github.io/symident/
25
+ Project-URL: Source, https://github.com/dModverse/symident
26
+ Project-URL: Issues, https://github.com/dModverse/symident/issues
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: numpy>=1.24
29
+ Requires-Dist: sympy>=1.12
30
+ Requires-Dist: scipy>=1.11
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest>=7; extra == "test"
33
+ Requires-Dist: pytest-xdist; extra == "test"
34
+ Provides-Extra: docs
35
+ Requires-Dist: sphinx>=8; extra == "docs"
36
+ Requires-Dist: numpydoc; extra == "docs"
37
+ Requires-Dist: pydata-sphinx-theme; extra == "docs"
38
+ Requires-Dist: myst-parser; extra == "docs"
39
+ Description-Content-Type: text/markdown
40
+
41
+ # symident
42
+
43
+ [![wheels](https://github.com/dModverse/symident/actions/workflows/wheels.yml/badge.svg)](https://github.com/dModverse/symident/actions/workflows/wheels.yml)
44
+ [![docs](https://img.shields.io/badge/docs-dmodverse.github.io%2Fsymident-blue)](https://dmodverse.github.io/symident/)
45
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
46
+
47
+ Structural identifiability of ODE models by Lie symmetries over finite fields.
48
+
49
+ symident finds the non-identifiable directions of an ODE model with observables,
50
+ conditions and events, returns them as exact generators where possible, and reduces
51
+ the model to identifiable parameters. The observability rank is computed modulo
52
+ primes in a C++ kernel; closed forms are reconstructed by sparse interpolation and
53
+ verified at fresh primes.
54
+
55
+ ## Installation
56
+
57
+ ```sh
58
+ pip install git+https://github.com/dModverse/symident
59
+ ```
60
+
61
+ This builds from source and needs a C++17 compiler and CMake; with OpenMP the kernel runs
62
+ on several threads. Once symident is on PyPI, `pip install symident` installs a wheel.
63
+ Wheels are built for Linux (x86_64, aarch64; tested on Ubuntu, Debian and Fedora), macOS
64
+ (x86_64, arm64) and Windows (x86_64).
65
+
66
+ Steady-state analyses (`equilibrate=True`) whose resting state is a coupled nonlinear
67
+ polynomial system use [msolve](https://msolve.lip6.fr). On Linux and macOS
68
+
69
+ ```python
70
+ import symident
71
+ symident.install_msolve()
72
+ ```
73
+
74
+ builds it with GMP, MPFR and FLINT into a per-user cache (needs a C compiler, `make`, `m4`
75
+ and `curl` or `wget`), where symident finds it. Alternatively point `SYMIDENT_MSOLVE` at an
76
+ msolve executable; on Windows that is the only way.
77
+
78
+ ## Example
79
+
80
+ ```python
81
+ import symident as si
82
+
83
+ m = si.Model({"A": "-k1*A", "B": "k1*A - k2*B"}, {"y": "s*B"})
84
+ res = si.detect(m, reconstruct=True)
85
+ print(res)
86
+ #> Result: rank 4 / 5 | 1 non-identifiable direction
87
+ res.symmetries[0].generator
88
+ #> {'A': 'A', 'B': 'B', 's': '-s'}
89
+ print(res.reduce())
90
+ #> Reduced 1 of 1 direction.
91
+ #> Trafo (non-identity entries)
92
+ #> A = 1
93
+ ```
94
+
95
+ ## Interface
96
+
97
+ | | |
98
+ |---|---|
99
+ | `Model(odes, observables, ...)` | ODEs or a reaction network, observables, `trafo`, `conditions`, `events`, `inputs`, `fixed` |
100
+ | `detect(model, ...)` | rank, identifiability and the non-identifiable directions (`Symmetries`) |
101
+ | `reduce(result, ...)`, `result.reduce()` | reparametrisation that removes the directions (`Reduction`) |
102
+ | `reconst_control(...)` | settings of the saturation and the reconstruction |
103
+
104
+ Both results print a report; `summary()` adds the computation details and
105
+ `to_dict()` returns the raw result.
106
+
107
+ ## Contact
108
+
109
+ Simon Beyer, simon.beyer@fdm.uni-freiburg.de. Requests for further functions in model
110
+ equations, questions and bug reports are welcome by e-mail or as an
111
+ [issue](https://github.com/dModverse/symident/issues); the supported functions are listed
112
+ in the [user guide](https://dmodverse.github.io/symident/guide.html#expressions).
113
+
114
+ ## License
115
+
116
+ MIT
@@ -0,0 +1,76 @@
1
+ # symident
2
+
3
+ [![wheels](https://github.com/dModverse/symident/actions/workflows/wheels.yml/badge.svg)](https://github.com/dModverse/symident/actions/workflows/wheels.yml)
4
+ [![docs](https://img.shields.io/badge/docs-dmodverse.github.io%2Fsymident-blue)](https://dmodverse.github.io/symident/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
6
+
7
+ Structural identifiability of ODE models by Lie symmetries over finite fields.
8
+
9
+ symident finds the non-identifiable directions of an ODE model with observables,
10
+ conditions and events, returns them as exact generators where possible, and reduces
11
+ the model to identifiable parameters. The observability rank is computed modulo
12
+ primes in a C++ kernel; closed forms are reconstructed by sparse interpolation and
13
+ verified at fresh primes.
14
+
15
+ ## Installation
16
+
17
+ ```sh
18
+ pip install git+https://github.com/dModverse/symident
19
+ ```
20
+
21
+ This builds from source and needs a C++17 compiler and CMake; with OpenMP the kernel runs
22
+ on several threads. Once symident is on PyPI, `pip install symident` installs a wheel.
23
+ Wheels are built for Linux (x86_64, aarch64; tested on Ubuntu, Debian and Fedora), macOS
24
+ (x86_64, arm64) and Windows (x86_64).
25
+
26
+ Steady-state analyses (`equilibrate=True`) whose resting state is a coupled nonlinear
27
+ polynomial system use [msolve](https://msolve.lip6.fr). On Linux and macOS
28
+
29
+ ```python
30
+ import symident
31
+ symident.install_msolve()
32
+ ```
33
+
34
+ builds it with GMP, MPFR and FLINT into a per-user cache (needs a C compiler, `make`, `m4`
35
+ and `curl` or `wget`), where symident finds it. Alternatively point `SYMIDENT_MSOLVE` at an
36
+ msolve executable; on Windows that is the only way.
37
+
38
+ ## Example
39
+
40
+ ```python
41
+ import symident as si
42
+
43
+ m = si.Model({"A": "-k1*A", "B": "k1*A - k2*B"}, {"y": "s*B"})
44
+ res = si.detect(m, reconstruct=True)
45
+ print(res)
46
+ #> Result: rank 4 / 5 | 1 non-identifiable direction
47
+ res.symmetries[0].generator
48
+ #> {'A': 'A', 'B': 'B', 's': '-s'}
49
+ print(res.reduce())
50
+ #> Reduced 1 of 1 direction.
51
+ #> Trafo (non-identity entries)
52
+ #> A = 1
53
+ ```
54
+
55
+ ## Interface
56
+
57
+ | | |
58
+ |---|---|
59
+ | `Model(odes, observables, ...)` | ODEs or a reaction network, observables, `trafo`, `conditions`, `events`, `inputs`, `fixed` |
60
+ | `detect(model, ...)` | rank, identifiability and the non-identifiable directions (`Symmetries`) |
61
+ | `reduce(result, ...)`, `result.reduce()` | reparametrisation that removes the directions (`Reduction`) |
62
+ | `reconst_control(...)` | settings of the saturation and the reconstruction |
63
+
64
+ Both results print a report; `summary()` adds the computation details and
65
+ `to_dict()` returns the raw result.
66
+
67
+ ## Contact
68
+
69
+ Simon Beyer, simon.beyer@fdm.uni-freiburg.de. Requests for further functions in model
70
+ equations, questions and bug reports are welcome by e-mail or as an
71
+ [issue](https://github.com/dModverse/symident/issues); the supported functions are listed
72
+ in the [user guide](https://dmodverse.github.io/symident/guide.html#expressions).
73
+
74
+ ## License
75
+
76
+ MIT