code: def _terminal_experience_parallel(
      self,
      *,
      episode_length,
      reward_horizon,
      reward_discount,
      states,
      internals,
      auxiliaries,
      actions,
      reward,
      terminal,
  ):
      # (similar to _nonterminal_experience)
      one = tf_util.constant(value=1, dtype="int")
      internals = (
          internals["baseline"]
          if self.separate_baseline
          else internals["policy"]
      )
  
      # Whether to predict horizon values now
      if self.predict_horizon_values != "early":
          assert self.trace_decay.is_constant(value=1.0)
  
          # Whether to predict all or only abort-terminals
          terminal_value = tf_util.constant(value=0.0, dtype="float")
          if not self.predict_terminal_values:
              is_terminal = tf.math.equal(x=terminal[-1], y=one)
              terminal_value = tf.where(
                  condition=is_terminal, x=reward[-1], y=terminal_value
              )
  
          # Horizon-expanded rewards and values
          horizon_values = tf_util.zeros(
              shape=tf.expand_dims(input=episode_length, axis=0),
              dtype="float",
          )
          reward = tf.concat(
              values=(
                  reward[:-1],
                  [terminal_value],
                  horizon_values[:reward_horizon],
              ),
              axis=0,
          )
  
      else:
          # Baseline horizon
          baseline_horizon = self.baseline.past_horizon(on_policy=True)
          assertions = (
              list()
          )  # (control dependency below, before baseline call)
          if not self.trace_decay.is_constant(value=1.0):
              zero = tf_util.constant(value=0, dtype="int")
              assertions.append(
                  tf.debugging.assert_equal(
                      x=baseline_horizon,
                      y=zero,
                      message="Baseline cannot have on-policy horizon if trace_decay != 1.0.",
                  )
              )
  
          # Index starts/ends
          if self.trace_decay.is_constant(value=1.0):
              # Only indices relevant for horizon values
              reward_horizon_start = reward_horizon
              zero = tf_util.constant(value=0, dtype="int")
              baseline_horizon_start = tf.maximum(
                  x=(reward_horizon_start - baseline_horizon), y=zero
              )
              baseline_horizon_end = episode_length - baseline_horizon
              baseline_horizon_end = tf.maximum(
                  x=baseline_horizon_end, y=baseline_horizon_start
              )
              horizons_start = tf.range(
                  baseline_horizon_end - baseline_horizon_start
              )
              horizons_length = reward_horizon_start + horizons_start
              horizons_length = tf.math.minimum(
                  x=horizons_length, y=(baseline_horizon + one)
              )
          else:
              # All indices
              reward_horizon_start = 1
              baseline_horizon_start = 1
              baseline_horizon_end = None
              horizons_start = tf.range(episode_length - one)
              horizons_length = tf.ones_like(input=horizons_start)
  
          # Baseline-horizon-sequence per timestep, as horizons indexing tensor
          horizons = tf.stack(
              values=(horizons_start, horizons_length), axis=1
          )
  
          # Predict values
          with tf.control_dependencies(control_inputs=assertions):
              if self.predict_action_values:
                  # TODO: option to re-sample action deterministically?
                  values = self.baseline.action_value(
                      states=states[baseline_horizon_start:],
                      horizons=horizons,
                      internals=internals[
                          baseline_horizon_start:baseline_horizon_end
                      ],
                      auxiliaries=auxiliaries[reward_horizon_start:],
                      actions=actions[reward_horizon_start:],
                  )
              else:
                  values = self.baseline.state_value(
                      states=states[baseline_horizon_start:],
                      horizons=horizons,
                      internals=internals[
                          baseline_horizon_start:baseline_horizon_end
                      ],
                      auxiliaries=auxiliaries[reward_horizon_start:],
                  )
  
          # Whether to predict all or only abort-terminals
          terminal_value = values[-1]
          if not self.predict_terminal_values:
              is_terminal = tf.math.equal(x=terminal[-1], y=one)
              terminal_value = tf.where(
                  condition=is_terminal, x=reward[-1], y=terminal_value
              )
  
          # Horizon-expanded rewards and values
          zeros_reward_horizon = tf_util.zeros(
              shape=tf.expand_dims(
                  input=(reward_horizon - one), axis=0
              ),
              dtype="float",
          )
          reward = tf.concat(
              values=(
                  reward[:-1],
                  [terminal_value],
                  zeros_reward_horizon,
              ),
              axis=0,
          )
          zeros_reward_horizon = tf_util.zeros(
              shape=tf.expand_dims(reward_horizon, axis=0),
              dtype="float",
          )
          values = tf.concat(
              values=(values, zeros_reward_horizon), axis=0
          )
  
          # Horizon values
          if self.trace_decay.is_constant(value=1.0):
              horizon_values = values
          else:
              horizon_values = values[reward_horizon - one :]
  
      # Recursive return
      if self.trace_decay.is_constant(value=1.0):
          # Discounted cumulative sum
          def recursive_return(next_return, index):
              return (
                  reward[index : index + episode_length]
                  + reward_discount * next_return
              )
  
      else:
          # TD-lambda
          one_float = tf_util.constant(value=1.0, dtype="float")
          trace_decay = self.trace_decay.value()
  
          def recursive_return(next_return, index):
              next_value = values[index : index + episode_length]
              next_return = (
                  one_float - trace_decay
              ) * next_value + trace_decay * next_return
              return (
                  reward[index : index + episode_length]
                  + reward_discount * next_return
              )
  
      return tf.foldr(
          fn=recursive_return,
          elems=tf.range(reward_horizon),
          initializer=horizon_values,
      )
  
imports: import logging
  import tensorflow
  from tensorforce import TensorforceError
  from tensorforce.core import ModuleDict, memory_modules, optimizer_modules, parameter_modules, SignatureDict, TensorDict, TensorSpec, TensorsSpec, tf_function, tf_util, VariableDict
  from tensorforce.core.models import Model
  from tensorforce.core.networks import Preprocessor
  from tensorforce.core.objectives import objective_modules
  from tensorforce.core.policies import policy_modules, StochasticPolicy
label_desc: Use image node_id 17 for calling the TensorforceModel obj's underlying member method code with example usage: obj._terminal_experience_parallel() and returns: tf, unknown, unknown