(self, source_padded: torch.Tensor, source_lengths: List[int])
return enc_hiddens, dec_init_state
Apply the encoder to source sentences to obtain encoder hidden states.
            Additionally, take the final states of the encoder and project them to obtain initial states for decoder.

        @param source_padded (Tensor): Tensor of padded source sentences with shape (src_len, b), where
                                        b = batch_size, src_len = maximum source sentence length. Note that 
                                       these have already been sorted in order of longest to shortest sentence.
        @param source_lengths (List[int]): List of actual lengths for each of the source sentences in the batch
        @returns enc_hiddens (Tensor): Tensor of hidden units with shape (b, src_len, h*2), where
                                        b = batch size, src_len = maximum source sentence length, h = hidden size.
        @returns dec_init_state (tuple(Tensor, Tensor)): Tuple of tensors representing the decoder's initial
                                                hidden state and cell.
Apply the encoder to source sentences to obtain encoder hidden states.
            Additionally, take the final states of the encoder and project them to obtain initial states for decoder.
Apply the encoder to source sentences to obtain encoder hidden states . Additionally take the final states of the encoder and project them to obtain initial states for decoder .
def encode(self, source_padded: torch.Tensor, source_lengths: List[int]) -> Tuple[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
        """ Apply the encoder to source sentences to obtain encoder hidden states.
            Additionally, take the final states of the encoder and project them to obtain initial states for decoder.

        @param source_padded (Tensor): Tensor of padded source sentences with shape (src_len, b), where
                                        b = batch_size, src_len = maximum source sentence length. Note that 
                                       these have already been sorted in order of longest to shortest sentence.
        @param source_lengths (List[int]): List of actual lengths for each of the source sentences in the batch
        @returns enc_hiddens (Tensor): Tensor of hidden units with shape (b, src_len, h*2), where
                                        b = batch size, src_len = maximum source sentence length, h = hidden size.
        @returns dec_init_state (tuple(Tensor, Tensor)): Tuple of tensors representing the decoder's initial
                                                hidden state and cell.
        """
        enc_hiddens, dec_init_state = None, None

        ### YOUR CODE HERE (~ 8 Lines)
        ### TODO:
        ###     1. Construct Tensor `X` of source sentences with shape (src_len, b, e) using the source model embeddings.
        ###         src_len = maximum source sentence length, b = batch size, e = embedding size. Note
        ###         that there is no initial hidden state or cell for the decoder.
        ###     2. Compute `enc_hiddens`, `last_hidden`, `last_cell` by applying the encoder to `X`.
        ###         - Before you can apply the encoder, you need to apply the `pack_padded_sequence` function to X.
        ###         - After you apply the encoder, you need to apply the `pad_packed_sequence` function to enc_hiddens.
        ###         - Note that the shape of the tensor returned by the encoder is (src_len, b, h*2) and we want to
        ###           return a tensor of shape (b, src_len, h*2) as `enc_hiddens`.
        ###     3. Compute `dec_init_state` = (init_decoder_hidden, init_decoder_cell):
        ###         - `init_decoder_hidden`:
        ###             `last_hidden` is a tensor shape (2, b, h). The first dimension corresponds to forwards and backwards.
        ###             Concatenate the forwards and backwards tensors to obtain a tensor shape (b, 2*h).
        ###             Apply the h_projection layer to this in order to compute init_decoder_hidden.
        ###             This is h_0^{dec} in the PDF. Here b = batch size, h = hidden size
        ###         - `init_decoder_cell`:
        ###             `last_cell` is a tensor shape (2, b, h). The first dimension corresponds to forwards and backwards.
        ###             Concatenate the forwards and backwards tensors to obtain a tensor shape (b, 2*h).
        ###             Apply the c_projection layer to this in order to compute init_decoder_cell.
        ###             This is c_0^{dec} in the PDF. Here b = batch size, h = hidden size
        ###
        ### See the following docs, as you may need to use some of the following functions in your implementation:
        ###     Pack the padded sequence X before passing to the encoder:
        ###         https://pytorch.org/docs/stable/nn.html#torch.nn.utils.rnn.pack_padded_sequence
        ###     Pad the packed sequence, enc_hiddens, returned by the encoder:
        ###         https://pytorch.org/docs/stable/nn.html#torch.nn.utils.rnn.pad_packed_sequence
        ###     Tensor Concatenation:
        ###         https://pytorch.org/docs/stable/torch.html#torch.cat
        ###     Tensor Permute:
        ###         https://pytorch.org/docs/stable/tensors.html#torch.Tensor.permute
        X = self.model_embeddings.source(source_padded)
        X = pack_padded_sequence(X, torch.tensor(source_lengths))
        enc_hiddens, (last_hidden, last_cell) = self.encoder(X)
        enc_hiddens, _ = pad_packed_sequence(enc_hiddens, batch_first=True)
        init_dec_hidden = self.h_projection(torch.cat((last_hidden[0], last_hidden[1]), 1))
        init_dec_cell = self.c_projection(torch.cat((last_cell[0], last_cell[1]), 1))
        dec_init_state = (init_dec_hidden, init_dec_cell)

        ### END YOUR CODE

        return enc_hiddens, dec_init_state
def encode ( self , source_padded : torch . Tensor , source_lengths : List [ int ] ) -> Tuple [ torch . Tensor , Tuple [ torch . Tensor , torch . Tensor ] ] : enc_hiddens , dec_init_state = None , None ### YOUR CODE HERE (~ 8 Lines) ### TODO: ###     1. Construct Tensor `X` of source sentences with shape (src_len, b, e) using the source model embeddings. ###         src_len = maximum source sentence length, b = batch size, e = embedding size. Note ###         that there is no initial hidden state or cell for the decoder. ###     2. Compute `enc_hiddens`, `last_hidden`, `last_cell` by applying the encoder to `X`. ###         - Before you can apply the encoder, you need to apply the `pack_padded_sequence` function to X. ###         - After you apply the encoder, you need to apply the `pad_packed_sequence` function to enc_hiddens. ###         - Note that the shape of the tensor returned by the encoder is (src_len, b, h*2) and we want to ###           return a tensor of shape (b, src_len, h*2) as `enc_hiddens`. ###     3. Compute `dec_init_state` = (init_decoder_hidden, init_decoder_cell): ###         - `init_decoder_hidden`: ###             `last_hidden` is a tensor shape (2, b, h). The first dimension corresponds to forwards and backwards. ###             Concatenate the forwards and backwards tensors to obtain a tensor shape (b, 2*h). ###             Apply the h_projection layer to this in order to compute init_decoder_hidden. ###             This is h_0^{dec} in the PDF. Here b = batch size, h = hidden size ###         - `init_decoder_cell`: ###             `last_cell` is a tensor shape (2, b, h). The first dimension corresponds to forwards and backwards. ###             Concatenate the forwards and backwards tensors to obtain a tensor shape (b, 2*h). ###             Apply the c_projection layer to this in order to compute init_decoder_cell. ###             This is c_0^{dec} in the PDF. Here b = batch size, h = hidden size ### ### See the following docs, as you may need to use some of the following functions in your implementation: ###     Pack the padded sequence X before passing to the encoder: ###         https://pytorch.org/docs/stable/nn.html#torch.nn.utils.rnn.pack_padded_sequence ###     Pad the packed sequence, enc_hiddens, returned by the encoder: ###         https://pytorch.org/docs/stable/nn.html#torch.nn.utils.rnn.pad_packed_sequence ###     Tensor Concatenation: ###         https://pytorch.org/docs/stable/torch.html#torch.cat ###     Tensor Permute: ###         https://pytorch.org/docs/stable/tensors.html#torch.Tensor.permute X = self . model_embeddings . source ( source_padded ) X = pack_padded_sequence ( X , torch . tensor ( source_lengths ) ) enc_hiddens , ( last_hidden , last_cell ) = self . encoder ( X ) enc_hiddens , _ = pad_packed_sequence ( enc_hiddens , batch_first = True ) init_dec_hidden = self . h_projection ( torch . cat ( ( last_hidden [ 0 ] , last_hidden [ 1 ] ) , 1 ) ) init_dec_cell = self . c_projection ( torch . cat ( ( last_cell [ 0 ] , last_cell [ 1 ] ) , 1 ) ) dec_init_state = ( init_dec_hidden , init_dec_cell ) ### END YOUR CODE return enc_hiddens , dec_init_state