aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python/MLRsearch/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libraries/python/MLRsearch/config.py')
-rw-r--r--resources/libraries/python/MLRsearch/config.py179
1 files changed, 179 insertions, 0 deletions
diff --git a/resources/libraries/python/MLRsearch/config.py b/resources/libraries/python/MLRsearch/config.py
new file mode 100644
index 0000000000..7aa8ed75a8
--- /dev/null
+++ b/resources/libraries/python/MLRsearch/config.py
@@ -0,0 +1,179 @@
+# Copyright (c) 2023 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Module defining Config class."""
+
+from collections.abc import Iterable
+from dataclasses import dataclass
+from typing import Optional
+
+from .dataclass import DataclassProperty
+from .search_goal import SearchGoal
+from .search_goal_tuple import SearchGoalTuple
+
+
+@dataclass
+class Config:
+ """Structure containing several static config items.
+
+ The main MLRsearch algorithm uses multiple customizable values.
+ Pylint complains if the values appear as long argument lists
+ or multiple local variables.
+
+ This class offers a storage for values which do not contain
+ internally mutable state and are set at an unknown time
+ before the search starts. This way users can override only some values,
+ and do it over multiple calls.
+ All "official" user inputs are contained here.
+
+ Properties are defined to enforce the requirements on allowed values.
+ All fields have default values, so instances can be created without any.
+ It is still recommended to set all values after instantiation,
+ as the defaults may change in the next version.
+
+ As some relations between values of different fields are required,
+ users must take care to set them in the correct order.
+
+ For example, min_load has to be set to a value smaller
+ than the current value of max_load.
+ """
+
+ # Externally visible "fields" (but in fact redefined as properties).
+ goals: SearchGoalTuple = SearchGoalTuple((SearchGoal(),))
+ """Container holding search goals."""
+ min_load: float = 9001.0
+ """Each trial measurement must have intended load at least this [tps]."""
+ max_load: float = 1e9
+ """Each trial measurement must have intended load at most this [tps]."""
+ search_duration_max: float = 1200.0
+ """The search will end as a failure this long [s] after it is started."""
+ warmup_duration: float = 1.0
+ """If specified, one trial at max load and this duration is performed
+ before the usual search starts. None converts to zero and means no warmup.
+ The results of that one trial are ignored."""
+
+ @DataclassProperty
+ def goals(self) -> SearchGoalTuple:
+ """Return the reference to the current container of goals.
+
+ :returns: The current container instance.
+ :rtype: SearchGoalTuple
+ """
+ return self._goals
+
+ @goals.setter
+ def goals(self, goals: Iterable[SearchGoal]) -> None:
+ """Create and store the goal container.
+
+ :param goals: Search goals to add to the container to store.
+ :type goals: Iterable[SearchGoal]
+ :raises ValueError: If there are no goals.
+ :raises TypeError: If any of the goals is not a SearchGoal.
+ """
+ self._goals = SearchGoalTuple(goals)
+
+ @DataclassProperty
+ def min_load(self) -> float:
+ """Getter for min load, no logic here.
+
+ :returns: Currently set minimal intended load [tps].
+ :rtype: float
+ """
+ return self._min_load
+
+ @min_load.setter
+ def min_load(self, load: float) -> None:
+ """Set min load after converting type and checking value.
+
+ :param load: Minimal intended load [tps] to set.
+ :type load: float
+ :raises ValueError: If the argument is found invalid.
+ """
+ load = float(load)
+ if load <= 0.0:
+ raise ValueError(f"Min load {load} must be positive.")
+ # At the time init is first called, _max_load is not set yet.
+ if hasattr(self, "_max_load") and load >= self.max_load:
+ raise ValueError(f"Min load {load} must be smaller.")
+ self._min_load = load
+
+ @DataclassProperty
+ def max_load(self) -> float:
+ """Getter for max load, no logic here.
+
+ :returns: Currently set maximal intended load [tps].
+ :rtype: float
+ """
+ return self._max_load
+
+ @max_load.setter
+ def max_load(self, load: float) -> None:
+ """Set max load after converting type and checking value.
+
+ :param load: Minimal intended load [tps] to set.
+ :type load: float
+ :raises ValueError: If the argument is found invalid.
+ """
+ load = float(load)
+ if load <= self.min_load:
+ raise ValueError(f"Max load {load} must be bigger.")
+ self._max_load = load
+
+ @DataclassProperty
+ def search_duration_max(self) -> float:
+ """Getter for max search duration, no logic here.
+
+ :returns: Currently set max search duration [s].
+ :rtype: float
+ """
+ return self._search_duration_max
+
+ @search_duration_max.setter
+ def search_duration_max(self, duration: float) -> None:
+ """Set max search duration after converting and checking value.
+
+ :param duration: Search duration maximum [s] to set.
+ :type duration: float
+ :raises ValueError: If the argument is found invalid.
+ """
+ duration = float(duration)
+ if duration <= 0.0:
+ raise ValueError(f"Search duration max too small: {duration}")
+ self._search_duration_max = duration
+
+ @DataclassProperty
+ def warmup_duration(self) -> float:
+ """Getter for warmup duration, no logic here.
+
+ :returns: Currently set max search duration [s].
+ :rtype: float
+ """
+ return self._warmup_duration
+
+ @warmup_duration.setter
+ def warmup_duration(self, duration: Optional[float]) -> None:
+ """Set warmup duration after converting and checking value.
+
+ Zero duration is treated as None, meaning no warmup trial.
+
+ :param duration: Warmup duration [s] to set.
+ :type duration: Optional(float)
+ :raises ValueError: If the argument is found invalid.
+ """
+ if duration:
+ duration = float(duration)
+ if duration < 0.0:
+ raise ValueError(f"Warmup duration too small: {duration}")
+ else:
+ duration = 0.0
+ self._warmup_duration = duration