docstr: Determines the stopping condition for gradient descent.
docstr_tok: ["Determines","the","stopping","condition","for","gradient","descent","."]
code: def stop_loop(self, itr, loss_diff):
      """Determines the stopping condition for gradient descent."""
  
      # intermediate projections
      if self.project_iter > 0 and itr > 0:
          if itr % self.project_iter == 0:
              self.round_off_cfs(assign=True)
  
      # do GD for min iterations
      if itr < self.min_iter:
          return False
  
      # stop GD if max iter is reached
      if itr >= self.max_iter:
          return True
  
      # else stop when loss diff is small & all CFs are valid (less or greater than a stopping threshold)
      if loss_diff <= self.loss_diff_thres:
          self.loss_converge_iter += 1
          if self.loss_converge_iter < self.loss_converge_maxiter:
              return False
          else:
              temp_cfs = self.round_off_cfs(assign=False)
              test_preds = [self.predict_fn(cf)[0] for cf in temp_cfs]
  
              if self.target_cf_class == 0 and all(
                  i <= self.stopping_threshold for i in test_preds
              ):
                  self.converged = True
                  return True
              elif self.target_cf_class == 1 and all(
                  i >= self.stopping_threshold for i in test_preds
              ):
                  self.converged = True
                  return True
              else:
                  return False
      else:
          self.loss_converge_iter = 0
          return False
  
imports: import copy
  import random
  import timeit
  import numpy
  import torch
  from dice_ml import diverse_counterfactuals
  from dice_ml.explainer_interfaces.explainer_base import ExplainerBase
label_desc: Use image node_id 19 for calling the DicePyTorch obj's underlying member method code with example usage: obj.stop_loop(itr, loss_diff) and returns: False, True, False, False, True, True, False