class_docstr: A Global Stopping Strategy which recommends stopping optimization if there
  is no significant improvement over recent iterations.
  
  This stopping strategy recommends stopping if there is no significant improvement
  over the past `window_size` trials, among those that are feasible
  (satisfying constraints). The meaning of a "significant"
  improvement differs between single-objective and multi-objective optimizations.
  For single-objective optimizations, improvement is as a fraction of the
  interquartile range (IQR) of the objective values seen so far. For
  multi-objective optimizations (MOO), improvement is as a fraction of the hypervolume
  obtained `window_size` iterations ago.
docstr: This is the `_should_stop_optimization` method of this class,
  specialized to single-objective experiments.
  
  It computes the interquartile range (IQR) of feasible objective values
  found so far, then computes the improvement in the best seen over the
  last `window_size` trials. If the recent improvement as a fraction of
  the IQR is less than `self.improvement_bar`, it recommends stopping.
  
  Args:
      experiment: The experiment to apply the strategy on.
      trial_to_check: The trial in the experiment at which we want to check
          for stopping. If None, we check at the latest trial.
  
  Returns:
      A Tuple with a boolean determining whether the optimization should stop,
      and a str declaring the reason for stopping.
docstr_tok: ["This","is","the","`","_should_stop_optimization","`","method","of","this","class",",","specialized","to","single-objective","experiments",".","It","computes","the","interquartile","range","(","IQR",")","of","feasible","objective","values","found","so","far",",","then","computes","the","improvement","in","the","best","seen","over","the","last","`","window_size","`","trials",".","If","the","recent","improvement","as","a","fraction","of","the","IQR","is","less","than","`","self.improvement_bar","`",",","it","recommends","stopping",".","Args",":","experiment",":","The","experiment","to","apply","the","strategy","on",".","trial_to_check",":","The","trial","in","the","experiment","at","which","we","want","to","check","for","stopping",".","If","None",",","we","check","at","the","latest","trial",".","Returns",":","A","Tuple","with","a","boolean","determining","whether","the","optimization","should","stop",",","and","a","str","declaring","the","reason","for","stopping","."]
code: def _should_stop_single_objective(
      self, experiment: Experiment, trial_to_check: int
  ) -> Tuple[bool, str]:
      """
      This is the `_should_stop_optimization` method of this class,
      specialized to single-objective experiments.
  
      It computes the interquartile range (IQR) of feasible objective values
      found so far, then computes the improvement in the best seen over the
      last `window_size` trials. If the recent improvement as a fraction of
      the IQR is less than `self.improvement_bar`, it recommends stopping.
  
      Args:
          experiment: The experiment to apply the strategy on.
          trial_to_check: The trial in the experiment at which we want to check
              for stopping. If None, we check at the latest trial.
  
      Returns:
          A Tuple with a boolean determining whether the optimization should stop,
          and a str declaring the reason for stopping.
      """
      objectives = []
      is_feasible = []
      for trial in experiment.trials_by_status[TrialStatus.COMPLETED]:
          if trial.index <= trial_to_check:
              tr = checked_cast(Trial, trial)
              objectives.append(tr.objective_mean)
              is_feasible.append(constraint_satisfaction(tr))
  
      if checked_cast(
          OptimizationConfig, experiment.optimization_config
      ).objective.minimize:
          selector, mask_val = np.minimum, np.inf
      else:
          selector, mask_val = np.maximum, -np.inf
  
      # Replace objective value at infeasible iterations with mask_val
      masked_obj = np.where(is_feasible, objectives, mask_val)
      running_optimum = selector.accumulate(masked_obj)
  
      # Computing the interquartile for scaling the difference
      feasible_objectives = np.array(objectives)[is_feasible]
      if len(feasible_objectives) <= 1:
          message = "There are not enough feasible arms tried yet."
          return False, message
  
      q3, q1 = np.percentile(feasible_objectives, [75, 25])
      iqr = q3 - q1
  
      relative_improvement = np.abs(
          (running_optimum[-1] - running_optimum[-self.window_size])
          / iqr
      )
      stop = relative_improvement < self.improvement_bar
  
      if stop:
          message = (
              f"The improvement in best objective in the past {self.window_size} "
              f"trials (={relative_improvement:.3f}) is less than "
              f"{self.improvement_bar} times the interquartile range (IQR) of "
              f"objectives attained so far (IQR={iqr:.3f})."
          )
      else:
          message = ""
  
      return stop, message
  
imports: from logging import Logger
  from typing import Any, Dict, List, Optional, Tuple
  import numpy
  from ax.core.base_trial import BaseTrial, TrialStatus
  from ax.core.data import Data
  from ax.core.experiment import Experiment
  from ax.core.optimization_config import MultiObjectiveOptimizationConfig, OptimizationConfig
  from ax.core.outcome_constraint import ObjectiveThreshold
  from ax.core.trial import Trial
  from ax.core.types import ComparisonOp
  from ax.global_stopping.strategies.base import BaseGlobalStoppingStrategy
  from ax.modelbridge.modelbridge_utils import observed_hypervolume
  from ax.plot.pareto_utils import get_tensor_converter_model
  from ax.service.utils.best_point import fill_missing_thresholds_from_nadir
  from ax.utils.common.logger import get_logger
  from ax.utils.common.typeutils import checked_cast, not_none
label_desc: Use image node_id 4 for calling the ImprovementGlobalStoppingStrategy obj's underlying member method code with example usage: obj._should_stop_single_objective(experiment, trial_to_check) and returns: stop,  message, False,  message