class_docstr: Performs constrained optimization via line search.
  
  The search direction is computed using a conjugate gradient algorithm,
  which gives x = A^{-1}g, where A is a second order approximation of the
  constraint and g is the gradient of the loss function.
  
  Args:
      cg_iters (int): The number of CG iterations used to calculate A^-1 g
      reg_coeff (float): A small value so that A -> A + reg*I
      subsample_factor (float): Subsampling factor to reduce samples when
          using "conjugate gradient. Since the computation time for the
          descent direction dominates, this can greatly reduce the overall
          computation time.
      backtrack_ratio (float): backtrack ratio for backtracking line search.
      max_backtracks (int): Max number of iterations for backtrack
          linesearch.
      accept_violation (bool): whether to accept the descent step if it
          violates the line search condition after exhausting all
          backtracking budgets.
      hvp_approach (HessianVectorProduct): A class that computes
          Hessian-Vector products.
      num_slices (int): Hessian-vector product function's inputs will be
          divided into num_slices and then averaged together to improve
          performance.
class_docstr_tok: ["Performs","constrained","optimization","via","line","search",".","The","search","direction","is","computed","using","a","conjugate","gradient","algorithm",",","which","gives","x","=","A^","{","-1","}","g",",","where","A","is","a","second","order","approximation","of","the","constraint","and","g","is","the","gradient","of","the","loss","function",".","Args",":","cg_iters","(","int",")",":","The","number","of","CG","iterations","used","to","calculate","A^-1","g","reg_coeff","(","float",")",":","A","small","value","so","that","A","-",">","A","+","reg","*","I","subsample_factor","(","float",")",":","Subsampling","factor","to","reduce","samples","when","using","``","conjugate","gradient",".","Since","the","computation","time","for","the","descent","direction","dominates",",","this","can","greatly","reduce","the","overall","computation","time",".","backtrack_ratio","(","float",")",":","backtrack","ratio","for","backtracking","line","search",".","max_backtracks","(","int",")",":","Max","number","of","iterations","for","backtrack","linesearch",".","accept_violation","(","bool",")",":","whether","to","accept","the","descent","step","if","it","violates","the","line","search","condition","after","exhausting","all","backtracking","budgets",".","hvp_approach","(","HessianVectorProduct",")",":","A","class","that","computes","Hessian-Vector","products",".","num_slices","(","int",")",":","Hessian-vector","product","function","'s","inputs","will","be","divided","into","num_slices","and","then","averaged","together","to","improve","performance","."]
docstr: Optimize the function.
  
  Args:
      inputs (list[numpy.ndarray]): A list inputs, which could be
          subsampled if needed. It is assumed that the first dimension
          of these inputs should correspond to the number of data points
      extra_inputs (list[numpy.ndarray]): A list of extra inputs which
          should not be subsampled.
      subsample_grouped_inputs (list[numpy.ndarray]): Subsampled inputs
          to be used when subsample_factor is less than one.
      name (str): The name argument for tf.name_scope.
docstr_tok: ["Optimize","the","function",".","Args",":","inputs","(","list","[","numpy.ndarray","]",")",":","A","list","inputs",",","which","could","be","subsampled","if","needed",".","It","is","assumed","that","the","first","dimension","of","these","inputs","should","correspond","to","the","number","of","data","points","extra_inputs","(","list","[","numpy.ndarray","]",")",":","A","list","of","extra","inputs","which","should","not","be","subsampled",".","subsample_grouped_inputs","(","list","[","numpy.ndarray","]",")",":","Subsampled","inputs","to","be","used","when","subsample_factor","is","less","than","one",".","name","(","str",")",":","The","name","argument","for","tf.name_scope","."]
code: def optimize(
      self,
      inputs,
      extra_inputs=None,
      subsample_grouped_inputs=None,
      name="optimize",
  ):
      """Optimize the function.
  
      Args:
          inputs (list[numpy.ndarray]): A list inputs, which could be
              subsampled if needed. It is assumed that the first dimension
              of these inputs should correspond to the number of data points
          extra_inputs (list[numpy.ndarray]): A list of extra inputs which
              should not be subsampled.
          subsample_grouped_inputs (list[numpy.ndarray]): Subsampled inputs
              to be used when subsample_factor is less than one.
          name (str): The name argument for tf.name_scope.
  
      """
      with tf.name_scope(name):
          prev_param = np.copy(self._target.get_param_values())
          inputs = tuple(inputs)
          if extra_inputs is None:
              extra_inputs = tuple()
  
          subsample_inputs = inputs
          if self._subsample_factor < 1:
              if subsample_grouped_inputs is None:
                  subsample_grouped_inputs = [inputs]
              subsample_inputs = tuple()
              for inputs_grouped in subsample_grouped_inputs:
                  n_samples = len(inputs_grouped[0])
                  inds = np.random.choice(
                      n_samples,
                      int(n_samples * self._subsample_factor),
                      replace=False,
                  )
                  subsample_inputs += tuple(
                      [x[inds] for x in inputs_grouped]
                  )
  
          logger.log(
              (
                  "Start CG optimization: "
                  "#parameters: %d, #inputs: %d, #subsample_inputs: %d"
              )
              % (
                  len(prev_param),
                  len(inputs[0]),
                  len(subsample_inputs[0]),
              )
          )
  
          logger.log("computing loss before")
          loss_before = _sliced_fn(
              self._opt_fun["f_loss"], self._num_slices
          )(inputs, extra_inputs)
  
          logger.log("computing gradient")
          flat_g = _sliced_fn(
              self._opt_fun["f_grad"], self._num_slices
          )(inputs, extra_inputs)
          logger.log("gradient computed")
  
          logger.log("computing descent direction")
          hx = self._hvp_approach.build_eval(
              subsample_inputs + extra_inputs
          )
          descent_direction = _cg(hx, flat_g, cg_iters=self._cg_iters)
  
          initial_step_size = np.sqrt(
              2.0
              * self._max_constraint_val
              * (
                  1.0
                  / (
                      descent_direction.dot(hx(descent_direction))
                      + 1e-8
                  )
              )
          )
          if np.isnan(initial_step_size):
              initial_step_size = 1.0
          flat_descent_step = initial_step_size * descent_direction
  
          logger.log("descent direction computed")
  
          n_iter = 0
          for n_iter, ratio in enumerate(
              self._backtrack_ratio ** np.arange(self._max_backtracks)
          ):  # yapf: disable
              cur_step = ratio * flat_descent_step
              cur_param = prev_param - cur_step
              self._target.set_param_values(cur_param)
              loss, constraint_val = _sliced_fn(
                  self._opt_fun["f_loss_constraint"], self._num_slices
              )(inputs, extra_inputs)
              if (
                  loss < loss_before
                  and constraint_val <= self._max_constraint_val
              ):
                  break
          if (
              np.isnan(loss)
              or np.isnan(constraint_val)
              or loss >= loss_before
              or constraint_val >= self._max_constraint_val
          ) and not self._accept_violation:
              logger.log(
                  "Line search condition violated. Rejecting the step!"
              )
              if np.isnan(loss):
                  logger.log("Violated because loss is NaN")
              if np.isnan(constraint_val):
                  logger.log(
                      "Violated because constraint %s is NaN"
                      % self._constraint_name
                  )
              if loss >= loss_before:
                  logger.log("Violated because loss not improving")
              if constraint_val >= self._max_constraint_val:
                  logger.log(
                      "Violated because constraint %s is violated"
                      % self._constraint_name
                  )
              self._target.set_param_values(prev_param)
          logger.log("backtrack iters: %d" % n_iter)
          logger.log("optimization finished")
  
imports: import abc
  from dowel import logger
  import numpy
  import tensorflow
  from garage.tf import compile_function, flatten_tensor_variables, new_tensor_like
  from garage.tf.optimizers._dtypes import LazyDict
label_desc: Use image node_id 5 for calling the ConjugateGradientOptimizer obj's underlying member method code with example usage: obj.optimize(inputs, extra_inputs, subsample_grouped_inputs, name) without return types