code: def __call__(self, *args, max_evals=10000):
      # init our queue with all the least costly actions
      q = queue.PriorityQueue()
      for i in range(len(self.action_groups)):
          group = self.action_groups[i]
          q.put((group[0].cost, [group[0]]))
  
      nevals = 0
      while not q.empty():
          # see if we have exceeded our runtime budget
          nevals += 1
          if nevals > max_evals:
              raise ConvergenceError(
                  f"Failed to find a solution with max_evals={max_evals}! Try reducing the number of actions or increasing max_evals."
              )
  
          # get the next cheapest set of actions we can do
          cost, actions = q.get()
  
          # apply those actions
          args_tmp = copy.deepcopy(args)
          for a in actions:
              a(*args_tmp)
  
          # if the model is now satisfied we are done!!
          v = self.model(*args_tmp)
          if v:
              return actions
  
          # if not then we add all possible follow-on actions to our queue
          else:
              for i in range(len(self.action_groups)):
                  group = self.action_groups[i]
  
                  # look to to see if we already have a action from this group, if so we need to
                  # move to a more expensive action in the same group
                  next_ind = 0
                  prev_in_group = -1
                  for j, a in enumerate(actions):
                      if a._group_index == i:
                          next_ind = max(next_ind, a._grouped_index + 1)
                          prev_in_group = j
  
                  # we are adding a new action type
                  if prev_in_group == -1:
                      new_actions = actions + [group[next_ind]]
                  # we are moving from one action to a more expensive one in the same group
                  elif next_ind < len(group):
                      new_actions = copy.copy(actions)
                      new_actions[prev_in_group] = group[next_ind]
                  # we don't have a more expensive action left in this group
                  else:
                      new_actions = None
  
                  # add the new option to our queue
                  if new_actions is not None:
                      q.put(
                          (
                              sum([a.cost for a in new_actions]),
                              new_actions,
                          )
                      )
  
file_path: shap/shap/actions/_optimizer.py
imports: import copy
  import queue
  import warnings
  from ..utils._exceptions import ConvergenceError, InvalidAction
  from ._action import Action
label_desc: Use image node_id 2 for calling the ActionOptimizer obj's underlying member method code with example usage: obj.__call__() and returns: actions