class_docstr: Implements the Sign-OPT attack `SignOPTAttack`. This is a query-efficient
  hard-label adversarial attack.
  
  Paper link: https://arxiv.org/pdf/1909.10773.pdf
docstr: Evaluate the sign of gradient
  
  :param x_0: An array with the original inputs to be attacked.
  :param y_0: Target value.
  :param epsilon: A very small smoothing parameter.
  :param theta: Initial query direction.
  :param initial_lbd: Previous solution.
  :param target: Target value. If `self.targeted` is true, it presents the targeted label. Defaults to None.
  :return: the sign of gradient
docstr_tok: ["Evaluate","the","sign","of","gradient",":","param","x_0",":","An","array","with","the","original","inputs","to","be","attacked",".",":","param","y_0",":","Target","value",".",":","param","epsilon",":","A","very","small","smoothing","parameter",".",":","param","theta",":","Initial","query","direction",".",":","param","initial_lbd",":","Previous","solution",".",":","param","target",":","Target","value",".","If","`","self.targeted","`","is","true",",","it","presents","the","targeted","label",".","Defaults","to","None",".",":","return",":","the","sign","of","gradient"]
code: def _sign_grad(
      self,
      x_0: np.ndarray,
      y_0: int,
      epsilon: float,
      theta: np.ndarray,
      initial_lbd: float,
      target: Optional[int],
  ) -> Tuple[np.ndarray, int]:
      """
      Evaluate the sign of gradient
  
      :param x_0: An array with the original inputs to be attacked.
      :param y_0: Target value.
      :param epsilon: A very small smoothing parameter.
      :param theta: Initial query direction.
      :param initial_lbd: Previous solution.
      :param target: Target value. If `self.targeted` is true, it presents the targeted label. Defaults to None.
      :return: the sign of gradient
      """
      sign_grad = np.zeros(theta.shape).astype(np.float32)
      queries = 0
      # use orthogonal transform
      for _ in range(self.k):  # for each u
          # Algorithm 1: Sign-OPT attack
          #     A:Randomly sample u1, . . . , uQ from a Gaussian or Uniform distribution;
          u_g = np.random.randn(*theta.shape).astype(np.float32)
          # gaussian
          u_g /= np.linalg.norm(u_g)
          # function (3) in the paper
          new_theta = theta + epsilon * u_g
          new_theta /= np.linalg.norm(new_theta)
          sign = 1
  
          if self.targeted and self._is_label(
              x_0 + initial_lbd * new_theta, target
          ):
              sign = -1
          elif not self.targeted and not self._is_label(
              x_0 + initial_lbd * new_theta, y_0
          ):
              sign = -1
  
          queries += 1
          sign_grad += u_g * sign
  
      sign_grad /= self.k
  
      return sign_grad, queries
  
imports: import logging
  from typing import Optional, TYPE_CHECKING, Tuple
  import time
  import numpy
  from tqdm.auto import tqdm
  from art.attacks.attack import EvasionAttack
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import compute_success, check_and_transform_label_format, get_labels_np_array
label_desc: Use image node_id 7 for calling the SignOPTAttack obj's underlying member method code with example usage: obj._sign_grad(x_0, y_0, epsilon, theta, initial_lbd, target) and returns: sign_grad,  queries