@@ -57,6 +57,26 @@ def get_minimum(self) -> int:
5757 """
5858 raise NotImplementedError
5959
60+ def encode_scalar (self , value : object ) -> float :
61+ """
62+ Encode a configuration value into a float for ML models.
63+
64+ This is used by surrogate-assisted algorithms to convert configurations
65+ into numerical vectors for prediction models.
66+
67+ Args:
68+ value: The configuration value to encode.
69+
70+ Returns:
71+ A float representing the encoded value.
72+ """
73+ # Default: convert to float if possible
74+ if not isinstance (value , (int , float , bool )):
75+ raise TypeError (
76+ f"Cannot encode { type (value ).__name__ } value { value !r} for ML"
77+ )
78+ return float (value )
79+
6080
6181@dataclasses .dataclass
6282class PermutationFragment (ConfigSpecFragment ):
@@ -121,6 +141,14 @@ def pattern_neighbors(self, current: object) -> list[object]:
121141 neighbors .append (upper )
122142 return neighbors
123143
144+ def encode_scalar (self , value : object ) -> float :
145+ """Encode integer values directly as floats."""
146+ if not isinstance (value , (int , float )):
147+ raise TypeError (
148+ f"Expected int/float for BaseIntegerFragment, got { type (value ).__name__ } : { value !r} "
149+ )
150+ return float (value )
151+
124152
125153class PowerOfTwoFragment (BaseIntegerFragment ):
126154 def random (self ) -> int :
@@ -152,6 +180,20 @@ def differential_mutation(self, a: object, b: object, c: object) -> int:
152180 return self .clamp (ai * 2 )
153181 return ai
154182
183+ def encode_scalar (self , value : object ) -> float :
184+ """Encode power-of-2 values using log2 transformation."""
185+ import math
186+
187+ if not isinstance (value , (int , float )):
188+ raise TypeError (
189+ f"Expected int/float for PowerOfTwoFragment, got { type (value ).__name__ } : { value !r} "
190+ )
191+ if value <= 0 :
192+ raise ValueError (
193+ f"Expected positive value for PowerOfTwoFragment, got { value } "
194+ )
195+ return math .log2 (float (value ))
196+
155197
156198class IntegerFragment (BaseIntegerFragment ):
157199 def random (self ) -> int :
@@ -193,6 +235,17 @@ def differential_mutation(self, a: object, b: object, c: object) -> object:
193235 choices .remove (a )
194236 return random .choice (choices )
195237
238+ def encode_scalar (self , value : object ) -> float :
239+ """Encode enum values as their index."""
240+ try :
241+ choice_idx = self .choices .index (value )
242+ except ValueError :
243+ raise ValueError (
244+ f"Invalid enum value { value !r} for EnumFragment. "
245+ f"Valid choices: { self .choices } "
246+ ) from None
247+ return float (choice_idx )
248+
196249
197250class BooleanFragment (ConfigSpecFragment ):
198251 def default (self ) -> bool :
0 commit comments