combinate 0.1.0rc1__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.
- combinate-0.1.0rc1/.gitignore +36 -0
- combinate-0.1.0rc1/PACKAGE_README.md +220 -0
- combinate-0.1.0rc1/PKG-INFO +250 -0
- combinate-0.1.0rc1/pyproject.toml +70 -0
- combinate-0.1.0rc1/src/combinate/__init__.py +54 -0
- combinate-0.1.0rc1/src/combinate/__main__.py +7 -0
- combinate-0.1.0rc1/src/combinate/cli.py +467 -0
- combinate-0.1.0rc1/src/combinate/client.py +272 -0
- combinate-0.1.0rc1/src/combinate/config.py +149 -0
- combinate-0.1.0rc1/src/combinate/errors.py +25 -0
- combinate-0.1.0rc1/src/combinate/normalization.py +158 -0
- combinate-0.1.0rc1/src/combinate/preflight.py +474 -0
- combinate-0.1.0rc1/src/combinate/result.py +344 -0
- combinate-0.1.0rc1/src/combinate/sdk.py +374 -0
- combinate-0.1.0rc1/src/combinate/validation.py +31 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.env
|
|
2
|
+
.env.*
|
|
3
|
+
!.env.example
|
|
4
|
+
.pypirc
|
|
5
|
+
TestPyPI-Recovery-Codes-*.txt
|
|
6
|
+
|
|
7
|
+
.git/
|
|
8
|
+
.multisweep/
|
|
9
|
+
.combinate/
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
__pycache__/
|
|
12
|
+
*.pyc
|
|
13
|
+
|
|
14
|
+
.venv/
|
|
15
|
+
venv/
|
|
16
|
+
.external-rehearsal-venv/
|
|
17
|
+
|
|
18
|
+
dist/
|
|
19
|
+
build/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
|
|
22
|
+
releases/.tmp*/
|
|
23
|
+
releases/.tmp-*/
|
|
24
|
+
|
|
25
|
+
.tmp_pkg_validate/
|
|
26
|
+
.tmp_testpypi_validate/
|
|
27
|
+
.tmp_testpypi_validate_a1/
|
|
28
|
+
.tmp-test-bootstrap.sqlite3
|
|
29
|
+
*.sqlite3
|
|
30
|
+
*.db
|
|
31
|
+
|
|
32
|
+
tmp/
|
|
33
|
+
tmp-*.json
|
|
34
|
+
tmp-*.js
|
|
35
|
+
.tmp_*.json
|
|
36
|
+
ecs-taskdef-*.json
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Combinate
|
|
2
|
+
|
|
3
|
+
Combinate is a Python-first cloud parameter-sweep platform for simulation-style workloads.
|
|
4
|
+
|
|
5
|
+
The SDK is designed for the common case where you already have a Python function and a set of parameter combinations you want to evaluate. Instead of managing nested loops, retries, and result collection yourself, you submit a sweep and get structured results back.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Current private-beta prerelease install target:
|
|
10
|
+
|
|
11
|
+
```powershell
|
|
12
|
+
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple combinate==0.1.0b1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This version is intentionally a prerelease. Do not use final `0.1.0` on TestPyPI while the install, onboarding, and support loop are still being proven in private beta.
|
|
16
|
+
|
|
17
|
+
This README is the minimum self-contained install-to-first-sweep guide that should be usable from the installed package alone.
|
|
18
|
+
|
|
19
|
+
Richer walkthroughs such as the repository quickstart and usage guides may exist outside the installed artifact and should not be assumed to be locally bundled in the wheel.
|
|
20
|
+
|
|
21
|
+
The published package intentionally contains only the Python SDK and CLI surface. The hosted control plane remains a separate deployed service and is not bundled into the PyPI artifact.
|
|
22
|
+
|
|
23
|
+
## Try It Locally First (No Account Required)
|
|
24
|
+
|
|
25
|
+
`local_sweep` runs your function in-process against a sampled parameter space without connecting to the Combinate cloud. No API key, project ID, or sign-in required.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from combinate import local_sweep
|
|
29
|
+
|
|
30
|
+
def simulate(alpha: float, beta: float) -> dict:
|
|
31
|
+
return {"objective": alpha * beta}
|
|
32
|
+
|
|
33
|
+
result = local_sweep(
|
|
34
|
+
simulate,
|
|
35
|
+
params={
|
|
36
|
+
"alpha": {"type": "range", "min": 0.1, "max": 10.0},
|
|
37
|
+
"beta": [1.0, 5.0, 10.0],
|
|
38
|
+
},
|
|
39
|
+
sampling_spec={"method": "random", "sampler": "sobol", "samples": 20, "seed": 42},
|
|
40
|
+
max_tasks=20,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print(result.describe())
|
|
44
|
+
for task in result.succeeded_tasks:
|
|
45
|
+
print(task.parameter_values, task.inline_output)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
When you are ready to scale to a full cloud run, change `local_sweep` to `sweep` and add a `CombinateConfig`. Everything else — params, sampling_spec, result inspection — stays identical.
|
|
49
|
+
|
|
50
|
+
`local_sweep` defaults to a cap of 25 tasks (hard limit: 200). Use it to validate your function signature, parameter space, and output shape before committing to a large cloud run.
|
|
51
|
+
|
|
52
|
+
## Pre-Sweep Validation
|
|
53
|
+
|
|
54
|
+
`run_preflight` analyzes your parameter space and function before any cloud submission. It runs two checks automatically:
|
|
55
|
+
|
|
56
|
+
**Static analysis** — inspects parameter definitions without executing your function:
|
|
57
|
+
- flags `min=0` on any dimension as a division or logarithm risk
|
|
58
|
+
- flags `min=1` as an off-by-one risk when your model uses `count - 1` patterns
|
|
59
|
+
- flags inverted ranges (`min > max`)
|
|
60
|
+
- flags grid sweeps above 500 tasks
|
|
61
|
+
|
|
62
|
+
**Boundary probes** — runs your function at 5 targeted parameter sets: all-min, all-max, midpoint, and two cross-combos (first half lo/second half hi, and vice versa). Cross-combos catch interaction bugs that only appear when two dimensions are simultaneously at their extremes.
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from combinate import run_preflight
|
|
66
|
+
|
|
67
|
+
def simulate(alpha: float, beta: float) -> dict:
|
|
68
|
+
return {"objective": alpha / beta} # would fail at beta=0
|
|
69
|
+
|
|
70
|
+
params = {
|
|
71
|
+
"alpha": {"type": "range", "min": 0.1, "max": 10.0},
|
|
72
|
+
"beta": {"type": "range", "min": 0.0, "max": 5.0}, # min=0 → flagged
|
|
73
|
+
}
|
|
74
|
+
spec = {"method": "random", "sampler": "sobol", "samples": 200}
|
|
75
|
+
|
|
76
|
+
report = run_preflight(simulate, params, "random", spec)
|
|
77
|
+
# prints formatted analysis to stderr
|
|
78
|
+
# report.static_warnings — list of warning strings
|
|
79
|
+
# report.probe_results — list of ProbeResult(label, params, elapsed_s, output, error)
|
|
80
|
+
# report.probe_failures — subset where error is not None
|
|
81
|
+
# report.task_count — estimated task count
|
|
82
|
+
# report.median_task_s — median probe wall time
|
|
83
|
+
# report.estimated_wall_s — task_count / parallelism * median_task_s
|
|
84
|
+
# report.estimated_cost_usd — planning estimate
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`sweep()` calls `run_preflight()` automatically before submission. Pass `preflight=False` to skip it:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
result = sweep(simulate, params=params, config=config, preflight=False)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Agent Quick Reference
|
|
94
|
+
|
|
95
|
+
If you are a coding agent integrating `combinate` into a fresh project, these are the current contract-critical facts:
|
|
96
|
+
|
|
97
|
+
- primary entry points: `from combinate import CombinateConfig, sweep, local_sweep, run_preflight`
|
|
98
|
+
- local validation path (no account): `local_sweep(fn, params=..., max_tasks=25)` — runs in-process, no credentials needed
|
|
99
|
+
- pre-submission analysis: `run_preflight(fn, params, method, spec)` — static warnings + 5 boundary probes, returns `PreflightReport`; called automatically by `sweep()` unless `preflight=False`
|
|
100
|
+
- setup path: install the package, then run `python -m combinate login ...` from the hosted onboarding page or set `COMBINATE_API_BASE_URL`, `COMBINATE_API_KEY`, and `COMBINATE_PROJECT_ID`
|
|
101
|
+
- outside private-alpha testers must use the deployed hosted control-plane URL from onboarding, not `localhost` or `127.0.0.1`
|
|
102
|
+
- stable submission mode: `grid`
|
|
103
|
+
- bounded stochastic mode: `sampling_spec={"method": "random", ...}`
|
|
104
|
+
- bounded experimental search mode: `sampling_spec={"method": "genetic", ...}`
|
|
105
|
+
|
|
106
|
+
Current alpha project limits:
|
|
107
|
+
|
|
108
|
+
- maximum active sweeps per project: `2`
|
|
109
|
+
- maximum active tasks per project: `6`
|
|
110
|
+
|
|
111
|
+
Current submission task estimation:
|
|
112
|
+
|
|
113
|
+
- `grid`: Cartesian product of list-valued parameter dimensions
|
|
114
|
+
- `random`: `samples`, defaulting to `1`
|
|
115
|
+
- `genetic`: `population_size * max_generations`
|
|
116
|
+
|
|
117
|
+
Current method defaults that matter:
|
|
118
|
+
|
|
119
|
+
- `random`: defaults to `samples=1`, `seed=0`, `sampler="uniform"`
|
|
120
|
+
- `genetic`: defaults to `planner="reference"`, `seed=0`, `population_size=4`, `max_generations=3`, `objective_metric="objective"`, `objective_goal="maximize"`, `elite_count=1`, `mutation_rate=0.2`, `range_mutation_locality=0.25`
|
|
121
|
+
|
|
122
|
+
Important alpha consequence:
|
|
123
|
+
|
|
124
|
+
- a bare `method="genetic"` submission uses the default genetic settings above, which estimate `4 * 3 = 12` tasks and will exceed the current `6`-task project cap
|
|
125
|
+
- for a small hosted alpha smoke, use an explicit bounded genetic `sampling_spec`, such as `population_size=2` and `max_generations=2`
|
|
126
|
+
|
|
127
|
+
## Quick Start
|
|
128
|
+
|
|
129
|
+
Preferred hosted setup path:
|
|
130
|
+
|
|
131
|
+
```powershell
|
|
132
|
+
python -m combinate login --api-base-url "https://<operator-provided-control-plane-url>" --api-key "<your-sdk-key>" --project-id "<your-project-id>"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Environment-variable equivalent:
|
|
136
|
+
|
|
137
|
+
```powershell
|
|
138
|
+
$env:COMBINATE_API_BASE_URL = "https://<operator-provided-control-plane-url>"
|
|
139
|
+
$env:COMBINATE_API_KEY = "<your-sdk-key>"
|
|
140
|
+
$env:COMBINATE_PROJECT_ID = "<your-project-id>"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
For outside private-alpha testers, `COMBINATE_API_BASE_URL` must be the deployed control-plane URL from the onboarding flow. Do not substitute `localhost` or `127.0.0.1`.
|
|
144
|
+
|
|
145
|
+
Then run a sweep from Python:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from combinate import CombinateConfig, sweep
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def simulate(alpha: float, beta: float) -> dict[str, float]:
|
|
152
|
+
return {"objective": alpha * beta}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
result = sweep(
|
|
156
|
+
simulate,
|
|
157
|
+
params={"alpha": [0.1, 0.2], "beta": [10.0, 20.0]},
|
|
158
|
+
config=CombinateConfig(project_id="proj-example"),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
print(result.describe())
|
|
162
|
+
print(result.to_dict())
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Useful follow-up CLI commands after a submission:
|
|
166
|
+
|
|
167
|
+
```powershell
|
|
168
|
+
python -m combinate show-config
|
|
169
|
+
python -m combinate list-sweeps
|
|
170
|
+
python -m combinate get-sweep <sweep-id>
|
|
171
|
+
python -m combinate watch-sweep <sweep-id>
|
|
172
|
+
python -m combinate cancel-sweep <sweep-id>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Current support rule of thumb:
|
|
176
|
+
|
|
177
|
+
- keep the returned `sweep_id` for any suspicious or failed run
|
|
178
|
+
- use `get-sweep` before retrying so operator support stays keyed on the same documented identifier
|
|
179
|
+
|
|
180
|
+
The same `sweep()` entry point also supports small alpha smoke cases for bounded random sampling and experimental genetic search through `sampling_spec`:
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
random_result = sweep(
|
|
184
|
+
simulate,
|
|
185
|
+
params={"alpha": [0.1, 0.2, 0.3], "beta": [10.0, 20.0, 30.0]},
|
|
186
|
+
sampling_spec={"method": "random", "samples": 3, "seed": 42},
|
|
187
|
+
config=CombinateConfig(),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
genetic_result = sweep(
|
|
191
|
+
simulate,
|
|
192
|
+
params={"alpha": [0.1, 0.2, 0.3], "beta": [10.0, 20.0, 30.0]},
|
|
193
|
+
sampling_spec={
|
|
194
|
+
"method": "genetic",
|
|
195
|
+
"population_size": 2,
|
|
196
|
+
"max_generations": 2,
|
|
197
|
+
"objective_metric": "objective",
|
|
198
|
+
"objective_goal": "maximize",
|
|
199
|
+
"seed": 7,
|
|
200
|
+
},
|
|
201
|
+
config=CombinateConfig(),
|
|
202
|
+
)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Result Model
|
|
206
|
+
|
|
207
|
+
The synchronous `sweep()` path returns a `SweepResult` that includes:
|
|
208
|
+
|
|
209
|
+
- sweep status and task counts
|
|
210
|
+
- per-task output summaries
|
|
211
|
+
- failed task summaries when execution does not fully succeed
|
|
212
|
+
- structured result data suitable for logs, notebooks, or downstream automation
|
|
213
|
+
|
|
214
|
+
## Current Alpha Notes
|
|
215
|
+
|
|
216
|
+
- the current alpha path uses an SDK credential issued from the browser onboarding flow
|
|
217
|
+
- `COMBINATE_API_KEY` is read by `CombinateConfig` from the environment by default
|
|
218
|
+
- prerelease artifacts are currently published through TestPyPI during the alpha phase
|
|
219
|
+
- run grid, random, and genetic smoke cases one at a time during private alpha so project concurrency limits do not hide the result behavior you are trying to inspect
|
|
220
|
+
- prefer explicit `sampling_spec` values for `random` and `genetic` instead of relying on method defaults during alpha smoke testing
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: combinate
|
|
3
|
+
Version: 0.1.0rc1
|
|
4
|
+
Summary: Agent-native cloud parameter sweeps for Python simulations.
|
|
5
|
+
Project-URL: Homepage, https://www.combinate.ai
|
|
6
|
+
Project-URL: Documentation, https://www.combinate.ai/#how-it-works
|
|
7
|
+
Author: Combinate
|
|
8
|
+
Keywords: design space exploration,parameter sweep,python sdk,simulation
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: Other/Proprietary License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: cloudpickle<4,>=3.0
|
|
19
|
+
Requires-Dist: httpx<1,>=0.28
|
|
20
|
+
Requires-Dist: scipy<2,>=1.14
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: alembic<2,>=1.13; extra == 'dev'
|
|
23
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
24
|
+
Requires-Dist: psycopg[binary]<4,>=3.2; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest<9,>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: python-dotenv<2,>=1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: twine<7,>=6.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: uvicorn<1,>=0.30; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Combinate
|
|
32
|
+
|
|
33
|
+
Combinate is a Python-first cloud parameter-sweep platform for simulation-style workloads.
|
|
34
|
+
|
|
35
|
+
The SDK is designed for the common case where you already have a Python function and a set of parameter combinations you want to evaluate. Instead of managing nested loops, retries, and result collection yourself, you submit a sweep and get structured results back.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
Current private-beta prerelease install target:
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple combinate==0.1.0b1
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This version is intentionally a prerelease. Do not use final `0.1.0` on TestPyPI while the install, onboarding, and support loop are still being proven in private beta.
|
|
46
|
+
|
|
47
|
+
This README is the minimum self-contained install-to-first-sweep guide that should be usable from the installed package alone.
|
|
48
|
+
|
|
49
|
+
Richer walkthroughs such as the repository quickstart and usage guides may exist outside the installed artifact and should not be assumed to be locally bundled in the wheel.
|
|
50
|
+
|
|
51
|
+
The published package intentionally contains only the Python SDK and CLI surface. The hosted control plane remains a separate deployed service and is not bundled into the PyPI artifact.
|
|
52
|
+
|
|
53
|
+
## Try It Locally First (No Account Required)
|
|
54
|
+
|
|
55
|
+
`local_sweep` runs your function in-process against a sampled parameter space without connecting to the Combinate cloud. No API key, project ID, or sign-in required.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from combinate import local_sweep
|
|
59
|
+
|
|
60
|
+
def simulate(alpha: float, beta: float) -> dict:
|
|
61
|
+
return {"objective": alpha * beta}
|
|
62
|
+
|
|
63
|
+
result = local_sweep(
|
|
64
|
+
simulate,
|
|
65
|
+
params={
|
|
66
|
+
"alpha": {"type": "range", "min": 0.1, "max": 10.0},
|
|
67
|
+
"beta": [1.0, 5.0, 10.0],
|
|
68
|
+
},
|
|
69
|
+
sampling_spec={"method": "random", "sampler": "sobol", "samples": 20, "seed": 42},
|
|
70
|
+
max_tasks=20,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
print(result.describe())
|
|
74
|
+
for task in result.succeeded_tasks:
|
|
75
|
+
print(task.parameter_values, task.inline_output)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
When you are ready to scale to a full cloud run, change `local_sweep` to `sweep` and add a `CombinateConfig`. Everything else — params, sampling_spec, result inspection — stays identical.
|
|
79
|
+
|
|
80
|
+
`local_sweep` defaults to a cap of 25 tasks (hard limit: 200). Use it to validate your function signature, parameter space, and output shape before committing to a large cloud run.
|
|
81
|
+
|
|
82
|
+
## Pre-Sweep Validation
|
|
83
|
+
|
|
84
|
+
`run_preflight` analyzes your parameter space and function before any cloud submission. It runs two checks automatically:
|
|
85
|
+
|
|
86
|
+
**Static analysis** — inspects parameter definitions without executing your function:
|
|
87
|
+
- flags `min=0` on any dimension as a division or logarithm risk
|
|
88
|
+
- flags `min=1` as an off-by-one risk when your model uses `count - 1` patterns
|
|
89
|
+
- flags inverted ranges (`min > max`)
|
|
90
|
+
- flags grid sweeps above 500 tasks
|
|
91
|
+
|
|
92
|
+
**Boundary probes** — runs your function at 5 targeted parameter sets: all-min, all-max, midpoint, and two cross-combos (first half lo/second half hi, and vice versa). Cross-combos catch interaction bugs that only appear when two dimensions are simultaneously at their extremes.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from combinate import run_preflight
|
|
96
|
+
|
|
97
|
+
def simulate(alpha: float, beta: float) -> dict:
|
|
98
|
+
return {"objective": alpha / beta} # would fail at beta=0
|
|
99
|
+
|
|
100
|
+
params = {
|
|
101
|
+
"alpha": {"type": "range", "min": 0.1, "max": 10.0},
|
|
102
|
+
"beta": {"type": "range", "min": 0.0, "max": 5.0}, # min=0 → flagged
|
|
103
|
+
}
|
|
104
|
+
spec = {"method": "random", "sampler": "sobol", "samples": 200}
|
|
105
|
+
|
|
106
|
+
report = run_preflight(simulate, params, "random", spec)
|
|
107
|
+
# prints formatted analysis to stderr
|
|
108
|
+
# report.static_warnings — list of warning strings
|
|
109
|
+
# report.probe_results — list of ProbeResult(label, params, elapsed_s, output, error)
|
|
110
|
+
# report.probe_failures — subset where error is not None
|
|
111
|
+
# report.task_count — estimated task count
|
|
112
|
+
# report.median_task_s — median probe wall time
|
|
113
|
+
# report.estimated_wall_s — task_count / parallelism * median_task_s
|
|
114
|
+
# report.estimated_cost_usd — planning estimate
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`sweep()` calls `run_preflight()` automatically before submission. Pass `preflight=False` to skip it:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
result = sweep(simulate, params=params, config=config, preflight=False)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Agent Quick Reference
|
|
124
|
+
|
|
125
|
+
If you are a coding agent integrating `combinate` into a fresh project, these are the current contract-critical facts:
|
|
126
|
+
|
|
127
|
+
- primary entry points: `from combinate import CombinateConfig, sweep, local_sweep, run_preflight`
|
|
128
|
+
- local validation path (no account): `local_sweep(fn, params=..., max_tasks=25)` — runs in-process, no credentials needed
|
|
129
|
+
- pre-submission analysis: `run_preflight(fn, params, method, spec)` — static warnings + 5 boundary probes, returns `PreflightReport`; called automatically by `sweep()` unless `preflight=False`
|
|
130
|
+
- setup path: install the package, then run `python -m combinate login ...` from the hosted onboarding page or set `COMBINATE_API_BASE_URL`, `COMBINATE_API_KEY`, and `COMBINATE_PROJECT_ID`
|
|
131
|
+
- outside private-alpha testers must use the deployed hosted control-plane URL from onboarding, not `localhost` or `127.0.0.1`
|
|
132
|
+
- stable submission mode: `grid`
|
|
133
|
+
- bounded stochastic mode: `sampling_spec={"method": "random", ...}`
|
|
134
|
+
- bounded experimental search mode: `sampling_spec={"method": "genetic", ...}`
|
|
135
|
+
|
|
136
|
+
Current alpha project limits:
|
|
137
|
+
|
|
138
|
+
- maximum active sweeps per project: `2`
|
|
139
|
+
- maximum active tasks per project: `6`
|
|
140
|
+
|
|
141
|
+
Current submission task estimation:
|
|
142
|
+
|
|
143
|
+
- `grid`: Cartesian product of list-valued parameter dimensions
|
|
144
|
+
- `random`: `samples`, defaulting to `1`
|
|
145
|
+
- `genetic`: `population_size * max_generations`
|
|
146
|
+
|
|
147
|
+
Current method defaults that matter:
|
|
148
|
+
|
|
149
|
+
- `random`: defaults to `samples=1`, `seed=0`, `sampler="uniform"`
|
|
150
|
+
- `genetic`: defaults to `planner="reference"`, `seed=0`, `population_size=4`, `max_generations=3`, `objective_metric="objective"`, `objective_goal="maximize"`, `elite_count=1`, `mutation_rate=0.2`, `range_mutation_locality=0.25`
|
|
151
|
+
|
|
152
|
+
Important alpha consequence:
|
|
153
|
+
|
|
154
|
+
- a bare `method="genetic"` submission uses the default genetic settings above, which estimate `4 * 3 = 12` tasks and will exceed the current `6`-task project cap
|
|
155
|
+
- for a small hosted alpha smoke, use an explicit bounded genetic `sampling_spec`, such as `population_size=2` and `max_generations=2`
|
|
156
|
+
|
|
157
|
+
## Quick Start
|
|
158
|
+
|
|
159
|
+
Preferred hosted setup path:
|
|
160
|
+
|
|
161
|
+
```powershell
|
|
162
|
+
python -m combinate login --api-base-url "https://<operator-provided-control-plane-url>" --api-key "<your-sdk-key>" --project-id "<your-project-id>"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Environment-variable equivalent:
|
|
166
|
+
|
|
167
|
+
```powershell
|
|
168
|
+
$env:COMBINATE_API_BASE_URL = "https://<operator-provided-control-plane-url>"
|
|
169
|
+
$env:COMBINATE_API_KEY = "<your-sdk-key>"
|
|
170
|
+
$env:COMBINATE_PROJECT_ID = "<your-project-id>"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
For outside private-alpha testers, `COMBINATE_API_BASE_URL` must be the deployed control-plane URL from the onboarding flow. Do not substitute `localhost` or `127.0.0.1`.
|
|
174
|
+
|
|
175
|
+
Then run a sweep from Python:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from combinate import CombinateConfig, sweep
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def simulate(alpha: float, beta: float) -> dict[str, float]:
|
|
182
|
+
return {"objective": alpha * beta}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
result = sweep(
|
|
186
|
+
simulate,
|
|
187
|
+
params={"alpha": [0.1, 0.2], "beta": [10.0, 20.0]},
|
|
188
|
+
config=CombinateConfig(project_id="proj-example"),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
print(result.describe())
|
|
192
|
+
print(result.to_dict())
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Useful follow-up CLI commands after a submission:
|
|
196
|
+
|
|
197
|
+
```powershell
|
|
198
|
+
python -m combinate show-config
|
|
199
|
+
python -m combinate list-sweeps
|
|
200
|
+
python -m combinate get-sweep <sweep-id>
|
|
201
|
+
python -m combinate watch-sweep <sweep-id>
|
|
202
|
+
python -m combinate cancel-sweep <sweep-id>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Current support rule of thumb:
|
|
206
|
+
|
|
207
|
+
- keep the returned `sweep_id` for any suspicious or failed run
|
|
208
|
+
- use `get-sweep` before retrying so operator support stays keyed on the same documented identifier
|
|
209
|
+
|
|
210
|
+
The same `sweep()` entry point also supports small alpha smoke cases for bounded random sampling and experimental genetic search through `sampling_spec`:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
random_result = sweep(
|
|
214
|
+
simulate,
|
|
215
|
+
params={"alpha": [0.1, 0.2, 0.3], "beta": [10.0, 20.0, 30.0]},
|
|
216
|
+
sampling_spec={"method": "random", "samples": 3, "seed": 42},
|
|
217
|
+
config=CombinateConfig(),
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
genetic_result = sweep(
|
|
221
|
+
simulate,
|
|
222
|
+
params={"alpha": [0.1, 0.2, 0.3], "beta": [10.0, 20.0, 30.0]},
|
|
223
|
+
sampling_spec={
|
|
224
|
+
"method": "genetic",
|
|
225
|
+
"population_size": 2,
|
|
226
|
+
"max_generations": 2,
|
|
227
|
+
"objective_metric": "objective",
|
|
228
|
+
"objective_goal": "maximize",
|
|
229
|
+
"seed": 7,
|
|
230
|
+
},
|
|
231
|
+
config=CombinateConfig(),
|
|
232
|
+
)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Result Model
|
|
236
|
+
|
|
237
|
+
The synchronous `sweep()` path returns a `SweepResult` that includes:
|
|
238
|
+
|
|
239
|
+
- sweep status and task counts
|
|
240
|
+
- per-task output summaries
|
|
241
|
+
- failed task summaries when execution does not fully succeed
|
|
242
|
+
- structured result data suitable for logs, notebooks, or downstream automation
|
|
243
|
+
|
|
244
|
+
## Current Alpha Notes
|
|
245
|
+
|
|
246
|
+
- the current alpha path uses an SDK credential issued from the browser onboarding flow
|
|
247
|
+
- `COMBINATE_API_KEY` is read by `CombinateConfig` from the environment by default
|
|
248
|
+
- prerelease artifacts are currently published through TestPyPI during the alpha phase
|
|
249
|
+
- run grid, random, and genetic smoke cases one at a time during private alpha so project concurrency limits do not hide the result behavior you are trying to inspect
|
|
250
|
+
- prefer explicit `sampling_spec` values for `random` and `genetic` instead of relying on method defaults during alpha smoke testing
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.24"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "combinate"
|
|
7
|
+
version = "0.1.0rc1"
|
|
8
|
+
description = "Agent-native cloud parameter sweeps for Python simulations."
|
|
9
|
+
readme = "PACKAGE_README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Combinate" }
|
|
13
|
+
]
|
|
14
|
+
keywords = [
|
|
15
|
+
"parameter sweep",
|
|
16
|
+
"simulation",
|
|
17
|
+
"design space exploration",
|
|
18
|
+
"python sdk",
|
|
19
|
+
]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
|
+
"Intended Audience :: Science/Research",
|
|
23
|
+
"Intended Audience :: Developers",
|
|
24
|
+
"License :: Other/Proprietary License",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12"
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"cloudpickle>=3.0,<4",
|
|
32
|
+
"httpx>=0.28,<1",
|
|
33
|
+
"scipy>=1.14,<2",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://www.combinate.ai"
|
|
38
|
+
Documentation = "https://www.combinate.ai/#how-it-works"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
combinate = "combinate.cli:main"
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
dev = [
|
|
45
|
+
"alembic>=1.13,<2",
|
|
46
|
+
"build>=1.2,<2",
|
|
47
|
+
"python-dotenv>=1.0,<2",
|
|
48
|
+
"psycopg[binary]>=3.2,<4",
|
|
49
|
+
"pytest>=8.0,<9",
|
|
50
|
+
"twine>=6.1,<7",
|
|
51
|
+
"uvicorn>=0.30,<1",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build]
|
|
55
|
+
exclude = [
|
|
56
|
+
"/.combinate",
|
|
57
|
+
"/.pytest_cache",
|
|
58
|
+
"/.tmp_pkg_validate",
|
|
59
|
+
"/.tmp_testpypi_validate",
|
|
60
|
+
"/dist",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[tool.hatch.build.targets.wheel]
|
|
64
|
+
packages = ["src/combinate"]
|
|
65
|
+
|
|
66
|
+
[tool.hatch.build.targets.sdist]
|
|
67
|
+
include = [
|
|
68
|
+
"src/combinate",
|
|
69
|
+
"PACKAGE_README.md",
|
|
70
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Public Combinate SDK surface.
|
|
2
|
+
|
|
3
|
+
The installed package intentionally exposes a small Python-first interface:
|
|
4
|
+
|
|
5
|
+
- `CombinateConfig` for SDK configuration
|
|
6
|
+
- `sweep()` for the default submit-and-inspect path
|
|
7
|
+
- `submit_sweep()` for submit-only behavior
|
|
8
|
+
- `list_sweeps()` and `CombinateClient` for explicit lifecycle operations
|
|
9
|
+
- result container types for inspection and support flows
|
|
10
|
+
|
|
11
|
+
For the current private-alpha path, outside testers should use the hosted onboarding
|
|
12
|
+
page's control-plane URL and SDK key instead of inferring local defaults.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .client import CombinateClient
|
|
16
|
+
from .config import CombinateConfig
|
|
17
|
+
from .errors import (
|
|
18
|
+
CombinateAPIError,
|
|
19
|
+
CombinateAuthenticationError,
|
|
20
|
+
CombinateConfigurationError,
|
|
21
|
+
CombinateError,
|
|
22
|
+
CombinateNotImplementedError,
|
|
23
|
+
CombinateValidationError,
|
|
24
|
+
)
|
|
25
|
+
from .normalization import NormalizedSweepRequest, normalize_params, prepare_sweep_request
|
|
26
|
+
from .preflight import PreflightReport, run_preflight
|
|
27
|
+
from .result import SweepResult, SweepResults, SweepSummary, SweepTask
|
|
28
|
+
from .sdk import list_sweeps, local_sweep, submit_sweep, sweep
|
|
29
|
+
from .validation import validate_sweep_call
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"CombinateAuthenticationError",
|
|
33
|
+
"CombinateAPIError",
|
|
34
|
+
"CombinateClient",
|
|
35
|
+
"CombinateConfig",
|
|
36
|
+
"CombinateConfigurationError",
|
|
37
|
+
"CombinateError",
|
|
38
|
+
"CombinateNotImplementedError",
|
|
39
|
+
"CombinateValidationError",
|
|
40
|
+
"NormalizedSweepRequest",
|
|
41
|
+
"PreflightReport",
|
|
42
|
+
"SweepResult",
|
|
43
|
+
"SweepResults",
|
|
44
|
+
"SweepSummary",
|
|
45
|
+
"SweepTask",
|
|
46
|
+
"list_sweeps",
|
|
47
|
+
"local_sweep",
|
|
48
|
+
"normalize_params",
|
|
49
|
+
"prepare_sweep_request",
|
|
50
|
+
"run_preflight",
|
|
51
|
+
"submit_sweep",
|
|
52
|
+
"sweep",
|
|
53
|
+
"validate_sweep_call",
|
|
54
|
+
]
|