class_docstr: A classifier based on the threshold optimization approach.
  
  The classifier is obtained by applying group-specific thresholds to the
  provided estimator. The thresholds are chosen to optimize the provided
  performance objective subject to the provided fairness constraints.
  
  Read more in the :ref:`User Guide <postprocessing>`.
  
  Parameters
  ----------
  estimator : object
      A `scikit-learn compatible estimator
      <https://scikit-learn.org/stable/developers/develop.html#estimators>`_
      whose output is postprocessed.
  
  constraints : str, default='demographic_parity'
      Fairness constraints under which threshold optimization is performed.
      Possible inputs are:
  
          'demographic_parity', 'selection_rate_parity' (synonymous)
              match the selection rate across groups
  
          '{false,true}_{positive,negative}_rate_parity'
              match the named metric across groups
  
          'equalized_odds'
              match true positive and false positive rates across groups
  
  objective : str, default='accuracy_score'
      Performance objective under which threshold optimization is performed.
      Not all objectives are allowed for all types of constraints.
      Possible inputs are:
  
          'accuracy_score', 'balanced_accuracy_score'
              allowed for all constraint types
  
          'selection_rate', 'true_positive_rate', 'true_negative_rate',
              allowed for all constraint types except 'equalized_odds'
  
  grid_size : int, default=1000
      The values of the constraint metric are discretized according to the
      grid of the specified size over the interval [0,1] and the optimization
      is performed with respect to the constraints achieving those values. In
      case of 'equalized_odds' the constraint metric is the false positive
      rate.
  
  flip : bool, default=False
      If True, then allow flipping the decision if it improves the resulting
  
  prefit : bool, default=False
      If True, avoid refitting the given estimator. Note that when used with
      :func:`sklearn.model_selection.cross_val_score`,
      :class:`sklearn.model_selection.GridSearchCV`, this will result in an
      error. In that case, please use ``prefit=False``.
  
  predict_method : {'auto', 'predict_proba', 'decision_function', 'predict'            }, default='auto'
  
      Defines which method of the ``estimator`` is used to get the output
      values.
  
          'auto'
              use one of :code:`predict_proba`, :code:`decision_function`, or
              :code:`predict`, in that order.
  
          'predict_proba'
              use the second column from the output of :code:`predict_proba`.
              It is assumed that the second column represents the positive
              outcome.
  
          'decision_function'
              use the raw values given by the :code:`decision_function`.
  
          'predict'
              use the hard values reported by the :code:`predict` method if
              estimator is a classifier, and the regression values if
              estimator is a regressor. This is equivalent to what
              is done in :footcite:`hardt2016equality`.
  
      .. versionadded:: 0.7
          In previous versions only the ``predict`` method was used
          implicitly.
  
      .. versionchanged:: 0.7
          From version 0.7, 'predict' is deprecated as the default value and
          the default will change to 'auto' from v0.10.
  
  Notes
  -----
  The procedure is based on the algorithm of
  Hardt et al. :footcite:`hardt2016equality`.
  
  References
  ----------
  .. footbibliography::
  
  Examples
  --------
  >>> from fairlearn.postprocessing import ThresholdOptimizer
  >>> from sklearn.linear_model import LogisticRegression
  >>> X                  = [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
  >>> y                  = [ 1 ,  1 ,  1 ,  1 ,  0,   0 ,  1 ,  0 ,  0 ,  0 ]
  >>> sensitive_features = ["a", "b", "a", "a", "b", "a", "b", "b", "a", "b"]
  >>> unmitigated_lr = LogisticRegression().fit(X, y)
  >>> postprocess_est = ThresholdOptimizer(
  ...                    estimator=unmitigated_lr,
  ...                    constraints="false_negative_rate_parity",
  ...                    objective="balanced_accuracy_score",
  ...                    prefit=True,
  ...                    predict_method='predict_proba')
  >>> postprocess_est.fit(X, y, sensitive_features=sensitive_features)
  ThresholdOptimizer(constraints='false_negative_rate_parity',
                     estimator=LogisticRegression(),
                     objective='balanced_accuracy_score',
                     predict_method='predict_proba', prefit=True)
docstr: Calculate the objective value across all values of constraints.
  
  These calculations are made at different thresholds over the scores. Subsequently weighs
  each sensitive feature value's objective by the
  frequency of the sensitive feature value in the data. The maximum objective point is the
  selected solution, which is recreated by interpolating between two points on the convex
  hull of all solutions. Each sensitive feature value has its own predictor in the resulting
  postprocessed predictor, which requires the sensitive feature value as an input.
  
  This method assumes that sensitive_features, labels, and scores are non-empty data
  structures of equal length, and labels contains only binary labels 0 and 1.
  
  Parameters
  ----------
  sensitive_features : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
      Sensitive features to identify groups by
  labels : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
      the labels of the dataset
  scores : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
      the scores produced by a predictor's prediction
  
  Returns
  -------
  InterpolatedThresholder
      the postprocessed predictor.
docstr_tok: ["Calculate","the","objective","value","across","all","values","of","constraints",".","These","calculations","are","made","at","different","thresholds","over","the","scores",".","Subsequently","weighs","each","sensitive","feature","value","'s","objective","by","the","frequency","of","the","sensitive","feature","value","in","the","data",".","The","maximum","objective","point","is","the","selected","solution",",","which","is","recreated","by","interpolating","between","two","points","on","the","convex","hull","of","all","solutions",".","Each","sensitive","feature","value","has","its","own","predictor","in","the","resulting","postprocessed","predictor",",","which","requires","the","sensitive","feature","value","as","an","input",".","This","method","assumes","that","sensitive_features",",","labels",",","and","scores","are","non-empty","data","structures","of","equal","length",",","and","labels","contains","only","binary","labels","0","and","1",".","Parameters","--","--","--","--","--","sensitive_features",":","list",",","numpy.ndarray",",","pandas.DataFrame",",","or","pandas.Series","Sensitive","features","to","identify","groups","by","labels",":","list",",","numpy.ndarray",",","pandas.DataFrame",",","or","pandas.Series","the","labels","of","the","dataset","scores",":","list",",","numpy.ndarray",",","pandas.DataFrame",",","or","pandas.Series","the","scores","produced","by","a","predictor","'s","prediction","Returns","--","--","--","-","InterpolatedThresholder","the","postprocessed","predictor","."]
code: def _threshold_optimization_for_simple_constraints(
      self, sensitive_features, labels, scores
  ):
      """Calculate the objective value across all values of constraints.
  
      These calculations are made at different thresholds over the scores. Subsequently weighs
      each sensitive feature value's objective by the
      frequency of the sensitive feature value in the data. The maximum objective point is the
      selected solution, which is recreated by interpolating between two points on the convex
      hull of all solutions. Each sensitive feature value has its own predictor in the resulting
      postprocessed predictor, which requires the sensitive feature value as an input.
  
      This method assumes that sensitive_features, labels, and scores are non-empty data
      structures of equal length, and labels contains only binary labels 0 and 1.
  
      Parameters
      ----------
      sensitive_features : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
          Sensitive features to identify groups by
      labels : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
          the labels of the dataset
      scores : list, numpy.ndarray, pandas.DataFrame, or pandas.Series
          the scores produced by a predictor's prediction
  
      Returns
      -------
      InterpolatedThresholder
          the postprocessed predictor.
      """
      n = len(labels)
      self._tradeoff_curve = {}
      self._x_grid = np.linspace(0, 1, self.grid_size + 1)
      overall_tradeoff_curve = 0 * self._x_grid
  
      data_grouped_by_sensitive_feature = _reformat_and_group_data(
          sensitive_features, labels, scores
      )
  
      for (
          sensitive_feature_value,
          group,
      ) in data_grouped_by_sensitive_feature:
          # Determine probability of current sensitive feature group based on data.
          p_sensitive_feature_value = len(group) / n
  
          roc_convex_hull = _tradeoff_curve(
              group,
              sensitive_feature_value,
              flip=self.flip,
              x_metric=self.x_metric_,
              y_metric=self.y_metric_,
          )
  
          self._tradeoff_curve[
              sensitive_feature_value
          ] = _interpolate_curve(
              roc_convex_hull, "x", "y", "operation", self._x_grid
          )
  
          # Add up objective for the current group multiplied by the probability of the current
          # group. This will help us in identifying the maximum overall objective.
          overall_tradeoff_curve += (
              p_sensitive_feature_value
              * self._tradeoff_curve[sensitive_feature_value]["y"]
          )
  
          logger.debug(OUTPUT_SEPARATOR)
          logger.debug("Processing %s", str(sensitive_feature_value))
          logger.debug(OUTPUT_SEPARATOR)
          logger.debug("DATA")
          logger.debug(group)
          logger.debug("Tradeoff curve")
          logger.debug(roc_convex_hull)
  
      # Find maximum objective point given that at each point the constraint value for each
      # sensitive feature value is identical by design.
      i_best = overall_tradeoff_curve.idxmax()
      self._x_best = self._x_grid[i_best]
  
      # Create the solution as interpolation of multiple points with a separate
      # interpolation per sensitive feature value.
      interpolation_dict = {}
      for sensitive_feature_value in self._tradeoff_curve.keys():
          best_interpolation = self._tradeoff_curve[
              sensitive_feature_value
          ].transpose()[i_best]
          interpolation_dict[sensitive_feature_value] = Bunch(
              p0=best_interpolation.p0,
              operation0=best_interpolation.operation0,
              p1=best_interpolation.p1,
              operation1=best_interpolation.operation1,
          )
  
      logger.debug(OUTPUT_SEPARATOR)
      logger.debug("From tradeoff curves")
      logger.debug(
          "Best point (simple constraints): %s=%.3f, %s=%.3f",
          self.y_metric_,
          overall_tradeoff_curve[i_best],
          self.x_metric_,
          self._x_best,
      )
      logger.debug(OUTPUT_SEPARATOR)
  
      return InterpolatedThresholder(
          self.estimator_,
          interpolation_dict,
          prefit=True,
          predict_method=self._predict_method,
      ).fit(None, None)
  
imports: import logging
  from warnings import warn
  import numpy
  import pandas
  from sklearn import clone
  from sklearn.base import BaseEstimator, MetaEstimatorMixin
  from sklearn.exceptions import NotFittedError
  from sklearn.utils import Bunch
  from sklearn.utils.validation import check_is_fitted
  from ..utils._common import _get_soft_predictions
  from ..utils._input_validation import _KW_CONTROL_FEATURES, _validate_and_reformat_input
  from ._constants import BASE_ESTIMATOR_NONE_ERROR_MESSAGE, BASE_ESTIMATOR_NOT_FITTED_WARNING, LABEL_KEY, OUTPUT_SEPARATOR, SCORE_KEY, SENSITIVE_FEATURE_KEY
  from ._interpolated_thresholder import InterpolatedThresholder
  from ._tradeoff_curve_utilities import METRIC_DICT, _extend_confusion_matrix, _interpolate_curve, _tradeoff_curve
label_desc: Use image node_id 5 for calling the ThresholdOptimizer obj's underlying member method code with example usage: obj._threshold_optimization_for_simple_constraints(sensitive_features, labels, scores) and returns: InterpolatedThresholder