import tensorflow as tf

    # These should hold all of the variables of the Q-function network and target network,
    # respectively. A convenient way to get these is to make use of TF's "scope" feature.
    # For example, you can create your Q-function network with the scope "q_func" like this:
    # <something> = q_func(obs_t_float, num_actions, scope="q_func", reuse=False)
    # And then you can obtain the variables like this:
    # q_func_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='q_func')
    # Older versions of TensorFlow may require using "VARIABLES" instead of "GLOBAL_VARIABLES"
    # Tip: use huber_loss (from dqn_utils) instead of squared error when defining self.total_error
    
    self.Q_vals = q_func(obs_t_float, self.num_actions, 'q_func', reuse = tf.AUTO_REUSE)

    q_func_ph = tf.gather_nd(self.Q_vals, tf.stack([tf.range(tf.shape(self.Q_vals)[0]), self.act_t_ph], axis=1))

    
    target_q_ph = q_func(obs_tp1_float, self.num_actions, 'target_q_func', reuse = tf.AUTO_REUSE)

    if double_q:
      target_index = tf.math.argmax(q_func(obs_tp1_float, self.num_actions, 'q_func', reuse = tf.AUTO_REUSE), axis = 1, output_type = tf.int32)
      target_v_ph = tf.gather_nd(target_q_ph, tf.stack([tf.range(tf.shape(target_q_ph)[0]), target_index], axis=1))
    else:
      target_v_ph = tf.math.reduce_max(target_q_ph, axis = 1)

