fxtensor-bayesnet 0.9.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 (36) hide show
  1. fxtensor_bayesnet-0.9.0/CHANGELOG.md +26 -0
  2. fxtensor_bayesnet-0.9.0/LICENSE +21 -0
  3. fxtensor_bayesnet-0.9.0/MANIFEST.in +7 -0
  4. fxtensor_bayesnet-0.9.0/PKG-INFO +346 -0
  5. fxtensor_bayesnet-0.9.0/README-ja.md +311 -0
  6. fxtensor_bayesnet-0.9.0/README.md +312 -0
  7. fxtensor_bayesnet-0.9.0/docs/make_images.py +42 -0
  8. fxtensor_bayesnet-0.9.0/examples/maintenance/config.en.json +137 -0
  9. fxtensor_bayesnet-0.9.0/examples/maintenance/config.json +137 -0
  10. fxtensor_bayesnet-0.9.0/examples/weather/config.en.json +118 -0
  11. fxtensor_bayesnet-0.9.0/examples/weather/config.json +118 -0
  12. fxtensor_bayesnet-0.9.0/pyproject.toml +60 -0
  13. fxtensor_bayesnet-0.9.0/setup.cfg +4 -0
  14. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/__init__.py +9 -0
  15. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/__main__.py +5 -0
  16. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/cli.py +148 -0
  17. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/config.py +136 -0
  18. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/history.py +90 -0
  19. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/i18n.py +74 -0
  20. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/inference.py +144 -0
  21. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/network.py +133 -0
  22. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/plot.py +407 -0
  23. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/report.py +66 -0
  24. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/PKG-INFO +346 -0
  25. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/SOURCES.txt +34 -0
  26. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/dependency_links.txt +1 -0
  27. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/entry_points.txt +2 -0
  28. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/requires.txt +9 -0
  29. fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/top_level.txt +1 -0
  30. fxtensor_bayesnet-0.9.0/tests/conftest.py +27 -0
  31. fxtensor_bayesnet-0.9.0/tests/test_bayes.py +93 -0
  32. fxtensor_bayesnet-0.9.0/tests/test_cli.py +77 -0
  33. fxtensor_bayesnet-0.9.0/tests/test_config.py +103 -0
  34. fxtensor_bayesnet-0.9.0/tests/test_einsum.py +64 -0
  35. fxtensor_bayesnet-0.9.0/tests/test_en.py +58 -0
  36. fxtensor_bayesnet-0.9.0/tests/test_plot.py +164 -0
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [0.9.0] - 2026-10-10
7
+
8
+ First public release.
9
+
10
+ ### Added
11
+ - Config-driven discrete Bayesian network inference built on fxtensor-salmon (`FXTensor`):
12
+ marginals per scenario, Bayesian updating on observations, and root-cause inference via `bayesian_inversion`.
13
+ - Automatic cross-check of every result against a direct numpy `einsum` computation; ancestor-set
14
+ computation for large joint distributions.
15
+ - Config validation (`--check`) reporting all errors at once (row sums, missing/extra rows, undefined parents, cycles, …).
16
+ - Daily snapshots (`--snapshot`, `--force`) and diffs against the previous snapshot (`--diff`).
17
+ - Output as JSON, Markdown (`--md`) and a colour-coded mermaid diagram (`model.mmd`); `--no-write`, `--out-dir`,
18
+ `--history-dir`, `--format-config`.
19
+ - Figures with matplotlib (optional extra `[plot]`): network structure with a layered layout, marginals by scenario,
20
+ prior vs posterior for observations, and day-over-day changes (`--plot`, `--plot-format png|svg`, `--plot-dpi`).
21
+ Japanese fonts are detected automatically.
22
+ - `--lang ja|en` for Markdown and figure text.
23
+ - Examples: weather and equipment maintenance, each in Japanese and English.
24
+ - README in English and Japanese.
25
+
26
+ [0.9.0]: https://github.com/salmonsnare/fxtensor-bayesnet/releases/tag/v0.9.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tadachika Oki
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,7 @@
1
+ include LICENSE README.md README-ja.md CHANGELOG.md
2
+ recursive-include examples *.json
3
+ recursive-include tests *.py
4
+ include docs/make_images.py
5
+ prune docs/images
6
+ global-exclude __pycache__ *.py[cod] results.json results.md model.mmd
7
+ prune **/history
@@ -0,0 +1,346 @@
1
+ Metadata-Version: 2.4
2
+ Name: fxtensor-bayesnet
3
+ Version: 0.9.0
4
+ Summary: Config-driven inference for discrete Bayesian networks: scenario comparison, Bayesian updating, root-cause inference and daily snapshots (built on fxtensor-salmon)
5
+ Author-email: Tadachika Oki <sakesnare@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/salmonsnare/fxtensor-bayesnet
8
+ Project-URL: Repository, https://github.com/salmonsnare/fxtensor-bayesnet
9
+ Project-URL: Issues, https://github.com/salmonsnare/fxtensor-bayesnet/issues
10
+ Project-URL: Changelog, https://github.com/salmonsnare/fxtensor-bayesnet/blob/main/CHANGELOG.md
11
+ Keywords: bayesian-network,probabilistic-graphical-model,markov-kernel,conditional-probability,bayesian-inference,scenario-analysis,decision-support,fxtensor
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Natural Language :: English
17
+ Classifier: Natural Language :: Japanese
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy>=1.20.0
27
+ Requires-Dist: fxtensor-salmon<2,>=1.2.2
28
+ Provides-Extra: plot
29
+ Requires-Dist: matplotlib>=3.5; extra == "plot"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: matplotlib>=3.5; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # fxtensor-bayesnet
36
+
37
+ **English** | [日本語](https://github.com/salmonsnare/fxtensor-bayesnet/blob/main/README-ja.md)
38
+
39
+ A config-driven inference tool for discrete Bayesian networks, built on [fxtensor-salmon](https://github.com/salmonsnare/fxtensor-salmon).
40
+
41
+ ## Overview
42
+
43
+ fxtensor-bayesnet is a decision-support tool that expresses cause-and-effect relationships between events as conditional probabilities and quantifies their overall impact. Assumptions and probabilities live in a configuration file, so they can be revised quickly without changing any code. It supports comparing multiple scenarios as well as working backwards from observed outcomes to their likely causes. Because the configuration and results can be recorded daily, the rationale behind each judgement and how it changed over time can be tracked continuously.
44
+
45
+ How it works:
46
+
47
+ - Each variable is discrete and takes one of a finite set of labels (e.g. `Clear / Cloudy / Overcast`).
48
+ - Variables without parents (roots) get a prior distribution; child variables get a conditional probability table ("parent label combination → child distribution", i.e. a Markov kernel).
49
+ - The joint distribution is built by composing states and kernels with fxtensor-salmon's `FXTensor`. From it the tool computes marginals per scenario, conditioning on observations (Bayesian updating), and root-cause inference via `bayesian_inversion`.
50
+ - On every run, results computed with the library are cross-checked against a direct numpy `einsum` computation; any mismatch stops the run (see the `検算` ("checks") field of the results).
51
+ - When the joint distribution would exceed 2 million entries, the tool automatically switches to computing over ancestor sets only (same results).
52
+ - `--plot` renders the network structure, scenario comparison, Bayesian updates and day-over-day changes as PNG / SVG (requires matplotlib).
53
+
54
+ > The probabilities in a config are the user's assumptions. The results are consequences of those assumptions; the tool does not validate the assumptions themselves.
55
+
56
+ ## Installation
57
+
58
+ Python 3.8 or later. Install from PyPI:
59
+
60
+ ```bash
61
+ pip install fxtensor-bayesnet # core (pulls in numpy and fxtensor-salmon)
62
+ pip install "fxtensor-bayesnet[plot]" # with figures (adds matplotlib)
63
+ ```
64
+
65
+ For development:
66
+
67
+ ```bash
68
+ git clone https://github.com/salmonsnare/fxtensor-bayesnet.git
69
+ cd fxtensor-bayesnet
70
+ python3 -m venv .venv
71
+ . .venv/bin/activate
72
+ pip install -e ".[dev]" # includes pytest and matplotlib
73
+ pytest
74
+ ```
75
+
76
+ ## Quick start
77
+
78
+ Example configs live in `examples/` (they are not part of the PyPI package, so fetch them from the repository).
79
+
80
+ ```bash
81
+ curl -o config.json https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/examples/weather/config.en.json
82
+ fxtensor-bayesnet --check # defaults to ./config.json
83
+ fxtensor-bayesnet --no-write --md --lang en # Markdown to stdout
84
+ fxtensor-bayesnet --no-write --plot --lang en --out-dir out/ # figures only, into out/
85
+ # python -m fxtensor_bayesnet ... works the same way
86
+ ```
87
+
88
+ ## Writing a config
89
+
90
+ A config is a single JSON file. Minimal example:
91
+
92
+ ```json
93
+ {
94
+ "as_of": "2026-10-10",
95
+ "horizon": "Next day",
96
+ "note": "All probabilities are assumptions",
97
+ "variables": {
98
+ "cloud": {"name": "Cloud cover", "labels": ["Clear", "Cloudy"]},
99
+ "rain": {"name": "Precipitation", "labels": ["None", "Some"]}
100
+ },
101
+ "priors": {
102
+ "cloud": {"p": [0.6, 0.4], "reason": "free-text rationale (optional)"}
103
+ },
104
+ "kernels": {
105
+ "rain": {
106
+ "parents": ["cloud"],
107
+ "reason": "free-text rationale (optional)",
108
+ "cpt": {
109
+ "Clear": [0.95, 0.05],
110
+ "Cloudy": [0.6, 0.4]
111
+ }
112
+ }
113
+ },
114
+ "scenarios": {
115
+ "A: Mostly cloudy": {"cloud": [0.2, 0.8]}
116
+ },
117
+ "observations": [
118
+ {"var": "rain", "label": "Some", "focus": ["cloud"]}
119
+ ],
120
+ "outputs": ["rain"]
121
+ }
122
+ ```
123
+
124
+ | Key | Required | Meaning |
125
+ |---|---|---|
126
+ | `as_of` | yes | Reference date (`YYYY-MM-DD`); used as the snapshot folder name |
127
+ | `horizon` / `note` | | Forecast horizon and a note (shown in the results) |
128
+ | `variables` | yes | Variable → `{"name": display name, "labels": [labels…]}`. At least 2 labels, no duplicates |
129
+ | `priors` | yes | Root variable → `{"p": [probability per label], "reason": optional}`. Must sum to 1 |
130
+ | `kernels` | yes | Child variable → `{"parents": [parents…], "cpt": {...}, "reason": optional}` |
131
+ | `scenarios` | | Scenario name → `{root variable: replacement prior}`. A base scenario is always included |
132
+ | `observations` | | `{"var", "label", "focus"}`. Computes posteriors given `var=label`. For the `focus` variables it also reports prior→posterior movement (difference, total variation distance TV, KL) and ranks them by movement (defaults to all roots) |
133
+ | `outputs` | | Variables shown in the result tables (defaults to all non-root variables) |
134
+
135
+ Writing a `cpt`:
136
+
137
+ - Each key joins the parents' labels with `|`, in `parents` order (e.g. with parents `["load", "age"]`: `"High|Old"`).
138
+ - Each value lists probabilities in the child's label order; every row must sum to 1.
139
+ - Every combination of parent labels needs a row (missing or extra rows are reported by `--check`).
140
+ - Each variable goes in exactly one of `priors` or `kernels`. No cycles. Up to 52 variables.
141
+
142
+ ## CLI
143
+
144
+ ```
145
+ fxtensor-bayesnet [--config PATH] [options]
146
+ ```
147
+
148
+ | Option | Meaning |
149
+ |---|---|
150
+ | `--config PATH` | Config file (default: `config.json` in the current directory) |
151
+ | `--check` | Validate the config only (rows sum to 1, missing/extra rows, undefined parents, cycles, …). Reports all errors and exits with code 2 |
152
+ | `--no-write` | Do not write `results.json` / `results.md` / `model.mmd`; print to stdout only |
153
+ | `--md` | Print Markdown instead of JSON |
154
+ | `--lang ja\|en` | Language of Markdown and figure titles/legends (default `ja`). The keys in `results.json` are fixed regardless of language |
155
+ | `--snapshot` | Save the config and results to `<history-dir>/<as_of>/` (exit code 1 if it already exists) |
156
+ | `--force` | Allow `--snapshot` to overwrite |
157
+ | `--diff [PATH]` | Diff against the previous snapshot (config changes plus result changes of 0.1 pt or more). Without PATH, the latest date before `as_of` is used |
158
+ | `--format-config` | Rewrite the config in a readable layout (one kernel row per line) |
159
+ | `--out-dir DIR` | Where results and figures go (default: the config's folder) |
160
+ | `--history-dir DIR` | Where snapshots go (default: `history/` next to the config) |
161
+ | `--plot` | Write figures to `--out-dir` (see below). Figures are written even with `--no-write`; ignored with `--check` |
162
+ | `--plot-format F…` | Figure format(s): `png` / `svg` (several allowed; default `png`) |
163
+ | `--plot-dpi N` | PNG resolution (default 150) |
164
+
165
+ Output files:
166
+
167
+ - `results.json` – priors, marginals per scenario, Bayesian updates, checks
168
+ - `results.md` – scenario tables and a summary of the Bayesian updates
169
+ - `model.mmd` – network structure as mermaid (roots, intermediate and output variables colour-coded)
170
+
171
+ ### Figures (`--plot`)
172
+
173
+ Requires matplotlib (`pip install "fxtensor-bayesnet[plot]"`). If it is missing, `--plot` prints installation instructions and exits with code 3 (everything else works without matplotlib).
174
+
175
+ | File | Contents | When |
176
+ |---|---|---|
177
+ | `network.png` | Network structure. Roots (blue), intermediate (grey) and output variables (orange), drawn with a layered layout (no graphviz needed) | normal run |
178
+ | `marginals.png` | Bar charts of each output variable's marginal, scenarios side by side | normal run |
179
+ | `updates.png` | For each observation, prior vs posterior of the focus variables (with TV distance) | when `observations` is set |
180
+ | `diff.png` | Change in marginals (pt) since the previous snapshot, per scenario | `--diff --plot` with a previous `results.json` |
181
+
182
+ ```bash
183
+ fxtensor-bayesnet --plot # results + figures (network / marginals / updates)
184
+ fxtensor-bayesnet --plot --plot-format png svg # both PNG and SVG
185
+ fxtensor-bayesnet --no-write --plot --lang en --out-dir figs/
186
+ fxtensor-bayesnet --diff --plot # diff + diff.png
187
+ ```
188
+
189
+ A font that can display Japanese (Noto Sans CJK JP, IPAexGothic, Hiragino Sans, Yu Gothic, Meiryo, …) is picked automatically so that Japanese labels render. If none is found, a warning is issued and the default font is used. Set the `FXTENSOR_BAYESNET_FONT` environment variable to choose a font. SVGs store text as paths, so they don't depend on the viewer's fonts.
190
+
191
+ ### Daily workflow
192
+
193
+ ```bash
194
+ cd my-model/ # folder containing config.json
195
+ # 1. update as_of, priors and (if needed) kernels in config.json
196
+ fxtensor-bayesnet --check # validate
197
+ fxtensor-bayesnet --diff # changes since the previous snapshot
198
+ fxtensor-bayesnet --snapshot --md # run, update results.*, record history/<as_of>/
199
+ fxtensor-bayesnet --plot --no-write # refresh figures
200
+ ```
201
+
202
+ ## Examples
203
+
204
+ `examples/` has two examples (probabilities are illustrative). Each comes as a Japanese `config.json` and a numerically identical English `config.en.json`. The figures below were generated from the English configs with `python docs/make_images.py` and are stored in `docs/images/en/` (Japanese versions in `docs/images/`).
205
+
206
+ ### Weather (`examples/weather/config.en.json`)
207
+
208
+ - Scenarios: "A: Typhoon approaching", "B: Dry spell"
209
+ - Observations: infer the pressure pattern and humidity from `rain=Heavy`, `traffic=Jammed`, `event=Cancelled`
210
+
211
+ Structure (mermaid; rendered as a diagram on GitHub):
212
+
213
+ ```mermaid
214
+ graph TD
215
+ pressure["pressure: Pressure pattern<br/>High pressure/Stationary front/Low approaching"]
216
+ humidity["humidity: Humidity<br/>Low/Medium/High"]
217
+ cloud["cloud: Cloud cover<br/>Clear/Cloudy/Overcast"]
218
+ rain["rain: Precipitation<br/>None/Light/Heavy"]
219
+ event["event: Outdoor event<br/>As planned/Shortened/Cancelled"]
220
+ traffic["traffic: Road traffic<br/>Smooth/Busy/Jammed"]
221
+ pressure --> cloud
222
+ humidity --> cloud
223
+ cloud --> rain
224
+ pressure --> rain
225
+ rain --> event
226
+ rain --> traffic
227
+ classDef root fill:#cfe3f7,stroke:#3b78b5
228
+ class pressure,humidity root
229
+ classDef output fill:#fde2c4,stroke:#d9822b
230
+ class cloud,rain,event,traffic output
231
+
232
+ ```
233
+
234
+ Network structure (`network.png` from `--plot`):
235
+
236
+ ![Weather: network structure](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/weather_network.png)
237
+
238
+ Marginals by scenario (`marginals.png`):
239
+
240
+ ![Weather: marginals by scenario](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/weather_marginals.png)
241
+
242
+ Bayesian update, prior vs posterior (`updates.png`). For example, observing heavy rain raises "Low approaching" for the pressure pattern from 25% to 67%:
243
+
244
+ ![Weather: Bayesian update](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/weather_updates.png)
245
+
246
+ Day-over-day change (`diff.png` from `--diff --plot`): the next day, the pressure and humidity priors are revised. Scenarios A and B override the pressure prior (B also humidity), so they change less (B not at all):
247
+
248
+ ![Weather: change since previous snapshot](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/weather_diff.png)
249
+
250
+ ### Equipment maintenance (`examples/maintenance/config.en.json`)
251
+
252
+ - Scenarios: "A: Peak season (high load)", "B: Stronger maintenance"
253
+ - Observations: infer load, age and maintenance status from `vibration=Abnormal`, `failure=Shutdown`, `temp=Elevated`
254
+ - `wear` (component wear) is not in `outputs`, so it is an intermediate variable and drawn in grey
255
+
256
+ ```mermaid
257
+ graph TD
258
+ load["load: Operating load<br/>Low/Medium/High"]
259
+ age["age: Equipment age<br/>New/Mid-life/Old"]
260
+ service["service: Scheduled maintenance<br/>On schedule/Delayed"]
261
+ wear["wear: Component wear (intermediate)<br/>Low/Medium/High"]
262
+ vibration["vibration: Vibration sensor<br/>Normal/Warning/Abnormal"]
263
+ temp["temp: Bearing temperature<br/>Normal/Elevated"]
264
+ failure["failure: Failure<br/>None/Minor/Shutdown"]
265
+ load --> wear
266
+ age --> wear
267
+ service --> wear
268
+ wear --> vibration
269
+ wear --> temp
270
+ load --> temp
271
+ wear --> failure
272
+ temp --> failure
273
+ classDef root fill:#cfe3f7,stroke:#3b78b5
274
+ class load,age,service root
275
+ classDef middle fill:#e6e6e6,stroke:#777777
276
+ class wear middle
277
+ classDef output fill:#fde2c4,stroke:#d9822b
278
+ class vibration,temp,failure output
279
+
280
+ ```
281
+
282
+ ![Maintenance: network structure](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/maintenance_network.png)
283
+
284
+ ![Maintenance: marginals by scenario](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/maintenance_marginals.png)
285
+
286
+ ![Maintenance: Bayesian update](https://raw.githubusercontent.com/salmonsnare/fxtensor-bayesnet/v0.9.0/docs/images/en/maintenance_updates.png)
287
+
288
+ Sample output (maintenance, excerpt of `--md --lang en`):
289
+
290
+ ```
291
+ ## failure (Failure)
292
+ | Scenario | None | Minor | Shutdown |
293
+ |---|---|---|---|
294
+ | Base | 85.9% | 9.2% | 4.9% |
295
+ | A: Peak season (high load) | 83.2% | 10.7% | 6.1% |
296
+ | B: Stronger maintenance | 86.8% | 8.7% | 4.5% |
297
+
298
+ ### Observed vibration=Abnormal (prior probability 11.2%)
299
+ - wear: Low 8.5% / Medium 32.2% / High 59.3%
300
+ - Ranking by movement (TV): age > load > service
301
+ ```
302
+
303
+ ## Python API
304
+
305
+ ```python
306
+ from fxtensor_bayesnet import load_config, run
307
+
308
+ cfg = load_config("examples/weather/config.en.json")
309
+ res = run(cfg)
310
+ # result keys are fixed (Japanese): "シナリオ" = scenarios, "周辺" = marginals, "基本" = base
311
+ print(res["シナリオ"]["A: Typhoon approaching"]["周辺"]["rain"])
312
+
313
+ # figures (requires matplotlib)
314
+ from fxtensor_bayesnet.plot import plot_all, plot_network
315
+ plot_network(cfg, "network.svg", lang="en")
316
+ plot_all(res, cfg, "figs", formats=("png",), lang="en")
317
+ ```
318
+
319
+ ## Layout
320
+
321
+ ```
322
+ src/fxtensor_bayesnet/
323
+ config.py loading, validation, formatting and hashing of configs
324
+ network.py building states/kernels with FXTensor; direct einsum computation
325
+ inference.py marginals per scenario, Bayesian updates, root-cause inference, checks
326
+ report.py Markdown / mermaid output
327
+ history.py snapshots and diffs
328
+ plot.py figures (structure, scenarios, updates, changes; matplotlib optional)
329
+ i18n.py strings for Markdown and figures (Japanese / English)
330
+ cli.py command line
331
+ tests/ pytest
332
+ examples/ example configs (Japanese and English)
333
+ docs/images/ README figures (regenerate with docs/make_images.py)
334
+ ```
335
+
336
+ ## Dependencies
337
+
338
+ - [fxtensor-salmon](https://github.com/salmonsnare/fxtensor-salmon) (MIT License) – `fxtensor-salmon>=1.2.2,<2` from PyPI; not vendored.
339
+ - numpy
340
+ - matplotlib (optional, `[plot]`) – only for figures
341
+
342
+ ## License
343
+
344
+ MIT License. See [LICENSE](https://github.com/salmonsnare/fxtensor-bayesnet/blob/main/LICENSE).
345
+
346
+ See [CHANGELOG.md](https://github.com/salmonsnare/fxtensor-bayesnet/blob/main/CHANGELOG.md) for the release history.