docs: def _is_converged(self, dual_threshold=None, integrality_gap_threshold=None):
          """
          This method checks the integrality gap to ensure either:
              * we have found a near to exact solution or
              * stuck on a local minima.
  
          Parameters
          ----------
          dual_threshold: double
                          This sets the minimum width between the dual objective decrements. If the decrement is lesser
                          than the threshold, then that means we have stuck on a local minima.
  
          integrality_gap_threshold: double
                                     This sets the threshold for the integrality gap below which we say that the solution
                                     is satisfactory.
  
          References
          ----------
          code presented by Sontag in 2012 here: http://cs.nyu.edu/~dsontag/code/README_v2.html
          """
          # Find the new objective after the message updates
          new_dual_lp = sum([np.amax(self.objective[obj].values) for obj in self.objective])
  
          # Update the dual_gap as the difference between the dual objective of the previous and the current iteration.
          self.dual_gap = abs(self.dual_lp - new_dual_lp)
  
          # Update the integrality_gap as the difference between our best result vs the dual objective of the lp.
          self.integrality_gap = abs(self.dual_lp - self.best_int_objective)
  
          # As the decrement of the dual_lp gets very low, we assume that we might have stuck in a local minima.
          if dual_threshold and self.dual_gap < dual_threshold:
              return True
          # Check the threshold for the integrality gap
          elif integrality_gap_threshold and self.integrality_gap < integrality_gap_threshold:
              return True
          else:
              self.dual_lp = new_dual_lp
              return False