diff options
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 @@ -172,6 +177,24 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): 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. @@ -187,6 +210,24 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): 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} |