morphtree 2.1.0__py3-none-win_amd64.whl
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.
- morphtree/__init__.py +28 -0
- morphtree/__main__.py +3 -0
- morphtree/_experimental/__init__.py +1 -0
- morphtree/_experimental/admission.py +364 -0
- morphtree/_experimental/base.py +215 -0
- morphtree/_experimental/component_cache_v2.py +263 -0
- morphtree/_experimental/evolution_report.py +307 -0
- morphtree/_experimental/execution_v2.py +697 -0
- morphtree/_experimental/facade.py +289 -0
- morphtree/_experimental/integrated.py +748 -0
- morphtree/_experimental/learning.py +418 -0
- morphtree/_experimental/manifest.json +204 -0
- morphtree/_experimental/numeric_fixture.py +21 -0
- morphtree/_experimental/parameter_contract.py +38 -0
- morphtree/_experimental/postfit.py +51 -0
- morphtree/_experimental/preprocessing.py +133 -0
- morphtree/_experimental/processes.py +191 -0
- morphtree/_experimental/producer.py +542 -0
- morphtree/_experimental/product.py +156 -0
- morphtree/_experimental/product_cli.py +43 -0
- morphtree/_experimental/roundtrip_v3.py +311 -0
- morphtree/_experimental/runtime_io.py +65 -0
- morphtree/_experimental/sampling.py +26 -0
- morphtree/_experimental/support.py +281 -0
- morphtree/_experimental/target.py +59 -0
- morphtree/_experimental/training.py +53 -0
- morphtree/_experimental/worker.py +682 -0
- morphtree/_installed.py +17 -0
- morphtree/_native/__init__.py +1 -0
- morphtree/_native/bin/win_amd64/morphtree_kernels.dll +0 -0
- morphtree/_native/buffers.py +82 -0
- morphtree/_native/loader.py +39 -0
- morphtree/_native/manifest.json +29 -0
- morphtree/_native/runtime.py +48 -0
- morphtree/_native/src/histogram.c +61 -0
- morphtree/_native/src/traversal.c +51 -0
- morphtree/api.py +388 -0
- morphtree/api_compat.py +65 -0
- morphtree/backend.py +162 -0
- morphtree/booster.py +252 -0
- morphtree/cli.py +52 -0
- morphtree/config.py +262 -0
- morphtree/control.py +20 -0
- morphtree/data.py +300 -0
- morphtree/diagnostics.py +158 -0
- morphtree/estimators.py +156 -0
- morphtree/examples.py +25 -0
- morphtree/exporting.py +224 -0
- morphtree/legacy_artifacts.py +32 -0
- morphtree/metrics.py +156 -0
- morphtree/model.py +1010 -0
- morphtree/mutations.py +205 -0
- morphtree/native_lab_backend.py +79 -0
- morphtree/numpy_backend.py +180 -0
- morphtree/optuna_tuner.py +154 -0
- morphtree/persistence.py +414 -0
- morphtree/prediction_output.py +35 -0
- morphtree/prepared_bins.py +82 -0
- morphtree/public.py +106 -0
- morphtree/resource_plan.py +170 -0
- morphtree/scalable.py +781 -0
- morphtree/scalable_backend.py +74 -0
- morphtree/scalable_checkpoint.py +129 -0
- morphtree/scalable_data.py +255 -0
- morphtree/scalable_receipts.py +92 -0
- morphtree/scalable_target.py +68 -0
- morphtree/scalable_variants.py +133 -0
- morphtree/sklearn_view.py +79 -0
- morphtree/source_markers.py +25 -0
- morphtree/species.py +47 -0
- morphtree/temporary.py +65 -0
- morphtree/training_fragment.py +130 -0
- morphtree/tree.py +231 -0
- morphtree/tuning.py +150 -0
- morphtree-2.1.0.dist-info/METADATA +212 -0
- morphtree-2.1.0.dist-info/RECORD +79 -0
- morphtree-2.1.0.dist-info/WHEEL +4 -0
- morphtree-2.1.0.dist-info/entry_points.txt +2 -0
- morphtree-2.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import copy, math, json, tempfile, os
|
|
2
|
+
from ..temporary import OwnedTemporaryDirectory
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from dataclasses import asdict, replace
|
|
5
|
+
from morphtree.config import AlgorithmGenome, HyperParams
|
|
6
|
+
from morphtree.persistence import read_json, write_json, LoadLimits
|
|
7
|
+
from morphtree.model import MorphTreeClassifier, MorphTreeRegressor, MorphTreeMulticlassClassifier
|
|
8
|
+
from morphtree.metrics import point_losses
|
|
9
|
+
from .admission import digest, sha, AdmissionError
|
|
10
|
+
from .runtime_io import artifact_path, configure_temp, reference, publish
|
|
11
|
+
NATIVE = {'binary': MorphTreeClassifier, 'multiclass': MorphTreeMulticlassClassifier, 'regression': MorphTreeRegressor}
|
|
12
|
+
TASKS = ('binary', 'multiclass', 'regression')
|
|
13
|
+
from .base import Base as Previous, PARAMS
|
|
14
|
+
from .preprocessing import TrainEncoder
|
|
15
|
+
from .runtime_io import require, explicit_input, configure
|
|
16
|
+
|
|
17
|
+
class VariantUnavailable(ValueError):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
class Control(Previous):
|
|
21
|
+
|
|
22
|
+
def __init__(self, *, task='auto', families='auto', morphing='auto', tuning='auto', preset='balanced', metric='auto', time_budget='auto', n_trials='auto', n_jobs='auto', random_state=None, verbose=0, capacity=None):
|
|
23
|
+
self.capacity = copy.deepcopy(capacity)
|
|
24
|
+
super().__init__(task=task, families=families, morphing=morphing, tuning=tuning, preset=preset, metric=metric, time_budget=time_budget, n_trials=n_trials, n_jobs=n_jobs, random_state=random_state, verbose=verbose)
|
|
25
|
+
|
|
26
|
+
def _validate(self):
|
|
27
|
+
super()._validate()
|
|
28
|
+
if self.capacity is not None:
|
|
29
|
+
if type(self.capacity) is not dict or not set(self.capacity) <= {'max_leaves', 'max_depth', 'n_estimators'}:
|
|
30
|
+
raise ValueError('capacity supports finite max_leaves/max_depth/n_estimators; no inactive options')
|
|
31
|
+
for name, value in self.capacity.items():
|
|
32
|
+
if type(value) is not int or not 1 <= value <= {'max_leaves': 16, 'max_depth': 8, 'n_estimators': 8}[name]:
|
|
33
|
+
raise ValueError('Finite integer structural capacity required')
|
|
34
|
+
|
|
35
|
+
def get_params(self, deep=True):
|
|
36
|
+
return copy.deepcopy({k: getattr(self, k) for k in (*PARAMS, 'capacity')})
|
|
37
|
+
|
|
38
|
+
def set_params(self, **values):
|
|
39
|
+
if set(values) - set(self.get_params()):
|
|
40
|
+
raise ValueError('Unknown estimator parameter')
|
|
41
|
+
new = type(self)(**self.get_params() | values)
|
|
42
|
+
self.__dict__ = new.__dict__
|
|
43
|
+
return self
|
|
44
|
+
|
|
45
|
+
def report(self):
|
|
46
|
+
value = super().report()
|
|
47
|
+
value['variants'] = self.available_variants()
|
|
48
|
+
return value
|
|
49
|
+
|
|
50
|
+
def available_variants(self):
|
|
51
|
+
self._fitted()
|
|
52
|
+
return {k: {'origin': v['origin'], 'params': copy.deepcopy(v['recipe']['params']), 'exportable': v['exportable'], 'evidence': v['evidence'], 'SEARCH_primary': v.get('SEARCH_primary')} for k, v in self._variants.items()}
|
|
53
|
+
|
|
54
|
+
def _variant(self, name):
|
|
55
|
+
self._fitted()
|
|
56
|
+
name = self._selected_variant if name == 'selected' else name
|
|
57
|
+
if name not in self._variants:
|
|
58
|
+
raise VariantUnavailable('Requested variant has no retained, verified weights; a separately budgeted fit may be needed')
|
|
59
|
+
v = self._variants[name]
|
|
60
|
+
if not v['exportable']:
|
|
61
|
+
raise VariantUnavailable('Software replay cannot be exported as a newly trained pure/tuned variant')
|
|
62
|
+
obj = Previous(**{k: v for k, v in self.get_params().items() if k != 'capacity'})
|
|
63
|
+
for k in ('encoder_', 'task_', 'n_features_in_', 'classes_', 'feature_names_in_'):
|
|
64
|
+
if hasattr(self, k):
|
|
65
|
+
setattr(obj, k, copy.deepcopy(getattr(self, k)))
|
|
66
|
+
obj.model_ = v['model']
|
|
67
|
+
obj.best_recipe_ = copy.deepcopy(v['recipe'])
|
|
68
|
+
obj.best_family_ = v['recipe']['family']
|
|
69
|
+
obj.best_params_ = copy.deepcopy(v['recipe']['params'])
|
|
70
|
+
obj.report_ = self.report()
|
|
71
|
+
obj.report_.update(exported_variant=name, SEARCH_primary=v.get('SEARCH_primary'), best_family=obj.best_family_)
|
|
72
|
+
obj.stop_reason_ = self.stop_reason_
|
|
73
|
+
return obj
|
|
74
|
+
|
|
75
|
+
def export_python(self, path, *, variant='selected'):
|
|
76
|
+
self._variant(variant).export_python(path)
|
|
77
|
+
|
|
78
|
+
def save_recipe(self, path, *, variant='selected'):
|
|
79
|
+
self._variant(variant).save_recipe(path)
|
|
80
|
+
|
|
81
|
+
def save(self, path, *, variant='all'):
|
|
82
|
+
self._fitted()
|
|
83
|
+
configure_temp()
|
|
84
|
+
names = list(self._variants) if variant == 'all' else [self._selected_variant if variant == 'selected' else variant]
|
|
85
|
+
packed = {}
|
|
86
|
+
origins = {}
|
|
87
|
+
with OwnedTemporaryDirectory() as tmp:
|
|
88
|
+
for name in names:
|
|
89
|
+
obj = self._variant(name)
|
|
90
|
+
p = artifact_path(Path(tmp) / (name + '.json'))
|
|
91
|
+
obj.save(p)
|
|
92
|
+
packed[name] = read_json(p, LoadLimits(max_bytes=32 * 1024 ** 2))
|
|
93
|
+
origins[name] = {'origin': self._variants[name]['origin'], 'evidence': self._variants[name]['evidence']}
|
|
94
|
+
body = {'schema': {'comp009-frozen-form-v1': 'comp009-native-control-v1', 'comp003-frozen-form-v1': 'comp003-native-control-v1', 'comp002-frozen-form-v1': 'comp002-native-control-v1', 'product002-frozen-form-v1': 'product002-native-control-v1', 'product003-frozen-form-v1': 'product003-native-control-v1', 'product006-frozen-form-v1': 'product006-native-control-v1'}.get(next(iter(packed.values()))['recipe']['schema'], 'morph027-native-control-v1'), 'constructor': self.get_params(), 'selected_variant': self._selected_variant if self._selected_variant in names else names[0], 'variants': packed, 'origins': origins}
|
|
95
|
+
if len(json.dumps(body, allow_nan=False).encode('utf8')) > 32 * 1024 ** 2:
|
|
96
|
+
raise ValueError('Bounded total variant payload required')
|
|
97
|
+
path = artifact_path(path)
|
|
98
|
+
if path.exists():
|
|
99
|
+
raise FileExistsError('Never overwrite research model evidence')
|
|
100
|
+
write_json(path, body)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def load(cls, path):
|
|
104
|
+
data = read_json(artifact_path(path), LoadLimits(max_bytes=32 * 1024 ** 2))
|
|
105
|
+
if set(data) != {'schema', 'constructor', 'selected_variant', 'variants', 'origins'} or data['schema'] not in ('morph027-native-control-v1', 'comp002-native-control-v1', 'comp003-native-control-v1', 'comp009-native-control-v1', 'product002-native-control-v1', 'product003-native-control-v1', 'product006-native-control-v1'):
|
|
106
|
+
raise ValueError('Exact bounded private control schema required')
|
|
107
|
+
vs = data['variants']
|
|
108
|
+
origins = data['origins']
|
|
109
|
+
if type(vs) is not dict or not vs or (not set(vs) <= {'pure', 'tuned'}) or (set(origins) != set(vs)) or (data['selected_variant'] not in vs):
|
|
110
|
+
raise ValueError('Bounded named variants required')
|
|
111
|
+
obj = cls(**data['constructor'])
|
|
112
|
+
configure_temp()
|
|
113
|
+
loaded = {}
|
|
114
|
+
with OwnedTemporaryDirectory() as tmp:
|
|
115
|
+
for name, body in vs.items():
|
|
116
|
+
if type(body) is not dict:
|
|
117
|
+
raise ValueError('Each model variant must be a JSON object')
|
|
118
|
+
o = origins[name]
|
|
119
|
+
if {'morph027-native-control-v1': 'morph026-native-estimator-v1', 'comp002-native-control-v1': 'comp002-native-estimator-v1', 'comp009-native-control-v1': 'comp009-native-estimator-v1', 'comp003-native-control-v1': 'comp003-native-estimator-v1', 'product002-native-control-v1': 'product002-native-estimator-v1', 'product003-native-control-v1': 'product003-native-estimator-v1', 'product006-native-control-v1': 'product006-native-estimator-v1'}[data['schema']] != body.get('schema'):
|
|
120
|
+
raise ValueError('Mixed experimental envelope versions')
|
|
121
|
+
if data['schema'] == 'morph027-native-control-v1' and 'COMP002_' in str(o):
|
|
122
|
+
raise ValueError('Never relabel fixture as historical training')
|
|
123
|
+
if set(o) != {'origin', 'evidence'} or o['origin'] not in ('PRE_FINAL_NUMERIC_SEARCH', 'VERIFIED_B0_UNTUNED', 'POST_FINAL_NUMERIC_SEARCH') or (not isinstance(o['evidence'], str)) or ('MOCK' in o['evidence']):
|
|
124
|
+
raise ValueError('Explicit genuine variant provenance required')
|
|
125
|
+
if name == 'pure' and o['origin'] == 'POST_FINAL_NUMERIC_SEARCH' or (name == 'tuned' and o['origin'] != 'POST_FINAL_NUMERIC_SEARCH'):
|
|
126
|
+
raise ValueError('Never relabel tuned weights as pure')
|
|
127
|
+
p = artifact_path(Path(tmp) / (name + '.json'))
|
|
128
|
+
write_json(p, body)
|
|
129
|
+
v = Previous.load(p)
|
|
130
|
+
if v.task_ != body['recipe']['task']:
|
|
131
|
+
raise ValueError('Changed task')
|
|
132
|
+
expected = HyperParams(**v.best_params_)
|
|
133
|
+
for m in v.model_.components:
|
|
134
|
+
actual = asdict(m.params_)
|
|
135
|
+
want = asdict(expected if v.best_family_ == 'boost' else replace(expected, n_estimators=1, learning_rate=1.0, row_fraction=1.0))
|
|
136
|
+
if actual != want:
|
|
137
|
+
raise ValueError('Recipe parameters do not describe the actual weights')
|
|
138
|
+
if name == 'tuned' and (not v.report_.get('trials') or not _numeric_evidence(data['schema'], o, v.report_)):
|
|
139
|
+
raise ValueError('No executed numeric trajectory for tuned variant')
|
|
140
|
+
loaded[name] = v
|
|
141
|
+
v = loaded[data['selected_variant']]
|
|
142
|
+
for other in loaded.values():
|
|
143
|
+
if (other.task_, other.classes_ if hasattr(other, 'classes_') else (), other.best_recipe_['structure'], other.best_recipe_['training_identity']) != (v.task_, v.classes_ if hasattr(v, 'classes_') else (), v.best_recipe_['structure'], v.best_recipe_['training_identity']):
|
|
144
|
+
raise ValueError('Variants must share the same frozen structure/data/map')
|
|
145
|
+
for k in ('model_', 'encoder_', 'task_', 'n_features_in_', 'classes_', 'feature_names_in_', 'best_family_', 'best_recipe_', 'best_params_', 'stop_reason_', 'report_'):
|
|
146
|
+
if hasattr(v, k):
|
|
147
|
+
setattr(obj, k, getattr(v, k))
|
|
148
|
+
obj.structure_ = copy.deepcopy(v.best_recipe_['structure'])
|
|
149
|
+
obj._selected_variant = data['selected_variant']
|
|
150
|
+
obj._variants = {k: {'model': v.model_, 'recipe': copy.deepcopy(v.best_recipe_), **origins[k], 'exportable': True, 'SEARCH_primary': v.report_.get('SEARCH_primary')} for k, v in loaded.items()}
|
|
151
|
+
return obj
|
|
152
|
+
|
|
153
|
+
def export_bundle(self, directory, *, variants=('pure',)):
|
|
154
|
+
if type(variants) is not tuple or not variants or len(set(variants)) != len(variants):
|
|
155
|
+
raise ValueError('Distinct variant tuple required')
|
|
156
|
+
for name in variants:
|
|
157
|
+
self._variant(name)
|
|
158
|
+
directory = artifact_path(directory)
|
|
159
|
+
if directory.exists():
|
|
160
|
+
raise FileExistsError('New export directory required')
|
|
161
|
+
directory.mkdir(parents=True)
|
|
162
|
+
out = []
|
|
163
|
+
for name in variants:
|
|
164
|
+
p = directory / (name + '.json')
|
|
165
|
+
self.save(p, variant=name)
|
|
166
|
+
out.append(reference(p))
|
|
167
|
+
p = directory / (name + '-recipe.json')
|
|
168
|
+
self.save_recipe(p, variant=name)
|
|
169
|
+
out.append(reference(p))
|
|
170
|
+
p = directory / (name + '-predictor.py')
|
|
171
|
+
self.export_python(p, variant=name)
|
|
172
|
+
out.append(reference(p))
|
|
173
|
+
p = directory / 'EXPORT.json'
|
|
174
|
+
write_json(p, {'schema': 'morph027-inference-export-v1', 'status': 'COMPLETE', 'artifacts': out, 'retraining_procedure': 'NOT_SUPPORTED', 'new_fits': 0, 'report': self.report()})
|
|
175
|
+
return reference(p)
|
|
176
|
+
|
|
177
|
+
def export_retrainable(self, path):
|
|
178
|
+
raise NotImplementedError('Only inference standalone and declarative recipe are qualified; generic retraining admission is missing')
|
|
179
|
+
|
|
180
|
+
class MorphTree(Control):
|
|
181
|
+
"""Installed retained-model facade. No fresh training implementation."""
|
|
182
|
+
|
|
183
|
+
@classmethod
|
|
184
|
+
def load(cls, path):
|
|
185
|
+
source = explicit_input(path)
|
|
186
|
+
data = read_json(source, LoadLimits(max_bytes=32 * 1024 ** 2))
|
|
187
|
+
if data.get('schema') == 'morph027-native-control-v1':
|
|
188
|
+
obj = super().load(source)
|
|
189
|
+
else:
|
|
190
|
+
v = Previous.load(source)
|
|
191
|
+
expected = HyperParams(**v.best_params_)
|
|
192
|
+
for member in v.model_.components:
|
|
193
|
+
want = expected if v.best_family_ == 'boost' else replace(expected, n_estimators=1, learning_rate=1.0, row_fraction=1.0)
|
|
194
|
+
if asdict(member.params_) != asdict(want):
|
|
195
|
+
raise ValueError('Recipe versus actual retained native parameters')
|
|
196
|
+
obj = cls(**v.get_params())
|
|
197
|
+
obj.__dict__.update(v.__dict__)
|
|
198
|
+
obj.capacity = None
|
|
199
|
+
obj._selected_variant = 'pure'
|
|
200
|
+
obj._variants = {'pure': {'model': v.model_, 'recipe': copy.deepcopy(v.best_recipe_), 'origin': 'VERIFIED_B0_UNTUNED', 'evidence': 'EXPLICIT_SUPPLIED_RETAINED_INPUT_NOT_NEW_FIT', 'exportable': True, 'SEARCH_primary': v.report_.get('SEARCH_primary')}}
|
|
201
|
+
engine, r = require(('load', 'replay'))
|
|
202
|
+
obj._admitted_component = next((v for v in r['components'] if artifact_path(engine.q['input_root']) / v['path'] == artifact_path(path)))
|
|
203
|
+
obj._check_admission(('load', 'replay'))
|
|
204
|
+
return obj
|
|
205
|
+
|
|
206
|
+
def _check_admission(self, operations):
|
|
207
|
+
e, r = require(operations)
|
|
208
|
+
actual = {'family': self.best_family_, 'members': len(self.model_.components), 'stages': self.best_params_['n_estimators'] if self.best_family_ == 'boost' else 1, 'classes': len(getattr(self, 'classes_', ())) or 1, 'genome_sha256': digest(self.best_recipe_['structure']['genome'])}
|
|
209
|
+
if r['task'] != self.task_ or r['recipe'] != actual or self._admitted_component not in r['components']:
|
|
210
|
+
raise ValueError('Model/request actual task, form or component mismatch')
|
|
211
|
+
|
|
212
|
+
def fit(self, X, y):
|
|
213
|
+
self.last_attempt_ = {'status': 'BLOCKED', 'new_fits': 0, 'new_trials': 0, 'reason': 'NEW_INSTALLED_TRAINING_REQUIRES_QUALIFIED_BOUNDARY_AND_NEW_OWNER_CONSENT'}
|
|
214
|
+
raise AdmissionError(self.last_attempt_)
|
|
215
|
+
|
|
216
|
+
def predict(self, X):
|
|
217
|
+
self._check_admission(('infer', 'replay'))
|
|
218
|
+
return super().predict(X)
|
|
219
|
+
|
|
220
|
+
def predict_proba(self, X):
|
|
221
|
+
self._check_admission(('infer', 'replay'))
|
|
222
|
+
return super().predict_proba(X)
|
|
223
|
+
|
|
224
|
+
def save(self, path, *, variant='all'):
|
|
225
|
+
self._check_admission(('save',))
|
|
226
|
+
e, r = require(('save',))
|
|
227
|
+
super().save(path, variant=variant)
|
|
228
|
+
return e.record_output(path)
|
|
229
|
+
|
|
230
|
+
def save_recipe(self, path, *, variant='selected'):
|
|
231
|
+
self._check_admission(('export',))
|
|
232
|
+
e, r = require(('export',))
|
|
233
|
+
super().save_recipe(path, variant=variant)
|
|
234
|
+
return e.record_output(path)
|
|
235
|
+
|
|
236
|
+
def export_python(self, path, *, variant='selected'):
|
|
237
|
+
self._check_admission(('export',))
|
|
238
|
+
e, r = require(('export',))
|
|
239
|
+
super().export_python(path, variant=variant)
|
|
240
|
+
return e.record_output(path)
|
|
241
|
+
|
|
242
|
+
def export_bundle(self, *a, **k):
|
|
243
|
+
raise NotImplementedError('Use separately admitted save/export operations; no broad bundle capability')
|
|
244
|
+
|
|
245
|
+
def recipe(self):
|
|
246
|
+
self._fitted()
|
|
247
|
+
return copy.deepcopy(self.best_recipe_)
|
|
248
|
+
|
|
249
|
+
def _numeric_evidence(schema, origin, report):
|
|
250
|
+
if schema=='product006-native-control-v1':
|
|
251
|
+
rows=[e for e in report.get('events',[]) if e.get('operation')=='COMP003_ACCOUNTING_AND_SCOPE']
|
|
252
|
+
if len(rows)!=1:return False
|
|
253
|
+
row=rows[0];counts=row['counts'];n=len(report.get('trials',[]))
|
|
254
|
+
if not (origin['evidence']=='USER_API_NATIVE_EXECUTION_NOT_SCIENTIFIC_CONFIRMATION'
|
|
255
|
+
and row['details']['trial_evidence']=='USER_DATA_REAL_OPTUNA_NOT_SCIENTIFIC_CONFIRMATION'
|
|
256
|
+
and 1<=n<=4 and n<=counts['Optuna_trials']<=4):return False
|
|
257
|
+
if counts['Optuna_trials']==n and counts['physical_fits_started']==counts['physical_fits_completed']:return True
|
|
258
|
+
p=report.get('morphing',{}).get('verified_report',{})
|
|
259
|
+
recovery=p.get('budget_recovery',{})
|
|
260
|
+
if (recovery.get('schema')!='product006-verified-budget-recovery-v1'
|
|
261
|
+
or recovery.get('phase_completion')!='PARTIAL_BUDGET_VALID_ANCHOR_RETURNED'
|
|
262
|
+
or p.get('counts',{}).get('real_trials_completed')!=n
|
|
263
|
+
or p['counts'].get('real_trials_created')!=counts['Optuna_trials']):return False
|
|
264
|
+
abandoned=recovery.get('unadopted_components',{})
|
|
265
|
+
incomplete=counts['physical_fits_started']-counts['physical_fits_completed']
|
|
266
|
+
return (incomplete>=0 and incomplete==sum(not x['native_completed'] for x in abandoned.values())
|
|
267
|
+
and all(x.get('used_in_final_model') is False for x in abandoned.values())
|
|
268
|
+
and any(e.get('kind')=='SEARCH_STOPPED_BUDGET' for e in p.get('events',[])))
|
|
269
|
+
|
|
270
|
+
if schema == 'product003-native-control-v1':
|
|
271
|
+
rows = [e for e in report.get('events', []) if e.get('operation') == 'COMP003_ACCOUNTING_AND_SCOPE']
|
|
272
|
+
if len(rows) != 1:
|
|
273
|
+
return False
|
|
274
|
+
row = rows[0]
|
|
275
|
+
counts = row['counts']
|
|
276
|
+
n = len(report.get('trials', []))
|
|
277
|
+
return origin['evidence'] == 'USER_API_NATIVE_EXECUTION_NOT_SCIENTIFIC_CONFIRMATION' and row['details']['trial_evidence'] == 'USER_DATA_REAL_OPTUNA_NOT_SCIENTIFIC_CONFIRMATION' and (1 <= n <= 4) and (counts['Optuna_trials'] == n) and (counts['physical_fits_started'] == counts['physical_fits_completed'])
|
|
278
|
+
if schema != 'comp003-native-control-v1':
|
|
279
|
+
return report.get('trial_evidence') in ('EXECUTOR_BOUND_NUMERIC_CALLBACKS', 'AUTHENTICATED_HISTORICAL_REAL_TPE4')
|
|
280
|
+
rows = [e for e in report.get('events', []) if e.get('operation') == 'COMP003_ACCOUNTING_AND_SCOPE']
|
|
281
|
+
if len(rows) != 1:
|
|
282
|
+
return False
|
|
283
|
+
e = rows[0]
|
|
284
|
+
kind = e['details']['trial_evidence']
|
|
285
|
+
counts = e['counts']
|
|
286
|
+
n = len(report['trials'])
|
|
287
|
+
if 'SOFTWARE_FIXTURE' in origin['evidence']:
|
|
288
|
+
return kind == 'SIMULATED_OPTUNA_FIXTURE_NOT_REAL_TRIALS' and counts['trials'] == 0 and (counts['simulated_trials'] == n) and (n == 2)
|
|
289
|
+
return origin['evidence'] == 'COMP003_EXACT_OWNER_ADMITTED_NATIVE_TRAINING' and kind == 'EXACT_OWNER_BOUND_REAL_OPTUNA_TRIALS' and (counts['trials'] == n) and (n == 2) and (counts['simulated_trials'] == 0)
|