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.
Files changed (79) hide show
  1. morphtree/__init__.py +28 -0
  2. morphtree/__main__.py +3 -0
  3. morphtree/_experimental/__init__.py +1 -0
  4. morphtree/_experimental/admission.py +364 -0
  5. morphtree/_experimental/base.py +215 -0
  6. morphtree/_experimental/component_cache_v2.py +263 -0
  7. morphtree/_experimental/evolution_report.py +307 -0
  8. morphtree/_experimental/execution_v2.py +697 -0
  9. morphtree/_experimental/facade.py +289 -0
  10. morphtree/_experimental/integrated.py +748 -0
  11. morphtree/_experimental/learning.py +418 -0
  12. morphtree/_experimental/manifest.json +204 -0
  13. morphtree/_experimental/numeric_fixture.py +21 -0
  14. morphtree/_experimental/parameter_contract.py +38 -0
  15. morphtree/_experimental/postfit.py +51 -0
  16. morphtree/_experimental/preprocessing.py +133 -0
  17. morphtree/_experimental/processes.py +191 -0
  18. morphtree/_experimental/producer.py +542 -0
  19. morphtree/_experimental/product.py +156 -0
  20. morphtree/_experimental/product_cli.py +43 -0
  21. morphtree/_experimental/roundtrip_v3.py +311 -0
  22. morphtree/_experimental/runtime_io.py +65 -0
  23. morphtree/_experimental/sampling.py +26 -0
  24. morphtree/_experimental/support.py +281 -0
  25. morphtree/_experimental/target.py +59 -0
  26. morphtree/_experimental/training.py +53 -0
  27. morphtree/_experimental/worker.py +682 -0
  28. morphtree/_installed.py +17 -0
  29. morphtree/_native/__init__.py +1 -0
  30. morphtree/_native/bin/win_amd64/morphtree_kernels.dll +0 -0
  31. morphtree/_native/buffers.py +82 -0
  32. morphtree/_native/loader.py +39 -0
  33. morphtree/_native/manifest.json +29 -0
  34. morphtree/_native/runtime.py +48 -0
  35. morphtree/_native/src/histogram.c +61 -0
  36. morphtree/_native/src/traversal.c +51 -0
  37. morphtree/api.py +388 -0
  38. morphtree/api_compat.py +65 -0
  39. morphtree/backend.py +162 -0
  40. morphtree/booster.py +252 -0
  41. morphtree/cli.py +52 -0
  42. morphtree/config.py +262 -0
  43. morphtree/control.py +20 -0
  44. morphtree/data.py +300 -0
  45. morphtree/diagnostics.py +158 -0
  46. morphtree/estimators.py +156 -0
  47. morphtree/examples.py +25 -0
  48. morphtree/exporting.py +224 -0
  49. morphtree/legacy_artifacts.py +32 -0
  50. morphtree/metrics.py +156 -0
  51. morphtree/model.py +1010 -0
  52. morphtree/mutations.py +205 -0
  53. morphtree/native_lab_backend.py +79 -0
  54. morphtree/numpy_backend.py +180 -0
  55. morphtree/optuna_tuner.py +154 -0
  56. morphtree/persistence.py +414 -0
  57. morphtree/prediction_output.py +35 -0
  58. morphtree/prepared_bins.py +82 -0
  59. morphtree/public.py +106 -0
  60. morphtree/resource_plan.py +170 -0
  61. morphtree/scalable.py +781 -0
  62. morphtree/scalable_backend.py +74 -0
  63. morphtree/scalable_checkpoint.py +129 -0
  64. morphtree/scalable_data.py +255 -0
  65. morphtree/scalable_receipts.py +92 -0
  66. morphtree/scalable_target.py +68 -0
  67. morphtree/scalable_variants.py +133 -0
  68. morphtree/sklearn_view.py +79 -0
  69. morphtree/source_markers.py +25 -0
  70. morphtree/species.py +47 -0
  71. morphtree/temporary.py +65 -0
  72. morphtree/training_fragment.py +130 -0
  73. morphtree/tree.py +231 -0
  74. morphtree/tuning.py +150 -0
  75. morphtree-2.1.0.dist-info/METADATA +212 -0
  76. morphtree-2.1.0.dist-info/RECORD +79 -0
  77. morphtree-2.1.0.dist-info/WHEEL +4 -0
  78. morphtree-2.1.0.dist-info/entry_points.txt +2 -0
  79. morphtree-2.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,418 @@
1
+ from .execution_v2 import SearchBudgetExhausted
2
+ import copy, importlib, importlib.util, json, math, random, tempfile, time
3
+ from ..temporary import OwnedTemporaryDirectory
4
+ from pathlib import Path
5
+ from dataclasses import asdict, replace
6
+ from morphtree.config import AlgorithmGenome, HyperParams
7
+ from morphtree.persistence import read_json, write_json, LoadLimits
8
+ from .runtime_io import artifact_path, configure_temp, reference
9
+ from .admission import digest, sha
10
+ from .support import FamilyChoice, TaskFinalizer, risk
11
+ from .parameter_contract import admit_space
12
+ from .base import Base as Previous, PARAMS, _payloads
13
+ from .preprocessing import TrainEncoder, _m26_rows
14
+ from .training import NativeExecutor, TrainingNotAdmitted
15
+ from .target import detect_target, _split, _NamedRows
16
+
17
+ class BudgetExhausted(RuntimeError):
18
+ """Finite opportunity cap; never convergence or a fresh budget."""
19
+
20
+ class StopRequested(RuntimeError):
21
+ """Explicit STOP; never a recoverable timeout."""
22
+
23
+ class VariantUnavailable(ValueError):
24
+ pass
25
+
26
+ def stop_reason(*, event, completed_proposals=0, improved=False, full_neighborhood_verified=False):
27
+ """Typed operational semantics, not a fitted stagnation detector."""
28
+ direct = {'planned': 'PLANNED_SEARCH_COMPLETE', 'no_actions': 'NO_ADMISSIBLE_CORRECTIVE_ACTION', 'budget': 'BUDGET_EXHAUSTED', 'timeout': 'TIMEOUT', 'stop': 'STOP_REQUESTED', 'error': 'ERROR_OR_INTERRUPTION', 'not_admitted': 'EXECUTION_NOT_ADMITTED'}
29
+ if event in direct:
30
+ return direct[event]
31
+ if type(completed_proposals) is not int or completed_proposals < 1 or type(improved) is not bool:
32
+ raise ValueError('A completed comparison is required before a stall claim')
33
+ if event == 'structural' and (not improved):
34
+ return 'STRUCTURAL_NO_IMPROVEMENT'
35
+ if event == 'family' and (not improved) and (full_neighborhood_verified is True):
36
+ return 'FAMILY_SEARCH_STALLED'
37
+ raise ValueError('No evidence of the requested stall')
38
+
39
+ def mutation_admission(mode):
40
+ """Reuse negative knowledge: no scientifically admitted automatic operator.
41
+
42
+ This admission decision is not a diagnostic measurement. No labels, OOF,
43
+ SEARCH or final GUARD are accepted by this function.
44
+ """
45
+ if mode not in ('none', 'auto'):
46
+ raise ValueError('Only none/auto morphing admitted')
47
+ return {'requested': mode, 'diagnosis_executed': False, 'diagnosis_status': 'OMITTED_DISABLED' if mode == 'none' else 'OMITTED_NO_ADMITTED_CORRECTION', 'information_acquisition': {'new_OOF': 0, 'new_fits': 0, 'measured_seconds': None}, 'eligible_operators': [], 'excluded_operators': [{'id': 'MORPH-013-atomic-trigger', 'reason': 'FAILED_STRONG_CONTROLS'}, {'id': 'MORPH-014-015-simple-mean', 'reason': 'FAILED_BEST_PARENT_CONTROLS'}, {'id': 'historical-lookahead', 'reason': 'NO_INDEPENDENT_DEFAULT_UTILITY'}], 'attempted': [], 'accepted': [], 'rollback': [], 'decision': 'DISABLED' if mode == 'none' else 'RETAIN_CURRENT_NO_ADMITTED_OPERATOR', 'rediagnosis': 'NOT_EXECUTED', 'utility': 'NOT_DEMONSTRATED'}
48
+
49
+ class LearningControl(Previous):
50
+ """Private three-task automatic facade, not a production estimator.
51
+
52
+ balanced resolves to serial, 30s, boost8/bag8, and at most four numeric
53
+ trials ONLY with a separately qualified executor. Without such admission,
54
+ auto skips tuning and explicit optuna refuses before learning. No automatic
55
+ OOF, structural mutation, composition, refit or final GUARD is enabled.
56
+ """
57
+
58
+ 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):
59
+ self.capacity = copy.deepcopy(capacity)
60
+ 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)
61
+
62
+ def _validate(self):
63
+ super()._validate()
64
+ if self.capacity is not None:
65
+ if type(self.capacity) is not dict or not set(self.capacity) <= {'max_leaves', 'max_depth'}:
66
+ raise ValueError('capacity supports only max_leaves/max_depth; no inactive options')
67
+ for name, value in self.capacity.items():
68
+ if type(value) is not int or not 1 <= value <= {'max_leaves': 16, 'max_depth': 8}[name]:
69
+ raise ValueError('Finite integer structural capacity required')
70
+
71
+ def get_params(self, deep=True):
72
+ return copy.deepcopy({k: getattr(self, k) for k in (*PARAMS, 'capacity')})
73
+
74
+ def set_params(self, **values):
75
+ if set(values) - set(self.get_params()):
76
+ raise ValueError('Unknown estimator parameter')
77
+ new = type(self)(**self.get_params() | values)
78
+ self.__dict__ = new.__dict__
79
+ return self
80
+
81
+ def _make_executor(self):
82
+ return NativeExecutor()
83
+
84
+ def _numeric_admitted(self, executor):
85
+ return False
86
+
87
+ def _optional_optuna(self):
88
+ return importlib.util.find_spec('optuna') is not None
89
+
90
+ def _load_optuna(self):
91
+ return importlib.import_module('optuna')
92
+
93
+ def _numeric_plan(self, executor):
94
+ if self.tuning == 'none':
95
+ return (None, 'DISABLED', 0)
96
+ if not self._optional_optuna():
97
+ if self.tuning == 'optuna':
98
+ raise ImportError('tuning="optuna" requires optional Optuna before any learning')
99
+ return (None, 'AUTO_SKIPPED_DEPENDENCY', 0)
100
+ if not self._numeric_admitted(executor):
101
+ if self.tuning == 'optuna':
102
+ raise TrainingNotAdmitted('Explicit numeric execution needs new source-bound fit/trial admission')
103
+ return (None, 'AUTO_SKIPPED_NUMERIC_ADMISSION', 0)
104
+ return (self._load_optuna(), 'ADMITTED', 2 if self.n_trials == 'auto' else self.n_trials)
105
+
106
+ def _log(self, events, start, operation, **values):
107
+ event = {'operation': operation, 'seconds_since_start': time.monotonic() - start, **values}
108
+ self._record_event(copy.deepcopy(event))
109
+ events.append(event)
110
+
111
+ def fit(self, X, y):
112
+ self._validate()
113
+ start = time.monotonic()
114
+ cpu = time.process_time()
115
+ events = []
116
+ attempt = {'status': 'INTENT', 'events': events, 'logical_family_requests': 0, 'numeric_callback_requests': 0, 'physical_fits': 'UNKNOWN_AT_UNADMITTED_BOUNDARY', 'best_verified_anchor': None, 'stop_reason': None}
117
+ self.last_attempt_ = attempt
118
+
119
+ def log(operation, **values):
120
+ self._log(events, start, operation, **values)
121
+
122
+ def check():
123
+ self._execution_check()
124
+ if time.monotonic() - start >= (150.0 if self.time_budget == 'auto' else self.time_budget):
125
+ raise TimeoutError('Finite operational deadline, not an algorithmic stall')
126
+ try:
127
+ executor = self._make_executor()
128
+ optuna, tuning_status, trial_cap = self._numeric_plan(executor)
129
+ check()
130
+ rows, names = _m26_rows(X)
131
+ task, targets, classes = detect_target(y, self.task)
132
+ if len(rows) != len(targets):
133
+ raise ValueError('Aligned X/y required')
134
+ metric = 'mse' if task == 'regression' else 'logloss'
135
+ if self.metric not in ('auto', metric):
136
+ raise ValueError('Metric is inconsistent with task')
137
+ seed = self.random_state if self.random_state is not None else random.SystemRandom().randrange(2 ** 31)
138
+ ti, si = _split(targets, task, seed)
139
+ log('split', TRAIN=ti, SEARCH=si, GUARD_used=False)
140
+ encoder = TrainEncoder().fit([rows[i] for i in ti])
141
+ encoder.state_['names'] = names
142
+ if encoder.width_ * len(rows) > 2000000:
143
+ raise ValueError('Expanded input exceeds finite 2000000-cell cap')
144
+ trainX = encoder.transform(_NamedRows([rows[i] for i in ti], names))
145
+ searchX = encoder.transform(_NamedRows([rows[i] for i in si], names))
146
+ ty = [targets[i] for i in ti]
147
+ sy = [targets[i] for i in si]
148
+ selection = {'role': 'SEARCH', 'ids': ['SEARCH:' + str(i) for i in si], 'X': searchX, 'y': sy}
149
+ identity = {'TRAIN': digest({'X': trainX, 'y': ty, 'ids': ti}), 'SEARCH': digest(selection)}
150
+ params = HyperParams(n_estimators=2, max_leaves=8, max_depth=4, max_bins=15, min_samples_leaf=2, row_fraction=1.0)
151
+ if self.capacity:
152
+ params = replace(params, **self.capacity)
153
+ params = self._parameters(params)
154
+ families = ['boost', 'bag'] if self.families == 'auto' else [self.families]
155
+ models = {}
156
+ packets = {}
157
+ completed = []
158
+ trials = []
159
+
160
+ def acquire(name, family, p, genome=None):
161
+ genome = AlgorithmGenome() if genome is None else genome
162
+ check()
163
+ if attempt['logical_family_requests'] >= len(families) + trial_cap + self._extra_opportunities():
164
+ raise BudgetExhausted('Finite family/trial opportunities exhausted')
165
+ self._admit_learning_batch(task, family, p, 'COMPLETE_FAMILY_REQUEST')
166
+ attempt['logical_family_requests'] += 1
167
+ log('learning_request', id=name, family=family, params=asdict(p))
168
+ model = executor.fit_family(task, family, trainX, ty, seed=seed, params=p, check=check, genome=genome, identity={**identity, 'preprocessing': encoder.to_dict(), 'seed': seed, 'task': task, 'family': family, 'TRAIN_ids': ['ROW:' + str(i) for i in ti], 'actual_TRAIN_X': trainX, 'actual_TRAIN_y': ty})
169
+ check()
170
+ payload = _payloads(model)
171
+ packet = {'id': name, 'task': task, 'family': family, 'recipe': self._structure_packet(genome, classes, len(model.components), encoder), 'learning_identity': identity, 'params': asdict(p), 'artifact_sha256': digest(payload)}
172
+ models[name] = model
173
+ packets[name] = packet
174
+ completed.append(name)
175
+ self._capture_report_packet(packet, model, selection, {'X': trainX, 'y': ty})
176
+ log('learning_completed', id=name, boundary=executor.evidence_level, packet=copy.deepcopy(packet))
177
+ return packet
178
+
179
+ def verify(packet, search):
180
+ check()
181
+ name = packet['id']
182
+ if packet != packets[name] or search != selection or digest(_payloads(models[name])) != packet['artifact_sha256']:
183
+ raise ValueError('Changed completed native model, frozen form or SEARCH')
184
+ return models[name].probabilities_or_values(search['X'])
185
+ anchor = acquire(families[0], families[0], params)
186
+ chooser = FamilyChoice(anchor, selection, checkpoint=lambda e: log('family_selection', **e), verify=verify)
187
+ attempt['best_verified_anchor'] = copy.deepcopy(chooser.best['packet'])
188
+ try:
189
+ result = chooser.run(acquire(families[1], families[1], params)) if len(families) > 1 else chooser.best
190
+ except SearchBudgetExhausted as budget_error:
191
+ self._budget_stopped('FAMILY', attempt['best_verified_anchor'], attempt, log, budget_error)
192
+ result = chooser.best
193
+ selected = result['packet']
194
+ attempt['best_verified_anchor'] = copy.deepcopy(selected)
195
+ morph = self._diagnose({'OOF': None, 'admitted_operators': []})
196
+ log('mutation_admission', **morph)
197
+ selected, result = self._structural_stage(selected, result, acquire, verify, selection, params, log, attempt)
198
+ pure = copy.deepcopy(selected)
199
+ pure_prediction = copy.deepcopy(result['prediction'])
200
+ frozen_result = TaskFinalizer(selected, selection, numeric_fields=[], max_trials=0, verify=verify, checkpoint=lambda e: log('finalization', **e)).run(None)
201
+ log('structure_frozen', sha256=digest(selected['recipe']), packet=copy.deepcopy(selected), numeric_budget=trial_cap)
202
+ self._begin_numeric_window()
203
+ try:
204
+ if trial_cap and self._search_budget_open():
205
+ space = {'l2': [0.1, 10.0], 'min_samples_leaf': [1, 8]}
206
+ if selected['family'] == 'boost':
207
+ space['learning_rate'] = [0.03, 0.3]
208
+ space = admit_space(space, family=selected['family'], task=task, genome=AlgorithmGenome(**selected['recipe']['genome']))['space']
209
+
210
+ def numeric_checkpoint(e):
211
+ log('numeric_selection', **e)
212
+ if e['status'] == 'COMPLETED':
213
+ attempt['best_verified_anchor'] = copy.deepcopy(packets[e['retained']])
214
+ finalizer = TaskFinalizer(selected, selection, numeric_fields=list(space), max_trials=trial_cap, verify=verify, checkpoint=numeric_checkpoint)
215
+ study = optuna.create_study(direction='minimize', sampler=optuna.samplers.TPESampler(seed=seed, n_startup_trials=2))
216
+ frozen = digest({'family': selected['family'], 'recipe': selected['recipe'], 'fixed_params': {k: v for k, v in selected['params'].items() if k not in space}})
217
+ log('structure_frozen', sha256=frozen, space=space)
218
+
219
+ def propose(i, frozen_anchor):
220
+ check()
221
+ attempt['numeric_callback_requests'] += 1
222
+ self._admit_learning_batch(task, frozen_anchor['family'], HyperParams(**frozen_anchor['params']), 'NUMERIC_BEFORE_ASK')
223
+ trial = study.ask()
224
+ try:
225
+ values = {n: trial.suggest_int(n, *b) if n == 'min_samples_leaf' else trial.suggest_float(n, *b, log=True) for n, b in space.items()}
226
+ p = replace(HyperParams(**frozen_anchor['params']), **values)
227
+ candidate = acquire('trial:' + str(i), frozen_anchor['family'], p, AlgorithmGenome(**frozen_anchor['recipe']['genome']))
228
+ loss = finalizer._verified(candidate)['loss']
229
+ study.tell(trial, loss)
230
+ trials.append({'number': trial.number, 'state': 'COMPLETE', 'params': values, 'SEARCH_primary': loss})
231
+ return candidate
232
+ except BaseException as primary_error:
233
+ if isinstance(primary_error, SearchBudgetExhausted):
234
+ self._close_search_budget('NUMERIC_SEARCH_WINDOW_EXHAUSTED')
235
+ try:
236
+ study.tell(trial, state=optuna.trial.TrialState.FAIL)
237
+ except BaseException as cleanup_error:
238
+ log('numeric_trial_cleanup_failed', number=trial.number, error=type(cleanup_error).__name__, original_error=type(primary_error).__name__, state='UNRESOLVED')
239
+ raise
240
+ selected = finalizer.run(propose)['packet']
241
+ attempt['best_verified_anchor'] = copy.deepcopy(selected)
242
+ tuning_status = 'OPTUNA_CALLBACKS_COMPLETE'
243
+ elif trial_cap:
244
+ tuning_status = 'SKIPPED_SEARCH_BUDGET'
245
+ log('numeric_budget_skipped', retained=selected['id'])
246
+ except SearchBudgetExhausted as budget_error:
247
+ self._budget_stopped('NUMERIC', attempt['best_verified_anchor'], attempt, log, budget_error)
248
+ selected = copy.deepcopy(attempt['best_verified_anchor'])
249
+ tuning_status = 'OPTUNA_STOPPED_SEARCH_BUDGET'
250
+ log('numeric_search_stopped', retained=selected['id'], reason=tuning_status)
251
+ self._finish_search_if_public('SEARCH_COMPLETE')
252
+ check()
253
+ prediction = verify(selected, selection)
254
+ primary = risk(task, sy, prediction, list(range(len(classes))))
255
+ if risk(task, sy, pure_prediction, list(range(len(classes)))) < primary:
256
+ raise ValueError('Lost verified untuned anchor')
257
+
258
+ def recipe(p):
259
+ return {'schema': 'morph026-frozen-form-v1', 'task': task, 'family': p['family'], 'structure': copy.deepcopy(p['recipe']), 'params': copy.deepcopy(p['params']), 'seed': seed, 'training_identity': copy.deepcopy(identity), 'preprocessing': encoder.to_dict(), 'mutations': []}
260
+ mock = 'MOCK' in executor.evidence_level
261
+ report = {'schema': 'morph027-research-report-v1', 'task': task, 'metric': metric, 'classes': classes, 'seed': seed, 'best_family': selected['family'], 'SEARCH_primary': primary, 'selection': 'BEST_VERIFIED_SEARCH_NOT_GENERALIZATION_GUARANTEE', 'families': {'evaluated': [packets[n]['family'] for n in completed if n in families], 'not_evaluated': [f for f in ['boost', 'bag'] if f not in [packets[n]['family'] for n in completed if n in families]], 'exclusion_reason': 'USER_FAMILY_LIMIT_OR_SEARCH_BUDGET'}, 'tuning': tuning_status, 'trials': trials, 'trial_evidence': 'MOCK_DRIVER_NOT_REAL_TRIALS' if mock else 'EXECUTOR_BOUND_NUMERIC_CALLBACKS', 'morphing': morph, 'stop_reason': stop_reason(event='planned'), 'stop_details': {'family': 'FINITE_PREDECLARED_CANDIDATES_COMPLETE_NOT_STALL', 'structural': stop_reason(event='no_actions') if self.morphing == 'auto' else 'DISABLED', 'numeric': 'PLANNED_TRIALS_COMPLETE' if trial_cap else tuning_status, 'global_optimum_claim': False}, 'budget': {'seconds': 150.0 if self.time_budget == 'auto' else self.time_budget, 'processes': 1, 'n_jobs': 1, 'max_family_requests': len(families) + trial_cap + self._extra_opportunities(), 'max_numeric_callbacks': trial_cap, 'model_bytes': 32 * 1024 ** 2, 'expanded_cells': 2000000, 'peak_RAM_limit_qualified': False, 'external_v2_learning_admission_required': True}, 'accounting': {k: attempt[k] for k in ('logical_family_requests', 'numeric_callback_requests', 'physical_fits')}, 'worker_admission': executor.evidence_level, 'events': events, 'refit_performed': False, 'GUARD_used': False, 'final_model_role': 'TRAIN_FITTED_SEARCH_SELECTED', 'wall_seconds': time.monotonic() - start, 'process_cpu_seconds': time.process_time() - cpu, 'descendant_cpu': 'UNKNOWN', 'peak_RSS': 'UNKNOWN', 'cost_scope': 'OPERATIONAL_ONLY_NOT_PERFORMANCE', 'stop_recovery': 'ERROR_OR_STOP_LEAVES_PRIOR_FITTED_OBJECT_UNCHANGED', 'limitations': ['Research import only', 'No new native E2E evidence from software replay', 'No admitted automatic mutation or OOF', 'No independent utility/performance/platform/sklearn qualification', 'No retrainable exported procedure']}
262
+ variants = {'pure': {'model': models[pure['id']], 'recipe': recipe(pure), 'origin': 'PRE_FINAL_NUMERIC_SEARCH', 'exportable': not mock, 'evidence': executor.evidence_level, 'SEARCH_primary': risk(task, sy, pure_prediction, list(range(len(classes))))}}
263
+ chosen = 'pure'
264
+ if trial_cap:
265
+ variants['tuned'] = {'model': models[selected['id']], 'recipe': recipe(selected), 'origin': 'POST_FINAL_NUMERIC_SEARCH', 'exportable': not mock, 'evidence': executor.evidence_level, 'SEARCH_primary': primary}
266
+ chosen = 'tuned'
267
+ learned = {'model_': models[selected['id']], 'encoder_': encoder, 'task_': task, 'n_features_in_': len(rows[0]), 'best_family_': selected['family'], 'best_recipe_': recipe(selected), 'best_params_': copy.deepcopy(selected['params']), 'structure_': copy.deepcopy(selected['recipe']), 'stop_reason_': report['stop_reason'], 'report_': report, '_variants': variants, '_selected_variant': chosen}
268
+ if task != 'regression':
269
+ learned['classes_'] = tuple(classes)
270
+ if names is not None:
271
+ learned['feature_names_in_'] = tuple(names)
272
+ for k in list(self.__dict__):
273
+ if k.endswith('_') and k != 'last_attempt_' or k in ('_variants', '_selected_variant', '_untuned_model', '_untuned_recipe'):
274
+ del self.__dict__[k]
275
+ self.__dict__.update(learned)
276
+ attempt.update(status='PASS', stop_reason=report['stop_reason'])
277
+ return self
278
+ except BaseException as exc:
279
+ event = 'timeout' if isinstance(exc, TimeoutError) else 'stop' if isinstance(exc, StopRequested) else 'budget' if isinstance(exc, BudgetExhausted) else 'not_admitted' if isinstance(exc, TrainingNotAdmitted) else 'error'
280
+ attempt.update(status='BLOCKED' if event == 'not_admitted' else 'STOP' if event in ('timeout', 'stop', 'budget') else 'FAIL', stop_reason=stop_reason(event=event), error=type(exc).__name__, message=str(exc))
281
+ raise
282
+
283
+ def _diagnose(self, context):
284
+ if context != {'OOF': None, 'admitted_operators': []}:
285
+ raise ValueError('No trained diagnostic producer admitted; GUARD and caller-provided evidence forbidden')
286
+ return mutation_admission(self.morphing)
287
+
288
+ def report(self):
289
+ value = super().report()
290
+ value['variants'] = self.available_variants()
291
+ return value
292
+
293
+ def _evaluate_mutation(self, proposal):
294
+ raise TrainingNotAdmitted('No default structural operator or mutation budget admitted')
295
+
296
+ def available_variants(self):
297
+ self._fitted()
298
+ 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()}
299
+
300
+ def _variant(self, name):
301
+ self._fitted()
302
+ name = self._selected_variant if name == 'selected' else name
303
+ if name not in self._variants:
304
+ raise VariantUnavailable('Requested variant has no retained, verified weights; a separately budgeted fit may be needed')
305
+ v = self._variants[name]
306
+ if not v['exportable']:
307
+ raise VariantUnavailable('Software replay cannot be exported as a newly trained pure/tuned variant')
308
+ obj = Previous(**{k: v for k, v in self.get_params().items() if k != 'capacity'})
309
+ for k in ('encoder_', 'task_', 'n_features_in_', 'classes_', 'feature_names_in_'):
310
+ if hasattr(self, k):
311
+ setattr(obj, k, copy.deepcopy(getattr(self, k)))
312
+ obj.model_ = v['model']
313
+ obj.best_recipe_ = copy.deepcopy(v['recipe'])
314
+ obj.best_family_ = v['recipe']['family']
315
+ obj.best_params_ = copy.deepcopy(v['recipe']['params'])
316
+ obj.report_ = self.report()
317
+ obj.report_.update(exported_variant=name, SEARCH_primary=v.get('SEARCH_primary'), best_family=obj.best_family_)
318
+ obj.stop_reason_ = self.stop_reason_
319
+ return obj
320
+
321
+ def export_python(self, path, *, variant='selected'):
322
+ self._variant(variant).export_python(path)
323
+
324
+ def save_recipe(self, path, *, variant='selected'):
325
+ self._variant(variant).save_recipe(path)
326
+
327
+ def save(self, path, *, variant='all'):
328
+ self._fitted()
329
+ configure_temp()
330
+ names = list(self._variants) if variant == 'all' else [self._selected_variant if variant == 'selected' else variant]
331
+ packed = {}
332
+ origins = {}
333
+ with OwnedTemporaryDirectory() as tmp:
334
+ for name in names:
335
+ obj = self._variant(name)
336
+ p = artifact_path(Path(tmp) / (name + '.json'))
337
+ obj.save(p)
338
+ packed[name] = read_json(p, LoadLimits(max_bytes=32 * 1024 ** 2))
339
+ origins[name] = {'origin': self._variants[name]['origin'], 'evidence': self._variants[name]['evidence']}
340
+ body = {'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}
341
+ if len(json.dumps(body, allow_nan=False).encode('utf8')) > 32 * 1024 ** 2:
342
+ raise ValueError('Bounded total variant payload required')
343
+ path = artifact_path(path)
344
+ if path.exists():
345
+ raise FileExistsError('Never overwrite research model evidence')
346
+ write_json(path, body)
347
+
348
+ @classmethod
349
+ def load(cls, path):
350
+ data = read_json(artifact_path(path), LoadLimits(max_bytes=32 * 1024 ** 2))
351
+ if set(data) != {'schema', 'constructor', 'selected_variant', 'variants', 'origins'} or data['schema'] != 'morph027-native-control-v1':
352
+ raise ValueError('Exact bounded private control schema required')
353
+ vs = data['variants']
354
+ origins = data['origins']
355
+ 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):
356
+ raise ValueError('Bounded named variants required')
357
+ obj = cls(**data['constructor'])
358
+ configure_temp()
359
+ loaded = {}
360
+ with OwnedTemporaryDirectory() as tmp:
361
+ for name, body in vs.items():
362
+ o = origins[name]
363
+ 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']):
364
+ raise ValueError('Explicit genuine variant provenance required')
365
+ if name == 'pure' and o['origin'] == 'POST_FINAL_NUMERIC_SEARCH' or (name == 'tuned' and o['origin'] != 'POST_FINAL_NUMERIC_SEARCH'):
366
+ raise ValueError('Never relabel tuned weights as pure')
367
+ p = artifact_path(Path(tmp) / (name + '.json'))
368
+ write_json(p, body)
369
+ v = Previous.load(p)
370
+ if v.task_ != body['recipe']['task']:
371
+ raise ValueError('Changed task')
372
+ expected = HyperParams(**v.best_params_)
373
+ for m in v.model_.components:
374
+ actual = asdict(m.params_)
375
+ want = asdict(expected if v.best_family_ == 'boost' else replace(expected, n_estimators=1, learning_rate=1.0, row_fraction=1.0))
376
+ if actual != want:
377
+ raise ValueError('Recipe parameters do not describe the actual weights')
378
+ if name == 'tuned' and (not v.report_.get('trials') or v.report_.get('trial_evidence') not in ('EXECUTOR_BOUND_NUMERIC_CALLBACKS', 'AUTHENTICATED_HISTORICAL_REAL_TPE4')):
379
+ raise ValueError('No executed numeric trajectory for tuned variant')
380
+ loaded[name] = v
381
+ v = loaded[data['selected_variant']]
382
+ for other in loaded.values():
383
+ 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']):
384
+ raise ValueError('Variants must share the same frozen structure/data/map')
385
+ for k in ('model_', 'encoder_', 'task_', 'n_features_in_', 'classes_', 'feature_names_in_', 'best_family_', 'best_recipe_', 'best_params_', 'stop_reason_', 'report_'):
386
+ if hasattr(v, k):
387
+ setattr(obj, k, getattr(v, k))
388
+ obj.structure_ = copy.deepcopy(v.best_recipe_['structure'])
389
+ obj._selected_variant = data['selected_variant']
390
+ 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()}
391
+ return obj
392
+
393
+ def export_bundle(self, directory, *, variants=('pure',)):
394
+ if type(variants) is not tuple or not variants or len(set(variants)) != len(variants):
395
+ raise ValueError('Distinct variant tuple required')
396
+ for name in variants:
397
+ self._variant(name)
398
+ directory = artifact_path(directory)
399
+ if directory.exists():
400
+ raise FileExistsError('New export directory required')
401
+ directory.mkdir(parents=True)
402
+ out = []
403
+ for name in variants:
404
+ p = directory / (name + '.json')
405
+ self.save(p, variant=name)
406
+ out.append(reference(p))
407
+ p = directory / (name + '-recipe.json')
408
+ self.save_recipe(p, variant=name)
409
+ out.append(reference(p))
410
+ p = directory / (name + '-predictor.py')
411
+ self.export_python(p, variant=name)
412
+ out.append(reference(p))
413
+ p = directory / 'EXPORT.json'
414
+ write_json(p, {'schema': 'morph027-inference-export-v1', 'status': 'COMPLETE', 'artifacts': out, 'retraining_procedure': 'NOT_SUPPORTED', 'new_fits': 0, 'report': self.report()})
415
+ return reference(p)
416
+
417
+ def export_retrainable(self, path):
418
+ raise NotImplementedError('Only inference standalone and declarative recipe are qualified; generic retraining admission is missing')
@@ -0,0 +1,204 @@
1
+ {
2
+ "Linux_wheel_audit": {
3
+ "extra_shared_libraries_bundled": 0,
4
+ "native_ELF_changed": false,
5
+ "requested_platform": "manylinux_2_17_x86_64",
6
+ "tool": "auditwheel6.8.2",
7
+ "versioned_symbols": [
8
+ "GLIBC_2.2.5"
9
+ ],
10
+ "whole_pipeline_on_older_glibc_tested": false
11
+ },
12
+ "backend": "automatic-native",
13
+ "capacity_profile": {
14
+ "default_estimators": 2,
15
+ "explicit_verified_estimators": 8,
16
+ "independent_real_test_confirmed": false,
17
+ "new_default_adopted": false
18
+ },
19
+ "files": {
20
+ "__init__.py": "a3d4e3364b56f0a2f952a81113f8bc3159f7b5a44d285300ccb6a2dcccd53cb7",
21
+ "__main__.py": "935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d",
22
+ "_experimental/__init__.py": "af368cce8e8a71327fdf5a8b61c81d6d6fdef62f924800408d7f2b2ca1d82e52",
23
+ "_experimental/admission.py": "7afaad7937655739b9e6c4f469d337c9ecaeeecbfbe4f435f669d07e8af5022c",
24
+ "_experimental/base.py": "3b24242af5bdde79eeba086354f23446cbf911f570c0b63246d491abd74316e5",
25
+ "_experimental/component_cache_v2.py": "8bcdf575213ed71a68fbc79cc86e58d2007e1539dd0e5e22ca80273696c3b78f",
26
+ "_experimental/evolution_report.py": "0496feeb84cfdde473679713a9432caa581a017db3dfb114fd30da6296bab642",
27
+ "_experimental/execution_v2.py": "596318d9e55faf9b94ba8430fd78b6152750d299c9ac7778769efd7e4e838c58",
28
+ "_experimental/facade.py": "0408181efdb8139470a8356a48231bdf357c06c0358c835c89729e8f2833e884",
29
+ "_experimental/integrated.py": "ccaa9ac5441897492d55ce94b47ead55338274ae1b9127ef9a78e23711311e37",
30
+ "_experimental/learning.py": "e2e7b68cc27a94451bcc4efa57f9c78d0b8dc3104088a26007a112c255e505c6",
31
+ "_experimental/numeric_fixture.py": "f05fb8cb1757ebb841863f3a32eb331999bd4c4fc2a51bc1f11cc8a52d6508d9",
32
+ "_experimental/parameter_contract.py": "261ee3edece961d78ec0bccc0c5c7edc77d0797620d93f916b8fb96bff81fea6",
33
+ "_experimental/postfit.py": "493ee24a0c8f5eb6374bf0afbf1f1c083de7d96e9750cad4c7fdc1c759d8d9f4",
34
+ "_experimental/preprocessing.py": "1136e69d814124a90e999a9f5701fdbda716ab623998529ea042c8fb35c1e682",
35
+ "_experimental/processes.py": "577394affa54f66c0bf0bc55ce1619b0e10a7e4f3177c1af0256196f7347e6b7",
36
+ "_experimental/producer.py": "07d07410b8e85efbe9e38ed4761f4495f5e909b3f56f8ff1b52abb639e3afebf",
37
+ "_experimental/product.py": "568b02f61e5f772ab165b72ccf37217c6e48a9d5455480cd1ecbf236893002c4",
38
+ "_experimental/product_cli.py": "2fdfddfc573a5f5fee5ebd14bdd8aca3e5fbe7e746f169c47347fa9da0247509",
39
+ "_experimental/roundtrip_v3.py": "fb2999bee513f40e076543323da81385d1ceb7cf68850054f921b3c2c2a37d39",
40
+ "_experimental/runtime_io.py": "605c37ccf425d48de4ed52456b58414c4577b2018d2932e1aa7e7d30fa06e29c",
41
+ "_experimental/sampling.py": "a4aeb4536f5cf8280f4166ba7051ca2fb76aad8619958114a799b89afa773975",
42
+ "_experimental/support.py": "e6108af84a75a39813a3a665d266a913e104168c8a3cfc334cd6293e07101cfc",
43
+ "_experimental/target.py": "d2da94f69f7a4cf59b8d62bec69cd82f6a8f300827553900e6cba587ce7f1f9c",
44
+ "_experimental/training.py": "af9e2cc7ebfc7418cad90c3133993990b196fe94be1670f988f0cd8e3cfb70d3",
45
+ "_experimental/worker.py": "acb03be1dfaef5aac0ebfc5e050d90184d2154e74206fe0fb6c445e705608fc3",
46
+ "_installed.py": "1346e28b929f4103b2203192fcb9a6949320e232927bc312843390df8e9efcfd",
47
+ "_native/__init__.py": "f7f1f59f08aba5c94c66779ff4ebeca960675e3350a7fe9613f64dc65c6cea67",
48
+ "_native/bin/win_amd64/morphtree_kernels.dll": "1c577f636a74d873942d31ab81a1278eda8096252531c52520d00db2471d2a14",
49
+ "_native/buffers.py": "f51313cf910123eb1729e9f73270f15548691d2be7f9dae5479572828d3541c5",
50
+ "_native/loader.py": "a099872a1e7341075f9526cc75840bd38aa2908d8999310e885d1859a17068cb",
51
+ "_native/manifest.json": "0e5ba02d5a565b1fa424b1c1c5fac891bb7082e535d2dceeae65c36df2eec4f3",
52
+ "_native/runtime.py": "304c82cd811c769a74148580ffcbe4b15e5ffd28ae6fbef1e74af4f2aee8123e",
53
+ "_native/src/histogram.c": "4b05c05dab1de35c2b8c7cee69cf743b51f746e1d0a14b782df73d3ce959bf39",
54
+ "_native/src/traversal.c": "487d8ca46c96faded18d99dcda0abcb3c8a0fa783070a7da23dd5692a7a69406",
55
+ "api.py": "3c333b859bc43bedd8067ae9e6ad297d755a43dc289890c14f876a175301abb9",
56
+ "api_compat.py": "ba72b57232bda81e0f6392119f662e2e6d1fec9e7fc3571bb0e9ef10e4d89a8b",
57
+ "backend.py": "881d6025e72cd5675cd6da7b5b2e950d6ade97d63a25735321e5a739c27ef26c",
58
+ "booster.py": "92040ddb5ec9dec32dc14c3dbb160398ac764f440e3018bff5e99cf374ad066e",
59
+ "cli.py": "e8b9c79e67e876716b22f1ce86142b24d789d15ec3115d1ad9505d25e08f21f3",
60
+ "config.py": "d47be3b353ebcd619fb2844beb1e9e5f0b6dea5ff642c579a10c127d57af7ac1",
61
+ "control.py": "2f1c20f9fdaf426ed02500404874445895a022fa2a00fda65e3f195e651ee3cd",
62
+ "data.py": "3123850c2f2b8bfa1c7d599697c8cf5f02c162f30f2691d018600d6231cc0451",
63
+ "diagnostics.py": "4bef87e037d16e58cb03d4d129ebd42db9eac880342c520aef073daca687adbc",
64
+ "estimators.py": "d387432935d564a357ffa3ea1b6b804583c2d135b93310528273dc1221aff58b",
65
+ "examples.py": "5b1deccceb772346e3fd5f6d2a9756477d99e458713fa015f125f4d7bef2a635",
66
+ "exporting.py": "161bebaee9728da105446e937b14ff50dcbefcd6a3ef63b197f357dcf24917f8",
67
+ "legacy_artifacts.py": "cd70250ffacb20085e32c31f29e4b728caa06ea1cf8ec060b4e455b889e5b309",
68
+ "metrics.py": "785f2a7d2c0338aca950107699721adea15d61fa7a6b103e471c99b308b4d6c5",
69
+ "model.py": "389ad29547ddd5eaca0bfdc325627f91f9d4b4734ac44d9aa69296918678dd38",
70
+ "mutations.py": "4d98f5d9a9b4f786d8d640f478356a3a034a78740a286ea2a0b121cd7a647cb5",
71
+ "native_lab_backend.py": "871774e0fc08ae448b60725f122df437ba6cf188eb8a3f7681a12bae972c52b5",
72
+ "numpy_backend.py": "71669be1bf84a96dfcc63fc5b89ecc0f9cf03463313953e573c0d162ccd48152",
73
+ "optuna_tuner.py": "969ee92fed53955b12de903034caff324714cdcdc1347591dd8d0d1250aa9d90",
74
+ "persistence.py": "e4c52f6c4dbc227adfa39e362ce5274306d7f320eb4b68f3a3f41a92d1446436",
75
+ "prediction_output.py": "f36e550b898fb9225b82c0ba0799daa517129debd09b10f346018b8c6d33d964",
76
+ "prepared_bins.py": "178f9c73744dcaeb6e91943deb23e8f410ef85ec97743f8802f4c3317622abbf",
77
+ "public.py": "775ef54dd1576f4f0bba15162cd3547e086a9245be4d9cc50c0af0f4a1c3b9db",
78
+ "resource_plan.py": "bebb6a781627cc1a3494a35747df7f4ffe1350480cf3ec0eb752b92e3558c5b2",
79
+ "scalable.py": "bed96c724ca3be9c10973f307b98eae3fb33866abc5b38fb72ca2e406b03333d",
80
+ "scalable_backend.py": "04221e17b552cc30ce600857be62785f55c4e7958b5b90728ceeb20c075effcc",
81
+ "scalable_checkpoint.py": "24fd03a2f41e5b157b7e1cbd53f2fa0a94977f3d3ee0affd63a3ff9af07212af",
82
+ "scalable_data.py": "e9a85f44cae2736594b5c76d37fcd36d40f47211b5f7ade9b7a0e62d22de1885",
83
+ "scalable_receipts.py": "15090c5d9019f21b2f04dbec9a5266a8bf7eb26d4f34320b47ed79cd05530f0d",
84
+ "scalable_target.py": "7ac25a34f753109756fda9a0e7d80ec57f4dd0186761c1c2ea16fe6760c4de06",
85
+ "scalable_variants.py": "c35cf11448f3c9f0d58a3fb1c0188c22ba83ccc4e1f0fb4c1527f9488acd75ff",
86
+ "sklearn_view.py": "5f5aebaca51ff78596ce842cb0d3b500365d42cf087954120fcaa8a6025260e8",
87
+ "source_markers.py": "0d44fe9364cb4902c16ee0d480dc2a5b843ddaa0ce179791b2d746e158ae6ddd",
88
+ "species.py": "2b8669426374cdee1eac5c14eac7f7c42b9438c70fc3b0a3af9e191bb40992bf",
89
+ "temporary.py": "29fc30a9644508d8d5f1f5254eb48e590b48f585947655952424f984edeead15",
90
+ "training_fragment.py": "3fbe4f25ca3fc3c23a781b2c1a955bb2e05b84f29c422ff92512b003e573848e",
91
+ "tree.py": "875f93a47b005ad362be77730af6bdb0cd82c39e369ffc525913aab2a2c1f4a5",
92
+ "tuning.py": "0765b39a34d5825028bb91c6c6af2b68a51164c622895d735722096597e60b66"
93
+ },
94
+ "historical_provenance": {
95
+ "frozen_engine_manifest_sha256": "cd090c6739f9ca4a6463616cff05383d6a200f76e41b50248713f8bb7b077685",
96
+ "learning_mathematics_changed": false,
97
+ "original_python_reference_version": "2.1.0",
98
+ "previous_native_reference_version": "2.1.0"
99
+ },
100
+ "native_lab": {
101
+ "default_backend": "Verified C histograms and cached traversal; equivalent Python traversal below 128 rows",
102
+ "evidence_campaigns": [
103
+ "VERSION121",
104
+ "VERSION122"
105
+ ],
106
+ "fresh_RC_profiles": [
107
+ "WindowsPython3.12.10",
108
+ "Ubuntu24.04WSL2Python3.12.3"
109
+ ],
110
+ "historical_evidence_campaigns": [
111
+ "RC116",
112
+ "RC117"
113
+ ],
114
+ "historical_training_distribution_version": "3.0.0rc1",
115
+ "public_release": false,
116
+ "publication_approved": false,
117
+ "qualification_labels_only_successor": true,
118
+ "qualification_scope": "Fresh2.1.0 full installed pipelines VERSION121Windows312 andVERSION122UbuntuWSL2312;3.13/3.14 retained source-lineage training plus fresh installed/inference checks;other platforms not claimed",
119
+ "qualified_profiles": [
120
+ {
121
+ "features": 7,
122
+ "os": "Windows 11 build 26300 x64",
123
+ "python": [
124
+ "3.12.10",
125
+ "3.13.17",
126
+ "3.14.9"
127
+ ],
128
+ "rows": 25003,
129
+ "tasks": [
130
+ "binary",
131
+ "multiclass",
132
+ "regression"
133
+ ]
134
+ },
135
+ {
136
+ "features": 7,
137
+ "os": "Ubuntu 24.04.4 WSL2 x86_64 glibc 2.39",
138
+ "python": [
139
+ "3.12.3",
140
+ "3.13.17",
141
+ "3.14.9"
142
+ ],
143
+ "rows": 25003,
144
+ "tasks": [
145
+ "binary",
146
+ "multiclass",
147
+ "regression"
148
+ ]
149
+ },
150
+ {
151
+ "features": 15,
152
+ "os": "Windows 11 build 26300 x64",
153
+ "python": [
154
+ "3.12.10"
155
+ ],
156
+ "rows": [
157
+ 10003,
158
+ 200003
159
+ ],
160
+ "tasks": [
161
+ "binary",
162
+ "multiclass",
163
+ "regression"
164
+ ]
165
+ }
166
+ ],
167
+ "training_distribution_version": "2.1.0",
168
+ "unqualified": [
169
+ "Linux small/large training",
170
+ "million-row training",
171
+ "Python 3.15 ordinary install",
172
+ "authentic macOS",
173
+ "other Linux distributions full pipeline",
174
+ "hosted Kaggle"
175
+ ],
176
+ "version_approved": true,
177
+ "whole_pipeline_native_qualified": true
178
+ },
179
+ "prediction_output_contract": {
180
+ "class_order": "classes_",
181
+ "default_standalone": "stdlib Python lists",
182
+ "new_training": false,
183
+ "numeric_values_changed": false,
184
+ "numpy_standalone": "output_format='numpy'",
185
+ "predict": "numpy.ndarray(n_samples,)",
186
+ "predict_proba": "numpy.float64(n_samples,n_classes)"
187
+ },
188
+ "private_research": false,
189
+ "public_description": {
190
+ "README_modified_by_agent": true,
191
+ "README_sha256": "0c567465e0db8cf91112fef749f83f31d78e5aa48f7088817a3617c91154d9f4",
192
+ "authorization_sha256": "da902c3c4bc4ca321a2e94e5e4513dc1f714935fa17c1d602c9e08e2d059f0b3",
193
+ "content_type": "text/markdown",
194
+ "normalized_description_sha256": "0c567465e0db8cf91112fef749f83f31d78e5aa48f7088817a3617c91154d9f4",
195
+ "source": "README.md",
196
+ "source_owner_review_pending": true,
197
+ "source_revision_authorization": "EXPLICIT_OWNER_DIRECTIVE"
198
+ },
199
+ "schema": "morph030-installed-payload-v1",
200
+ "scientific_training_authority": 0,
201
+ "scope": "LOCAL_RC_WITH_RETAINED_QUALIFIED_ENGINE",
202
+ "version": "2.1.0",
203
+ "workspace_sources_required": false
204
+ }