class_docstr: Base class flexible RNNs.
  
  Forward function can handle sequences of length 0.
docstr: Forward function of rnn that allows zero-length sequences.
  
  Functions as normal for RNN. Only changes output if lengths are defined.
  
  Args:
      x (Union[rnn.PackedSequence, torch.Tensor]): input to RNN. either packed sequence or tensor of
          padded sequences
      hx (HiddenState, optional): hidden state. Defaults to None.
      lengths (torch.LongTensor, optional): lengths of sequences. If not None, used to determine correct returned
          hidden state. Can contain zeros. Defaults to None.
      enforce_sorted (bool, optional): if lengths are passed, determines if RNN expects them to be sorted.
          Defaults to True.
  
  Returns:
      Tuple[Union[rnn.PackedSequence, torch.Tensor], HiddenState]: output and hidden state.
          Output is packed sequence if input has been a packed sequence.
docstr_tok: ["Forward","function","of","rnn","that","allows","zero-length","sequences",".","Functions","as","normal","for","RNN",".","Only","changes","output","if","lengths","are","defined",".","Args",":","x","(","Union","[","rnn.PackedSequence",",","torch.Tensor","]",")",":","input","to","RNN",".","either","packed","sequence","or","tensor","of","padded","sequences","hx","(","HiddenState",",","optional",")",":","hidden","state",".","Defaults","to","None",".","lengths","(","torch.LongTensor",",","optional",")",":","lengths","of","sequences",".","If","not","None",",","used","to","determine","correct","returned","hidden","state",".","Can","contain","zeros",".","Defaults","to","None",".","enforce_sorted","(","bool",",","optional",")",":","if","lengths","are","passed",",","determines","if","RNN","expects","them","to","be","sorted",".","Defaults","to","True",".","Returns",":","Tuple","[","Union","[","rnn.PackedSequence",",","torch.Tensor","]",",","HiddenState","]",":","output","and","hidden","state",".","Output","is","packed","sequence","if","input","has","been","a","packed","sequence","."]
code: def forward(
      self,
      x: Union[rnn.PackedSequence, torch.Tensor],
      hx: HiddenState = None,
      lengths: torch.LongTensor = None,
      enforce_sorted: bool = True,
  ) -> Tuple[Union[rnn.PackedSequence, torch.Tensor], HiddenState]:
      """
      Forward function of rnn that allows zero-length sequences.
  
      Functions as normal for RNN. Only changes output if lengths are defined.
  
      Args:
          x (Union[rnn.PackedSequence, torch.Tensor]): input to RNN. either packed sequence or tensor of
              padded sequences
          hx (HiddenState, optional): hidden state. Defaults to None.
          lengths (torch.LongTensor, optional): lengths of sequences. If not None, used to determine correct returned
              hidden state. Can contain zeros. Defaults to None.
          enforce_sorted (bool, optional): if lengths are passed, determines if RNN expects them to be sorted.
              Defaults to True.
  
      Returns:
          Tuple[Union[rnn.PackedSequence, torch.Tensor], HiddenState]: output and hidden state.
              Output is packed sequence if input has been a packed sequence.
      """
      if isinstance(x, rnn.PackedSequence) or lengths is None:
          assert (
              lengths is None
          ), "cannot combine x of type PackedSequence with lengths argument"
          return super().forward(x, hx=hx)
      else:
          min_length = lengths.min()
          max_length = lengths.max()
          assert (
              min_length >= 0
          ), "sequence lengths must be great equals 0"
  
          if max_length == 0:
              hidden_state = self.init_hidden_state(x)
              if self.batch_first:
                  out = torch.zeros(
                      lengths.size(0),
                      x.size(1),
                      self.hidden_size,
                      dtype=x.dtype,
                      device=x.device,
                  )
              else:
                  out = torch.zeros(
                      x.size(0),
                      lengths.size(0),
                      self.hidden_size,
                      dtype=x.dtype,
                      device=x.device,
                  )
              return out, hidden_state
          else:
              pack_lengths = lengths.where(
                  lengths > 0, torch.ones_like(lengths)
              )
              packed_out, hidden_state = super().forward(
                  rnn.pack_padded_sequence(
                      x,
                      pack_lengths.cpu(),
                      enforce_sorted=enforce_sorted,
                      batch_first=self.batch_first,
                  ),
                  hx=hx,
              )
              # replace hidden cell with initial input if encoder_length is zero to determine correct initial state
              if min_length == 0:
                  no_encoding = (lengths == 0)[
                      None, :, None
                  ]  # shape: n_layers * n_directions x batch_size x hidden_size
                  if hx is None:
                      initial_hidden_state = self.init_hidden_state(x)
                  else:
                      initial_hidden_state = hx
                  # propagate initial hidden state when sequence length was 0
                  hidden_state = self.handle_no_encoding(
                      hidden_state, no_encoding, initial_hidden_state
                  )
  
              # return unpacked sequence
              out, _ = rnn.pad_packed_sequence(
                  packed_out, batch_first=self.batch_first
              )
              return out, hidden_state
  
imports: from abc import ABC, abstractmethod
  from typing import Tuple, Type, Union
  import torch
  from torch import nn
  from torch.nn.utils import rnn
label_desc: Use image node_id 4 for calling the RNN obj's underlying member method code with example usage: obj.forward(x, hx, lengths, enforce_sorted) and returns: super, out,  hidden_state, out,  hidden_state