morphml 1.0.0__py3-none-any.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.
Potentially problematic release.
This version of morphml might be problematic. Click here for more details.
- morphml/__init__.py +14 -0
- morphml/api/__init__.py +26 -0
- morphml/api/app.py +326 -0
- morphml/api/auth.py +193 -0
- morphml/api/client.py +338 -0
- morphml/api/models.py +132 -0
- morphml/api/rate_limit.py +192 -0
- morphml/benchmarking/__init__.py +36 -0
- morphml/benchmarking/comparison.py +430 -0
- morphml/benchmarks/__init__.py +56 -0
- morphml/benchmarks/comparator.py +409 -0
- morphml/benchmarks/datasets.py +280 -0
- morphml/benchmarks/metrics.py +199 -0
- morphml/benchmarks/openml_suite.py +201 -0
- morphml/benchmarks/problems.py +289 -0
- morphml/benchmarks/suite.py +318 -0
- morphml/cli/__init__.py +5 -0
- morphml/cli/commands/experiment.py +329 -0
- morphml/cli/main.py +457 -0
- morphml/cli/quickstart.py +312 -0
- morphml/config.py +278 -0
- morphml/constraints/__init__.py +19 -0
- morphml/constraints/handler.py +205 -0
- morphml/constraints/predicates.py +285 -0
- morphml/core/__init__.py +3 -0
- morphml/core/crossover.py +449 -0
- morphml/core/dsl/README.md +359 -0
- morphml/core/dsl/__init__.py +72 -0
- morphml/core/dsl/ast_nodes.py +364 -0
- morphml/core/dsl/compiler.py +318 -0
- morphml/core/dsl/layers.py +368 -0
- morphml/core/dsl/lexer.py +336 -0
- morphml/core/dsl/parser.py +455 -0
- morphml/core/dsl/search_space.py +386 -0
- morphml/core/dsl/syntax.py +199 -0
- morphml/core/dsl/type_system.py +361 -0
- morphml/core/dsl/validator.py +386 -0
- morphml/core/graph/__init__.py +40 -0
- morphml/core/graph/edge.py +124 -0
- morphml/core/graph/graph.py +507 -0
- morphml/core/graph/mutations.py +409 -0
- morphml/core/graph/node.py +196 -0
- morphml/core/graph/serialization.py +361 -0
- morphml/core/graph/visualization.py +431 -0
- morphml/core/objectives/__init__.py +20 -0
- morphml/core/search/__init__.py +33 -0
- morphml/core/search/individual.py +252 -0
- morphml/core/search/parameters.py +453 -0
- morphml/core/search/population.py +375 -0
- morphml/core/search/search_engine.py +340 -0
- morphml/distributed/__init__.py +76 -0
- morphml/distributed/fault_tolerance.py +497 -0
- morphml/distributed/health_monitor.py +348 -0
- morphml/distributed/master.py +709 -0
- morphml/distributed/proto/README.md +224 -0
- morphml/distributed/proto/__init__.py +74 -0
- morphml/distributed/proto/worker.proto +170 -0
- morphml/distributed/proto/worker_pb2.py +79 -0
- morphml/distributed/proto/worker_pb2_grpc.py +423 -0
- morphml/distributed/resource_manager.py +416 -0
- morphml/distributed/scheduler.py +567 -0
- morphml/distributed/storage/__init__.py +33 -0
- morphml/distributed/storage/artifacts.py +381 -0
- morphml/distributed/storage/cache.py +366 -0
- morphml/distributed/storage/checkpointing.py +329 -0
- morphml/distributed/storage/database.py +459 -0
- morphml/distributed/worker.py +549 -0
- morphml/evaluation/__init__.py +5 -0
- morphml/evaluation/heuristic.py +237 -0
- morphml/exceptions.py +55 -0
- morphml/execution/__init__.py +5 -0
- morphml/execution/local_executor.py +350 -0
- morphml/integrations/__init__.py +28 -0
- morphml/integrations/jax_adapter.py +206 -0
- morphml/integrations/pytorch_adapter.py +530 -0
- morphml/integrations/sklearn_adapter.py +206 -0
- morphml/integrations/tensorflow_adapter.py +230 -0
- morphml/logging_config.py +93 -0
- morphml/meta_learning/__init__.py +66 -0
- morphml/meta_learning/architecture_similarity.py +277 -0
- morphml/meta_learning/experiment_database.py +240 -0
- morphml/meta_learning/knowledge_base/__init__.py +19 -0
- morphml/meta_learning/knowledge_base/embedder.py +179 -0
- morphml/meta_learning/knowledge_base/knowledge_base.py +313 -0
- morphml/meta_learning/knowledge_base/meta_features.py +265 -0
- morphml/meta_learning/knowledge_base/vector_store.py +271 -0
- morphml/meta_learning/predictors/__init__.py +27 -0
- morphml/meta_learning/predictors/ensemble.py +221 -0
- morphml/meta_learning/predictors/gnn_predictor.py +552 -0
- morphml/meta_learning/predictors/learning_curve.py +231 -0
- morphml/meta_learning/predictors/proxy_metrics.py +261 -0
- morphml/meta_learning/strategy_evolution/__init__.py +27 -0
- morphml/meta_learning/strategy_evolution/adaptive_optimizer.py +226 -0
- morphml/meta_learning/strategy_evolution/bandit.py +276 -0
- morphml/meta_learning/strategy_evolution/portfolio.py +230 -0
- morphml/meta_learning/transfer.py +581 -0
- morphml/meta_learning/warm_start.py +286 -0
- morphml/optimizers/__init__.py +74 -0
- morphml/optimizers/adaptive_operators.py +399 -0
- morphml/optimizers/bayesian/__init__.py +52 -0
- morphml/optimizers/bayesian/acquisition.py +387 -0
- morphml/optimizers/bayesian/base.py +319 -0
- morphml/optimizers/bayesian/gaussian_process.py +635 -0
- morphml/optimizers/bayesian/smac.py +534 -0
- morphml/optimizers/bayesian/tpe.py +411 -0
- morphml/optimizers/differential_evolution.py +220 -0
- morphml/optimizers/evolutionary/__init__.py +61 -0
- morphml/optimizers/evolutionary/cma_es.py +416 -0
- morphml/optimizers/evolutionary/differential_evolution.py +556 -0
- morphml/optimizers/evolutionary/encoding.py +426 -0
- morphml/optimizers/evolutionary/particle_swarm.py +449 -0
- morphml/optimizers/genetic_algorithm.py +486 -0
- morphml/optimizers/gradient_based/__init__.py +22 -0
- morphml/optimizers/gradient_based/darts.py +550 -0
- morphml/optimizers/gradient_based/enas.py +585 -0
- morphml/optimizers/gradient_based/operations.py +474 -0
- morphml/optimizers/gradient_based/utils.py +601 -0
- morphml/optimizers/hill_climbing.py +169 -0
- morphml/optimizers/multi_objective/__init__.py +56 -0
- morphml/optimizers/multi_objective/indicators.py +504 -0
- morphml/optimizers/multi_objective/nsga2.py +647 -0
- morphml/optimizers/multi_objective/visualization.py +427 -0
- morphml/optimizers/nsga2.py +308 -0
- morphml/optimizers/random_search.py +172 -0
- morphml/optimizers/simulated_annealing.py +181 -0
- morphml/plugins/__init__.py +35 -0
- morphml/plugins/custom_evaluator_example.py +81 -0
- morphml/plugins/custom_optimizer_example.py +63 -0
- morphml/plugins/plugin_system.py +454 -0
- morphml/reports/__init__.py +30 -0
- morphml/reports/generator.py +362 -0
- morphml/tracking/__init__.py +7 -0
- morphml/tracking/experiment.py +309 -0
- morphml/tracking/logger.py +301 -0
- morphml/tracking/reporter.py +357 -0
- morphml/utils/__init__.py +6 -0
- morphml/utils/checkpoint.py +189 -0
- morphml/utils/comparison.py +390 -0
- morphml/utils/export.py +407 -0
- morphml/utils/progress.py +392 -0
- morphml/utils/validation.py +392 -0
- morphml/version.py +7 -0
- morphml/visualization/__init__.py +50 -0
- morphml/visualization/analytics.py +423 -0
- morphml/visualization/architecture_diagrams.py +353 -0
- morphml/visualization/architecture_plot.py +223 -0
- morphml/visualization/convergence_plot.py +174 -0
- morphml/visualization/crossover_viz.py +386 -0
- morphml/visualization/graph_viz.py +338 -0
- morphml/visualization/pareto_plot.py +149 -0
- morphml/visualization/plotly_dashboards.py +422 -0
- morphml/visualization/population.py +309 -0
- morphml/visualization/progress.py +260 -0
- morphml-1.0.0.dist-info/METADATA +434 -0
- morphml-1.0.0.dist-info/RECORD +158 -0
- morphml-1.0.0.dist-info/WHEEL +4 -0
- morphml-1.0.0.dist-info/entry_points.txt +3 -0
- morphml-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"""Search space validation utilities.
|
|
2
|
+
|
|
3
|
+
Validate search spaces before running expensive NAS operations.
|
|
4
|
+
|
|
5
|
+
Example:
|
|
6
|
+
>>> from morphml.utils.validation import validate_search_space
|
|
7
|
+
>>>
|
|
8
|
+
>>> issues = validate_search_space(space)
|
|
9
|
+
>>> if issues:
|
|
10
|
+
... for issue in issues:
|
|
11
|
+
... print(f"Warning: {issue}")
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import List, Optional
|
|
15
|
+
|
|
16
|
+
from morphml.core.dsl import SearchSpace
|
|
17
|
+
from morphml.logging_config import get_logger
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ValidationIssue:
|
|
23
|
+
"""Represents a validation issue."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, severity: str, message: str, suggestion: Optional[str] = None):
|
|
26
|
+
"""
|
|
27
|
+
Initialize validation issue.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
severity: "error", "warning", or "info"
|
|
31
|
+
message: Issue description
|
|
32
|
+
suggestion: Optional fix suggestion
|
|
33
|
+
"""
|
|
34
|
+
self.severity = severity
|
|
35
|
+
self.message = message
|
|
36
|
+
self.suggestion = suggestion
|
|
37
|
+
|
|
38
|
+
def __str__(self) -> str:
|
|
39
|
+
result = f"[{self.severity.upper()}] {self.message}"
|
|
40
|
+
if self.suggestion:
|
|
41
|
+
result += f"\n Suggestion: {self.suggestion}"
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
def __repr__(self) -> str:
|
|
45
|
+
return f"ValidationIssue(severity='{self.severity}', message='{self.message}')"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class SearchSpaceValidator:
|
|
49
|
+
"""
|
|
50
|
+
Validate search spaces for common issues.
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
>>> validator = SearchSpaceValidator(space)
|
|
54
|
+
>>> validator.validate()
|
|
55
|
+
>>> validator.print_report()
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, search_space: SearchSpace):
|
|
59
|
+
"""
|
|
60
|
+
Initialize validator.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
search_space: Search space to validate
|
|
64
|
+
"""
|
|
65
|
+
self.search_space = search_space
|
|
66
|
+
self.issues: List[ValidationIssue] = []
|
|
67
|
+
|
|
68
|
+
def validate(self) -> List[ValidationIssue]:
|
|
69
|
+
"""
|
|
70
|
+
Run all validation checks.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
List of validation issues
|
|
74
|
+
"""
|
|
75
|
+
self.issues.clear()
|
|
76
|
+
|
|
77
|
+
self._check_layer_count()
|
|
78
|
+
self._check_layer_types()
|
|
79
|
+
self._check_search_space_size()
|
|
80
|
+
self._check_flatten_usage()
|
|
81
|
+
self._check_parameter_ranges()
|
|
82
|
+
self._check_connectivity()
|
|
83
|
+
|
|
84
|
+
return self.issues
|
|
85
|
+
|
|
86
|
+
def _check_layer_count(self):
|
|
87
|
+
"""Check if layer count is reasonable."""
|
|
88
|
+
num_layers = len(self.search_space.layers)
|
|
89
|
+
|
|
90
|
+
if num_layers == 0:
|
|
91
|
+
self.issues.append(
|
|
92
|
+
ValidationIssue(
|
|
93
|
+
"error", "Search space has no layers", "Add layers using space.add_layers()"
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
elif num_layers < 3:
|
|
97
|
+
self.issues.append(
|
|
98
|
+
ValidationIssue(
|
|
99
|
+
"warning",
|
|
100
|
+
f"Search space has only {num_layers} layers",
|
|
101
|
+
"Consider adding more layers for meaningful search",
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
elif num_layers > 50:
|
|
105
|
+
self.issues.append(
|
|
106
|
+
ValidationIssue(
|
|
107
|
+
"warning",
|
|
108
|
+
f"Search space has {num_layers} layers (very deep)",
|
|
109
|
+
"Deep spaces may be slow to search",
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def _check_layer_types(self):
|
|
114
|
+
"""Check layer type distribution."""
|
|
115
|
+
layer_types = {}
|
|
116
|
+
has_input = False
|
|
117
|
+
has_output = False
|
|
118
|
+
|
|
119
|
+
for layer_spec in self.search_space.layers:
|
|
120
|
+
op = layer_spec.operation
|
|
121
|
+
layer_types[op] = layer_types.get(op, 0) + 1
|
|
122
|
+
|
|
123
|
+
if op == "input":
|
|
124
|
+
has_input = True
|
|
125
|
+
if op in ["output", "softmax"]:
|
|
126
|
+
has_output = True
|
|
127
|
+
|
|
128
|
+
# Check for input layer
|
|
129
|
+
if not has_input:
|
|
130
|
+
self.issues.append(
|
|
131
|
+
ValidationIssue(
|
|
132
|
+
"warning",
|
|
133
|
+
"No explicit input layer",
|
|
134
|
+
"Add Layer.input(shape=...) at the beginning",
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Check for output activation
|
|
139
|
+
if not has_output:
|
|
140
|
+
self.issues.append(
|
|
141
|
+
ValidationIssue(
|
|
142
|
+
"info",
|
|
143
|
+
"No explicit output activation",
|
|
144
|
+
"Consider adding Layer.softmax() or Layer.sigmoid() at the end",
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Check for activation functions
|
|
149
|
+
activations = sum(layer_types.get(act, 0) for act in ["relu", "sigmoid", "tanh", "softmax"])
|
|
150
|
+
if activations == 0:
|
|
151
|
+
self.issues.append(
|
|
152
|
+
ValidationIssue(
|
|
153
|
+
"warning",
|
|
154
|
+
"No activation functions found",
|
|
155
|
+
"Add activation layers like Layer.relu()",
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def _check_search_space_size(self):
|
|
160
|
+
"""Estimate search space size."""
|
|
161
|
+
try:
|
|
162
|
+
size = 1
|
|
163
|
+
for layer_spec in self.search_space.layers:
|
|
164
|
+
# Count choices for each parameter
|
|
165
|
+
layer_choices = 1
|
|
166
|
+
for param_values in layer_spec.param_ranges.values():
|
|
167
|
+
if isinstance(param_values, list) and len(param_values) > 1:
|
|
168
|
+
layer_choices *= len(param_values)
|
|
169
|
+
size *= max(layer_choices, 1)
|
|
170
|
+
|
|
171
|
+
if size > 1e12:
|
|
172
|
+
self.issues.append(
|
|
173
|
+
ValidationIssue(
|
|
174
|
+
"warning",
|
|
175
|
+
f"Extremely large search space (~{size:.2e} combinations)",
|
|
176
|
+
"Consider reducing parameter choices",
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
elif size > 1e9:
|
|
180
|
+
self.issues.append(
|
|
181
|
+
ValidationIssue(
|
|
182
|
+
"info",
|
|
183
|
+
f"Large search space (~{size:.2e} combinations)",
|
|
184
|
+
"May require many generations to explore",
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
elif size < 100:
|
|
188
|
+
self.issues.append(
|
|
189
|
+
ValidationIssue(
|
|
190
|
+
"info",
|
|
191
|
+
f"Small search space (~{size} combinations)",
|
|
192
|
+
"Consider adding more parameter choices for richer search",
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logger.debug(f"Could not estimate search space size: {e}")
|
|
198
|
+
|
|
199
|
+
def _check_flatten_usage(self):
|
|
200
|
+
"""Check flatten layer usage."""
|
|
201
|
+
has_conv = False
|
|
202
|
+
has_dense = False
|
|
203
|
+
has_flatten = False
|
|
204
|
+
|
|
205
|
+
for layer_spec in self.search_space.layers:
|
|
206
|
+
if layer_spec.operation in ["conv2d", "maxpool", "avgpool"]:
|
|
207
|
+
has_conv = True
|
|
208
|
+
elif layer_spec.operation == "dense":
|
|
209
|
+
has_dense = True
|
|
210
|
+
elif layer_spec.operation == "flatten":
|
|
211
|
+
has_flatten = True
|
|
212
|
+
|
|
213
|
+
# If has both conv and dense, should have flatten
|
|
214
|
+
if has_conv and has_dense and not has_flatten:
|
|
215
|
+
self.issues.append(
|
|
216
|
+
ValidationIssue(
|
|
217
|
+
"warning",
|
|
218
|
+
"Conv layers followed by Dense without Flatten",
|
|
219
|
+
"Add Layer.flatten() between conv and dense layers",
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
def _check_parameter_ranges(self):
|
|
224
|
+
"""Check parameter value ranges."""
|
|
225
|
+
for layer_spec in self.search_space.layers:
|
|
226
|
+
op = layer_spec.operation
|
|
227
|
+
|
|
228
|
+
# Check conv2d filters
|
|
229
|
+
if op == "conv2d":
|
|
230
|
+
filters = layer_spec.param_ranges.get("filters", [])
|
|
231
|
+
if isinstance(filters, list):
|
|
232
|
+
if any(f < 1 for f in filters):
|
|
233
|
+
self.issues.append(
|
|
234
|
+
ValidationIssue(
|
|
235
|
+
"error",
|
|
236
|
+
f"Conv2d has invalid filter count: {filters}",
|
|
237
|
+
"Filters must be positive integers",
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
if any(f > 1024 for f in filters):
|
|
241
|
+
self.issues.append(
|
|
242
|
+
ValidationIssue(
|
|
243
|
+
"warning",
|
|
244
|
+
f"Conv2d has very large filter count: {max(filters)}",
|
|
245
|
+
"Large filter counts increase parameters significantly",
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# Check dense units
|
|
250
|
+
if op == "dense":
|
|
251
|
+
units = layer_spec.param_ranges.get("units", [])
|
|
252
|
+
if isinstance(units, list):
|
|
253
|
+
if any(u < 1 for u in units):
|
|
254
|
+
self.issues.append(
|
|
255
|
+
ValidationIssue(
|
|
256
|
+
"error",
|
|
257
|
+
f"Dense has invalid unit count: {units}",
|
|
258
|
+
"Units must be positive integers",
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Check dropout rate
|
|
263
|
+
if op == "dropout":
|
|
264
|
+
rates = layer_spec.param_ranges.get("rate", [])
|
|
265
|
+
if isinstance(rates, list):
|
|
266
|
+
if any(r < 0 or r >= 1 for r in rates):
|
|
267
|
+
self.issues.append(
|
|
268
|
+
ValidationIssue(
|
|
269
|
+
"error",
|
|
270
|
+
f"Dropout has invalid rate: {rates}",
|
|
271
|
+
"Dropout rate must be in [0, 1)",
|
|
272
|
+
)
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
def _check_connectivity(self):
|
|
276
|
+
"""Check if sampled architectures will be connected."""
|
|
277
|
+
try:
|
|
278
|
+
# Sample a few architectures to check
|
|
279
|
+
for _ in range(3):
|
|
280
|
+
graph = self.search_space.sample()
|
|
281
|
+
|
|
282
|
+
if not graph.is_valid():
|
|
283
|
+
self.issues.append(
|
|
284
|
+
ValidationIssue(
|
|
285
|
+
"error",
|
|
286
|
+
"Sampled architecture is not a valid DAG",
|
|
287
|
+
"Check search space definition",
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
break
|
|
291
|
+
|
|
292
|
+
except Exception as e:
|
|
293
|
+
self.issues.append(
|
|
294
|
+
ValidationIssue(
|
|
295
|
+
"error",
|
|
296
|
+
f"Failed to sample from search space: {e}",
|
|
297
|
+
"Check layer definitions and parameters",
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
def print_report(self):
|
|
302
|
+
"""Print validation report."""
|
|
303
|
+
if not self.issues:
|
|
304
|
+
print("✓ Search space validation passed!")
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
print("\nSearch Space Validation Report")
|
|
308
|
+
print("=" * 70)
|
|
309
|
+
|
|
310
|
+
errors = [i for i in self.issues if i.severity == "error"]
|
|
311
|
+
warnings = [i for i in self.issues if i.severity == "warning"]
|
|
312
|
+
infos = [i for i in self.issues if i.severity == "info"]
|
|
313
|
+
|
|
314
|
+
if errors:
|
|
315
|
+
print(f"\n❌ Errors ({len(errors)}):")
|
|
316
|
+
for issue in errors:
|
|
317
|
+
print(f" {issue}")
|
|
318
|
+
|
|
319
|
+
if warnings:
|
|
320
|
+
print(f"\n⚠️ Warnings ({len(warnings)}):")
|
|
321
|
+
for issue in warnings:
|
|
322
|
+
print(f" {issue}")
|
|
323
|
+
|
|
324
|
+
if infos:
|
|
325
|
+
print(f"\nℹ️ Info ({len(infos)}):")
|
|
326
|
+
for issue in infos:
|
|
327
|
+
print(f" {issue}")
|
|
328
|
+
|
|
329
|
+
print("=" * 70)
|
|
330
|
+
|
|
331
|
+
if errors:
|
|
332
|
+
print("\n❌ Validation failed! Fix errors before running NAS.")
|
|
333
|
+
elif warnings:
|
|
334
|
+
print("\n⚠️ Validation passed with warnings. Review before running NAS.")
|
|
335
|
+
else:
|
|
336
|
+
print("\n✓ Validation passed!")
|
|
337
|
+
|
|
338
|
+
def has_errors(self) -> bool:
|
|
339
|
+
"""Check if there are any errors."""
|
|
340
|
+
return any(i.severity == "error" for i in self.issues)
|
|
341
|
+
|
|
342
|
+
def has_warnings(self) -> bool:
|
|
343
|
+
"""Check if there are any warnings."""
|
|
344
|
+
return any(i.severity == "warning" for i in self.issues)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def validate_search_space(
|
|
348
|
+
search_space: SearchSpace,
|
|
349
|
+
print_report: bool = True,
|
|
350
|
+
) -> List[ValidationIssue]:
|
|
351
|
+
"""
|
|
352
|
+
Validate search space and optionally print report.
|
|
353
|
+
|
|
354
|
+
Args:
|
|
355
|
+
search_space: Search space to validate
|
|
356
|
+
print_report: Whether to print validation report
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
List of validation issues
|
|
360
|
+
|
|
361
|
+
Example:
|
|
362
|
+
>>> issues = validate_search_space(space)
|
|
363
|
+
>>> if any(i.severity == "error" for i in issues):
|
|
364
|
+
... print("Fix errors before running NAS!")
|
|
365
|
+
"""
|
|
366
|
+
validator = SearchSpaceValidator(search_space)
|
|
367
|
+
issues = validator.validate()
|
|
368
|
+
|
|
369
|
+
if print_report:
|
|
370
|
+
validator.print_report()
|
|
371
|
+
|
|
372
|
+
return issues
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def quick_validate(search_space: SearchSpace) -> bool:
|
|
376
|
+
"""
|
|
377
|
+
Quick validation returning True if no errors.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
search_space: Search space to validate
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
True if validation passed (no errors)
|
|
384
|
+
|
|
385
|
+
Example:
|
|
386
|
+
>>> if quick_validate(space):
|
|
387
|
+
... # Run NAS
|
|
388
|
+
... pass
|
|
389
|
+
"""
|
|
390
|
+
validator = SearchSpaceValidator(search_space)
|
|
391
|
+
validator.validate()
|
|
392
|
+
return not validator.has_errors()
|
morphml/version.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Version information for MorphML."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.0.0"
|
|
4
|
+
__author__ = "Vedanth & Eshan Roy"
|
|
5
|
+
__email__ = "vedanth@vedanthq.com, eshanized@proton.me"
|
|
6
|
+
__organization__ = "TONMOY INFRASTRUCTURE & VISION"
|
|
7
|
+
__repository__ = "https://github.com/TIVerse/MorphML"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Visualization tools for architectures and optimization."""
|
|
2
|
+
|
|
3
|
+
from morphml.visualization.analytics import PerformanceAnalytics
|
|
4
|
+
from morphml.visualization.architecture_diagrams import ArchitectureDiagramGenerator
|
|
5
|
+
from morphml.visualization.architecture_plot import (
|
|
6
|
+
plot_architecture,
|
|
7
|
+
plot_architecture_hierarchy,
|
|
8
|
+
plot_architecture_stats,
|
|
9
|
+
)
|
|
10
|
+
from morphml.visualization.convergence_plot import (
|
|
11
|
+
plot_convergence,
|
|
12
|
+
plot_convergence_comparison,
|
|
13
|
+
plot_fitness_distribution,
|
|
14
|
+
)
|
|
15
|
+
from morphml.visualization.graph_viz import GraphVisualizer
|
|
16
|
+
|
|
17
|
+
# Phase 2: Advanced visualization
|
|
18
|
+
from morphml.visualization.pareto_plot import (
|
|
19
|
+
plot_parallel_coordinates,
|
|
20
|
+
plot_pareto_front_2d,
|
|
21
|
+
plot_pareto_front_3d,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Phase 5: Interactive dashboards and professional diagrams
|
|
25
|
+
from morphml.visualization.plotly_dashboards import InteractiveDashboard
|
|
26
|
+
from morphml.visualization.population import PopulationVisualizer
|
|
27
|
+
from morphml.visualization.progress import ProgressPlotter
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
# Phase 1
|
|
31
|
+
"GraphVisualizer",
|
|
32
|
+
"ProgressPlotter",
|
|
33
|
+
"PopulationVisualizer",
|
|
34
|
+
# Phase 2: Pareto
|
|
35
|
+
"plot_pareto_front_2d",
|
|
36
|
+
"plot_pareto_front_3d",
|
|
37
|
+
"plot_parallel_coordinates",
|
|
38
|
+
# Phase 2: Convergence
|
|
39
|
+
"plot_convergence",
|
|
40
|
+
"plot_convergence_comparison",
|
|
41
|
+
"plot_fitness_distribution",
|
|
42
|
+
# Phase 2: Architecture
|
|
43
|
+
"plot_architecture",
|
|
44
|
+
"plot_architecture_hierarchy",
|
|
45
|
+
"plot_architecture_stats",
|
|
46
|
+
# Phase 5: Interactive & Professional
|
|
47
|
+
"InteractiveDashboard",
|
|
48
|
+
"ArchitectureDiagramGenerator",
|
|
49
|
+
"PerformanceAnalytics",
|
|
50
|
+
]
|