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,230 @@
1
+ """Portfolio optimization - run multiple strategies in parallel.
2
+
3
+ Author: Eshan Roy <eshanized@proton.me>
4
+ Organization: TONMOY INFRASTRUCTURE & VISION
5
+ """
6
+
7
+ from concurrent.futures import ThreadPoolExecutor, as_completed
8
+ from typing import Any, Callable, Dict, List
9
+
10
+ from morphml.core.dsl import SearchSpace
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 PortfolioOptimizer:
18
+ """
19
+ Run multiple optimization strategies in parallel.
20
+
21
+ Allocates computational budget across different strategies
22
+ and combines their results.
23
+
24
+ Args:
25
+ search_space: Search space definition
26
+ evaluator: Architecture evaluation function
27
+ strategies: Dict mapping strategy name to configuration
28
+ budget_allocation: Budget allocation strategy
29
+ - 'equal': Equal budget to each
30
+ - 'performance': Allocate based on past performance
31
+
32
+ Example:
33
+ >>> strategies = {
34
+ ... 'random': {'num_samples': 100},
35
+ ... 'ga': {'population_size': 50, 'num_generations': 10},
36
+ ... 'hc': {'num_iterations': 200}
37
+ ... }
38
+ >>>
39
+ >>> portfolio = PortfolioOptimizer(
40
+ ... search_space=space,
41
+ ... evaluator=evaluator,
42
+ ... strategies=strategies
43
+ ... )
44
+ >>>
45
+ >>> best_archs = portfolio.optimize(total_budget=500)
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ search_space: SearchSpace,
51
+ evaluator: Callable[[ModelGraph], float],
52
+ strategies: Dict[str, Dict[str, Any]],
53
+ budget_allocation: str = "equal",
54
+ parallel: bool = False,
55
+ ):
56
+ """Initialize portfolio optimizer."""
57
+ self.search_space = search_space
58
+ self.evaluator = evaluator
59
+ self.strategies = strategies
60
+ self.budget_allocation = budget_allocation
61
+ self.parallel = parallel
62
+
63
+ self.results = {}
64
+
65
+ logger.info(
66
+ f"Initialized PortfolioOptimizer with {len(strategies)} strategies: "
67
+ f"{list(strategies.keys())}"
68
+ )
69
+
70
+ def optimize(self, total_budget: int = 500, top_k: int = 10) -> List[ModelGraph]:
71
+ """
72
+ Run portfolio optimization.
73
+
74
+ Args:
75
+ total_budget: Total evaluation budget
76
+ top_k: Number of best architectures to return
77
+
78
+ Returns:
79
+ List of best architectures across all strategies
80
+ """
81
+ logger.info(f"Starting portfolio optimization with budget={total_budget}")
82
+
83
+ # Allocate budget
84
+ budgets = self._allocate_budget(total_budget)
85
+
86
+ logger.info(f"Budget allocation: {budgets}")
87
+
88
+ # Run strategies
89
+ if self.parallel:
90
+ all_results = self._run_parallel(budgets)
91
+ else:
92
+ all_results = self._run_sequential(budgets)
93
+
94
+ # Combine and sort
95
+ combined = []
96
+ for _strategy, results in all_results.items():
97
+ combined.extend(results)
98
+
99
+ # Sort by fitness
100
+ combined.sort(key=lambda x: x[1], reverse=True)
101
+
102
+ # Extract top-k architectures
103
+ best_architectures = [arch for arch, _ in combined[:top_k]]
104
+
105
+ logger.info(f"Portfolio optimization complete! " f"Best fitness: {combined[0][1]:.4f}")
106
+
107
+ return best_architectures
108
+
109
+ def _allocate_budget(self, total_budget: int) -> Dict[str, int]:
110
+ """
111
+ Allocate budget across strategies.
112
+
113
+ Args:
114
+ total_budget: Total budget
115
+
116
+ Returns:
117
+ Dict mapping strategy to allocated budget
118
+ """
119
+ budgets = {}
120
+
121
+ if self.budget_allocation == "equal":
122
+ # Equal allocation
123
+ budget_per_strategy = total_budget // len(self.strategies)
124
+ for strategy in self.strategies:
125
+ budgets[strategy] = budget_per_strategy
126
+
127
+ elif self.budget_allocation == "performance":
128
+ # Allocate based on past performance
129
+ # (simplified - would use historical data in practice)
130
+ budget_per_strategy = total_budget // len(self.strategies)
131
+ for strategy in self.strategies:
132
+ budgets[strategy] = budget_per_strategy
133
+
134
+ else:
135
+ raise ValueError(f"Unknown allocation: {self.budget_allocation}")
136
+
137
+ return budgets
138
+
139
+ def _run_sequential(self, budgets: Dict[str, int]) -> Dict[str, List[tuple]]:
140
+ """Run strategies sequentially."""
141
+ all_results = {}
142
+
143
+ for strategy, budget in budgets.items():
144
+ logger.info(f"Running {strategy} with budget {budget}")
145
+
146
+ results = self._run_strategy(strategy, budget)
147
+ all_results[strategy] = results
148
+
149
+ best_fitness = max(f for _, f in results) if results else 0.0
150
+ logger.info(
151
+ f"{strategy} complete: {len(results)} evaluations, " f"best={best_fitness:.4f}"
152
+ )
153
+
154
+ return all_results
155
+
156
+ def _run_parallel(self, budgets: Dict[str, int]) -> Dict[str, List[tuple]]:
157
+ """Run strategies in parallel."""
158
+ all_results = {}
159
+
160
+ with ThreadPoolExecutor(max_workers=len(self.strategies)) as executor:
161
+ # Submit all strategies
162
+ futures = {
163
+ executor.submit(self._run_strategy, strategy, budget): strategy
164
+ for strategy, budget in budgets.items()
165
+ }
166
+
167
+ # Collect results
168
+ for future in as_completed(futures):
169
+ strategy = futures[future]
170
+ try:
171
+ results = future.result()
172
+ all_results[strategy] = results
173
+
174
+ best_fitness = max(f for _, f in results) if results else 0.0
175
+ logger.info(
176
+ f"{strategy} complete: {len(results)} evaluations, "
177
+ f"best={best_fitness:.4f}"
178
+ )
179
+ except Exception as e:
180
+ logger.error(f"{strategy} failed: {e}")
181
+ all_results[strategy] = []
182
+
183
+ return all_results
184
+
185
+ def _run_strategy(self, strategy: str, budget: int) -> List[tuple]:
186
+ """
187
+ Run a single strategy.
188
+
189
+ Args:
190
+ strategy: Strategy name
191
+ budget: Evaluation budget
192
+
193
+ Returns:
194
+ List of (architecture, fitness) tuples
195
+ """
196
+ results = []
197
+ config = self.strategies[strategy]
198
+
199
+ if strategy == "random":
200
+ # Random search
201
+ for _ in range(budget):
202
+ arch = self.search_space.sample()
203
+ fitness = self.evaluator(arch)
204
+ results.append((arch, fitness))
205
+
206
+ elif strategy in ["ga", "genetic"]:
207
+ # Genetic algorithm
208
+ from morphml.optimizers import GeneticAlgorithm
209
+
210
+ pop_size = config.get("population_size", 20)
211
+ num_gen = budget // pop_size
212
+
213
+ ga = GeneticAlgorithm(
214
+ search_space=self.search_space,
215
+ evaluator=self.evaluator,
216
+ population_size=pop_size,
217
+ num_generations=num_gen,
218
+ )
219
+
220
+ ga.search()
221
+ results = [(ind.architecture, ind.fitness) for ind in ga.history]
222
+
223
+ else:
224
+ # Fallback to random
225
+ for _ in range(budget):
226
+ arch = self.search_space.sample()
227
+ fitness = self.evaluator(arch)
228
+ results.append((arch, fitness))
229
+
230
+ return results