diff --git a/enstools/compression/analyzer/analyzer_utils.py b/enstools/compression/analyzer/analyzer_utils.py index a1c7870f3a67b8577d725fb762bc1e4ece4b0ed0..6fb53f69c3e4e7c873d70f42462ec3f621fae33f 100644 --- a/enstools/compression/analyzer/analyzer_utils.py +++ b/enstools/compression/analyzer/analyzer_utils.py @@ -150,6 +150,7 @@ def continuous_bisection_method(parameter_range: tuple, retry_repeated=5, threshold=0.1, direct_relation=True, + results=None, ): """ Recursively refine a parameter range by evaluating the parameter that lies in the middle of the range. @@ -170,8 +171,13 @@ def continuous_bisection_method(parameter_range: tuple, :param direct_relation: If True, the relation between the function and the parameter is direct, that is, increasing the parameter will increase the function value. If False, the relation is inverse, that is, increasing the parameter will decrease the function value. + :param results: A dictionary that stores the function values for each parameter that has been evaluated. + :return: The best value of the parameter that meets the exit conditions. """ + + if results is None: + results = {} # Get start and end from parameter range start, end = parameter_range @@ -186,24 +192,23 @@ def continuous_bisection_method(parameter_range: tuple, # TODO: use logging and a debug mode to print this kind of things logging.debug("start=%.2e,end=%.2e value_at_middle=%f", start, end, float(value_at_middle)) - # If the value at the middle is positive (all thresholds are fulfilled) we can return the parameter at the middle, - # otherwise select the safer one. - parameter_to_return = middle if value_at_middle > 0.0 else end + # Save result + results[middle] = value_at_middle # In case the accuracy exit condition is reached, return the parameter value at that point - if 0.0 <= value_at_middle < threshold: - return parameter_to_return + if 0.0 <= value_at_middle < threshold or depth >= max_depth or\ + (value_at_middle == last_value and retry_repeated == 0): + positive_results = {k: v for k,v in results.items() if v > 0} + if positive_results: + return min(positive_results, key=positive_results.get) + else: + return middle + # If the value is the same that the last try, we can retry few times if value_at_middle == last_value: - if retry_repeated == 0: - return parameter_to_return retry_repeated -= 1 - # In case having reached the maximum depth, return the proper value - if depth >= max_depth: - return parameter_to_return - # # Otherwise, set new parameter range and call the function again if comparison(value_at_middle, direct_relation=direct_relation): new_start, new_end = start, middle @@ -218,6 +223,7 @@ def continuous_bisection_method(parameter_range: tuple, retry_repeated=retry_repeated, threshold=threshold, direct_relation=direct_relation, + results=results ) @@ -246,6 +252,7 @@ def discrete_bisection_method(parameters_list: list, :param threshold: The threshold for the method exit condition. :param direct_relation: Boolean indicating whether the relation between the parameter and the function value is direct or inverse. + :param results: A dictionary that stores the function values for each parameter that has been evaluated. :return: The parameter value that satisfies the constrain function.