class_docstr: Repeats the wrapped attack and returns the best result
class_docstr_tok: ["Repeats","the","wrapped","attack","and","returns","the","best","result"]
code: def __call__(  # noqa: F811
      self,
      model: Model,
      inputs: T,
      criterion: Any,
      *,
      epsilons: Union[Sequence[Union[float, None]], float, None],
      **kwargs: Any,
  ) -> Union[Tuple[List[T], List[T], T], Tuple[T, T, T]]:
      x, restore_type = ep.astensor_(inputs)
      del inputs
  
      verify_input_bounds(x, model)
  
      criterion = get_criterion(criterion)
  
      was_iterable = True
      if not isinstance(epsilons, Iterable):
          epsilons = [epsilons]
          was_iterable = False
  
      N = len(x)
      K = len(epsilons)
  
      for i in range(self.times):
          # run the attack
          xps, xpcs, success = self.attack(
              model, x, criterion, epsilons=epsilons, **kwargs
          )
          assert len(xps) == K
          assert len(xpcs) == K
          for xp in xps:
              assert xp.shape == x.shape
          for xpc in xpcs:
              assert xpc.shape == x.shape
          assert success.shape == (K, N)
  
          if i == 0:
              best_xps = xps
              best_xpcs = xpcs
              best_success = success
              continue
  
          # TODO: test if stacking the list to a single tensor and
          # getting rid of the loop is faster
  
          for k, epsilon in enumerate(epsilons):
              first = best_success[k].logical_not()
              assert first.shape == (N,)
              if epsilon is None:
                  # if epsilon is None, we need the minimum
  
                  # TODO: maybe cache some of these distances
                  # and then remove the else part
                  closer = self.distance(x, xps[k]) < self.distance(
                      x, best_xps[k]
                  )
                  assert closer.shape == (N,)
                  new_best = ep.logical_and(
                      success[k], ep.logical_or(closer, first)
                  )
              else:
                  # for concrete epsilon, we just need a successful one
                  new_best = ep.logical_and(success[k], first)
              new_best = atleast_kd(new_best, x.ndim)
              best_xps[k] = ep.where(new_best, xps[k], best_xps[k])
              best_xpcs[k] = ep.where(new_best, xpcs[k], best_xpcs[k])
  
          best_success = ep.logical_or(success, best_success)
  
      best_xps_ = [restore_type(xp) for xp in best_xps]
      best_xpcs_ = [restore_type(xpc) for xpc in best_xpcs]
      if was_iterable:
          return best_xps_, best_xpcs_, restore_type(best_success)
      else:
          assert len(best_xps_) == 1
          assert len(best_xpcs_) == 1
          return (
              best_xps_[0],
              best_xpcs_[0],
              restore_type(best_success.squeeze(axis=0)),
          )
  
imports: from typing import Callable, TypeVar, Any, Union, Optional, Sequence, List, Tuple, Dict
  from typing_extensions import final, overload
  from abc import ABC, abstractmethod
  from collections.abc import Iterable
  import eagerpy
  from ..models import Model
  from ..criteria import Criterion
  from ..criteria import Misclassification
  from ..devutils import atleast_kd
  from ..distances import Distance
label_desc: Use image node_id 5 for calling the Repeated obj's underlying member method code with example usage: obj.__call__(model, inputs, criterion) and returns: best_xps_,  best_xpcs_,  restore_type, best_xps_,  best_xpcs_,  restore_type