class_docstr: Operations related to the Lagrangian.
  
  Parameters
  ----------
  X : {numpy.ndarray, pandas.DataFrame}
      the training features
  sensitive_features : {numpy.ndarray, pandas.Series, pandas.DataFrame, list}
      the sensitive features to use for constraints
  y : {numpy.ndarray, pandas.Series, pandas.DataFrame, list}
      the training labels
  estimator :
      the estimator to fit in every iteration of :meth:`best_h` using a
      :meth:`fit` method with arguments `X`, `y`, and `sample_weight`
  constraints : fairlearn.reductions.Moment
      Object describing the fairness constraints. This provides the reweighting
      and relabelling.
  objective : fairlearn.reductions.Moment
      Object describing the optimization objective. The default is :code:`ErrorRate()` for
      binary classification and :code:`MeanLoss(...)` for regression.
  B : float
      bound on the L1-norm of the lambda vector
  opt_lambda : bool
      indicates whether to optimize lambda during the calculation of the
      Lagrangian; optional with default value True
  sample_weight_name : str
      Name of the argument to `estimator.fit()` which supplies the sample weights
      (defaults to `sample_weight`)
docstr: Return the duality gap object for the given :math:`Q` and :math:`\hat{\lambda}`.
docstr_tok: ["Return","the","duality","gap","object","for","the","given",":","math",":","`","Q","`","and",":","math",":","`","\\hat","{","\\lambda","}","`","."]
code: def eval_gap(self, Q, lambda_hat, nu):
      r"""Return the duality gap object for the given :math:`Q` and :math:`\hat{\lambda}`."""
      L, L_high, gamma, error = self._eval(Q, lambda_hat)
      result = _GapResult(L, L, L_high, gamma, error)
      for mul in [1.0, 2.0, 5.0, 10.0]:
          _, h_hat_idx = self.best_h(mul * lambda_hat)
          logger.debug("%smul=%.0f", _INDENTATION, mul)
          L_low_mul, _, _, _ = self._eval(
              pd.Series({h_hat_idx: 1.0}), lambda_hat
          )
          if L_low_mul < result.L_low:
              result.L_low = L_low_mul
          if result.gap() > nu + _PRECISION:
              break
      return result
  
imports: import logging
  from time import time
  import numpy
  import pandas
  import scipy.optimize
  from sklearn import clone
  from sklearn.dummy import DummyClassifier
  from fairlearn.reductions._moments import ClassificationMoment
  from ._constants import _INDENTATION, _LINE, _PRECISION
label_desc: Use image node_id 3 for calling the _Lagrangian obj's underlying member method code with example usage: obj.eval_gap(Q, lambda_hat, nu) and returns: result