docstr: Take in samples (action, rewards, propensities, etc.) and output lists
  of equal-length trajectories (episodes) according to terminals.
  As the raw trajectories are of various lengths, the shorter ones are
  filled with zeros(ones) at the end.
docstr_tok: ["Take","in","samples","(","action",",","rewards",",","propensities",",","etc",".",")","and","output","lists","of","equal-length","trajectories","(","episodes",")","according","to","terminals",".","As","the","raw","trajectories","are","of","various","lengths",",","the","shorter","ones","are","filled","with","zeros","(","ones",")","at","the","end","."]
code: def transform_to_equal_length_trajectories(
      mdp_ids,
      actions,
      rewards,
      logged_propensities,
      target_propensities,
      estimated_q_values,
  ):
      """
      Take in samples (action, rewards, propensities, etc.) and output lists
      of equal-length trajectories (episodes) according to terminals.
      As the raw trajectories are of various lengths, the shorter ones are
      filled with zeros(ones) at the end.
      """
      num_actions = len(target_propensities[0])
  
      terminals = np.zeros(mdp_ids.shape[0])
      for x in range(0, mdp_ids.shape[0]):
          if (
              x + 1 == mdp_ids.shape[0]
              or mdp_ids[x, 0] != mdp_ids[x + 1, 0]
          ):
              terminals[x] = 1
  
      trajectories = []
      episode_start = 0
      episode_ends = np.nonzero(terminals)[0]
      if len(terminals) - 1 not in episode_ends:
          episode_ends = np.append(episode_ends, len(terminals) - 1)
  
      for episode_end in episode_ends:
          trajectories.append(np.arange(episode_start, episode_end + 1))
          episode_start = episode_end + 1
  
      action_trajectories = []
      reward_trajectories = []
      logged_propensity_trajectories = []
      target_propensity_trajectories = []
      Q_value_trajectories = []
  
      for trajectory in trajectories:
          action_trajectories.append(actions[trajectory])
          reward_trajectories.append(rewards[trajectory])
          logged_propensity_trajectories.append(
              logged_propensities[trajectory]
          )
          target_propensity_trajectories.append(
              target_propensities[trajectory]
          )
          Q_value_trajectories.append(estimated_q_values[trajectory])
  
      def to_equal_length(x, fill_value):
          x_equal_length = np.array(
              list(itertools.zip_longest(*x, fillvalue=fill_value))
          ).swapaxes(0, 1)
          return x_equal_length
  
      action_trajectories = to_equal_length(
          action_trajectories, np.zeros([num_actions])
      )
      reward_trajectories = to_equal_length(reward_trajectories, 0)
      logged_propensity_trajectories = to_equal_length(
          logged_propensity_trajectories, 1
      )
      target_propensity_trajectories = to_equal_length(
          target_propensity_trajectories, np.zeros([num_actions])
      )
      Q_value_trajectories = to_equal_length(
          Q_value_trajectories, np.zeros([num_actions])
      )
  
      return (
          action_trajectories,
          reward_trajectories,
          logged_propensity_trajectories,
          target_propensity_trajectories,
          Q_value_trajectories,
      )
  
file_path: ReAgent/reagent/evaluation/weighted_sequential_doubly_robust_estimator.py
imports: import itertools
  import logging
  import numpy
  import scipy
  from reagent.evaluation.cpe import CpeEstimate
  from reagent.evaluation.evaluation_data_page import EvaluationDataPage
label_desc: Use image node_id 4 for calling the WeightedSequentialDoublyRobustEstimator obj's underlying member method code with example usage: obj.transform_to_equal_length_trajectories(mdp_ids, actions, rewards, logged_propensities, target_propensities, estimated_q_values) and returns: action_trajectories,  reward_trajectories,  logged_propensity_trajectories,  target_propensity_trajectories,  Q_value_trajectories, x_equal_length