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,392 @@
1
+ """Progress tracking utilities for optimization.
2
+
3
+ Provides rich progress bars and status displays for long-running NAS operations.
4
+
5
+ Example:
6
+ >>> from morphml.utils.progress import OptimizationProgress
7
+ >>>
8
+ >>> progress = OptimizationProgress(total_generations=100)
9
+ >>> for gen in range(100):
10
+ ... progress.update(gen, best_fitness=0.95, diversity=0.7)
11
+ """
12
+
13
+ from datetime import datetime, timedelta
14
+ from typing import Any, Dict, Optional
15
+
16
+ try:
17
+ from rich.console import Console
18
+ from rich.layout import Layout
19
+ from rich.live import Live
20
+ from rich.panel import Panel
21
+ from rich.progress import (
22
+ BarColumn,
23
+ Progress,
24
+ SpinnerColumn,
25
+ TaskProgressColumn,
26
+ TextColumn,
27
+ TimeRemainingColumn,
28
+ )
29
+ from rich.table import Table
30
+
31
+ RICH_AVAILABLE = True
32
+ except ImportError:
33
+ RICH_AVAILABLE = False
34
+
35
+ from morphml.logging_config import get_logger
36
+
37
+ logger = get_logger(__name__)
38
+
39
+
40
+ class OptimizationProgress:
41
+ """
42
+ Track and display optimization progress with rich formatting.
43
+
44
+ Attributes:
45
+ total_generations: Total number of generations
46
+ show_stats: Whether to show detailed statistics
47
+
48
+ Example:
49
+ >>> progress = OptimizationProgress(total_generations=50)
50
+ >>> progress.start()
51
+ >>> for gen in range(50):
52
+ ... progress.update(gen, best_fitness=0.9, diversity=0.5)
53
+ >>> progress.finish()
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ total_generations: int,
59
+ show_stats: bool = True,
60
+ refresh_rate: float = 0.5,
61
+ ):
62
+ """
63
+ Initialize progress tracker.
64
+
65
+ Args:
66
+ total_generations: Total number of generations
67
+ show_stats: Whether to show detailed statistics
68
+ refresh_rate: Update frequency in seconds
69
+ """
70
+ self.total_generations = total_generations
71
+ self.show_stats = show_stats
72
+ self.refresh_rate = refresh_rate
73
+
74
+ self.start_time = None
75
+ self.current_gen = 0
76
+ self.best_fitness = 0.0
77
+ self.history = []
78
+
79
+ if RICH_AVAILABLE:
80
+ self.console = Console()
81
+ self.progress = None
82
+ self.task_id = None
83
+ else:
84
+ logger.warning("Rich not available. Install with: pip install rich")
85
+ self.console = None
86
+
87
+ def start(self):
88
+ """Start progress tracking."""
89
+ self.start_time = datetime.now()
90
+
91
+ if RICH_AVAILABLE and self.console:
92
+ self.progress = Progress(
93
+ SpinnerColumn(),
94
+ TextColumn("[progress.description]{task.description}"),
95
+ BarColumn(),
96
+ TaskProgressColumn(),
97
+ TimeRemainingColumn(),
98
+ console=self.console,
99
+ )
100
+ self.progress.start()
101
+ self.task_id = self.progress.add_task(
102
+ "[cyan]Optimizing...", total=self.total_generations
103
+ )
104
+ else:
105
+ print(f"Starting optimization: {self.total_generations} generations")
106
+
107
+ def update(
108
+ self,
109
+ generation: int,
110
+ best_fitness: Optional[float] = None,
111
+ diversity: Optional[float] = None,
112
+ **kwargs,
113
+ ):
114
+ """
115
+ Update progress.
116
+
117
+ Args:
118
+ generation: Current generation number
119
+ best_fitness: Best fitness so far
120
+ diversity: Population diversity
121
+ **kwargs: Additional statistics
122
+ """
123
+ self.current_gen = generation
124
+
125
+ if best_fitness is not None:
126
+ self.best_fitness = best_fitness
127
+
128
+ # Track history
129
+ self.history.append(
130
+ {
131
+ "generation": generation,
132
+ "best_fitness": best_fitness,
133
+ "diversity": diversity,
134
+ **kwargs,
135
+ }
136
+ )
137
+
138
+ if RICH_AVAILABLE and self.progress:
139
+ # Update progress bar
140
+ self.progress.update(
141
+ self.task_id,
142
+ completed=generation + 1,
143
+ description=f"[cyan]Gen {generation+1}/{self.total_generations} | Best: {self.best_fitness:.4f}",
144
+ )
145
+ else:
146
+ # Simple text output
147
+ if generation % 10 == 0 or generation == self.total_generations - 1:
148
+ elapsed = (datetime.now() - self.start_time).total_seconds()
149
+ print(
150
+ f"Gen {generation+1}/{self.total_generations} | "
151
+ f"Best: {self.best_fitness:.4f} | "
152
+ f"Time: {elapsed:.1f}s"
153
+ )
154
+
155
+ def finish(self):
156
+ """Finish progress tracking and show summary."""
157
+ if RICH_AVAILABLE and self.progress:
158
+ self.progress.stop()
159
+ self._show_summary()
160
+ else:
161
+ elapsed = (datetime.now() - self.start_time).total_seconds()
162
+ print("\nOptimization complete!")
163
+ print(f"Total time: {elapsed:.2f}s")
164
+ print(f"Best fitness: {self.best_fitness:.4f}")
165
+
166
+ def _show_summary(self):
167
+ """Show optimization summary."""
168
+ if not RICH_AVAILABLE:
169
+ return
170
+
171
+ elapsed = datetime.now() - self.start_time
172
+
173
+ # Create summary table
174
+ table = Table(title="Optimization Summary", show_header=True)
175
+ table.add_column("Metric", style="cyan")
176
+ table.add_column("Value", style="green")
177
+
178
+ table.add_row("Total Generations", str(self.total_generations))
179
+ table.add_row("Best Fitness", f"{self.best_fitness:.6f}")
180
+ table.add_row("Total Time", str(elapsed).split(".")[0])
181
+ table.add_row(
182
+ "Time per Generation", f"{elapsed.total_seconds() / self.total_generations:.2f}s"
183
+ )
184
+
185
+ if self.history:
186
+ improvements = sum(
187
+ 1
188
+ for i in range(1, len(self.history))
189
+ if self.history[i].get("best_fitness", 0)
190
+ > self.history[i - 1].get("best_fitness", 0)
191
+ )
192
+ table.add_row("Improvements", str(improvements))
193
+
194
+ self.console.print(table)
195
+
196
+
197
+ class SimpleProgressBar:
198
+ """
199
+ Simple progress bar without rich dependency.
200
+
201
+ Example:
202
+ >>> bar = SimpleProgressBar(total=100, desc="Processing")
203
+ >>> for i in range(100):
204
+ ... bar.update(i)
205
+ >>> bar.finish()
206
+ """
207
+
208
+ def __init__(self, total: int, desc: str = "Progress", width: int = 50):
209
+ """
210
+ Initialize simple progress bar.
211
+
212
+ Args:
213
+ total: Total number of steps
214
+ desc: Description
215
+ width: Bar width in characters
216
+ """
217
+ self.total = total
218
+ self.desc = desc
219
+ self.width = width
220
+ self.current = 0
221
+ self.start_time = datetime.now()
222
+
223
+ def update(self, current: int):
224
+ """Update progress bar."""
225
+ self.current = current
226
+
227
+ # Calculate progress
228
+ progress = current / self.total
229
+ filled = int(self.width * progress)
230
+ bar = "█" * filled + "░" * (self.width - filled)
231
+
232
+ # Calculate time
233
+ elapsed = (datetime.now() - self.start_time).total_seconds()
234
+ if current > 0:
235
+ eta = elapsed * (self.total - current) / current
236
+ eta_str = str(timedelta(seconds=int(eta)))
237
+ else:
238
+ eta_str = "??:??:??"
239
+
240
+ # Print bar
241
+ print(
242
+ f"\r{self.desc}: |{bar}| {current}/{self.total} [{progress*100:.1f}%] ETA: {eta_str}",
243
+ end="",
244
+ flush=True,
245
+ )
246
+
247
+ def finish(self):
248
+ """Finish progress bar."""
249
+ elapsed = (datetime.now() - self.start_time).total_seconds()
250
+ print(f"\n{self.desc} complete! Time: {elapsed:.2f}s")
251
+
252
+
253
+ def create_progress_tracker(total_generations: int, use_rich: bool = True, **kwargs) -> Any:
254
+ """
255
+ Create appropriate progress tracker.
256
+
257
+ Args:
258
+ total_generations: Total number of generations
259
+ use_rich: Whether to use rich progress (if available)
260
+ **kwargs: Additional arguments
261
+
262
+ Returns:
263
+ Progress tracker instance
264
+
265
+ Example:
266
+ >>> tracker = create_progress_tracker(100)
267
+ >>> tracker.start()
268
+ >>> for i in range(100):
269
+ ... tracker.update(i, best_fitness=0.9)
270
+ >>> tracker.finish()
271
+ """
272
+ if use_rich and RICH_AVAILABLE:
273
+ return OptimizationProgress(total_generations, **kwargs)
274
+ else:
275
+ return SimpleProgressBar(total_generations, desc="Optimization", **kwargs)
276
+
277
+
278
+ class LiveDashboard:
279
+ """
280
+ Live dashboard for real-time optimization monitoring.
281
+
282
+ Shows multiple metrics in a live-updating display.
283
+
284
+ Example:
285
+ >>> dashboard = LiveDashboard()
286
+ >>> dashboard.start()
287
+ >>> for gen in range(100):
288
+ ... dashboard.update({
289
+ ... 'generation': gen,
290
+ ... 'best_fitness': 0.95,
291
+ ... 'diversity': 0.7,
292
+ ... 'crossover_rate': 0.8
293
+ ... })
294
+ >>> dashboard.stop()
295
+ """
296
+
297
+ def __init__(self):
298
+ """Initialize live dashboard."""
299
+ if not RICH_AVAILABLE:
300
+ logger.warning("Live dashboard requires rich. Install with: pip install rich")
301
+ self.enabled = False
302
+ return
303
+
304
+ self.enabled = True
305
+ self.console = Console()
306
+ self.live = None
307
+ self.layout = Layout()
308
+ self.stats = {}
309
+
310
+ def start(self):
311
+ """Start live dashboard."""
312
+ if not self.enabled:
313
+ return
314
+
315
+ self.layout.split_column(
316
+ Layout(name="header", size=3),
317
+ Layout(name="body"),
318
+ Layout(name="footer", size=3),
319
+ )
320
+
321
+ self.live = Live(self.layout, console=self.console, refresh_per_second=4)
322
+ self.live.start()
323
+
324
+ def update(self, stats: Dict[str, Any]):
325
+ """
326
+ Update dashboard with new statistics.
327
+
328
+ Args:
329
+ stats: Dictionary of statistics to display
330
+ """
331
+ if not self.enabled or not self.live:
332
+ return
333
+
334
+ self.stats.update(stats)
335
+
336
+ # Update header
337
+ self.layout["header"].update(
338
+ Panel("[bold cyan]MorphML Optimization Dashboard[/bold cyan]", style="cyan")
339
+ )
340
+
341
+ # Update body with stats table
342
+ table = Table(show_header=True, header_style="bold magenta")
343
+ table.add_column("Metric", style="cyan")
344
+ table.add_column("Value", style="green")
345
+
346
+ for key, value in self.stats.items():
347
+ if isinstance(value, float):
348
+ table.add_row(key.replace("_", " ").title(), f"{value:.4f}")
349
+ else:
350
+ table.add_row(key.replace("_", " ").title(), str(value))
351
+
352
+ self.layout["body"].update(table)
353
+
354
+ # Update footer
355
+ self.layout["footer"].update(Panel("[dim]Press Ctrl+C to stop[/dim]", style="dim"))
356
+
357
+ def stop(self):
358
+ """Stop live dashboard."""
359
+ if self.enabled and self.live:
360
+ self.live.stop()
361
+
362
+
363
+ # Convenience function
364
+ def with_progress(func):
365
+ """
366
+ Decorator to add progress tracking to optimization functions.
367
+
368
+ Example:
369
+ >>> @with_progress
370
+ ... def my_optimization(num_generations=100):
371
+ ... for gen in range(num_generations):
372
+ ... # optimization logic
373
+ ... yield gen, {"best_fitness": 0.9}
374
+ """
375
+
376
+ def wrapper(*args, **kwargs):
377
+ total = kwargs.get("num_generations", 100)
378
+ progress = create_progress_tracker(total)
379
+ progress.start()
380
+
381
+ try:
382
+ result = func(*args, **kwargs)
383
+ if hasattr(result, "__iter__"):
384
+ for gen, stats in result:
385
+ progress.update(gen, **stats)
386
+ return result
387
+ else:
388
+ return result
389
+ finally:
390
+ progress.finish()
391
+
392
+ return wrapper