code: def greedy_search(
      image: np.ndarray,
      estimator,
      iterations: int,
      actual_class: int,
      actual_class_confidence: float,
      adv_object_generator: AdvObjectGenerator,
      image_generator: ImageGenerator,
      debug: Optional[DebugInfo] = None,
  ) -> Tuple[Optional[AdversarialObject], Optional[int]]:
      """
      Greedy search algorithm used to generate parameters of an adversarial object that added to the :image will mislead
      the neural network.
      Based on the paper:
      https://openaccess.thecvf.com/content/CVPR2021/papers/Duan_Adversarial_Laser_Beam_Effective_Physical-World_Attack_to_DNNs_in_a_CVPR_2021_paper.pdf
  
      :param image: Image to attack.
      :param estimator: Predictor of the image class.
      :param iterations: Maximum number of iterations of the algorithm.
      :param actual_class:
      :param actual_class_confidence:
      :param adv_object_generator: Object responsible for adversarial object generation.
      :param image_generator: Object responsible for image generation.
      :param debug: Optional debug handler.
      """
  
      params = adv_object_generator.random()
      for _ in range(iterations):
          for sign in [-1, 1]:
              params_prim = adv_object_generator.update_params(
                  params, sign=sign
              )
              adversarial_image = image_generator.update_image(
                  image, params_prim
              )
              prediction = estimator.predict(adversarial_image)
              if debug is not None:
                  DebugInfo.report(
                      debug,
                      params_prim,
                      np.squeeze(adversarial_image, 0),
                  )
              predicted_class = prediction.argmax()
              confidence_adv = prediction[0][actual_class]
  
              if confidence_adv <= actual_class_confidence:
                  params = params_prim
                  actual_class_confidence = confidence_adv
                  break
  
          if predicted_class != actual_class:
              return params, predicted_class
  
      return None, None
  
imports: from typing import Optional, Tuple
  import numpy
  from art.attacks.evasion.laser_attack.utils import AdversarialObject, AdvObjectGenerator, DebugInfo, ImageGenerator
label_desc: Use image node_id 1 for calling a global function with example usage: greedy_search(image, estimator, iterations, actual_class, actual_class_confidence, adv_object_generator, image_generator, debug) and returns: None,  None, params,  predicted_class