Run the optimization, call run_one_step with suitable placeholders.

    Returns:
      True if certificate is found
      False otherwise

def run_optimization(self):
    """Run the optimization, call run_one_step with suitable placeholders.

    Returns:
      True if certificate is found
      False otherwise
    """
    penalty_val = self.params['init_penalty']
    # Don't use smoothing initially - very inaccurate for large dimension
    self.smooth_on = False
    smooth_val = 0
    learning_rate_val = self.params['init_learning_rate']
    self.current_outer_step = 1


    while self.current_outer_step <= self.params['outer_num_steps']:
      tf.logging.info('Running outer step %d with penalty %f',
                      self.current_outer_step, penalty_val)
      # Running inner loop of optimization with current_smooth_val,
      # current_penalty as smoothness parameters and penalty respectively
      self.current_step = 0
      # Run first step with random eig initialization and large number of steps
      found_cert = self.run_one_step(
          self.dual_object.m_min_vec_estimate,
          self.params['large_eig_num_steps'], smooth_val, penalty_val, learning_rate_val)
      if found_cert:
        return True
      while self.current_step < self.params['inner_num_steps']:
        self.current_step = self.current_step + 1
        found_cert = self.run_one_step(self.dual_object.m_min_vec_estimate,
                                       self.params['small_eig_num_steps'],
                                       smooth_val, penalty_val,
                                       learning_rate_val)
        if found_cert:
          return True
      # Update penalty only if it looks like current objective is optimizes
      if self.current_total_objective < UPDATE_PARAM_CONSTANT:
        penalty_val = penalty_val * self.params['beta']
        learning_rate_val = learning_rate_val*self.params['learning_rate_decay']
      else:
        # To get more accurate gradient estimate
        self.params['small_eig_num_steps'] = (
            1.5 * self.params['small_eig_num_steps'])

      # If eigen values seem small enough, turn on smoothing
      # useful only when performing full eigen decomposition
      if np.abs(self.current_eig_val_estimate) < 0.01:
        smooth_val = self.params['smoothness_parameter']
      self.current_outer_step = self.current_outer_step + 1
    return False