From 56fe9e512019d90a5647f4a244ffb8b6f6ff9c47 Mon Sep 17 00:00:00 2001 From: Vratko Polak Date: Mon, 30 Jul 2018 17:48:50 +0200 Subject: [PATCH] CSIT-1222: Do two doublings in external MLRsearch 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 --- PyPI/MLRsearch/setup.py | 2 +- .../libraries/python/MLRsearch/AbstractMeasurer.py | 2 +- .../python/MLRsearch/AbstractSearchAlgorithm.py | 4 +- .../python/MLRsearch/MultipleLossRatioSearch.py | 67 ++++++++++++++++++---- .../libraries/python/MLRsearch/NdrPdrResult.py | 4 +- .../python/MLRsearch/ReceiveRateInterval.py | 4 +- resources/libraries/python/TrafficGenerator.py | 9 ++- .../robot/performance/performance_utils.robot | 6 +- 8 files changed, 75 insertions(+), 23 deletions(-) diff --git a/PyPI/MLRsearch/setup.py b/PyPI/MLRsearch/setup.py index 2411f4765a..a40f6c6634 100644 --- a/PyPI/MLRsearch/setup.py +++ b/PyPI/MLRsearch/setup.py @@ -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", diff --git a/resources/libraries/python/MLRsearch/AbstractMeasurer.py b/resources/libraries/python/MLRsearch/AbstractMeasurer.py index b972c4eb18..c9b5987124 100644 --- a/resources/libraries/python/MLRsearch/AbstractMeasurer.py +++ b/resources/libraries/python/MLRsearch/AbstractMeasurer.py @@ -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 diff --git a/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py b/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py index 538322a42c..08f8b7e0a9 100644 --- a/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py +++ b/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py @@ -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 diff --git a/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py b/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py index 0eb1d7da4c..be7ffba3a3 100644 --- a/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py +++ b/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py @@ -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 diff --git a/resources/libraries/python/MLRsearch/NdrPdrResult.py b/resources/libraries/python/MLRsearch/NdrPdrResult.py index b69a57ecbe..80df0ef333 100644 --- a/resources/libraries/python/MLRsearch/NdrPdrResult.py +++ b/resources/libraries/python/MLRsearch/NdrPdrResult.py @@ -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? diff --git a/resources/libraries/python/MLRsearch/ReceiveRateInterval.py b/resources/libraries/python/MLRsearch/ReceiveRateInterval.py index 05e0f10013..6dff1b8a7a 100644 --- a/resources/libraries/python/MLRsearch/ReceiveRateInterval.py +++ b/resources/libraries/python/MLRsearch/ReceiveRateInterval.py @@ -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? diff --git a/resources/libraries/python/TrafficGenerator.py b/resources/libraries/python/TrafficGenerator.py index 8acf1eb28b..1398072ce1 100644 --- a/resources/libraries/python/TrafficGenerator.py +++ b/resources/libraries/python/TrafficGenerator.py @@ -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 diff --git a/resources/libraries/robot/performance/performance_utils.robot b/resources/libraries/robot/performance/performance_utils.robot index 1935337445..80aaa1dc2c 100644 --- a/resources/libraries/robot/performance/performance_utils.robot +++ b/resources/libraries/robot/performance/performance_utils.robot @@ -469,25 +469,27 @@ | | ... | - 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} -- 2.16.6