class_docstr: The bidirectional greedy algorithm.
  
  Most submodular optimizers assume that the function is *monotone*, i.e., 
  that the gain from each successive example is positive. However, there 
  are some cases where the key diminishing returns property holds, but 
  the gains are not necessarily positive. The most obvious of these is a
  difference in submodular functions. In these cases, the naive greedy 
  algorithm is not guaranteed to return a good result. 
  
  The bidirectional greedy algorithm was developed to optimize non-monotone 
  submodular functions. While it has a guarantee that is lower than the 
  naive greedy algorithm has for monotone functions, it generally returns 
  better sets than the greedy algorithm.
  
  .. code::python
  
          from apricot import FeatureBasedSelection
  
          X = numpy.random.randint(10, size=(10000, 100))
  
          selector = FeatureBasedSelection(100, 'sqrt', optimizer='bidirectional')
          selector.fit(X)
  
  Parameters
  ----------
  self.function : base.BaseSelection
          A submodular function that implements the `_calculate_gains` and
          `_select_next` methods. This is the function that will be
          optimized.
  
  self.verbose : bool
          Whether to display a progress bar during the optimization process.
  
  
  Attributes
  ----------
  self.function : base.BaseSelection
          A submodular function that implements the `_calculate_gains` and
          `_select_next` methods. This is the function that will be
          optimized.
  
  self.verbose : bool
          Whether to display a progress bar during the optimization process.
  
  self.gains_ : numpy.ndarray or None
          The gain that each example would give the last time that it was
          evaluated.
class_docstr_tok: ["The","bidirectional","greedy","algorithm",".","Most","submodular","optimizers","assume","that","the","function","is","*","monotone","*",",","i.e.",",","that","the","gain","from","each","successive","example","is","positive",".","However",",","there","are","some","cases","where","the","key","diminishing","returns","property","holds",",","but","the","gains","are","not","necessarily","positive",".","The","most","obvious","of","these","is","a","difference","in","submodular","functions",".","In","these","cases",",","the","naive","greedy","algorithm","is","not","guaranteed","to","return","a","good","result",".","The","bidirectional","greedy","algorithm","was","developed","to","optimize","non-monotone","submodular","functions",".","While","it","has","a","guarantee","that","is","lower","than","the","naive","greedy","algorithm","has","for","monotone","functions",",","it","generally","returns","better","sets","than","the","greedy","algorithm",".","..","code",":",":python","from","apricot","import","FeatureBasedSelection","X","=","numpy.random.randint","(","10",",","size=","(","10000",",","100",")",")","selector","=","FeatureBasedSelection","(","100",",","'sqrt","'",",","optimizer='bidirectional","'",")","selector.fit","(","X",")","Parameters","--","--","--","--","--","self.function",":","base.BaseSelection","A","submodular","function","that","implements","the","`","_calculate_gains","`","and","`","_select_next","`","methods",".","This","is","the","function","that","will","be","optimized",".","self.verbose",":","bool","Whether","to","display","a","progress","bar","during","the","optimization","process",".","Attributes","--","--","--","--","--","self.function",":","base.BaseSelection","A","submodular","function","that","implements","the","`","_calculate_gains","`","and","`","_select_next","`","methods",".","This","is","the","function","that","will","be","optimized",".","self.verbose",":","bool","Whether","to","display","a","progress","bar","during","the","optimization","process",".","self.gains_",":","numpy.ndarray","or","None","The","gain","that","each","example","would","give","the","last","time","that","it","was","evaluated","."]
code: def __init__(
      self, function=None, random_state=None, n_jobs=None, verbose=False
  ):
      super(BidirectionalGreedy, self).__init__(
          function=function,
          random_state=random_state,
          n_jobs=n_jobs,
          verbose=verbose,
      )
  
imports: import os
  import copy
  import numpy
  import scipy
  from tqdm import tqdm
  from .utils import PriorityQueue
  from .utils import check_random_state
  from .utils import _calculate_pairwise_distances
label_desc: Use image node_id 1 to create a new BidirectionalGreedy object from inherited base classes: BaseOptimizer with example: obj = BidirectionalGreedy(function, random_state, n_jobs, verbose)