class_docstr: Profile HMM state arrangement. Parameterizes an HMM according to
  Equation S40 in [1] (with r_{M+1,j} = 1 and u_{M+1,j} = 0
  for j in {0, 1, 2}). For further background on profile HMMs see [2].
  
  **References**
  
  [1] E. N. Weinstein, D. S. Marks (2021)
  "Generative probabilistic biological sequence models that account for
  mutational variability"
  https://www.biorxiv.org/content/10.1101/2020.07.31.231381v2.full.pdf
  
  [2] R. Durbin, S. R. Eddy, A. Krogh, and G. Mitchison (1998)
  "Biological sequence analysis: probabilistic models of proteins and nucleic
  acids"
  Cambridge university press
  
  :param M: Length of regressor sequence.
  :type M: int
  :param epsilon: A small value for numerical stability.
  :type epsilon: float
docstr: Set up linear transformations (transfer matrices) for converting
  from profile HMM parameters to standard HMM parameters.
docstr_tok: ["Set","up","linear","transformations","(","transfer","matrices",")","for","converting","from","profile","HMM","parameters","to","standard","HMM","parameters","."]
code: def _make_transfer(self):
      """Set up linear transformations (transfer matrices) for converting
      from profile HMM parameters to standard HMM parameters."""
      M, K = self.M, self.K
  
      # Overview:
      # r -> insertion parameters
      # u -> deletion parameters
      # indices: m in {0, ..., M} and j in {0, 1, 2}; final index corresponds
      # to simplex dimensions, i.e. 1 - r and r (in that order)
      # null -> locations in the transition matrix equal to 0
      # ...transf_0 -> initial transition vector
      # ...transf -> transition matrix
      # We fix r_{M+1,j} = 1 for j in {0, 1, 2}
      self.register_buffer("r_transf_0", torch.zeros((M, 3, 2, K)))
      self.register_buffer("u_transf_0", torch.zeros((M, 3, 2, K)))
      self.register_buffer("null_transf_0", torch.zeros((K,)))
      m, g = -1, 0
      for gp in range(2):
          for mp in range(M + gp):
              kp = mg2k(mp, gp, M)
              if m + 1 - g == mp and gp == 0:
                  self.r_transf_0[m + 1 - g, g, 0, kp] = 1
                  self.u_transf_0[m + 1 - g, g, 0, kp] = 1
  
              elif m + 1 - g < mp and gp == 0:
                  self.r_transf_0[m + 1 - g, g, 0, kp] = 1
                  self.u_transf_0[m + 1 - g, g, 1, kp] = 1
                  for mpp in range(m + 2 - g, mp):
                      self.r_transf_0[mpp, 2, 0, kp] = 1
                      self.u_transf_0[mpp, 2, 1, kp] = 1
                  self.r_transf_0[mp, 2, 0, kp] = 1
                  self.u_transf_0[mp, 2, 0, kp] = 1
  
              elif m + 1 - g == mp and gp == 1:
                  if mp < M:
                      self.r_transf_0[m + 1 - g, g, 1, kp] = 1
  
              elif m + 1 - g < mp and gp == 1:
                  self.r_transf_0[m + 1 - g, g, 0, kp] = 1
                  self.u_transf_0[m + 1 - g, g, 1, kp] = 1
                  for mpp in range(m + 2 - g, mp):
                      self.r_transf_0[mpp, 2, 0, kp] = 1
                      self.u_transf_0[mpp, 2, 1, kp] = 1
                  if mp < M:
                      self.r_transf_0[mp, 2, 1, kp] = 1
  
              else:
                  self.null_transf_0[kp] = 1
  
      self.register_buffer("r_transf", torch.zeros((M, 3, 2, K, K)))
      self.register_buffer("u_transf", torch.zeros((M, 3, 2, K, K)))
      self.register_buffer("null_transf", torch.zeros((K, K)))
      for g in range(2):
          for m in range(M + g):
              for gp in range(2):
                  for mp in range(M + gp):
                      k, kp = mg2k(m, g, M), mg2k(mp, gp, M)
                      if m + 1 - g == mp and gp == 0:
                          self.r_transf[m + 1 - g, g, 0, k, kp] = 1
                          self.u_transf[m + 1 - g, g, 0, k, kp] = 1
  
                      elif m + 1 - g < mp and gp == 0:
                          self.r_transf[m + 1 - g, g, 0, k, kp] = 1
                          self.u_transf[m + 1 - g, g, 1, k, kp] = 1
                          self.r_transf[
                              (m + 2 - g) : mp, 2, 0, k, kp
                          ] = 1
                          self.u_transf[
                              (m + 2 - g) : mp, 2, 1, k, kp
                          ] = 1
                          self.r_transf[mp, 2, 0, k, kp] = 1
                          self.u_transf[mp, 2, 0, k, kp] = 1
  
                      elif m + 1 - g == mp and gp == 1:
                          if mp < M:
                              self.r_transf[m + 1 - g, g, 1, k, kp] = 1
  
                      elif m + 1 - g < mp and gp == 1:
                          self.r_transf[m + 1 - g, g, 0, k, kp] = 1
                          self.u_transf[m + 1 - g, g, 1, k, kp] = 1
                          self.r_transf[
                              (m + 2 - g) : mp, 2, 0, k, kp
                          ] = 1
                          self.u_transf[
                              (m + 2 - g) : mp, 2, 1, k, kp
                          ] = 1
                          if mp < M:
                              self.r_transf[mp, 2, 1, k, kp] = 1
  
                      else:
                          self.null_transf[k, kp] = 1
  
      self.register_buffer("vx_transf", torch.zeros((M, K)))
      self.register_buffer("vc_transf", torch.zeros((M + 1, K)))
      for g in range(2):
          for m in range(M + g):
              k = mg2k(m, g, M)
              if g == 0:
                  self.vx_transf[m, k] = 1
              elif g == 1:
                  self.vc_transf[m, k] = 1
  
file_path: pyro/pyro/contrib/mue/statearrangers.py
imports: import torch
  import torch.nn
label_desc: Use image node_id 2 for calling the Profile obj's underlying member method code with example usage: obj._make_transfer() without return types