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.

Files changed (158) hide show
  1. morphml/__init__.py +14 -0
  2. morphml/api/__init__.py +26 -0
  3. morphml/api/app.py +326 -0
  4. morphml/api/auth.py +193 -0
  5. morphml/api/client.py +338 -0
  6. morphml/api/models.py +132 -0
  7. morphml/api/rate_limit.py +192 -0
  8. morphml/benchmarking/__init__.py +36 -0
  9. morphml/benchmarking/comparison.py +430 -0
  10. morphml/benchmarks/__init__.py +56 -0
  11. morphml/benchmarks/comparator.py +409 -0
  12. morphml/benchmarks/datasets.py +280 -0
  13. morphml/benchmarks/metrics.py +199 -0
  14. morphml/benchmarks/openml_suite.py +201 -0
  15. morphml/benchmarks/problems.py +289 -0
  16. morphml/benchmarks/suite.py +318 -0
  17. morphml/cli/__init__.py +5 -0
  18. morphml/cli/commands/experiment.py +329 -0
  19. morphml/cli/main.py +457 -0
  20. morphml/cli/quickstart.py +312 -0
  21. morphml/config.py +278 -0
  22. morphml/constraints/__init__.py +19 -0
  23. morphml/constraints/handler.py +205 -0
  24. morphml/constraints/predicates.py +285 -0
  25. morphml/core/__init__.py +3 -0
  26. morphml/core/crossover.py +449 -0
  27. morphml/core/dsl/README.md +359 -0
  28. morphml/core/dsl/__init__.py +72 -0
  29. morphml/core/dsl/ast_nodes.py +364 -0
  30. morphml/core/dsl/compiler.py +318 -0
  31. morphml/core/dsl/layers.py +368 -0
  32. morphml/core/dsl/lexer.py +336 -0
  33. morphml/core/dsl/parser.py +455 -0
  34. morphml/core/dsl/search_space.py +386 -0
  35. morphml/core/dsl/syntax.py +199 -0
  36. morphml/core/dsl/type_system.py +361 -0
  37. morphml/core/dsl/validator.py +386 -0
  38. morphml/core/graph/__init__.py +40 -0
  39. morphml/core/graph/edge.py +124 -0
  40. morphml/core/graph/graph.py +507 -0
  41. morphml/core/graph/mutations.py +409 -0
  42. morphml/core/graph/node.py +196 -0
  43. morphml/core/graph/serialization.py +361 -0
  44. morphml/core/graph/visualization.py +431 -0
  45. morphml/core/objectives/__init__.py +20 -0
  46. morphml/core/search/__init__.py +33 -0
  47. morphml/core/search/individual.py +252 -0
  48. morphml/core/search/parameters.py +453 -0
  49. morphml/core/search/population.py +375 -0
  50. morphml/core/search/search_engine.py +340 -0
  51. morphml/distributed/__init__.py +76 -0
  52. morphml/distributed/fault_tolerance.py +497 -0
  53. morphml/distributed/health_monitor.py +348 -0
  54. morphml/distributed/master.py +709 -0
  55. morphml/distributed/proto/README.md +224 -0
  56. morphml/distributed/proto/__init__.py +74 -0
  57. morphml/distributed/proto/worker.proto +170 -0
  58. morphml/distributed/proto/worker_pb2.py +79 -0
  59. morphml/distributed/proto/worker_pb2_grpc.py +423 -0
  60. morphml/distributed/resource_manager.py +416 -0
  61. morphml/distributed/scheduler.py +567 -0
  62. morphml/distributed/storage/__init__.py +33 -0
  63. morphml/distributed/storage/artifacts.py +381 -0
  64. morphml/distributed/storage/cache.py +366 -0
  65. morphml/distributed/storage/checkpointing.py +329 -0
  66. morphml/distributed/storage/database.py +459 -0
  67. morphml/distributed/worker.py +549 -0
  68. morphml/evaluation/__init__.py +5 -0
  69. morphml/evaluation/heuristic.py +237 -0
  70. morphml/exceptions.py +55 -0
  71. morphml/execution/__init__.py +5 -0
  72. morphml/execution/local_executor.py +350 -0
  73. morphml/integrations/__init__.py +28 -0
  74. morphml/integrations/jax_adapter.py +206 -0
  75. morphml/integrations/pytorch_adapter.py +530 -0
  76. morphml/integrations/sklearn_adapter.py +206 -0
  77. morphml/integrations/tensorflow_adapter.py +230 -0
  78. morphml/logging_config.py +93 -0
  79. morphml/meta_learning/__init__.py +66 -0
  80. morphml/meta_learning/architecture_similarity.py +277 -0
  81. morphml/meta_learning/experiment_database.py +240 -0
  82. morphml/meta_learning/knowledge_base/__init__.py +19 -0
  83. morphml/meta_learning/knowledge_base/embedder.py +179 -0
  84. morphml/meta_learning/knowledge_base/knowledge_base.py +313 -0
  85. morphml/meta_learning/knowledge_base/meta_features.py +265 -0
  86. morphml/meta_learning/knowledge_base/vector_store.py +271 -0
  87. morphml/meta_learning/predictors/__init__.py +27 -0
  88. morphml/meta_learning/predictors/ensemble.py +221 -0
  89. morphml/meta_learning/predictors/gnn_predictor.py +552 -0
  90. morphml/meta_learning/predictors/learning_curve.py +231 -0
  91. morphml/meta_learning/predictors/proxy_metrics.py +261 -0
  92. morphml/meta_learning/strategy_evolution/__init__.py +27 -0
  93. morphml/meta_learning/strategy_evolution/adaptive_optimizer.py +226 -0
  94. morphml/meta_learning/strategy_evolution/bandit.py +276 -0
  95. morphml/meta_learning/strategy_evolution/portfolio.py +230 -0
  96. morphml/meta_learning/transfer.py +581 -0
  97. morphml/meta_learning/warm_start.py +286 -0
  98. morphml/optimizers/__init__.py +74 -0
  99. morphml/optimizers/adaptive_operators.py +399 -0
  100. morphml/optimizers/bayesian/__init__.py +52 -0
  101. morphml/optimizers/bayesian/acquisition.py +387 -0
  102. morphml/optimizers/bayesian/base.py +319 -0
  103. morphml/optimizers/bayesian/gaussian_process.py +635 -0
  104. morphml/optimizers/bayesian/smac.py +534 -0
  105. morphml/optimizers/bayesian/tpe.py +411 -0
  106. morphml/optimizers/differential_evolution.py +220 -0
  107. morphml/optimizers/evolutionary/__init__.py +61 -0
  108. morphml/optimizers/evolutionary/cma_es.py +416 -0
  109. morphml/optimizers/evolutionary/differential_evolution.py +556 -0
  110. morphml/optimizers/evolutionary/encoding.py +426 -0
  111. morphml/optimizers/evolutionary/particle_swarm.py +449 -0
  112. morphml/optimizers/genetic_algorithm.py +486 -0
  113. morphml/optimizers/gradient_based/__init__.py +22 -0
  114. morphml/optimizers/gradient_based/darts.py +550 -0
  115. morphml/optimizers/gradient_based/enas.py +585 -0
  116. morphml/optimizers/gradient_based/operations.py +474 -0
  117. morphml/optimizers/gradient_based/utils.py +601 -0
  118. morphml/optimizers/hill_climbing.py +169 -0
  119. morphml/optimizers/multi_objective/__init__.py +56 -0
  120. morphml/optimizers/multi_objective/indicators.py +504 -0
  121. morphml/optimizers/multi_objective/nsga2.py +647 -0
  122. morphml/optimizers/multi_objective/visualization.py +427 -0
  123. morphml/optimizers/nsga2.py +308 -0
  124. morphml/optimizers/random_search.py +172 -0
  125. morphml/optimizers/simulated_annealing.py +181 -0
  126. morphml/plugins/__init__.py +35 -0
  127. morphml/plugins/custom_evaluator_example.py +81 -0
  128. morphml/plugins/custom_optimizer_example.py +63 -0
  129. morphml/plugins/plugin_system.py +454 -0
  130. morphml/reports/__init__.py +30 -0
  131. morphml/reports/generator.py +362 -0
  132. morphml/tracking/__init__.py +7 -0
  133. morphml/tracking/experiment.py +309 -0
  134. morphml/tracking/logger.py +301 -0
  135. morphml/tracking/reporter.py +357 -0
  136. morphml/utils/__init__.py +6 -0
  137. morphml/utils/checkpoint.py +189 -0
  138. morphml/utils/comparison.py +390 -0
  139. morphml/utils/export.py +407 -0
  140. morphml/utils/progress.py +392 -0
  141. morphml/utils/validation.py +392 -0
  142. morphml/version.py +7 -0
  143. morphml/visualization/__init__.py +50 -0
  144. morphml/visualization/analytics.py +423 -0
  145. morphml/visualization/architecture_diagrams.py +353 -0
  146. morphml/visualization/architecture_plot.py +223 -0
  147. morphml/visualization/convergence_plot.py +174 -0
  148. morphml/visualization/crossover_viz.py +386 -0
  149. morphml/visualization/graph_viz.py +338 -0
  150. morphml/visualization/pareto_plot.py +149 -0
  151. morphml/visualization/plotly_dashboards.py +422 -0
  152. morphml/visualization/population.py +309 -0
  153. morphml/visualization/progress.py +260 -0
  154. morphml-1.0.0.dist-info/METADATA +434 -0
  155. morphml-1.0.0.dist-info/RECORD +158 -0
  156. morphml-1.0.0.dist-info/WHEEL +4 -0
  157. morphml-1.0.0.dist-info/entry_points.txt +3 -0
  158. morphml-1.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,361 @@
1
+ """Type system for MorphML DSL.
2
+
3
+ Provides type checking and type inference for DSL constructs.
4
+
5
+ Author: Eshan Roy <eshanized@proton.me>
6
+ Organization: TONMOY INFRASTRUCTURE & VISION
7
+ """
8
+
9
+ from enum import Enum
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from morphml.core.dsl.ast_nodes import (
13
+ ASTVisitor,
14
+ ExperimentNode,
15
+ LayerNode,
16
+ ParamNode,
17
+ SearchSpaceNode,
18
+ )
19
+ from morphml.logging_config import get_logger
20
+
21
+ logger = get_logger(__name__)
22
+
23
+
24
+ class Type(Enum):
25
+ """Type system for DSL values."""
26
+
27
+ # Primitive types
28
+ INT = "int"
29
+ FLOAT = "float"
30
+ STRING = "string"
31
+ BOOL = "bool"
32
+
33
+ # Collection types
34
+ LIST = "list"
35
+ DICT = "dict"
36
+
37
+ # Special types
38
+ ANY = "any"
39
+ NONE = "none"
40
+ LAYER = "layer"
41
+ PARAM = "param"
42
+
43
+ def __repr__(self) -> str:
44
+ """String representation."""
45
+ return f"Type.{self.name}"
46
+
47
+
48
+ class TypeEnvironment:
49
+ """
50
+ Type environment for type checking.
51
+
52
+ Maintains a symbol table mapping names to types.
53
+ """
54
+
55
+ def __init__(self, parent: Optional["TypeEnvironment"] = None):
56
+ """
57
+ Initialize type environment.
58
+
59
+ Args:
60
+ parent: Parent environment for nested scopes
61
+ """
62
+ self.parent = parent
63
+ self.symbols: Dict[str, Type] = {}
64
+
65
+ def define(self, name: str, type_: Type) -> None:
66
+ """Define a symbol with its type."""
67
+ self.symbols[name] = type_
68
+
69
+ def lookup(self, name: str) -> Optional[Type]:
70
+ """Look up symbol type."""
71
+ if name in self.symbols:
72
+ return self.symbols[name]
73
+ elif self.parent:
74
+ return self.parent.lookup(name)
75
+ return None
76
+
77
+ def __repr__(self) -> str:
78
+ """String representation."""
79
+ return f"TypeEnvironment({self.symbols})"
80
+
81
+
82
+ class TypeError:
83
+ """Represents a type error."""
84
+
85
+ def __init__(
86
+ self,
87
+ message: str,
88
+ node: str = "Unknown",
89
+ expected: Optional[Type] = None,
90
+ actual: Optional[Type] = None,
91
+ ):
92
+ """
93
+ Initialize type error.
94
+
95
+ Args:
96
+ message: Error message
97
+ node: Node type where error occurred
98
+ expected: Expected type
99
+ actual: Actual type
100
+ """
101
+ self.message = message
102
+ self.node = node
103
+ self.expected = expected
104
+ self.actual = actual
105
+
106
+ def __str__(self) -> str:
107
+ """String representation."""
108
+ if self.expected and self.actual:
109
+ return (
110
+ f"[{self.node}] {self.message}\n"
111
+ f" Expected: {self.expected}\n"
112
+ f" Actual: {self.actual}"
113
+ )
114
+ return f"[{self.node}] {self.message}"
115
+
116
+
117
+ class TypeChecker(ASTVisitor):
118
+ """
119
+ Type checker for MorphML DSL.
120
+
121
+ Performs static type checking on the AST to catch type errors
122
+ before compilation.
123
+
124
+ Example:
125
+ >>> checker = TypeChecker()
126
+ >>> errors = checker.check(ast)
127
+ >>> if errors:
128
+ ... for error in errors:
129
+ ... print(error)
130
+ """
131
+
132
+ def __init__(self) -> None:
133
+ """Initialize type checker."""
134
+ self.errors: List[TypeError] = []
135
+ self.env = TypeEnvironment()
136
+ self.current_layer_type: Optional[str] = None
137
+
138
+ # Parameter type requirements for each layer type
139
+ self.layer_param_types: Dict[str, Dict[str, Type]] = {
140
+ "conv2d": {
141
+ "filters": Type.INT,
142
+ "kernel_size": Type.INT,
143
+ "strides": Type.INT,
144
+ "padding": Type.STRING,
145
+ },
146
+ "dense": {"units": Type.INT, "activation": Type.STRING},
147
+ "dropout": {"rate": Type.FLOAT},
148
+ "max_pool": {"pool_size": Type.INT},
149
+ "avg_pool": {"pool_size": Type.INT},
150
+ }
151
+
152
+ def check(self, ast: ExperimentNode) -> List[TypeError]:
153
+ """
154
+ Type check complete experiment AST.
155
+
156
+ Args:
157
+ ast: ExperimentNode to type check
158
+
159
+ Returns:
160
+ List of type errors (empty if type-safe)
161
+ """
162
+ logger.info("Starting type checking")
163
+
164
+ # Reset state
165
+ self.errors.clear()
166
+ self.env = TypeEnvironment()
167
+
168
+ # Type check via visitor pattern
169
+ ast.accept(self)
170
+
171
+ if self.errors:
172
+ logger.warning(f"Type checking found {len(self.errors)} errors")
173
+ else:
174
+ logger.info("Type checking successful")
175
+
176
+ return self.errors
177
+
178
+ def visit_search_space(self, node: SearchSpaceNode) -> None:
179
+ """Type check search space."""
180
+ # Create new scope for search space
181
+ old_env = self.env
182
+ self.env = TypeEnvironment(parent=old_env)
183
+
184
+ # Type check global parameters
185
+ for param_name, param_node in node.global_params.items():
186
+ param_type = self._infer_param_type(param_node)
187
+ self.env.define(param_name, param_type)
188
+
189
+ # Type check layers
190
+ super().visit_search_space(node)
191
+
192
+ # Restore environment
193
+ self.env = old_env
194
+
195
+ def visit_layer(self, node: LayerNode) -> None:
196
+ """Type check layer."""
197
+ self.current_layer_type = node.layer_type
198
+
199
+ # Get expected parameter types for this layer
200
+ expected_types = self.layer_param_types.get(node.layer_type, {})
201
+
202
+ # Check each parameter
203
+ for param_name, param_node in node.params.items():
204
+ # Infer actual type
205
+ actual_type = self._infer_param_type(param_node)
206
+
207
+ # Check against expected type if known
208
+ if param_name in expected_types:
209
+ expected_type = expected_types[param_name]
210
+
211
+ if not self._is_compatible(actual_type, expected_type):
212
+ self.errors.append(
213
+ TypeError(
214
+ f"Type mismatch for parameter '{param_name}' in layer '{node.layer_type}'",
215
+ node="Layer",
216
+ expected=expected_type,
217
+ actual=actual_type,
218
+ )
219
+ )
220
+
221
+ super().visit_layer(node)
222
+
223
+ self.current_layer_type = None
224
+
225
+ def visit_param(self, node: ParamNode) -> None:
226
+ """Type check parameter."""
227
+ # Check type consistency within parameter values
228
+ if len(node.values) > 1:
229
+ types = [self._infer_type(v) for v in node.values]
230
+ if len(set(types)) > 1:
231
+ # Allow int/float mixing
232
+ if not (set(types) <= {Type.INT, Type.FLOAT}):
233
+ self.errors.append(
234
+ TypeError(
235
+ f"Inconsistent types in parameter '{node.name}': {types}",
236
+ node="Parameter",
237
+ )
238
+ )
239
+
240
+ def _infer_type(self, value: Any) -> Type:
241
+ """
242
+ Infer type from Python value.
243
+
244
+ Args:
245
+ value: Python value
246
+
247
+ Returns:
248
+ Type enum
249
+ """
250
+ if isinstance(value, bool):
251
+ return Type.BOOL
252
+ elif isinstance(value, int):
253
+ return Type.INT
254
+ elif isinstance(value, float):
255
+ return Type.FLOAT
256
+ elif isinstance(value, str):
257
+ return Type.STRING
258
+ elif isinstance(value, list):
259
+ return Type.LIST
260
+ elif isinstance(value, dict):
261
+ return Type.DICT
262
+ elif value is None:
263
+ return Type.NONE
264
+ else:
265
+ return Type.ANY
266
+
267
+ def _infer_param_type(self, param_node: ParamNode) -> Type:
268
+ """
269
+ Infer type for a parameter node.
270
+
271
+ Args:
272
+ param_node: Parameter node
273
+
274
+ Returns:
275
+ Inferred type
276
+ """
277
+ if not param_node.values:
278
+ return Type.NONE
279
+
280
+ # Infer from first value
281
+ first_type = self._infer_type(param_node.values[0])
282
+
283
+ # Check if all values have same type
284
+ all_same = all(self._infer_type(v) == first_type for v in param_node.values)
285
+
286
+ if all_same:
287
+ return first_type
288
+
289
+ # Mixed types - check for numeric
290
+ types = [self._infer_type(v) for v in param_node.values]
291
+ if set(types) <= {Type.INT, Type.FLOAT}:
292
+ return Type.FLOAT
293
+
294
+ return Type.ANY
295
+
296
+ def _is_compatible(self, actual: Type, expected: Type) -> bool:
297
+ """
298
+ Check if actual type is compatible with expected type.
299
+
300
+ Args:
301
+ actual: Actual type
302
+ expected: Expected type
303
+
304
+ Returns:
305
+ True if compatible
306
+ """
307
+ # Same type is compatible
308
+ if actual == expected:
309
+ return True
310
+
311
+ # ANY is compatible with everything
312
+ if actual == Type.ANY or expected == Type.ANY:
313
+ return True
314
+
315
+ # INT is compatible with FLOAT
316
+ if actual == Type.INT and expected == Type.FLOAT:
317
+ return True
318
+
319
+ return False
320
+
321
+
322
+ def check_types(ast: ExperimentNode) -> List[TypeError]:
323
+ """
324
+ Convenience function to type check AST.
325
+
326
+ Args:
327
+ ast: ExperimentNode to check
328
+
329
+ Returns:
330
+ List of type errors
331
+ """
332
+ checker = TypeChecker()
333
+ return checker.check(ast)
334
+
335
+
336
+ def infer_value_type(value: Any) -> str:
337
+ """
338
+ Infer type name from Python value.
339
+
340
+ Args:
341
+ value: Python value
342
+
343
+ Returns:
344
+ Type name as string
345
+ """
346
+ if isinstance(value, bool):
347
+ return "boolean"
348
+ elif isinstance(value, int):
349
+ return "integer"
350
+ elif isinstance(value, float):
351
+ return "float"
352
+ elif isinstance(value, str):
353
+ return "string"
354
+ elif isinstance(value, list):
355
+ return "list"
356
+ elif isinstance(value, dict):
357
+ return "dict"
358
+ elif value is None:
359
+ return "none"
360
+ else:
361
+ return "any"