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.
- fxtensor_bayesnet-0.9.0/CHANGELOG.md +26 -0
- fxtensor_bayesnet-0.9.0/LICENSE +21 -0
- fxtensor_bayesnet-0.9.0/MANIFEST.in +7 -0
- fxtensor_bayesnet-0.9.0/PKG-INFO +346 -0
- fxtensor_bayesnet-0.9.0/README-ja.md +311 -0
- fxtensor_bayesnet-0.9.0/README.md +312 -0
- fxtensor_bayesnet-0.9.0/docs/make_images.py +42 -0
- fxtensor_bayesnet-0.9.0/examples/maintenance/config.en.json +137 -0
- fxtensor_bayesnet-0.9.0/examples/maintenance/config.json +137 -0
- fxtensor_bayesnet-0.9.0/examples/weather/config.en.json +118 -0
- fxtensor_bayesnet-0.9.0/examples/weather/config.json +118 -0
- fxtensor_bayesnet-0.9.0/pyproject.toml +60 -0
- fxtensor_bayesnet-0.9.0/setup.cfg +4 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/__init__.py +9 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/__main__.py +5 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/cli.py +148 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/config.py +136 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/history.py +90 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/i18n.py +74 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/inference.py +144 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/network.py +133 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/plot.py +407 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet/report.py +66 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/PKG-INFO +346 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/SOURCES.txt +34 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/dependency_links.txt +1 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/entry_points.txt +2 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/requires.txt +9 -0
- fxtensor_bayesnet-0.9.0/src/fxtensor_bayesnet.egg-info/top_level.txt +1 -0
- fxtensor_bayesnet-0.9.0/tests/conftest.py +27 -0
- fxtensor_bayesnet-0.9.0/tests/test_bayes.py +93 -0
- fxtensor_bayesnet-0.9.0/tests/test_cli.py +77 -0
- fxtensor_bayesnet-0.9.0/tests/test_config.py +103 -0
- fxtensor_bayesnet-0.9.0/tests/test_einsum.py +64 -0
- fxtensor_bayesnet-0.9.0/tests/test_en.py +58 -0
- 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,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
|
+

|
|
237
|
+
|
|
238
|
+
Marginals by scenario (`marginals.png`):
|
|
239
|
+
|
|
240
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
283
|
+
|
|
284
|
+

|
|
285
|
+
|
|
286
|
+

|
|
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.
|