class_docstr: DualFormulation is a class that creates the dual objective function
  and access to matrix vector products for the matrix that is constrained
  to be Positive semidefinite
class_docstr_tok: ["DualFormulation","is","a","class","that","creates","the","dual","objective","function","and","access","to","matrix","vector","products","for","the","matrix","that","is","constrained","to","be","Positive","semidefinite"]
docstr: Function that provides matrix product interface with PSD matrix.
  
  Args:
    vector: the vector to be multiplied with matrix H
  
  Returns:
    result_product: Matrix product of H and vector
docstr_tok: ["Function","that","provides","matrix","product","interface","with","PSD","matrix",".","Args",":","vector",":","the","vector","to","be","multiplied","with","matrix","H","Returns",":","result_product",":","Matrix","product","of","H","and","vector"]
code: def get_h_product(self, vector, dtype=None):
      """Function that provides matrix product interface with PSD matrix.
  
      Args:
        vector: the vector to be multiplied with matrix H
  
      Returns:
        result_product: Matrix product of H and vector
      """
      # Computing the product of matrix_h with beta (input vector)
      # At first layer, h is simply diagonal
      if dtype is None:
          dtype = self.nn_dtype
      beta = tf.cast(vector, self.nn_dtype)
      h_beta_rows = []
      for i in range(self.nn_params.num_hidden_layers):
          # Split beta of this block into [gamma, delta]
          gamma = beta[self.dual_index[i] : self.dual_index[i + 1]]
          delta = beta[self.dual_index[i + 1] : self.dual_index[i + 2]]
  
          # Expanding the product with diagonal matrices
          if i == 0:
              h_beta_rows.append(
                  tf.multiply(2 * self.lambda_lu[i], gamma)
                  - self.nn_params.forward_pass(
                      tf.multiply(self.lambda_quad[i + 1], delta),
                      i,
                      is_transpose=True,
                  )
              )
          else:
              h_beta_rows[i] = (
                  h_beta_rows[i]
                  + tf.multiply(
                      self.lambda_quad[i] + self.lambda_lu[i], gamma
                  )
                  - self.nn_params.forward_pass(
                      tf.multiply(self.lambda_quad[i + 1], delta),
                      i,
                      is_transpose=True,
                  )
              )
  
          new_row = tf.multiply(
              self.lambda_quad[i + 1] + self.lambda_lu[i + 1], delta
          ) - tf.multiply(
              self.lambda_quad[i + 1],
              self.nn_params.forward_pass(gamma, i),
          )
          h_beta_rows.append(new_row)
  
      # Last boundary case
      h_beta_rows[self.nn_params.num_hidden_layers] = h_beta_rows[
          self.nn_params.num_hidden_layers
      ] + tf.multiply(
          (
              self.lambda_quad[self.nn_params.num_hidden_layers]
              + self.lambda_lu[self.nn_params.num_hidden_layers]
          ),
          delta,
      )
  
      h_beta = tf.concat(h_beta_rows, axis=0)
      return tf.cast(h_beta, dtype)
  
file_path: cleverhans/cleverhans/experimental/certification/dual_formulation.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from scipy.sparse.linalg import eigs, LinearOperator
  import tensorflow
  from tensorflow.contrib import autograph
  import numpy
  from cleverhans.experimental.certification import utils
label_desc: Use image node_id 5 for calling the DualFormulation obj's underlying member method code with example usage: obj.get_h_product(vector, dtype) and returns: tf