//  [python]
def prepare_hierarchical_input(self):
        """ Supports hierarchical data input
        Converts word level -> sentence level
        """
        # tylib/lib/seq_op/clip_sentence
        # q1_inputs, self.qmax = clip_sentence(self.q1_inputs, self.q1_len)
        # q2_inputs, self.a1max = clip_sentence(self.q2_inputs, self.q2_len)
        # q3_inputs, self.a2max = clip_sentence(self.q3_inputs, self.q3_len)

        print(self.q1_inputs)
        print(self.q2_inputs)

        # Build word-level masks
        self.q1_mask = tf.cast(self.q1_inputs, tf.bool)
        self.q2_mask = tf.cast(self.q2_inputs, tf.bool)
        self.q3_mask = tf.cast(self.q3_inputs, tf.bool)

        def make_hmasks(inputs, smax):
            # Hierarchical Masks
            # Inputs are bsz x (dmax * smax)
            inputs = tf.reshape(inputs,[-1, smax]) # -> (bsz * dmax) x smax
            masked_inputs = tf.cast(inputs, tf.bool)
            return masked_inputs

        # Build review-level masks
        self.q1_hmask = make_hmasks(self.q1_inputs, self.args.smax)
        self.q2_hmask = make_hmasks(self.q2_inputs, self.args.smax)
        self.q3_hmask = make_hmasks(self.q3_inputs, self.args.smax)

        with tf.device('/cpu:0'):
            q1_embed =  tf.nn.embedding_lookup(self.embeddings,
                                                self.q1_inputs)
            q2_embed =  tf.nn.embedding_lookup(self.embeddings,
                                                self.q2_inputs)
            q3_embed = tf.nn.embedding_lookup(self.embeddings,
                                                self.q3_inputs)

        print("=============================================")
        # This is found in nn.py in tylib
        print("Hierarchical Flattening")
        q1_embed, q1_len = hierarchical_flatten(q1_embed,
                                            self.q1_len,
                                            self.args.smax)
        q2_embed, q2_len = hierarchical_flatten(q2_embed,
                                            self.q2_len,
                                            self.args.smax)
        q3_embed, q3_len = hierarchical_flatten(q3_embed,
                                            self.q3_len,
                                            self.args.smax)
        # After flatten -> (bsz * dmax) x smax x dim
        print(q1_embed)
        print(q1_len)

        # o_emb is q_emb before the learn_single_repr layer
        self.o1_embed = q1_embed
        self.o2_embed = q2_embed
        self.o3_embed = q3_embed
        self.o1_len = q1_len
        self.o2_len = q2_len
        self.o3_len = q3_len
        _, q1_embed = self.learn_single_repr(q1_embed, q1_len, self.args.smax,
                                            self.args.base_encoder,
                                            reuse=None, pool=True,
                                            name='sent', mask=self.q1_hmask)
        _, q2_embed = self.learn_single_repr(q2_embed, q2_len, self.args.smax,
                                            self.args.base_encoder,
                                            reuse=True, pool=True,
                                            name='sent', mask=self.q2_hmask)
        _, q3_embed = self.learn_single_repr(q3_embed, q3_len, self.args.smax,
                                            self.args.base_encoder,
                                            reuse=True, pool=True,
                                            name='sent', mask=self.q3_hmask)
        # According to the paper, each review is represented as a sum of its constituent word embeddings
        # Therefore, q_emb is summed over seq_len dimension -> (bsz * dmax) x dim 
        _dim = q1_embed.get_shape().as_list()[1]
        q1_embed = tf.reshape(q1_embed, [-1, self.args.dmax, _dim])
        q2_embed = tf.reshape(q2_embed, [-1, self.args.dmax, _dim])
        q3_embed = tf.reshape(q3_embed, [-1, self.args.dmax, _dim])
        self.q1_embed = q1_embed
        self.q2_embed = q2_embed
        self.q3_embed = q3_embed
        # set value
        self.qmax = self.args.dmax
        self.a1max = self.args.dmax
        self.a2max = self.args.dmax
        # Doesn't support any of these yet
        self.c1_cnn, self.c2_cnn, self.c3_cnn = None, None, None
        self.p1_pos, self.p2_pos, self.p3_pos = None, None, None
        if('TNET' in self.args.rnn_type):
            t_inputs, _ = clip_sentence(self.trans_inputs, self.trans_len)
            self.trans_embed = tf.nn.embedding_lookup(self.embeddings,
                                                        t_inputs)
        print("=================================================")