Source code for src.tools.algorithms
"""Algorithm type definitions for EngiOpt integration.
This is the SINGLE FILE to update when adding a new algorithm type:
1. Add to AlgorithmId Literal type
2. Add to SUPPORTED_ALGORITHMS mapping with properties
Everything else (algorithm lists, registries) is derived automatically.
"""
from typing import Literal, get_args
# Type alias for algorithm IDs - single source of truth for supported algorithms
AlgorithmId = Literal["cgan_cnn_2d", "diffusion_2d_cond"]
# Supported algorithms and their properties
SUPPORTED_ALGORITHMS = {
"cgan_cnn_2d": {
"class": "Inverse Design",
"dimensions": "2D",
"conditional": True,
"model": "GAN + CNN",
"model_types": ["generator", "discriminator"],
},
"diffusion_2d_cond": {
"class": "Inverse Design",
"dimensions": "2D",
"conditional": True,
"model": "Diffusion",
"model_types": ["model"],
},
}
# List of supported algorithm IDs - automatically derived from AlgorithmId
ALGORITHM_IDS = list(get_args(AlgorithmId))
[docs]
def canonical_algorithm(script_stem: str) -> str | None:
"""Map a candidate script's filename stem to its canonical engiopt algorithm.
``write_training_script`` versions candidate filenames
(``<algo>_candidate_<timestamp>_…``), so a stem is not itself a valid engiopt
algorithm id. The prompt instructs the agent to name candidates
``<algo>_candidate.py``, so the canonical id is the ``SUPPORTED_ALGORITHMS``
entry the stem starts with. Both ``validate_training_script`` (to pick the
contract/family) and ``generate_training_slurm`` (to pass ``--algo`` so the
trained wandb artifact is the canonical name ``evaluate_model`` downloads)
derive the algorithm this way, so the filename stem is the single source of
truth across the local + cluster halves of the workflow.
Returns ``None`` when no supported algorithm matches; callers decide whether
to fall back to a default or surface an actionable error.
"""
# Longest-first so a shorter id can't shadow a longer one that shares a prefix.
for algo in sorted(SUPPORTED_ALGORITHMS, key=len, reverse=True):
if script_stem == algo or script_stem.startswith(f"{algo}_"):
return algo
return None
# Export for use in other modules
__all__ = [
"ALGORITHM_IDS",
"SUPPORTED_ALGORITHMS",
"AlgorithmId",
"canonical_algorithm",
]