diff --git a/RATapi/inputs.py b/RATapi/inputs.py index 07dc7087..49e7b0aa 100644 --- a/RATapi/inputs.py +++ b/RATapi/inputs.py @@ -451,7 +451,7 @@ def make_controls(input_controls: RATapi.Controls, checks: Checks) -> Control: controls.populationSize = input_controls.populationSize controls.fWeight = input_controls.fWeight controls.crossoverProbability = input_controls.crossoverProbability - controls.strategy = input_controls.strategy.value # Required for the IntEnum + controls.strategy = int(input_controls.strategy) # RAT core expects strategy as an integer controls.targetValue = input_controls.targetValue controls.numGenerations = input_controls.numGenerations # NS diff --git a/RATapi/utils/enums.py b/RATapi/utils/enums.py index 26eea4a9..dcefd3e2 100644 --- a/RATapi/utils/enums.py +++ b/RATapi/utils/enums.py @@ -1,4 +1,4 @@ -from enum import Enum +from typing import Union try: from enum import StrEnum @@ -48,15 +48,28 @@ class Display(RATEnum): Final = "final" -class Strategies(Enum): - """Defines the available options for strategies""" +class Strategies(RATEnum): + """Defines the available options for differential evolution strategies""" - Random = 1 - LocalToBest = 2 - BestWithJitter = 3 - RandomWithPerVectorDither = 4 - RandomWithPerGenerationDither = 5 - RandomEitherOrAlgorithm = 6 + Random = "random" + LocalToBest = "local to best" + BestWithJitter = "best jitter" + RandomWithPerVectorDither = "vector dither" + RandomWithPerGenerationDither = "generation dither" + RandomEitherOrAlgorithm = "either or" + + @classmethod + def _missing_(cls, value: Union[int, str]): + # legacy compatibility with strategies being 1-indexed ints under the hood + if isinstance(value, int): + if value < 1 or value > 6: + raise IndexError("Strategy indices must be between 1 and 6.") + return list(cls)[value - 1] + return super()._missing_(value) + + def __int__(self): + # as RAT core expects strategy as an integer + return list(Strategies).index(self) + 1 class BoundHandling(RATEnum): diff --git a/tests/test_controls.py b/tests/test_controls.py index b0c33a24..391d2e35 100644 --- a/tests/test_controls.py +++ b/tests/test_controls.py @@ -374,23 +374,23 @@ def setup_class(self): @pytest.fixture def table_str(self): table_str = ( - "+----------------------+--------------------------------------+\n" - "| Property | Value |\n" - "+----------------------+--------------------------------------+\n" - "| procedure | de |\n" - "| parallel | single |\n" - "| calcSldDuringFit | False |\n" - "| resampleParams | [0.9, 50] |\n" - "| display | iter |\n" - "| populationSize | 20 |\n" - "| fWeight | 0.5 |\n" - "| crossoverProbability | 0.8 |\n" - "| strategy | Strategies.RandomWithPerVectorDither |\n" - "| targetValue | 1.0 |\n" - "| numGenerations | 500 |\n" - "| updateFreq | 1 |\n" - "| updatePlotFreq | 20 |\n" - "+----------------------+--------------------------------------+" + "+----------------------+---------------+\n" + "| Property | Value |\n" + "+----------------------+---------------+\n" + "| procedure | de |\n" + "| parallel | single |\n" + "| calcSldDuringFit | False |\n" + "| resampleParams | [0.9, 50] |\n" + "| display | iter |\n" + "| populationSize | 20 |\n" + "| fWeight | 0.5 |\n" + "| crossoverProbability | 0.8 |\n" + "| strategy | vector dither |\n" + "| targetValue | 1.0 |\n" + "| numGenerations | 500 |\n" + "| updateFreq | 1 |\n" + "| updatePlotFreq | 20 |\n" + "+----------------------+---------------+" ) return table_str diff --git a/tests/test_enums.py b/tests/test_enums.py index 0b3911ae..fe885e31 100644 --- a/tests/test_enums.py +++ b/tests/test_enums.py @@ -17,6 +17,7 @@ Priors, Procedures, RATEnum, + Strategies, TypeOptions, ) @@ -98,3 +99,8 @@ def test_alternative_spellings(test_enum: Callable, test_str: str, expected_valu assert test_enum(test_str) == expected_value assert test_enum(test_str.upper()) == expected_value assert test_enum(test_str.title()) == expected_value + + +def test_integer_strategies(): + """Test that strategies can be input as integers.""" + assert [Strategies(i) for i in range(1, len(Strategies) + 1)] == list(Strategies)