References¶
Parameter Classes¶
The package provides a collection of concrete parameter classes designed to wrap Python’s nominal types (int, float, str, and bool) and an extension to support UFloat types from the uncertainties package. These parameter classes are intended to serve as robust building blocks for systems implementing a parameterized version of the Strategy pattern. The purpose is to facilitate the validation and use of configurable parameters across different algorithms and strategies.
The parameter classes included offer features such as:
Initialization to None by default, unless a value is explicitly provided.
Methods to safely change the parameter values while maintaining internal consistency.
Extensive validation to reduce the chance of errors when using the parameters.
The guaranteed type of value, boundary checking (for numeric types), and accepted values checking (for string types).
- Classes:
IntParameter: Wraps an integer value with an optional min and max boundary. FloatParameter: Wraps a float value with an optional min and max boundary. StrParameter: Wraps a string value, with optional accepted values. BoolParameter: Wraps a boolean value. UFloatParameter: Wraps a UFloat (uncertain float) value, encapsulating numbers with uncertainties, whilst allowing optional min and max boundaries based on the nominal value.
Every parameter class have the ‘name’ attribute, which is used to identify the parameter. The ‘value’ attribute is used to store the value of the parameter. The optional default attribute is used to set the default value of the parameter. Each parameter class possess different properties, depending on the type of the parameter. They all possess a param_type attribute containing the type the parameter wraps.
The IntParameter, FloatParameter, and UFloatParameter classes have the optional ‘min’ and ‘max’ attributes, which are used to set the boundaries of the parameter. The StrParameter class has the optional accepted_values attribute, which is used to set the accepted values of the parameter.
Both the value. the defualt, and the other parameter attributes can be set set upos instantiation of the parameter class. However, only the value of the parameter should be changed after instantiation, using the set_value() method.
Class Diagram¶
classDiagram
class Parameter {
<<abstract>>
+String name
+get_value()
+set_value(value)
+param_type (Property)
}
class IntParameter {
-Optional[int] default
-Optional[int] min
-Optional[int] max
+set_value(value: Optional[int])
}
class FloatParameter {
-Optional[float] default
-Optional[float] min
-Optional[float] max
+set_value(value: Optional[float])
}
class StrParameter {
-Optional[str] default
-Optional[List[str]] accepted_values
+set_value(value: Optional[str])
}
class BoolParameter {
-Optional[bool] default
+set_value(value: Optional[bool])
}
class UFloatParameter {
-Optional[UFloat] default
-Optional[UFloat] min
-Optional[UFloat] max
+set_value(value: Optional[UFloat])
}
class IterableParameter {
-Optional[Iterable] default
-Optional[Iterable] accepted_values
+set_value(value: Optional[Iterable])
}
Parameter <|-- IntParameter
Parameter <|-- FloatParameter
Parameter <|-- StrParameter
Parameter <|-- BoolParameter
Parameter <|-- UFloatParameter
Parameter <|-- IterableParameter
Example Usage:
>>> from pumas.architecture.parameters import IntParameter
>>> int_param = IntParameter(name="IntParam", default=10, min=0, max=20)
>>> int_param.value
10
>>> int_param.set_value(15)
>>> int_param.value
15
>>> from uncertainties import ufloat
>>> from pumas.architecture.parameters import UFloatParameter
>>> ufloat_param = UFloatParameter(name="UFloatParam", default=ufloat(1, 0.1), min=ufloat(0, 0.1), max=ufloat(2, 0.1))
>>> ufloat_param.value.nominal_value
1.0
>>> ufloat_param.set_value(ufloat(1.5, 0.1))
>>> ufloat_param.value.nominal_value
1.5
The use of these parameter classes helps to enforce a consistent approach to handling parameters across different parts of an application.
Note
Instantiation of any parameter with a type that doesn’t match the expected will result in InvalidParameterTypeError.
Attempting to set values outside the range for IntParameter, FloatParameter, and UFloatParameter will result in InvalidBoundaryError.
Passing non-strings for a parameter name will result in InvalidParameterNameError.
Setting an unrecognized string value for StrParameter when accepted_values is defined will result in InvalidAcceptedValuesError.
Parameter Manager¶
The ParameterManager class is responsible for generatign Parameter objects from a function using its type hints. In addition to that the ParameterManager class is also responsible for updating the parameters attributes. This is necessary because, in our implementation the attributes of the parameters, are not supposed to be changed, with the nociable exception of the value attribute, that can be changed by the Parametert set_value() method. The ParameterManager class is thus responsible for updating the parameters attributes, by creating a new instance of the parameter class, initialized with the new attributes.
Example Usage:
>>> from pumas.architecture.parameters import ParameterManager
Initialize the ParameterManager with parameter definitions.
>>> param_defs = {
... "q": {"type": "int", "default": 5}
... }
>>> pm = ParameterManager(param_defs)
Check the initial state of the parameters managed by the ParameterManager. The expected output should show a dictionary containing representation of an IntParameter instance for ‘x’. In this case, the default value of ‘q’ is 5, and no boundaries are defined.
>>> pm.parameters_map
{'q': IntParameter(name='q', default=5, min=None, max=None)}
Check the current value of the parameter: it defaults to 5.
>>> pm.parameters_map['q'].value
5
>>> id_1 = id(pm.parameters_map['q'])
>>> pm.set_parameter_value('q', 10) # Set a new value for the parameter.
>>> pm.parameters_map['q'].value # Check the new value of the parameter.
10
>>> id_2 = id(pm.parameters_map['q'])
Changing the value of the parameter should not change the parameter instance. >>> id_1 == id_2 True