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,221 @@
1
+ """Ensemble predictor combining multiple methods.
2
+
3
+ Author: Eshan Roy <eshanized@proton.me>
4
+ Organization: TONMOY INFRASTRUCTURE & VISION
5
+ """
6
+
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ import numpy as np
10
+
11
+ from morphml.core.graph import ModelGraph
12
+ from morphml.logging_config import get_logger
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ class EnsemblePredictor:
18
+ """
19
+ Ensemble of multiple performance predictors.
20
+
21
+ Combines predictions from:
22
+ - Proxy metric predictor
23
+ - Learning curve predictor
24
+ - GNN predictor (if available)
25
+
26
+ Args:
27
+ predictors: List of predictor instances
28
+ weights: Weights for each predictor (default: equal)
29
+ aggregation: How to combine ('weighted_average', 'max', 'min')
30
+
31
+ Example:
32
+ >>> from morphml.meta_learning.predictors import (
33
+ ... ProxyMetricPredictor,
34
+ ... EnsemblePredictor
35
+ ... )
36
+ >>>
37
+ >>> # Create predictors
38
+ >>> proxy_pred = ProxyMetricPredictor()
39
+ >>> proxy_pred.train(training_data)
40
+ >>>
41
+ >>> # Ensemble
42
+ >>> ensemble = EnsemblePredictor(
43
+ ... predictors=[proxy_pred],
44
+ ... weights=[1.0]
45
+ ... )
46
+ >>>
47
+ >>> prediction = ensemble.predict(new_graph)
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ predictors: List[Any],
53
+ weights: Optional[List[float]] = None,
54
+ aggregation: str = "weighted_average",
55
+ ):
56
+ """Initialize ensemble predictor."""
57
+ self.predictors = predictors
58
+
59
+ # Default: equal weights
60
+ if weights is None:
61
+ weights = [1.0 / len(predictors)] * len(predictors)
62
+
63
+ # Normalize weights
64
+ total = sum(weights)
65
+ self.weights = [w / total for w in weights]
66
+
67
+ self.aggregation = aggregation
68
+
69
+ logger.info(
70
+ f"Initialized EnsemblePredictor with {len(predictors)} predictors "
71
+ f"(aggregation={aggregation})"
72
+ )
73
+
74
+ def predict(self, graph: ModelGraph, **predictor_kwargs) -> float:
75
+ """
76
+ Predict using ensemble.
77
+
78
+ Args:
79
+ graph: Architecture to evaluate
80
+ **predictor_kwargs: Additional kwargs for specific predictors
81
+
82
+ Returns:
83
+ Ensemble prediction
84
+ """
85
+ predictions = []
86
+
87
+ for i, predictor in enumerate(self.predictors):
88
+ try:
89
+ # Get prediction
90
+ if hasattr(predictor, "predict"):
91
+ pred = predictor.predict(graph, **predictor_kwargs)
92
+ predictions.append(pred)
93
+ else:
94
+ logger.warning(f"Predictor {i} has no predict method, skipping")
95
+ except Exception as e:
96
+ logger.warning(f"Predictor {i} failed: {e}")
97
+
98
+ if not predictions:
99
+ logger.warning("No valid predictions, returning 0.5")
100
+ return 0.5
101
+
102
+ # Aggregate
103
+ if self.aggregation == "weighted_average":
104
+ # Use weights corresponding to valid predictions
105
+ valid_weights = self.weights[: len(predictions)]
106
+ total_weight = sum(valid_weights)
107
+ valid_weights = [w / total_weight for w in valid_weights]
108
+
109
+ result = sum(w * p for w, p in zip(valid_weights, predictions))
110
+
111
+ elif self.aggregation == "max":
112
+ result = max(predictions)
113
+
114
+ elif self.aggregation == "min":
115
+ result = min(predictions)
116
+
117
+ elif self.aggregation == "median":
118
+ result = np.median(predictions)
119
+
120
+ else:
121
+ raise ValueError(f"Unknown aggregation: {self.aggregation}")
122
+
123
+ return float(result)
124
+
125
+ def batch_predict(self, graphs: List[ModelGraph], **predictor_kwargs) -> np.ndarray:
126
+ """
127
+ Batch prediction for efficiency.
128
+
129
+ Args:
130
+ graphs: List of architectures
131
+ **predictor_kwargs: Additional kwargs
132
+
133
+ Returns:
134
+ Array of predictions
135
+ """
136
+ # Try batch prediction if available
137
+ all_predictions = []
138
+
139
+ for predictor in self.predictors:
140
+ try:
141
+ if hasattr(predictor, "batch_predict"):
142
+ preds = predictor.batch_predict(graphs, **predictor_kwargs)
143
+ else:
144
+ # Fallback to sequential
145
+ preds = np.array([predictor.predict(g, **predictor_kwargs) for g in graphs])
146
+
147
+ all_predictions.append(preds)
148
+ except Exception as e:
149
+ logger.warning(f"Batch prediction failed for predictor: {e}")
150
+
151
+ if not all_predictions:
152
+ return np.full(len(graphs), 0.5)
153
+
154
+ # Aggregate
155
+ all_predictions = np.array(all_predictions) # Shape: (n_predictors, n_graphs)
156
+
157
+ if self.aggregation == "weighted_average":
158
+ weights = np.array(self.weights[: len(all_predictions)])
159
+ weights = weights / weights.sum()
160
+ result = np.average(all_predictions, axis=0, weights=weights)
161
+
162
+ elif self.aggregation == "max":
163
+ result = np.max(all_predictions, axis=0)
164
+
165
+ elif self.aggregation == "min":
166
+ result = np.min(all_predictions, axis=0)
167
+
168
+ elif self.aggregation == "median":
169
+ result = np.median(all_predictions, axis=0)
170
+
171
+ else:
172
+ raise ValueError(f"Unknown aggregation: {self.aggregation}")
173
+
174
+ return result
175
+
176
+ def get_individual_predictions(self, graph: ModelGraph, **predictor_kwargs) -> Dict[str, float]:
177
+ """
178
+ Get predictions from each individual predictor.
179
+
180
+ Useful for debugging and analysis.
181
+
182
+ Args:
183
+ graph: Architecture to evaluate
184
+ **predictor_kwargs: Additional kwargs
185
+
186
+ Returns:
187
+ Dictionary mapping predictor name to prediction
188
+ """
189
+ predictions = {}
190
+
191
+ for i, predictor in enumerate(self.predictors):
192
+ name = predictor.__class__.__name__
193
+ try:
194
+ pred = predictor.predict(graph, **predictor_kwargs)
195
+ predictions[f"{name}_{i}"] = pred
196
+ except Exception as e:
197
+ logger.warning(f"Predictor {name} failed: {e}")
198
+ predictions[f"{name}_{i}"] = None
199
+
200
+ # Add ensemble prediction
201
+ predictions["ensemble"] = self.predict(graph, **predictor_kwargs)
202
+
203
+ return predictions
204
+
205
+ def update_weights(self, new_weights: List[float]) -> None:
206
+ """
207
+ Update predictor weights.
208
+
209
+ Useful for adaptive weighting based on performance.
210
+
211
+ Args:
212
+ new_weights: New weights (will be normalized)
213
+ """
214
+ if len(new_weights) != len(self.predictors):
215
+ raise ValueError(f"Expected {len(self.predictors)} weights, got {len(new_weights)}")
216
+
217
+ # Normalize
218
+ total = sum(new_weights)
219
+ self.weights = [w / total for w in new_weights]
220
+
221
+ logger.info(f"Updated weights: {self.weights}")