mdbench 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.
- mdbench-0.1.0/LICENSE +0 -0
- mdbench-0.1.0/PKG-INFO +237 -0
- mdbench-0.1.0/README.md +212 -0
- mdbench-0.1.0/mdbench.egg-info/PKG-INFO +237 -0
- mdbench-0.1.0/mdbench.egg-info/SOURCES.txt +73 -0
- mdbench-0.1.0/mdbench.egg-info/dependency_links.txt +1 -0
- mdbench-0.1.0/mdbench.egg-info/entry_points.txt +2 -0
- mdbench-0.1.0/mdbench.egg-info/requires.txt +17 -0
- mdbench-0.1.0/mdbench.egg-info/top_level.txt +1 -0
- mdbench-0.1.0/pyproject.toml +41 -0
- mdbench-0.1.0/setup.cfg +4 -0
- mdbench-0.1.0/src/cli/run.py +69 -0
- mdbench-0.1.0/src/core/__init__.py +8 -0
- mdbench-0.1.0/src/core/problem.py +81 -0
- mdbench-0.1.0/src/core/solution.py +25 -0
- mdbench-0.1.0/src/evaluate_result.py +690 -0
- mdbench-0.1.0/src/features/__init__.py +21 -0
- mdbench-0.1.0/src/features/answer.py +45 -0
- mdbench-0.1.0/src/features/evaluation/__init__.py +9 -0
- mdbench-0.1.0/src/features/evaluation/evaluation_package.py +103 -0
- mdbench-0.1.0/src/features/evaluation/mechanism_trace.py +162 -0
- mdbench-0.1.0/src/features/io/__init__.py +10 -0
- mdbench-0.1.0/src/features/io/load_problem.py +160 -0
- mdbench-0.1.0/src/features/io/load_submission.py +154 -0
- mdbench-0.1.0/src/features/io/solve_mechanism_equations.py +281 -0
- mdbench-0.1.0/src/features/sampling/__init__.py +5 -0
- mdbench-0.1.0/src/features/sampling/range_inferrer.py +45 -0
- mdbench-0.1.0/src/features/units/__init__.py +5 -0
- mdbench-0.1.0/src/features/units/unit_inference.py +130 -0
- mdbench-0.1.0/src/features/validation/__init__.py +14 -0
- mdbench-0.1.0/src/features/validation/mechanism_derivation.py +86 -0
- mdbench-0.1.0/src/features/validation/mechanism_fundamentality.py +208 -0
- mdbench-0.1.0/src/features/visualization/__init__.py +5 -0
- mdbench-0.1.0/src/features/visualization/mechanism_graph.py +258 -0
- mdbench-0.1.0/src/metrics/__init__.py +20 -0
- mdbench-0.1.0/src/metrics/formula_similarity.py +46 -0
- mdbench-0.1.0/src/metrics/hybrid_formula_similarity.py +232 -0
- mdbench-0.1.0/src/metrics/mechanism_fundamentality.py +116 -0
- mdbench-0.1.0/src/metrics/mechanism_similarity.py +225 -0
- mdbench-0.1.0/src/metrics/mechanism_simplicity.py +34 -0
- mdbench-0.1.0/src/prepare_problem.py +280 -0
- mdbench-0.1.0/src/synthetic_data.py +247 -0
- mdbench-0.1.0/src/utils/__init__.py +8 -0
- mdbench-0.1.0/src/utils/console.py +15 -0
- mdbench-0.1.0/src/utils/lazy_loader.py +37 -0
- mdbench-0.1.0/src/utils/llm/__init__.py +22 -0
- mdbench-0.1.0/src/utils/llm/core.py +69 -0
- mdbench-0.1.0/src/utils/llm/deepseek_api.py +111 -0
- mdbench-0.1.0/src/utils/llm/gemini_api.py +99 -0
- mdbench-0.1.0/src/utils/llm/llm_api.py +159 -0
- mdbench-0.1.0/src/utils/llm/manual_api.py +56 -0
- mdbench-0.1.0/src/utils/llm/openai_api.py +303 -0
- mdbench-0.1.0/src/utils/llm/openrouter_api.py +141 -0
- mdbench-0.1.0/src/utils/llm/siliconflow_api.py +175 -0
- mdbench-0.1.0/src/utils/llm/tool_call_mixin.py +80 -0
- mdbench-0.1.0/src/utils/log_exception.py +12 -0
- mdbench-0.1.0/src/utils/logger.py +330 -0
- mdbench-0.1.0/src/utils/path_utils.py +28 -0
- mdbench-0.1.0/src/utils/tag2ansi.py +165 -0
- mdbench-0.1.0/src/utils/unit_parser.py +48 -0
- mdbench-0.1.0/src/validate_problem.py +344 -0
- mdbench-0.1.0/src/visualize_mechanism.py +48 -0
- mdbench-0.1.0/tests/test_evaluation_modes.py +162 -0
- mdbench-0.1.0/tests/test_evaluation_trace.py +93 -0
- mdbench-0.1.0/tests/test_hybrid_formula_similarity.py +52 -0
- mdbench-0.1.0/tests/test_implicit_solver.py +261 -0
- mdbench-0.1.0/tests/test_load_problem.py +176 -0
- mdbench-0.1.0/tests/test_load_submission.py +140 -0
- mdbench-0.1.0/tests/test_mechanism_fundamentality.py +164 -0
- mdbench-0.1.0/tests/test_mechanism_graph.py +87 -0
- mdbench-0.1.0/tests/test_prepare_and_score.py +281 -0
- mdbench-0.1.0/tests/test_structural_mechanism_similarity.py +43 -0
- mdbench-0.1.0/tests/test_synthetic_data.py +68 -0
- mdbench-0.1.0/tests/test_unit_inference.py +81 -0
- mdbench-0.1.0/tests/test_validate_problem.py +154 -0
mdbench-0.1.0/LICENSE
ADDED
|
File without changes
|
mdbench-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mdbench
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A benchmark for discovering scientific mechanisms
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: numpy>=1.24
|
|
9
|
+
Requires-Dist: PyYAML>=6.0
|
|
10
|
+
Requires-Dist: nd2py>=3.2.3
|
|
11
|
+
Requires-Dist: openai>=1.0
|
|
12
|
+
Requires-Dist: google-genai>=1.0
|
|
13
|
+
Requires-Dist: requests>=2.28
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0
|
|
15
|
+
Requires-Dist: sympy>=1.13
|
|
16
|
+
Requires-Dist: scipy>=1.14
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
19
|
+
Requires-Dist: sphinx>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: sphinx-book-theme>=1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: myst-parser>=3.0; extra == "dev"
|
|
22
|
+
Requires-Dist: sphinx-autodoc-typehints>=2.0; extra == "dev"
|
|
23
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# MDBench
|
|
27
|
+
|
|
28
|
+
[简体中文](README.zh-CN.md)
|
|
29
|
+
|
|
30
|
+
MDBench evaluates whether an AI system can recover scientific laws and the
|
|
31
|
+
mechanisms that produce them from equations or observations.
|
|
32
|
+
|
|
33
|
+
## What mechanism discovery means
|
|
34
|
+
|
|
35
|
+
MDBench treats a phenomenological equation as the observable consequence of
|
|
36
|
+
several simple, mutually consistent relationships. The phenomenological law
|
|
37
|
+
describes *what* variables do; a mechanism explains *why* through physical
|
|
38
|
+
relationships, assumptions, and intermediate variables.
|
|
39
|
+
|
|
40
|
+
For example, Kepler's third law for a circular orbit follows from gravitation,
|
|
41
|
+
Newton's second law, and uniform circular motion. See
|
|
42
|
+
[`problems/demo_problem.yaml`](problems/demo_problem.yaml).
|
|
43
|
+
|
|
44
|
+
Each mechanism relationship uses `variable = formula`, where the formula must
|
|
45
|
+
be parseable by [nd2py](https://pypi.org/project/nd2py/). Explicit relationships
|
|
46
|
+
form a DAG:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
a = f1(x)
|
|
50
|
+
b = f2(x, a)
|
|
51
|
+
y = f3(x, a, b)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Implicit systems are also supported. Relationships are collected until the
|
|
55
|
+
unknown variables form a closed system, then solved symbolically or with a
|
|
56
|
+
numerical root finder:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
a = f1(x, a, b)
|
|
60
|
+
b = f2(x, a, b)
|
|
61
|
+
y = f3(x, a, b)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
All variables are declared under `variable_description` as `target`, `inputs`,
|
|
65
|
+
`intermediates`, or `auxiliary_inputs`. The latter are external variables used
|
|
66
|
+
only by the mechanism and eliminated from the final law. The original
|
|
67
|
+
relationships remain in `Problem.mechanism`; executable solution steps are
|
|
68
|
+
stored in `Problem.solution`.
|
|
69
|
+
|
|
70
|
+
## Tasks and evaluation
|
|
71
|
+
|
|
72
|
+
MDBench provides three tasks:
|
|
73
|
+
|
|
74
|
+
1. **Symbolic regression:** `(X, y) → phenomenological equation`.
|
|
75
|
+
2. **Mechanism explanation:** phenomenological equation → mechanism equations.
|
|
76
|
+
3. **Mechanism discovery:** `(X, y) → mechanism equations`.
|
|
77
|
+
|
|
78
|
+
Mechanism evaluation reports independent metrics and deliberately has no
|
|
79
|
+
overall score:
|
|
80
|
+
|
|
81
|
+
- **Prediction accuracy:** for symbolic regression and mechanism discovery,
|
|
82
|
+
Pearson correlation, R², MAE, RMSE, sMAPE, and tolerance accuracy on public
|
|
83
|
+
training data (feedback) or train/ID/OOD data (final).
|
|
84
|
+
- **Derived-equation equivalence:** final-only SymPy, numeric, and LLM
|
|
85
|
+
cross-check against the private phenomenological equation.
|
|
86
|
+
- **Mechanism fundamentality:** LLM assessment dominated by the least
|
|
87
|
+
fundamental submitted relationship; no reference answer is required.
|
|
88
|
+
- **Ground-truth structure recovery:** soft formula-AST and dependency-graph
|
|
89
|
+
matching against the reference mechanism. Variable names and numeric literal
|
|
90
|
+
values are ignored.
|
|
91
|
+
- **Mechanism description complexity:** reference-free mean, maximum, and total
|
|
92
|
+
nd2py AST nodes; lower values describe simpler submitted relationships.
|
|
93
|
+
|
|
94
|
+
Install MDBench with Python 3.12 or newer:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install -e ".[dev]"
|
|
98
|
+
mdbench --help
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The Sphinx documentation lives in [`docs/`](docs/). Build it with:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cd docs
|
|
105
|
+
make html
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Commands
|
|
109
|
+
|
|
110
|
+
All lifecycle commands accept one or more YAML files or directories through
|
|
111
|
+
`--problems`; the default is `./problems`.
|
|
112
|
+
|
|
113
|
+
### Validate problems
|
|
114
|
+
|
|
115
|
+
Checks schemas, variable usage, units, sampling specifications, explicit and
|
|
116
|
+
implicit equation solving, and derivation of the target law:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
mdbench validate
|
|
120
|
+
mdbench validate --problems problems/demo_problem.yaml
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
An optional LLM check evaluates whether every relationship is sufficiently
|
|
124
|
+
fundamental. API or response failures are reported directly and do not fall
|
|
125
|
+
back to heuristics.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
mdbench validate --check-fundamentality \
|
|
129
|
+
--llm-provider deepseek --llm-model deepseek-v4-flash
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Generate synthetic data
|
|
133
|
+
|
|
134
|
+
Creates reproducible train, ID-test, and OOD-test splits:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
mdbench synthetic --problems problems/ --output-dir data/synthetic_data/
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Each NPZ stores the three arrays, their row order in `variables`, and a JSON
|
|
141
|
+
`generation_config` containing the seed and sample counts. Auxiliary inputs are
|
|
142
|
+
generated here and may be hidden later during task preparation.
|
|
143
|
+
|
|
144
|
+
### Prepare tasks
|
|
145
|
+
|
|
146
|
+
Synthetic data must already exist. Answers are private by default:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
mdbench prepare \
|
|
150
|
+
--problems problems/ \
|
|
151
|
+
--synthetic-data-dir data/synthetic_data/ \
|
|
152
|
+
--task mechanism_discovery \
|
|
153
|
+
--format directory
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use `--save-answer` to include answers and test splits, `--reveal-auxiliary` to
|
|
157
|
+
expose auxiliary inputs in mechanism tasks, and `--force` to approve planned
|
|
158
|
+
overwrites. Existing directories are never cleared; redundant files are
|
|
159
|
+
reported. `--format directory` writes flat files, while `--format file` packs
|
|
160
|
+
the same logical artifacts into one NPZ.
|
|
161
|
+
|
|
162
|
+
### Evaluate submissions
|
|
163
|
+
|
|
164
|
+
A submission may be an inline formula, semicolon-separated mechanism equations,
|
|
165
|
+
or a plain-text file with one equation per non-empty line. JSON and YAML
|
|
166
|
+
submissions are intentionally unsupported.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
mdbench evaluate \
|
|
170
|
+
--evaluation-mode feedback \
|
|
171
|
+
--problem data/problem/PREPARED_TASK \
|
|
172
|
+
--submission submission.txt \
|
|
173
|
+
--verbose
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Feedback mode uses only the public task and training data. Benchmark operators
|
|
177
|
+
run final evaluation with `--evaluation-mode final --answer answer.json`, which
|
|
178
|
+
also enables hidden ID/OOD tests and reference-mechanism recovery. For Agent
|
|
179
|
+
runs, copy only the prepared public task into an isolated temporary working
|
|
180
|
+
directory and require the Agent to remain there. Without source problem YAML or
|
|
181
|
+
private answer artifacts, the other lifecycle commands and final evaluation
|
|
182
|
+
cannot access the material they require. `--verbose` prints concise equation
|
|
183
|
+
chains for explicit or implicit solution steps.
|
|
184
|
+
|
|
185
|
+
Fundamentality scoring automatically uses the configured external model and
|
|
186
|
+
prints its provider and model:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
mdbench evaluate \
|
|
190
|
+
--evaluation-mode feedback \
|
|
191
|
+
--problem data/problem/PREPARED_TASK \
|
|
192
|
+
--submission submission.txt \
|
|
193
|
+
--llm-provider deepseek \
|
|
194
|
+
--llm-model deepseek-v4-flash
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Standalone entry points with equivalent behavior are available in `scripts/`:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
validate_problem_main.py validate problem definitions
|
|
201
|
+
synthetic_data_main.py generate synthetic datasets
|
|
202
|
+
prepare_problem_main.py prepare public/private task artifacts
|
|
203
|
+
evaluate_result_main.py evaluate a submission
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`scripts/visualize_mechanism_main.py` renders a solved mechanism as DOT, SVG,
|
|
207
|
+
PNG, or PDF. Non-DOT formats require Graphviz.
|
|
208
|
+
|
|
209
|
+
## Directory conventions
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
problems/ source problem YAML files
|
|
213
|
+
data/
|
|
214
|
+
synthetic_data/ generated train/ID/OOD datasets
|
|
215
|
+
problem/ prepared benchmark tasks
|
|
216
|
+
src/
|
|
217
|
+
core/ dependency-light data models
|
|
218
|
+
features/ project-specific I/O, solving, validation, sampling
|
|
219
|
+
metrics/ formula and mechanism metrics
|
|
220
|
+
utils/ reusable utilities and LLM clients
|
|
221
|
+
scripts/ standalone command entry points
|
|
222
|
+
tests/ unit tests and validation fixtures
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
A prepared directory contains:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
problem.json public task description
|
|
229
|
+
data_train.npy public training data
|
|
230
|
+
answer.json optional private answer
|
|
231
|
+
data_id_test.npy optional private ID test data
|
|
232
|
+
data_ood_test.npy optional private OOD test data
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Without `--save-answer`, only `problem.json` and `data_train.npy` are written.
|
|
236
|
+
Public interchange types remain simple: units are `Dict[str, int | float]`,
|
|
237
|
+
formulas are nd2py-compatible strings, and arrays use NumPy formats.
|
mdbench-0.1.0/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# MDBench
|
|
2
|
+
|
|
3
|
+
[简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
MDBench evaluates whether an AI system can recover scientific laws and the
|
|
6
|
+
mechanisms that produce them from equations or observations.
|
|
7
|
+
|
|
8
|
+
## What mechanism discovery means
|
|
9
|
+
|
|
10
|
+
MDBench treats a phenomenological equation as the observable consequence of
|
|
11
|
+
several simple, mutually consistent relationships. The phenomenological law
|
|
12
|
+
describes *what* variables do; a mechanism explains *why* through physical
|
|
13
|
+
relationships, assumptions, and intermediate variables.
|
|
14
|
+
|
|
15
|
+
For example, Kepler's third law for a circular orbit follows from gravitation,
|
|
16
|
+
Newton's second law, and uniform circular motion. See
|
|
17
|
+
[`problems/demo_problem.yaml`](problems/demo_problem.yaml).
|
|
18
|
+
|
|
19
|
+
Each mechanism relationship uses `variable = formula`, where the formula must
|
|
20
|
+
be parseable by [nd2py](https://pypi.org/project/nd2py/). Explicit relationships
|
|
21
|
+
form a DAG:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
a = f1(x)
|
|
25
|
+
b = f2(x, a)
|
|
26
|
+
y = f3(x, a, b)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Implicit systems are also supported. Relationships are collected until the
|
|
30
|
+
unknown variables form a closed system, then solved symbolically or with a
|
|
31
|
+
numerical root finder:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
a = f1(x, a, b)
|
|
35
|
+
b = f2(x, a, b)
|
|
36
|
+
y = f3(x, a, b)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
All variables are declared under `variable_description` as `target`, `inputs`,
|
|
40
|
+
`intermediates`, or `auxiliary_inputs`. The latter are external variables used
|
|
41
|
+
only by the mechanism and eliminated from the final law. The original
|
|
42
|
+
relationships remain in `Problem.mechanism`; executable solution steps are
|
|
43
|
+
stored in `Problem.solution`.
|
|
44
|
+
|
|
45
|
+
## Tasks and evaluation
|
|
46
|
+
|
|
47
|
+
MDBench provides three tasks:
|
|
48
|
+
|
|
49
|
+
1. **Symbolic regression:** `(X, y) → phenomenological equation`.
|
|
50
|
+
2. **Mechanism explanation:** phenomenological equation → mechanism equations.
|
|
51
|
+
3. **Mechanism discovery:** `(X, y) → mechanism equations`.
|
|
52
|
+
|
|
53
|
+
Mechanism evaluation reports independent metrics and deliberately has no
|
|
54
|
+
overall score:
|
|
55
|
+
|
|
56
|
+
- **Prediction accuracy:** for symbolic regression and mechanism discovery,
|
|
57
|
+
Pearson correlation, R², MAE, RMSE, sMAPE, and tolerance accuracy on public
|
|
58
|
+
training data (feedback) or train/ID/OOD data (final).
|
|
59
|
+
- **Derived-equation equivalence:** final-only SymPy, numeric, and LLM
|
|
60
|
+
cross-check against the private phenomenological equation.
|
|
61
|
+
- **Mechanism fundamentality:** LLM assessment dominated by the least
|
|
62
|
+
fundamental submitted relationship; no reference answer is required.
|
|
63
|
+
- **Ground-truth structure recovery:** soft formula-AST and dependency-graph
|
|
64
|
+
matching against the reference mechanism. Variable names and numeric literal
|
|
65
|
+
values are ignored.
|
|
66
|
+
- **Mechanism description complexity:** reference-free mean, maximum, and total
|
|
67
|
+
nd2py AST nodes; lower values describe simpler submitted relationships.
|
|
68
|
+
|
|
69
|
+
Install MDBench with Python 3.12 or newer:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install -e ".[dev]"
|
|
73
|
+
mdbench --help
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The Sphinx documentation lives in [`docs/`](docs/). Build it with:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cd docs
|
|
80
|
+
make html
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Commands
|
|
84
|
+
|
|
85
|
+
All lifecycle commands accept one or more YAML files or directories through
|
|
86
|
+
`--problems`; the default is `./problems`.
|
|
87
|
+
|
|
88
|
+
### Validate problems
|
|
89
|
+
|
|
90
|
+
Checks schemas, variable usage, units, sampling specifications, explicit and
|
|
91
|
+
implicit equation solving, and derivation of the target law:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
mdbench validate
|
|
95
|
+
mdbench validate --problems problems/demo_problem.yaml
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
An optional LLM check evaluates whether every relationship is sufficiently
|
|
99
|
+
fundamental. API or response failures are reported directly and do not fall
|
|
100
|
+
back to heuristics.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
mdbench validate --check-fundamentality \
|
|
104
|
+
--llm-provider deepseek --llm-model deepseek-v4-flash
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Generate synthetic data
|
|
108
|
+
|
|
109
|
+
Creates reproducible train, ID-test, and OOD-test splits:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
mdbench synthetic --problems problems/ --output-dir data/synthetic_data/
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Each NPZ stores the three arrays, their row order in `variables`, and a JSON
|
|
116
|
+
`generation_config` containing the seed and sample counts. Auxiliary inputs are
|
|
117
|
+
generated here and may be hidden later during task preparation.
|
|
118
|
+
|
|
119
|
+
### Prepare tasks
|
|
120
|
+
|
|
121
|
+
Synthetic data must already exist. Answers are private by default:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
mdbench prepare \
|
|
125
|
+
--problems problems/ \
|
|
126
|
+
--synthetic-data-dir data/synthetic_data/ \
|
|
127
|
+
--task mechanism_discovery \
|
|
128
|
+
--format directory
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `--save-answer` to include answers and test splits, `--reveal-auxiliary` to
|
|
132
|
+
expose auxiliary inputs in mechanism tasks, and `--force` to approve planned
|
|
133
|
+
overwrites. Existing directories are never cleared; redundant files are
|
|
134
|
+
reported. `--format directory` writes flat files, while `--format file` packs
|
|
135
|
+
the same logical artifacts into one NPZ.
|
|
136
|
+
|
|
137
|
+
### Evaluate submissions
|
|
138
|
+
|
|
139
|
+
A submission may be an inline formula, semicolon-separated mechanism equations,
|
|
140
|
+
or a plain-text file with one equation per non-empty line. JSON and YAML
|
|
141
|
+
submissions are intentionally unsupported.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
mdbench evaluate \
|
|
145
|
+
--evaluation-mode feedback \
|
|
146
|
+
--problem data/problem/PREPARED_TASK \
|
|
147
|
+
--submission submission.txt \
|
|
148
|
+
--verbose
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Feedback mode uses only the public task and training data. Benchmark operators
|
|
152
|
+
run final evaluation with `--evaluation-mode final --answer answer.json`, which
|
|
153
|
+
also enables hidden ID/OOD tests and reference-mechanism recovery. For Agent
|
|
154
|
+
runs, copy only the prepared public task into an isolated temporary working
|
|
155
|
+
directory and require the Agent to remain there. Without source problem YAML or
|
|
156
|
+
private answer artifacts, the other lifecycle commands and final evaluation
|
|
157
|
+
cannot access the material they require. `--verbose` prints concise equation
|
|
158
|
+
chains for explicit or implicit solution steps.
|
|
159
|
+
|
|
160
|
+
Fundamentality scoring automatically uses the configured external model and
|
|
161
|
+
prints its provider and model:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
mdbench evaluate \
|
|
165
|
+
--evaluation-mode feedback \
|
|
166
|
+
--problem data/problem/PREPARED_TASK \
|
|
167
|
+
--submission submission.txt \
|
|
168
|
+
--llm-provider deepseek \
|
|
169
|
+
--llm-model deepseek-v4-flash
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Standalone entry points with equivalent behavior are available in `scripts/`:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
validate_problem_main.py validate problem definitions
|
|
176
|
+
synthetic_data_main.py generate synthetic datasets
|
|
177
|
+
prepare_problem_main.py prepare public/private task artifacts
|
|
178
|
+
evaluate_result_main.py evaluate a submission
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`scripts/visualize_mechanism_main.py` renders a solved mechanism as DOT, SVG,
|
|
182
|
+
PNG, or PDF. Non-DOT formats require Graphviz.
|
|
183
|
+
|
|
184
|
+
## Directory conventions
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
problems/ source problem YAML files
|
|
188
|
+
data/
|
|
189
|
+
synthetic_data/ generated train/ID/OOD datasets
|
|
190
|
+
problem/ prepared benchmark tasks
|
|
191
|
+
src/
|
|
192
|
+
core/ dependency-light data models
|
|
193
|
+
features/ project-specific I/O, solving, validation, sampling
|
|
194
|
+
metrics/ formula and mechanism metrics
|
|
195
|
+
utils/ reusable utilities and LLM clients
|
|
196
|
+
scripts/ standalone command entry points
|
|
197
|
+
tests/ unit tests and validation fixtures
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
A prepared directory contains:
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
problem.json public task description
|
|
204
|
+
data_train.npy public training data
|
|
205
|
+
answer.json optional private answer
|
|
206
|
+
data_id_test.npy optional private ID test data
|
|
207
|
+
data_ood_test.npy optional private OOD test data
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Without `--save-answer`, only `problem.json` and `data_train.npy` are written.
|
|
211
|
+
Public interchange types remain simple: units are `Dict[str, int | float]`,
|
|
212
|
+
formulas are nd2py-compatible strings, and arrays use NumPy formats.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mdbench
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A benchmark for discovering scientific mechanisms
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: numpy>=1.24
|
|
9
|
+
Requires-Dist: PyYAML>=6.0
|
|
10
|
+
Requires-Dist: nd2py>=3.2.3
|
|
11
|
+
Requires-Dist: openai>=1.0
|
|
12
|
+
Requires-Dist: google-genai>=1.0
|
|
13
|
+
Requires-Dist: requests>=2.28
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0
|
|
15
|
+
Requires-Dist: sympy>=1.13
|
|
16
|
+
Requires-Dist: scipy>=1.14
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
19
|
+
Requires-Dist: sphinx>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: sphinx-book-theme>=1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: myst-parser>=3.0; extra == "dev"
|
|
22
|
+
Requires-Dist: sphinx-autodoc-typehints>=2.0; extra == "dev"
|
|
23
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# MDBench
|
|
27
|
+
|
|
28
|
+
[简体中文](README.zh-CN.md)
|
|
29
|
+
|
|
30
|
+
MDBench evaluates whether an AI system can recover scientific laws and the
|
|
31
|
+
mechanisms that produce them from equations or observations.
|
|
32
|
+
|
|
33
|
+
## What mechanism discovery means
|
|
34
|
+
|
|
35
|
+
MDBench treats a phenomenological equation as the observable consequence of
|
|
36
|
+
several simple, mutually consistent relationships. The phenomenological law
|
|
37
|
+
describes *what* variables do; a mechanism explains *why* through physical
|
|
38
|
+
relationships, assumptions, and intermediate variables.
|
|
39
|
+
|
|
40
|
+
For example, Kepler's third law for a circular orbit follows from gravitation,
|
|
41
|
+
Newton's second law, and uniform circular motion. See
|
|
42
|
+
[`problems/demo_problem.yaml`](problems/demo_problem.yaml).
|
|
43
|
+
|
|
44
|
+
Each mechanism relationship uses `variable = formula`, where the formula must
|
|
45
|
+
be parseable by [nd2py](https://pypi.org/project/nd2py/). Explicit relationships
|
|
46
|
+
form a DAG:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
a = f1(x)
|
|
50
|
+
b = f2(x, a)
|
|
51
|
+
y = f3(x, a, b)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Implicit systems are also supported. Relationships are collected until the
|
|
55
|
+
unknown variables form a closed system, then solved symbolically or with a
|
|
56
|
+
numerical root finder:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
a = f1(x, a, b)
|
|
60
|
+
b = f2(x, a, b)
|
|
61
|
+
y = f3(x, a, b)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
All variables are declared under `variable_description` as `target`, `inputs`,
|
|
65
|
+
`intermediates`, or `auxiliary_inputs`. The latter are external variables used
|
|
66
|
+
only by the mechanism and eliminated from the final law. The original
|
|
67
|
+
relationships remain in `Problem.mechanism`; executable solution steps are
|
|
68
|
+
stored in `Problem.solution`.
|
|
69
|
+
|
|
70
|
+
## Tasks and evaluation
|
|
71
|
+
|
|
72
|
+
MDBench provides three tasks:
|
|
73
|
+
|
|
74
|
+
1. **Symbolic regression:** `(X, y) → phenomenological equation`.
|
|
75
|
+
2. **Mechanism explanation:** phenomenological equation → mechanism equations.
|
|
76
|
+
3. **Mechanism discovery:** `(X, y) → mechanism equations`.
|
|
77
|
+
|
|
78
|
+
Mechanism evaluation reports independent metrics and deliberately has no
|
|
79
|
+
overall score:
|
|
80
|
+
|
|
81
|
+
- **Prediction accuracy:** for symbolic regression and mechanism discovery,
|
|
82
|
+
Pearson correlation, R², MAE, RMSE, sMAPE, and tolerance accuracy on public
|
|
83
|
+
training data (feedback) or train/ID/OOD data (final).
|
|
84
|
+
- **Derived-equation equivalence:** final-only SymPy, numeric, and LLM
|
|
85
|
+
cross-check against the private phenomenological equation.
|
|
86
|
+
- **Mechanism fundamentality:** LLM assessment dominated by the least
|
|
87
|
+
fundamental submitted relationship; no reference answer is required.
|
|
88
|
+
- **Ground-truth structure recovery:** soft formula-AST and dependency-graph
|
|
89
|
+
matching against the reference mechanism. Variable names and numeric literal
|
|
90
|
+
values are ignored.
|
|
91
|
+
- **Mechanism description complexity:** reference-free mean, maximum, and total
|
|
92
|
+
nd2py AST nodes; lower values describe simpler submitted relationships.
|
|
93
|
+
|
|
94
|
+
Install MDBench with Python 3.12 or newer:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install -e ".[dev]"
|
|
98
|
+
mdbench --help
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The Sphinx documentation lives in [`docs/`](docs/). Build it with:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cd docs
|
|
105
|
+
make html
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Commands
|
|
109
|
+
|
|
110
|
+
All lifecycle commands accept one or more YAML files or directories through
|
|
111
|
+
`--problems`; the default is `./problems`.
|
|
112
|
+
|
|
113
|
+
### Validate problems
|
|
114
|
+
|
|
115
|
+
Checks schemas, variable usage, units, sampling specifications, explicit and
|
|
116
|
+
implicit equation solving, and derivation of the target law:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
mdbench validate
|
|
120
|
+
mdbench validate --problems problems/demo_problem.yaml
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
An optional LLM check evaluates whether every relationship is sufficiently
|
|
124
|
+
fundamental. API or response failures are reported directly and do not fall
|
|
125
|
+
back to heuristics.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
mdbench validate --check-fundamentality \
|
|
129
|
+
--llm-provider deepseek --llm-model deepseek-v4-flash
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Generate synthetic data
|
|
133
|
+
|
|
134
|
+
Creates reproducible train, ID-test, and OOD-test splits:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
mdbench synthetic --problems problems/ --output-dir data/synthetic_data/
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Each NPZ stores the three arrays, their row order in `variables`, and a JSON
|
|
141
|
+
`generation_config` containing the seed and sample counts. Auxiliary inputs are
|
|
142
|
+
generated here and may be hidden later during task preparation.
|
|
143
|
+
|
|
144
|
+
### Prepare tasks
|
|
145
|
+
|
|
146
|
+
Synthetic data must already exist. Answers are private by default:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
mdbench prepare \
|
|
150
|
+
--problems problems/ \
|
|
151
|
+
--synthetic-data-dir data/synthetic_data/ \
|
|
152
|
+
--task mechanism_discovery \
|
|
153
|
+
--format directory
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use `--save-answer` to include answers and test splits, `--reveal-auxiliary` to
|
|
157
|
+
expose auxiliary inputs in mechanism tasks, and `--force` to approve planned
|
|
158
|
+
overwrites. Existing directories are never cleared; redundant files are
|
|
159
|
+
reported. `--format directory` writes flat files, while `--format file` packs
|
|
160
|
+
the same logical artifacts into one NPZ.
|
|
161
|
+
|
|
162
|
+
### Evaluate submissions
|
|
163
|
+
|
|
164
|
+
A submission may be an inline formula, semicolon-separated mechanism equations,
|
|
165
|
+
or a plain-text file with one equation per non-empty line. JSON and YAML
|
|
166
|
+
submissions are intentionally unsupported.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
mdbench evaluate \
|
|
170
|
+
--evaluation-mode feedback \
|
|
171
|
+
--problem data/problem/PREPARED_TASK \
|
|
172
|
+
--submission submission.txt \
|
|
173
|
+
--verbose
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Feedback mode uses only the public task and training data. Benchmark operators
|
|
177
|
+
run final evaluation with `--evaluation-mode final --answer answer.json`, which
|
|
178
|
+
also enables hidden ID/OOD tests and reference-mechanism recovery. For Agent
|
|
179
|
+
runs, copy only the prepared public task into an isolated temporary working
|
|
180
|
+
directory and require the Agent to remain there. Without source problem YAML or
|
|
181
|
+
private answer artifacts, the other lifecycle commands and final evaluation
|
|
182
|
+
cannot access the material they require. `--verbose` prints concise equation
|
|
183
|
+
chains for explicit or implicit solution steps.
|
|
184
|
+
|
|
185
|
+
Fundamentality scoring automatically uses the configured external model and
|
|
186
|
+
prints its provider and model:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
mdbench evaluate \
|
|
190
|
+
--evaluation-mode feedback \
|
|
191
|
+
--problem data/problem/PREPARED_TASK \
|
|
192
|
+
--submission submission.txt \
|
|
193
|
+
--llm-provider deepseek \
|
|
194
|
+
--llm-model deepseek-v4-flash
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Standalone entry points with equivalent behavior are available in `scripts/`:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
validate_problem_main.py validate problem definitions
|
|
201
|
+
synthetic_data_main.py generate synthetic datasets
|
|
202
|
+
prepare_problem_main.py prepare public/private task artifacts
|
|
203
|
+
evaluate_result_main.py evaluate a submission
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`scripts/visualize_mechanism_main.py` renders a solved mechanism as DOT, SVG,
|
|
207
|
+
PNG, or PDF. Non-DOT formats require Graphviz.
|
|
208
|
+
|
|
209
|
+
## Directory conventions
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
problems/ source problem YAML files
|
|
213
|
+
data/
|
|
214
|
+
synthetic_data/ generated train/ID/OOD datasets
|
|
215
|
+
problem/ prepared benchmark tasks
|
|
216
|
+
src/
|
|
217
|
+
core/ dependency-light data models
|
|
218
|
+
features/ project-specific I/O, solving, validation, sampling
|
|
219
|
+
metrics/ formula and mechanism metrics
|
|
220
|
+
utils/ reusable utilities and LLM clients
|
|
221
|
+
scripts/ standalone command entry points
|
|
222
|
+
tests/ unit tests and validation fixtures
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
A prepared directory contains:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
problem.json public task description
|
|
229
|
+
data_train.npy public training data
|
|
230
|
+
answer.json optional private answer
|
|
231
|
+
data_id_test.npy optional private ID test data
|
|
232
|
+
data_ood_test.npy optional private OOD test data
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Without `--save-answer`, only `problem.json` and `data_train.npy` are written.
|
|
236
|
+
Public interchange types remain simple: units are `Dict[str, int | float]`,
|
|
237
|
+
formulas are nd2py-compatible strings, and arrays use NumPy formats.
|