marimo-flow 0.4.2__tar.gz → 0.4.4__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 (87) hide show
  1. {marimo_flow-0.4.2/src/marimo_flow.egg-info → marimo_flow-0.4.4}/PKG-INFO +25 -25
  2. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/pyproject.toml +31 -31
  3. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/control.py +6 -1
  4. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/control/heat_rod.py +24 -9
  5. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/control/mpc.py +39 -6
  6. {marimo_flow-0.4.2 → marimo_flow-0.4.4/src/marimo_flow.egg-info}/PKG-INFO +25 -25
  7. marimo_flow-0.4.4/src/marimo_flow.egg-info/requires.txt +39 -0
  8. marimo_flow-0.4.2/src/marimo_flow.egg-info/requires.txt +0 -39
  9. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/LICENSE +0 -0
  10. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/README.md +0 -0
  11. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/setup.cfg +0 -0
  12. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/__init__.py +0 -0
  13. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/__init__.py +0 -0
  14. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/chat.py +0 -0
  15. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/deps.py +0 -0
  16. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/graph.py +0 -0
  17. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/lead.py +0 -0
  18. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/mcp.py +0 -0
  19. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/__init__.py +0 -0
  20. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/mlflow_node.py +0 -0
  21. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/model.py +0 -0
  22. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/notebook.py +0 -0
  23. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/problem.py +0 -0
  24. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/route.py +0 -0
  25. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/solver.py +0 -0
  26. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/training.py +0 -0
  27. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/triage.py +0 -0
  28. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/nodes/validation.py +0 -0
  29. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/runner.py +0 -0
  30. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/__init__.py +0 -0
  31. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/artifacts.py +0 -0
  32. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/control.py +0 -0
  33. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/decisions.py +0 -0
  34. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/equation.py +0 -0
  35. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/mesh.py +0 -0
  36. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/observation.py +0 -0
  37. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/optimization.py +0 -0
  38. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/preset.py +0 -0
  39. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/problem.py +0 -0
  40. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/run.py +0 -0
  41. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/stochastic.py +0 -0
  42. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/schemas/task.py +0 -0
  43. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/server/__init__.py +0 -0
  44. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/server/a2a.py +0 -0
  45. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/server/ag_ui.py +0 -0
  46. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/__init__.py +0 -0
  47. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/composer.py +0 -0
  48. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/design.py +0 -0
  49. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/experiment.py +0 -0
  50. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/mesh_domain.py +0 -0
  51. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/orchestrator.py +0 -0
  52. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/preset_catalog.py +0 -0
  53. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/services/provenance.py +0 -0
  54. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/skills.py +0 -0
  55. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/state.py +0 -0
  56. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/__init__.py +0 -0
  57. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/_registry.py +0 -0
  58. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/_specs.py +0 -0
  59. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/curator.py +0 -0
  60. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/data.py +0 -0
  61. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/design.py +0 -0
  62. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/lead.py +0 -0
  63. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/model.py +0 -0
  64. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/problem.py +0 -0
  65. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/skills.py +0 -0
  66. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/solver.py +0 -0
  67. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/training.py +0 -0
  68. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/agents/toolsets/validation.py +0 -0
  69. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/cli.py +0 -0
  70. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/control/__init__.py +0 -0
  71. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/control/pinn_surrogate.py +0 -0
  72. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/__init__.py +0 -0
  73. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/model_factory.py +0 -0
  74. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/model_manager.py +0 -0
  75. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/problem_manager.py +0 -0
  76. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/solver_manager.py +0 -0
  77. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/training.py +0 -0
  78. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/visualization.py +0 -0
  79. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/viz3d.py +0 -0
  80. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow/core/walrus.py +0 -0
  81. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow.egg-info/SOURCES.txt +0 -0
  82. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow.egg-info/dependency_links.txt +0 -0
  83. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow.egg-info/entry_points.txt +0 -0
  84. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow.egg-info/not-zip-safe +0 -0
  85. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/src/marimo_flow.egg-info/top_level.txt +0 -0
  86. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/tests/test_cli.py +0 -0
  87. {marimo_flow-0.4.2 → marimo_flow-0.4.4}/tests/test_training.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marimo-flow
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: Agentic scientific-computing platform: a reactive multi-agent team orchestrating PINA physics-informed neural-network workflows via pydantic-graph, with MLflow tracing/provenance and a marimo chat UI.
5
5
  Author-email: Björn Bethge <helloworld@synapticore.io>
6
6
  License-Expression: MIT
@@ -20,44 +20,44 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Python: >=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: marimo[lsp,mcp,recommended,sql]>=0.23.1
23
+ Requires-Dist: marimo[lsp,mcp,recommended,sql]>=0.25.0
24
24
  Requires-Dist: mlflow[genai]>=3.16.1
25
25
  Requires-Dist: fastmcp>=4.0.9
26
- Requires-Dist: optuna>=4.8.0
27
- Requires-Dist: pina-mathlab>=0.2.6
28
- Requires-Dist: transformers[accelerate,tiktoken]>=5.5.4
29
- Requires-Dist: authlib>=1.6.9
30
- Requires-Dist: pillow>=12.2.0
31
- Requires-Dist: cryptography>=49.0.0
32
- Requires-Dist: langgraph>=1.1.8
26
+ Requires-Dist: optuna>=5.0.0
27
+ Requires-Dist: pina-mathlab>=0.3.2.post2609
28
+ Requires-Dist: transformers[accelerate,tiktoken]>=5.17.0
29
+ Requires-Dist: authlib>=1.8.0
30
+ Requires-Dist: pillow>=12.3.0
31
+ Requires-Dist: cryptography>=50.0.1
32
+ Requires-Dist: langgraph>=1.2.12
33
33
  Requires-Dist: werkzeug>=3.1.8
34
34
  Requires-Dist: sqlparse>=0.6.0
35
35
  Requires-Dist: diskcache>=5.6.3
36
36
  Requires-Dist: protobuf>=6.33.6
37
- Requires-Dist: python-multipart>=0.0.27
38
- Requires-Dist: ujson>=5.12.0
39
- Requires-Dist: pyasn1>=0.6.3
40
- Requires-Dist: pyjwt>=2.12.1
37
+ Requires-Dist: python-multipart>=0.0.32
38
+ Requires-Dist: ujson>=6.0.0
39
+ Requires-Dist: pyasn1>=0.6.4
40
+ Requires-Dist: pyjwt>=2.15.0
41
41
  Requires-Dist: flask>=3.1.3
42
- Requires-Dist: gitpython>=3.1.59
43
- Requires-Dist: httpx2>=2.12.0
44
- Requires-Dist: httpcore2>=2.10.0
42
+ Requires-Dist: gitpython>=3.1.62
43
+ Requires-Dist: httpx2>=2.13.1
44
+ Requires-Dist: httpcore2>=2.13.1
45
45
  Requires-Dist: lightning>=2.6.6
46
46
  Requires-Dist: aiohttp>=3.14.3
47
47
  Requires-Dist: accelerate>=1.15.0
48
- Requires-Dist: pymdown-extensions>=11.0.1
49
- Requires-Dist: optuna-integration[pytorch-lightning]>=4.8.0
50
- Requires-Dist: plotly[express,kaleido]>=6.7.0
51
- Requires-Dist: pydantic-ai-slim[ag-ui]>=2.10.0
48
+ Requires-Dist: pymdown-extensions>=11.0.2
49
+ Requires-Dist: optuna-integration[pytorch-lightning]>=5.0.0
50
+ Requires-Dist: plotly[express,kaleido]>=7.1.0
51
+ Requires-Dist: pydantic-ai-slim[ag-ui]>=2.49.0
52
52
  Requires-Dist: pyyaml>=6.0.3
53
- Requires-Dist: python-dotenv>=1.2.2
54
- Requires-Dist: typer>=0.24.1
53
+ Requires-Dist: python-dotenv>=1.2.3
54
+ Requires-Dist: typer>=0.27.2
55
55
  Requires-Dist: sympy>=1.14.0
56
56
  Requires-Dist: meshio>=5.3.5
57
- Requires-Dist: fasta2a>=0.6.1
57
+ Requires-Dist: fasta2a>=2.0.1
58
58
  Provides-Extra: all
59
- Requires-Dist: torch>=2.11.0; extra == "all"
60
- Requires-Dist: torch-geometric>=2.7.0; extra == "all"
59
+ Requires-Dist: torch>=2.14.0; extra == "all"
60
+ Requires-Dist: torch-geometric>=2.8.0.post1; extra == "all"
61
61
  Dynamic: license-file
62
62
 
63
63
  # Marimo Flow 🌊
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "marimo-flow"
7
- version = "0.4.2"
7
+ version = "0.4.4"
8
8
  description = "Agentic scientific-computing platform: a reactive multi-agent team orchestrating PINA physics-informed neural-network workflows via pydantic-graph, with MLflow tracing/provenance and a marimo chat UI."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -43,62 +43,62 @@ classifiers = [
43
43
  "Topic :: Software Development :: Libraries :: Python Modules",
44
44
  ]
45
45
  dependencies = [
46
- "marimo[lsp,recommended,sql,mcp]>=0.23.1",
46
+ "marimo[lsp,recommended,sql,mcp]>=0.25.0",
47
47
  # No [mcp] extra: it pins fastmcp<4, which pip resolves to fastmcp 2.x +
48
48
  # mcp 2.x (ImportError on McpError). We need the fastmcp client directly.
49
49
  "mlflow[genai]>=3.16.1",
50
50
  "fastmcp>=4.0.9",
51
- "optuna>=4.8.0",
52
- "pina-mathlab>=0.2.6",
53
- "transformers[accelerate,tiktoken]>=5.5.4",
51
+ "optuna>=5.0.0",
52
+ "pina-mathlab>=0.3.2.post2609",
53
+ "transformers[accelerate,tiktoken]>=5.17.0",
54
54
  # security: explicit minimums for vulnerable transitive deps
55
- "authlib>=1.6.9",
56
- "pillow>=12.2.0",
57
- "cryptography>=49.0.0",
58
- "langgraph>=1.1.8",
55
+ "authlib>=1.8.0",
56
+ "pillow>=12.3.0",
57
+ "cryptography>=50.0.1",
58
+ "langgraph>=1.2.12",
59
59
  "werkzeug>=3.1.8",
60
60
  "sqlparse>=0.6.0",
61
61
  "diskcache>=5.6.3",
62
62
  "protobuf>=6.33.6",
63
- "python-multipart>=0.0.27",
64
- "ujson>=5.12.0",
65
- "pyasn1>=0.6.3",
66
- "pyjwt>=2.12.1",
63
+ "python-multipart>=0.0.32",
64
+ "ujson>=6.0.0",
65
+ "pyasn1>=0.6.4",
66
+ "pyjwt>=2.15.0",
67
67
  "flask>=3.1.3",
68
- "gitpython>=3.1.59",
69
- "httpx2>=2.12.0",
70
- "httpcore2>=2.10.0",
68
+ "gitpython>=3.1.62",
69
+ "httpx2>=2.13.1",
70
+ "httpcore2>=2.13.1",
71
71
  "lightning>=2.6.6",
72
72
  "aiohttp>=3.14.3",
73
73
  "accelerate>=1.15.0",
74
- "pymdown-extensions>=11.0.1",
75
- "optuna-integration[pytorch-lightning]>=4.8.0",
76
- "plotly[express,kaleido]>=6.7.0",
74
+ "pymdown-extensions>=11.0.2",
75
+ "optuna-integration[pytorch-lightning]>=5.0.0",
76
+ "plotly[express,kaleido]>=7.1.0",
77
77
  # pydantic-ai 2.x dropped the bundled `a2a` extra; A2A now comes via the
78
78
  # standalone `fasta2a` dep below (still the same agent_to_a2a API).
79
- "pydantic-ai-slim[ag-ui]>=2.10.0",
79
+ "pydantic-ai-slim[ag-ui]>=2.49.0",
80
80
  "pyyaml>=6.0.3",
81
- "python-dotenv>=1.2.2",
82
- "typer>=0.24.1",
81
+ "python-dotenv>=1.2.3",
82
+ "typer>=0.27.2",
83
83
  "sympy>=1.14.0",
84
84
  "meshio>=5.3.5",
85
- "fasta2a>=0.6.1",
85
+ "fasta2a>=2.0.1",
86
86
  ]
87
87
 
88
88
  [project.optional-dependencies]
89
89
  all = [
90
- "torch>=2.11.0",
91
- "torch-geometric>=2.7.0",
90
+ "torch>=2.14.0",
91
+ "torch-geometric>=2.8.0.post1",
92
92
  ]
93
93
 
94
94
  [dependency-groups]
95
95
  dev = [
96
- "mypy>=1.20.1",
97
- "pre-commit>=4.5.1",
98
- "pytest>=9.0.3",
99
- "pytest-asyncio>=1.3.0",
100
- "pytest-cov>=7.0.0",
101
- "ruff>=0.15.11",
96
+ "mypy>=2.3.1",
97
+ "pre-commit>=4.6.2",
98
+ "pytest>=9.1.1",
99
+ "pytest-asyncio>=1.4.0",
100
+ "pytest-cov>=7.1.0",
101
+ "ruff>=0.16.9",
102
102
  ]
103
103
  docs = [
104
104
  "sphinx>=9.0.4",
@@ -115,7 +115,11 @@ def closed_loop_simulation(
115
115
  true_dynamics_registry_key: str,
116
116
  n_steps: int = 20,
117
117
  ) -> dict[str, list[list[float]]]:
118
- """Run a closed-loop rollout and return the state / control trajectory."""
118
+ """Run an offset-free closed-loop rollout.
119
+
120
+ Returns the state and control trajectories plus ``disturbance``, the
121
+ observer's estimate of the surrogate's bias at each step.
122
+ """
119
123
  from marimo_flow.control.mpc import simulate_closed_loop
120
124
 
121
125
  plan_model = ControlPlan.model_validate(plan)
@@ -135,4 +139,5 @@ def closed_loop_simulation(
135
139
  return {
136
140
  "states": traj["states"].tolist(),
137
141
  "controls": traj["controls"].tolist(),
142
+ "disturbance": traj["disturbance"].tolist(),
138
143
  }
@@ -119,8 +119,13 @@ def train_step_surrogate(
119
119
  epochs: int = 200,
120
120
  lr: float = 1e-3,
121
121
  batch_size: int = 256,
122
+ seed: int | None = None,
122
123
  ) -> PredictStepFn:
123
- """Fit a small MLP on plant rollouts; return a numpy predict callable."""
124
+ """Fit a small MLP on plant rollouts; return a numpy predict callable.
125
+
126
+ ``seed`` makes weight init and batch shuffling reproducible without
127
+ touching torch's global RNG state.
128
+ """
124
129
  if inputs.ndim != 2 or inputs.shape[1] != 2:
125
130
  raise ValueError("inputs must have shape (n, 2)")
126
131
  if targets.ndim != 2 or targets.shape[1] != 1:
@@ -139,13 +144,23 @@ def train_step_surrogate(
139
144
  x_norm = (inputs - x_mean) / x_std
140
145
  y_norm = (targets - y_mean) / y_std
141
146
 
142
- layers: list[nn.Module] = []
143
- in_dim = 2
144
- for width in hidden:
145
- layers.extend([nn.Linear(in_dim, width), nn.Tanh()])
146
- in_dim = width
147
- layers.append(nn.Linear(in_dim, 1))
148
- model = nn.Sequential(*layers)
147
+ generator = torch.Generator()
148
+ if seed is None:
149
+ generator.seed()
150
+ else:
151
+ generator.manual_seed(seed)
152
+
153
+ # nn.Linear initialises from the global RNG; fork it so a seeded run
154
+ # neither depends on nor changes the caller's torch RNG state.
155
+ with torch.random.fork_rng(devices=[]):
156
+ torch.manual_seed(generator.initial_seed())
157
+ layers: list[nn.Module] = []
158
+ in_dim = 2
159
+ for width in hidden:
160
+ layers.extend([nn.Linear(in_dim, width), nn.Tanh()])
161
+ in_dim = width
162
+ layers.append(nn.Linear(in_dim, 1))
163
+ model = nn.Sequential(*layers)
149
164
 
150
165
  x_t = torch.tensor(x_norm, dtype=torch.float32)
151
166
  y_t = torch.tensor(y_norm, dtype=torch.float32)
@@ -154,7 +169,7 @@ def train_step_surrogate(
154
169
 
155
170
  n = len(x_t)
156
171
  for _ in range(epochs):
157
- perm = torch.randperm(n)
172
+ perm = torch.randperm(n, generator=generator)
158
173
  for start in range(0, n, batch_size):
159
174
  idx = perm[start : start + batch_size]
160
175
  pred = model(x_t[idx])
@@ -19,6 +19,13 @@ Returns:
19
19
  * ``state_trajectory``: shape ``(horizon, n_states)`` — predicted next states.
20
20
  """
21
21
 
22
+ # Surrogates are usually torch networks evaluated in float32. SLSQP's default
23
+ # finite-difference step (~1.5e-8) is below float32 resolution, so the
24
+ # objective would not change, the gradient would be zero and the solver would
25
+ # stop at the initial guess. sqrt(float32 eps) is the standard forward-
26
+ # difference step for float32-noisy functions.
27
+ _FD_REL_STEP = float(np.sqrt(np.finfo(np.float32).eps))
28
+
22
29
 
23
30
  def run_mpc_step(
24
31
  plan: ControlPlan,
@@ -26,12 +33,15 @@ def run_mpc_step(
26
33
  surrogate: SurrogateFn,
27
34
  *,
28
35
  prev_controls: np.ndarray | None = None,
36
+ disturbance: np.ndarray | None = None,
29
37
  ) -> tuple[np.ndarray, dict[str, float]]:
30
38
  """Solve one MPC horizon; return the chosen control sequence + info.
31
39
 
32
40
  Only the first control column is applied by the caller — the rest
33
41
  is the MPC's look-ahead. ``prev_controls`` warm-starts the solver
34
- with the previous horizon shifted by one step.
42
+ with the previous horizon shifted by one step. ``disturbance`` (shape
43
+ ``(n_states,)``) is added to every predicted state — the output
44
+ disturbance estimate of offset-free MPC.
35
45
  """
36
46
  h = plan.horizon
37
47
  n_ctrl = len(plan.controls)
@@ -47,12 +57,13 @@ def run_mpc_step(
47
57
 
48
58
  targets = np.array([s.target if s.target is not None else 0.0 for s in plan.states])
49
59
  weights = np.array([s.weight for s in plan.states])
60
+ offset = np.zeros(n_state) if disturbance is None else disturbance
50
61
 
51
62
  def flat_to_seq(x: np.ndarray) -> np.ndarray:
52
63
  return x.reshape(h, n_ctrl)
53
64
 
54
65
  def objective(x: np.ndarray) -> float:
55
- traj = surrogate(state_now, flat_to_seq(x))
66
+ traj = surrogate(state_now, flat_to_seq(x)) + offset
56
67
  err = traj - targets
57
68
  return float(np.sum(weights * (err**2)))
58
69
 
@@ -64,8 +75,9 @@ def run_mpc_step(
64
75
  objective,
65
76
  x0=x0.flatten(),
66
77
  method="SLSQP",
78
+ jac="2-point",
67
79
  bounds=bounds,
68
- options={"maxiter": 50, "ftol": 1e-6},
80
+ options={"maxiter": 50, "ftol": 1e-6, "finite_diff_rel_step": _FD_REL_STEP},
69
81
  )
70
82
  return flat_to_seq(result.x), {
71
83
  "cost": float(result.fun),
@@ -81,25 +93,46 @@ def simulate_closed_loop(
81
93
  true_dynamics: SurrogateFn,
82
94
  *,
83
95
  n_steps: int,
96
+ offset_free: bool = True,
97
+ disturbance_gain: float = 0.3,
84
98
  ) -> dict[str, np.ndarray]:
85
99
  """Run n_steps of MPC + true-dynamics rollout; return the trajectory.
86
100
 
87
101
  ``true_dynamics`` plays the role of the real plant (for sim work).
88
102
  In production the caller replaces it with a measurement hook.
103
+
104
+ With ``offset_free`` (default) an integrating output-disturbance
105
+ observer corrects the surrogate: ``d += disturbance_gain * (measured -
106
+ (surrogate + d))``, and every horizon is planned on ``surrogate + d``.
107
+ A surrogate bias then leaves no steady-state error; ``d`` stays zero
108
+ when the surrogate matches the plant. A gain below 1 keeps the estimate
109
+ from chasing input-dependent (e.g. gain) model errors step by step,
110
+ which would make the loop oscillate.
111
+ Returns ``states`` and ``disturbance`` of shape ``(n_steps + 1,
112
+ n_states)`` and ``controls`` of shape ``(n_steps, n_controls)``.
89
113
  """
90
114
  n_ctrl = len(plan.controls)
115
+ n_state = len(plan.states)
91
116
  state = initial_state.copy()
92
117
  applied = np.zeros((n_steps, n_ctrl))
93
- states = np.zeros((n_steps + 1, len(plan.states)))
118
+ states = np.zeros((n_steps + 1, n_state))
119
+ disturbances = np.zeros((n_steps + 1, n_state))
94
120
  states[0] = state
95
121
  prev = None
122
+ d = np.zeros(n_state)
96
123
  for k in range(n_steps):
97
- ctrl_seq, _ = run_mpc_step(plan, state, surrogate, prev_controls=prev)
124
+ ctrl_seq, _ = run_mpc_step(
125
+ plan, state, surrogate, prev_controls=prev, disturbance=d
126
+ )
98
127
  applied[k] = ctrl_seq[0]
128
+ predicted = surrogate(state, ctrl_seq[:1])[0] + d
99
129
  state = true_dynamics(state, ctrl_seq[:1])[0]
130
+ if offset_free:
131
+ d = d + disturbance_gain * (state - predicted)
100
132
  states[k + 1] = state
133
+ disturbances[k + 1] = d
101
134
  prev = ctrl_seq
102
- return {"states": states, "controls": applied}
135
+ return {"states": states, "controls": applied, "disturbance": disturbances}
103
136
 
104
137
 
105
138
  def _warm_start(plan: ControlPlan, prev_controls: np.ndarray | None) -> np.ndarray:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marimo-flow
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: Agentic scientific-computing platform: a reactive multi-agent team orchestrating PINA physics-informed neural-network workflows via pydantic-graph, with MLflow tracing/provenance and a marimo chat UI.
5
5
  Author-email: Björn Bethge <helloworld@synapticore.io>
6
6
  License-Expression: MIT
@@ -20,44 +20,44 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Python: >=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: marimo[lsp,mcp,recommended,sql]>=0.23.1
23
+ Requires-Dist: marimo[lsp,mcp,recommended,sql]>=0.25.0
24
24
  Requires-Dist: mlflow[genai]>=3.16.1
25
25
  Requires-Dist: fastmcp>=4.0.9
26
- Requires-Dist: optuna>=4.8.0
27
- Requires-Dist: pina-mathlab>=0.2.6
28
- Requires-Dist: transformers[accelerate,tiktoken]>=5.5.4
29
- Requires-Dist: authlib>=1.6.9
30
- Requires-Dist: pillow>=12.2.0
31
- Requires-Dist: cryptography>=49.0.0
32
- Requires-Dist: langgraph>=1.1.8
26
+ Requires-Dist: optuna>=5.0.0
27
+ Requires-Dist: pina-mathlab>=0.3.2.post2609
28
+ Requires-Dist: transformers[accelerate,tiktoken]>=5.17.0
29
+ Requires-Dist: authlib>=1.8.0
30
+ Requires-Dist: pillow>=12.3.0
31
+ Requires-Dist: cryptography>=50.0.1
32
+ Requires-Dist: langgraph>=1.2.12
33
33
  Requires-Dist: werkzeug>=3.1.8
34
34
  Requires-Dist: sqlparse>=0.6.0
35
35
  Requires-Dist: diskcache>=5.6.3
36
36
  Requires-Dist: protobuf>=6.33.6
37
- Requires-Dist: python-multipart>=0.0.27
38
- Requires-Dist: ujson>=5.12.0
39
- Requires-Dist: pyasn1>=0.6.3
40
- Requires-Dist: pyjwt>=2.12.1
37
+ Requires-Dist: python-multipart>=0.0.32
38
+ Requires-Dist: ujson>=6.0.0
39
+ Requires-Dist: pyasn1>=0.6.4
40
+ Requires-Dist: pyjwt>=2.15.0
41
41
  Requires-Dist: flask>=3.1.3
42
- Requires-Dist: gitpython>=3.1.59
43
- Requires-Dist: httpx2>=2.12.0
44
- Requires-Dist: httpcore2>=2.10.0
42
+ Requires-Dist: gitpython>=3.1.62
43
+ Requires-Dist: httpx2>=2.13.1
44
+ Requires-Dist: httpcore2>=2.13.1
45
45
  Requires-Dist: lightning>=2.6.6
46
46
  Requires-Dist: aiohttp>=3.14.3
47
47
  Requires-Dist: accelerate>=1.15.0
48
- Requires-Dist: pymdown-extensions>=11.0.1
49
- Requires-Dist: optuna-integration[pytorch-lightning]>=4.8.0
50
- Requires-Dist: plotly[express,kaleido]>=6.7.0
51
- Requires-Dist: pydantic-ai-slim[ag-ui]>=2.10.0
48
+ Requires-Dist: pymdown-extensions>=11.0.2
49
+ Requires-Dist: optuna-integration[pytorch-lightning]>=5.0.0
50
+ Requires-Dist: plotly[express,kaleido]>=7.1.0
51
+ Requires-Dist: pydantic-ai-slim[ag-ui]>=2.49.0
52
52
  Requires-Dist: pyyaml>=6.0.3
53
- Requires-Dist: python-dotenv>=1.2.2
54
- Requires-Dist: typer>=0.24.1
53
+ Requires-Dist: python-dotenv>=1.2.3
54
+ Requires-Dist: typer>=0.27.2
55
55
  Requires-Dist: sympy>=1.14.0
56
56
  Requires-Dist: meshio>=5.3.5
57
- Requires-Dist: fasta2a>=0.6.1
57
+ Requires-Dist: fasta2a>=2.0.1
58
58
  Provides-Extra: all
59
- Requires-Dist: torch>=2.11.0; extra == "all"
60
- Requires-Dist: torch-geometric>=2.7.0; extra == "all"
59
+ Requires-Dist: torch>=2.14.0; extra == "all"
60
+ Requires-Dist: torch-geometric>=2.8.0.post1; extra == "all"
61
61
  Dynamic: license-file
62
62
 
63
63
  # Marimo Flow 🌊
@@ -0,0 +1,39 @@
1
+ marimo[lsp,mcp,recommended,sql]>=0.25.0
2
+ mlflow[genai]>=3.16.1
3
+ fastmcp>=4.0.9
4
+ optuna>=5.0.0
5
+ pina-mathlab>=0.3.2.post2609
6
+ transformers[accelerate,tiktoken]>=5.17.0
7
+ authlib>=1.8.0
8
+ pillow>=12.3.0
9
+ cryptography>=50.0.1
10
+ langgraph>=1.2.12
11
+ werkzeug>=3.1.8
12
+ sqlparse>=0.6.0
13
+ diskcache>=5.6.3
14
+ protobuf>=6.33.6
15
+ python-multipart>=0.0.32
16
+ ujson>=6.0.0
17
+ pyasn1>=0.6.4
18
+ pyjwt>=2.15.0
19
+ flask>=3.1.3
20
+ gitpython>=3.1.62
21
+ httpx2>=2.13.1
22
+ httpcore2>=2.13.1
23
+ lightning>=2.6.6
24
+ aiohttp>=3.14.3
25
+ accelerate>=1.15.0
26
+ pymdown-extensions>=11.0.2
27
+ optuna-integration[pytorch-lightning]>=5.0.0
28
+ plotly[express,kaleido]>=7.1.0
29
+ pydantic-ai-slim[ag-ui]>=2.49.0
30
+ pyyaml>=6.0.3
31
+ python-dotenv>=1.2.3
32
+ typer>=0.27.2
33
+ sympy>=1.14.0
34
+ meshio>=5.3.5
35
+ fasta2a>=2.0.1
36
+
37
+ [all]
38
+ torch>=2.14.0
39
+ torch-geometric>=2.8.0.post1
@@ -1,39 +0,0 @@
1
- marimo[lsp,mcp,recommended,sql]>=0.23.1
2
- mlflow[genai]>=3.16.1
3
- fastmcp>=4.0.9
4
- optuna>=4.8.0
5
- pina-mathlab>=0.2.6
6
- transformers[accelerate,tiktoken]>=5.5.4
7
- authlib>=1.6.9
8
- pillow>=12.2.0
9
- cryptography>=49.0.0
10
- langgraph>=1.1.8
11
- werkzeug>=3.1.8
12
- sqlparse>=0.6.0
13
- diskcache>=5.6.3
14
- protobuf>=6.33.6
15
- python-multipart>=0.0.27
16
- ujson>=5.12.0
17
- pyasn1>=0.6.3
18
- pyjwt>=2.12.1
19
- flask>=3.1.3
20
- gitpython>=3.1.59
21
- httpx2>=2.12.0
22
- httpcore2>=2.10.0
23
- lightning>=2.6.6
24
- aiohttp>=3.14.3
25
- accelerate>=1.15.0
26
- pymdown-extensions>=11.0.1
27
- optuna-integration[pytorch-lightning]>=4.8.0
28
- plotly[express,kaleido]>=6.7.0
29
- pydantic-ai-slim[ag-ui]>=2.10.0
30
- pyyaml>=6.0.3
31
- python-dotenv>=1.2.2
32
- typer>=0.24.1
33
- sympy>=1.14.0
34
- meshio>=5.3.5
35
- fasta2a>=0.6.1
36
-
37
- [all]
38
- torch>=2.11.0
39
- torch-geometric>=2.7.0
File without changes
File without changes
File without changes