class_docstr: Draws randomly from the given dataset until adversarial examples for all
  inputs have been found.
  
  To pass data form the dataset to this attack, call :meth:`feed()`.
  :meth:`feed()` can be called several times and should only be called with
  batches that are small enough that they can be passed through the model.
  
  Args:
      distance : Distance measure for which minimal adversarial examples are searched.
class_docstr_tok: ["Draws","randomly","from","the","given","dataset","until","adversarial","examples","for","all","inputs","have","been","found",".","To","pass","data","form","the","dataset","to","this","attack",",","call",":","meth",":","`","feed","(",")","`",".",":","meth",":","`","feed","(",")","`","can","be","called","several","times","and","should","only","be","called","with","batches","that","are","small","enough","that","they","can","be","passed","through","the","model",".","Args",":","distance",":","Distance","measure","for","which","minimal","adversarial","examples","are","searched","."]
code: def run(
      self,
      model: Model,
      inputs: T,
      criterion: Union[Criterion, T],
      *,
      early_stop: Optional[float] = None,
      **kwargs: Any,
  ) -> T:
      raise_if_kwargs(kwargs)
      self.process_raw()
      assert self.inputs is not None
      assert self.outputs is not None
      x, restore_type = ep.astensor_(inputs)
      del inputs, kwargs
  
      verify_input_bounds(x, model)
  
      criterion = get_criterion(criterion)
  
      result = x
      found = criterion(x, model(x))
  
      batch_size = len(x)
  
      # for every sample try every other sample
      index_pools: List[List[int]] = []
      for i in range(batch_size):
          indices = list(range(batch_size))
          indices.remove(i)
          np.random.shuffle(indices)
          index_pools.append(indices)
  
      for i in range(batch_size - 1):
          if found.all():
              break
  
          indices_np = np.array([pool[i] for pool in index_pools])
  
          xp = self.inputs[indices_np]
          yp = self.outputs[indices_np]
          is_adv = criterion(xp, yp)
  
          new_found = ep.logical_and(is_adv, found.logical_not())
          result = ep.where(
              atleast_kd(new_found, result.ndim), xp, result
          )
          found = ep.logical_or(found, new_found)
  
      return restore_type(result)
  
file_path: foolbox/foolbox/attacks/dataset_attack.py
imports: from typing import Union, Optional, Any, List
  import numpy
  import eagerpy
  from ..devutils import atleast_kd
  from ..models import Model
  from ..distances import Distance
  from ..criteria import Criterion
  from .base import FlexibleDistanceMinimizationAttack
  from .base import T
  from .base import get_criterion
  from .base import raise_if_kwargs
  from .base import verify_input_bounds
label_desc: Use image node_id 4 for calling the DatasetAttack obj's underlying member method code with example usage: obj.run(model, inputs, criterion) and returns: restore_type