CSIT-1222: Do two doublings in external MLRsearch 11/13811/8
authorVratko Polak <vrpolak@cisco.com>
Mon, 30 Jul 2018 15:48:50 +0000 (17:48 +0200)
committerPeter Mikus <pmikus@cisco.com>
Wed, 22 Aug 2018 06:40:35 +0000 (06:40 +0000)
Make number of doublings configurable,
keep Python default at 1, set Robot default to 2.

Also make docstring types unique
(pylint was complaining about classes and modules having the same name).

Increase MLRsearch version to 0.2.0.

Change-Id: Ib846032e79ff52994503c0cfef2f86655502c275
Signed-off-by: Vratko Polak <vrpolak@cisco.com>
PyPI/MLRsearch/setup.py
resources/libraries/python/MLRsearch/AbstractMeasurer.py
resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py
resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py
resources/libraries/python/MLRsearch/NdrPdrResult.py
resources/libraries/python/MLRsearch/ReceiveRateInterval.py
resources/libraries/python/TrafficGenerator.py
resources/libraries/robot/performance/performance_utils.robot

index 2411f47..a40f6c6 100644 (file)
@@ -14,7 +14,7 @@ with open(path.join(here, "README.rst"), encoding="utf-8") as f:
 
 setup(
     name="MLRsearch",
-    version="0.1.1",  # This is currently the only place listing the version.
+    version="0.2.0",  # This is currently the only place listing the version.
     description="Library for speeding up binary search using shorter measurements.",
     long_description=long_description,
     long_description_content_type="text/x-rst",
index b972c4e..c9b5987 100644 (file)
@@ -30,6 +30,6 @@ class AbstractMeasurer(object):
         :type duration: float
         :type transmit_rate: float
         :returns: Structure containing the result of the measurement.
-        :rtype: ReceiveRateMeasurement
+        :rtype: ReceiveRateMeasurement.ReceiveRateMeasurement
         """
         pass
index 538322a..08f8b7e 100644 (file)
@@ -25,7 +25,7 @@ class AbstractSearchAlgorithm(object):
         """Store the rate provider.
 
         :param measurer: Object able to perform trial or composite measurements.
-        :type measurer: AbstractMeasurer
+        :type measurer: AbstractMeasurer.AbstractMeasurer
         """
         # TODO: Type check for AbstractMeasurer?
         self.measurer = measurer
@@ -45,7 +45,7 @@ class AbstractSearchAlgorithm(object):
         :type packet_loss_ratio: float
         :returns: Structure containing narrowed down intervals
             and their measurements.
-        :rtype: NdrPdrResult
+        :rtype: NdrPdrResult.NdrPdrResult
         """
         # TODO: Do we agree on arguments related to precision or trial duration?
         pass
index 0eb1d7d..be7ffba 100644 (file)
@@ -97,7 +97,7 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
                 for the current search [pps].
             :param maximum_transmit_rate: Maximum target transmit rate
                 for the current search [pps].
-            :type result: NdrPdrResult
+            :type result: NdrPdrResult.NdrPdrResult
             :type phases: int
             :type duration: float
             :type width_goal: float
@@ -115,7 +115,7 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
 
     def __init__(self, measurer, final_relative_width=0.005,
                  final_trial_duration=30.0, initial_trial_duration=1.0,
-                 number_of_intermediate_phases=2, timeout=600.0):
+                 number_of_intermediate_phases=2, timeout=600.0, doublings=1):
         """Store the measurer object and additional arguments.
 
         :param measurer: Rate provider to use by this search object.
@@ -128,12 +128,16 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
             to perform before the final phase [1].
         :param timeout: The search will fail itself when not finished
             before this overall time [s].
-        :type measurer: AbstractMeasurer
+        :param doublings: How many doublings to do in external search step.
+            Default 1 is suitable for fairly stable tests,
+            less stable tests might get better overal duration with 2 or more.
+        :type measurer: AbstractMeasurer.AbstractMeasurer
         :type final_relative_width: float
         :type final_trial_duration: float
         :type initial_trial_duration: int
         :type number_of_intermediate_phases: int
         :type timeout: float
+        :type doublings: int
         """
         super(MultipleLossRatioSearch, self).__init__(measurer)
         self.final_trial_duration = float(final_trial_duration)
@@ -141,6 +145,7 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
         self.number_of_intermediate_phases = int(number_of_intermediate_phases)
         self.initial_trial_duration = float(initial_trial_duration)
         self.timeout = float(timeout)
+        self.doublings = int(doublings)
 
 
     @staticmethod
@@ -171,6 +176,24 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
             1.0 - MultipleLossRatioSearch.double_relative_width(
                 relative_width))
 
+    @staticmethod
+    def expand_down(relative_width, doublings, current_bound):
+        """Return rate of expanded logarithmic width below.
+
+        :param relative_width: The base relative width to double.
+        :param doublings: How many doublings to do for expansion.
+        :param current_bound: The current target transmit rate to move [pps].
+        :type relative_width: float
+        :type doublings: int
+        :type current_bound: float
+        :returns: Transmit rate smaller by logarithmically double width [pps].
+        :rtype: float
+        """
+        for _ in range(doublings):
+            relative_width = MultipleLossRatioSearch.double_relative_width(
+                relative_width)
+        return current_bound * (1.0 - relative_width)
+
     @staticmethod
     def double_step_up(relative_width, current_bound):
         """Return rate of double logarithmic width above.
@@ -186,6 +209,24 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
             1.0 - MultipleLossRatioSearch.double_relative_width(
                 relative_width))
 
+    @staticmethod
+    def expand_up(relative_width, doublings, current_bound):
+        """Return rate of expanded logarithmic width above.
+
+        :param relative_width: The base relative width to double.
+        :param doublings: How many doublings to do for expansion.
+        :param current_bound: The current target transmit rate to move [pps].
+        :type relative_width: float
+        :type doublings: int
+        :type current_bound: float
+        :returns: Transmit rate smaller by logarithmically double width [pps].
+        :rtype: float
+        """
+        for _ in range(doublings):
+            relative_width = MultipleLossRatioSearch.double_relative_width(
+                relative_width)
+        return current_bound / (1.0 - relative_width)
+
     @staticmethod
     def half_relative_width(relative_width):
         """Return relative width corresponding to half logarithmic width.
@@ -224,7 +265,7 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
         :type packet_loss_ratio: float
         :returns: Structure containing narrowed down intervals
             and their measurements.
-        :rtype: NdrPdrResult
+        :rtype: NdrPdrResult.NdrPdrResult
         :raises RuntimeError: If total duration is larger than timeout.
         """
         minimum_transmit_rate = float(minimum_transmit_rate)
@@ -296,11 +337,11 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
         :param old_interval: The current interval before the measurement.
         :param measurement: The new meaqsurement to take into account.
         :param packet_loss_ratio: Fraction for PDR (or zero for NDR).
-        :type old_interval: ReceiveRateInterval
-        :type measurement: ReceiveRateMeasurement
+        :type old_interval: ReceiveRateInterval.ReceiveRateInterval
+        :type measurement: ReceiveRateMeasurement.ReceiveRateMeasurement
         :type packet_loss_ratio: float
         :returns: The updated interval.
-        :rtype: ReceiveRateInterval
+        :rtype: ReceiveRateInterval.ReceiveRateInterval
         """
         old_lo, old_hi = old_interval.measured_low, old_interval.measured_high
         # Priority zero: direct replace if the target Tr is the same.
@@ -399,7 +440,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
                 if ndr_lo.target_tr > state.minimum_transmit_rate:
                     new_tr = max(
                         state.minimum_transmit_rate,
-                        self.double_step_down(ndr_rel_width, ndr_lo.target_tr))
+                        self.expand_down(
+                            ndr_rel_width, self.doublings, ndr_lo.target_tr))
                     logging.info("ndr lo external %s", new_tr)
                     state = self._measure_and_update_state(state, new_tr)
                     continue
@@ -412,7 +454,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
                 if pdr_lo.target_tr > state.minimum_transmit_rate:
                     new_tr = max(
                         state.minimum_transmit_rate,
-                        self.double_step_down(pdr_rel_width, pdr_lo.target_tr))
+                        self.expand_down(
+                            pdr_rel_width, self.doublings, pdr_lo.target_tr))
                     logging.info("pdr lo external %s", new_tr)
                     state = self._measure_and_update_state(state, new_tr)
                     continue
@@ -425,7 +468,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
                 if ndr_hi.target_tr < state.maximum_transmit_rate:
                     new_tr = min(
                         state.maximum_transmit_rate,
-                        self.double_step_up(ndr_rel_width, ndr_hi.target_tr))
+                        self.expand_up(
+                            ndr_rel_width, self.doublings, ndr_hi.target_tr))
                     logging.info("ndr hi external %s", new_tr)
                     state = self._measure_and_update_state(state, new_tr)
                     continue
@@ -438,7 +482,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm):
                 if pdr_hi.target_tr < state.maximum_transmit_rate:
                     new_tr = min(
                         state.maximum_transmit_rate,
-                        self.double_step_up(pdr_rel_width, pdr_hi.target_tr))
+                        self.expand_up(
+                            pdr_rel_width, self.doublings, pdr_hi.target_tr))
                     logging.info("pdr hi external %s", new_tr)
                     state = self._measure_and_update_state(state, new_tr)
                     continue
index b69a57e..80df0ef 100644 (file)
@@ -27,8 +27,8 @@ class NdrPdrResult(object):
 
         :param ndr_interval: Object containing data for NDR part of the result.
         :param pdr_interval: Object containing data for PDR part of the result.
-        :type ndr_interval: ReceiveRateInterval
-        :type pdr_interval: ReceiveRateInterval
+        :type ndr_interval: ReceiveRateInterval.ReceiveRateInterval
+        :type pdr_interval: ReceiveRateInterval.ReceiveRateInterval
         """
         # TODO: Type checking is not very pythonic,
         # perhaps users can fix wrong usage without it?
index 05e0f10..6dff1b8 100644 (file)
@@ -26,8 +26,8 @@ class ReceiveRateInterval(object):
 
         :param measured_low: Measurement for the lower bound.
         :param measured_high: Measurement for the upper bound.
-        :type measured_low: ReceiveRateMeasurement
-        :type measured_high: ReceiveRateMeasurement
+        :type measured_low: ReceiveRateMeasurement.ReceiveRateMeasurement
+        :type measured_high: ReceiveRateMeasurement.ReceiveRateMeasurement
         """
         # TODO: Type checking is not very pythonic,
         # perhaps users can fix wrong usage without it?
index 8acf1eb..1398072 100644 (file)
@@ -613,7 +613,7 @@ class OptimizedSearch(object):
             maximum_transmit_rate, packet_loss_ratio=0.005,
             final_relative_width=0.005, final_trial_duration=30.0,
             initial_trial_duration=1.0, number_of_intermediate_phases=2,
-            timeout=720.0):
+            timeout=720.0, doublings=1):
         """Setup initialized TG, perform optimized search, return intervals.
 
         :param frame_size: Frame size identifier or value [B].
@@ -633,6 +633,9 @@ class OptimizedSearch(object):
             to perform before the final phase [1].
         :param timeout: The search will fail itself when not finished
             before this overall time [s].
+        :param doublings: How many doublings to do in external search step.
+            Default 1 is suitable for fairly stable tests,
+            less stable tests might get better overal duration with 2 or more.
         :type frame_size: str or int
         :type traffic_type: str
         :type minimum_transmit_rate: float
@@ -643,6 +646,7 @@ class OptimizedSearch(object):
         :type initial_trial_duration: float
         :type number_of_intermediate_phases: int
         :type timeout: float
+        :type doublings: int
         :returns: Structure containing narrowed down NDR and PDR intervals
             and their measurements.
         :rtype: NdrPdrResult
@@ -657,7 +661,8 @@ class OptimizedSearch(object):
             measurer=tg_instance, final_trial_duration=final_trial_duration,
             final_relative_width=final_relative_width,
             number_of_intermediate_phases=number_of_intermediate_phases,
-            initial_trial_duration=initial_trial_duration, timeout=timeout)
+            initial_trial_duration=initial_trial_duration, timeout=timeout,
+            doublings=doublings)
         result = algorithm.narrow_down_ndr_and_pdr(
             minimum_transmit_rate, maximum_transmit_rate, packet_loss_ratio)
         return result
index 1935337..80aaa1d 100644 (file)
 | | ... | - initial_trial_duration - Duration of initial trials [s]. Type: float
 | | ... | - intermediate phases - Number of intermediate phases [1]. Type: int
 | | ... | - timeout - Fail if search duration is longer [s]. Type: float
+| | ... | - doublings - How many doublings to do when expanding [1]. Type: int
 | | ...
 | | ... | *Example:*
 | | ...
 | | ... | \| Find NDR and PDR intervals using optimized search \| \${64} \| \
 | | ... | 3-node-IPv4 \| \${100000} \| \${14880952} \| \${0.005} \| \${0.005} \
-| | ... | \| \${30.0} \| \${1.0} \| \${2} \| ${600.0} \|
+| | ... | \| \${30.0} \| \${1.0} \| \${2} \| ${600.0} \| ${2} \|
 | | ...
 | | [Arguments] | ${frame_size} | ${topology_type} | ${minimum_transmit_rate}
 | | ... | ${maximum_transmit_rate} | ${packet_loss_ratio}=${0.005}
 | | ... | ${final_relative_width}=${0.005} | ${final_trial_duration}=${30.0}
 | | ... | ${initial_trial_duration}=${1.0}
 | | ... | ${number_of_intermediate_phases}=${2} | ${timeout}=${720.0}
+| | ... | ${doublings}=${2}
 | | ...
 | | ${result} = | Perform optimized ndrpdr search | ${frame_size}
 | | ... | ${topology_type} | ${minimum_transmit_rate*2}
 | | ... | ${maximum_transmit_rate*2} | ${packet_loss_ratio}
 | | ... | ${final_relative_width} | ${final_trial_duration}
 | | ... | ${initial_trial_duration} | ${number_of_intermediate_phases}
-| | ... | timeout=${timeout}
+| | ... | timeout=${timeout} | doublings=${doublings}
 | | Display result of NDRPDR search | ${result} | ${frame_size}
 | | Check NDRPDR interval validity | ${result.pdr_interval}
 | | ... | ${packet_loss_ratio}