class_docstr: A hidden Markov model with a dense transition matrix.
  
  A hidden Markov model is an extension of a mixture model to sequences by
  including a transition matrix between the elements of the mixture. Each of
  the algorithms for a hidden Markov model are essentially just a revision
  of those algorithms to incorporate this transition matrix.
  
  This object is a wrapper for a hidden Markov model with a dense transition
  matrix.
  
  This object is a wrapper for both implementations, which can be specified
  using the `kind` parameter. Choosing the right implementation will not
  effect the accuracy of the results but will change the speed at which they
  are calculated.         
  
  Separately, there are two ways to instantiate the hidden Markov model. The
  first is by passing in a set of distributions, a dense transition matrix, 
  and optionally start/end probabilities. The second is to initialize the
  object without these and then to add edges using the `add_edge` method
  and to add distributions using the `add_distributions` method. Importantly, the way that
  you choose to initialize the hidden Markov model is independent of the
  implementation that you end up choosing. If you pass in a dense transition
  matrix, this will be converted to a sparse matrix with all the zeros
  dropped if you choose `kind='sparse'`.
  
  
  Parameters
  ----------
  distributions: tuple or list
          A set of distribution objects. These objects do not need to be
          initialized, i.e., can be "Normal()". 
  
  edges: numpy.ndarray, torch.Tensor, or None. shape=(k,k), optional
          A dense transition matrix of probabilities for how each node or
          distribution passed in connects to each other one. This can contain
          many zeroes, and when paired with `kind='sparse'`, will drop those
          elements from the matrix.
  
  starts: list, numpy.ndarray, torch.Tensor, or None. shape=(k,), optional
          The probability of starting at each node. If not provided, assumes
          these probabilities are uniform.
  
  ends: list, numpy.ndarray, torch.Tensor, or None. shape=(k,), optional
          The probability of ending at each node. If not provided, assumes
          these probabilities are uniform.
  
  inertia: float, [0, 1], optional
          Indicates the proportion of the update to apply to the parameters
          during training. When the inertia is 0.0, the update is applied in
          its entirety and the previous parameters are ignored. When the
          inertia is 1.0, the update is entirely ignored and the previous
          parameters are kept, equivalently to if the parameters were frozen.
  
  frozen: bool, optional
          Whether all the parameters associated with this distribution are frozen.
          If you want to freeze individual pameters, or individual values in those
          parameters, you must modify the `frozen` attribute of the tensor or
          parameter directly. Default is False.
  
  check_data: bool, optional
          Whether to check properties of the data and potentially recast it to
          torch.tensors. This does not prevent checking of parameters but can
          slightly speed up computation when you know that your inputs are valid.
          Setting this to False is also necessary for compiling. Default is True.
class_docstr_tok: ["A","hidden","Markov","model","with","a","dense","transition","matrix",".","A","hidden","Markov","model","is","an","extension","of","a","mixture","model","to","sequences","by","including","a","transition","matrix","between","the","elements","of","the","mixture",".","Each","of","the","algorithms","for","a","hidden","Markov","model","are","essentially","just","a","revision","of","those","algorithms","to","incorporate","this","transition","matrix",".","This","object","is","a","wrapper","for","a","hidden","Markov","model","with","a","dense","transition","matrix",".","This","object","is","a","wrapper","for","both","implementations",",","which","can","be","specified","using","the","`","kind","`","parameter",".","Choosing","the","right","implementation","will","not","effect","the","accuracy","of","the","results","but","will","change","the","speed","at","which","they","are","calculated",".","Separately",",","there","are","two","ways","to","instantiate","the","hidden","Markov","model",".","The","first","is","by","passing","in","a","set","of","distributions",",","a","dense","transition","matrix",",","and","optionally","start\/end","probabilities",".","The","second","is","to","initialize","the","object","without","these","and","then","to","add","edges","using","the","`","add_edge","`","method","and","to","add","distributions","using","the","`","add_distributions","`","method",".","Importantly",",","the","way","that","you","choose","to","initialize","the","hidden","Markov","model","is","independent","of","the","implementation","that","you","end","up","choosing",".","If","you","pass","in","a","dense","transition","matrix",",","this","will","be","converted","to","a","sparse","matrix","with","all","the","zeros","dropped","if","you","choose","`","kind='sparse","'","`",".","Parameters","--","--","--","--","--","distributions",":","tuple","or","list","A","set","of","distribution","objects",".","These","objects","do","not","need","to","be","initialized",",","i.e.",",","can","be","``","Normal","(",")","''",".","edges",":","numpy.ndarray",",","torch.Tensor",",","or","None",".","shape=","(","k",",","k",")",",","optional","A","dense","transition","matrix","of","probabilities","for","how","each","node","or","distribution","passed","in","connects","to","each","other","one",".","This","can","contain","many","zeroes",",","and","when","paired","with","`","kind='sparse","'","`",",","will","drop","those","elements","from","the","matrix",".","starts",":","list",",","numpy.ndarray",",","torch.Tensor",",","or","None",".","shape=","(","k",",",")",",","optional","The","probability","of","starting","at","each","node",".","If","not","provided",",","assumes","these","probabilities","are","uniform",".","ends",":","list",",","numpy.ndarray",",","torch.Tensor",",","or","None",".","shape=","(","k",",",")",",","optional","The","probability","of","ending","at","each","node",".","If","not","provided",",","assumes","these","probabilities","are","uniform",".","inertia",":","float",",","[","0",",","1","]",",","optional","Indicates","the","proportion","of","the","update","to","apply","to","the","parameters","during","training",".","When","the","inertia","is","0.0",",","the","update","is","applied","in","its","entirety","and","the","previous","parameters","are","ignored",".","When","the","inertia","is","1.0",",","the","update","is","entirely","ignored","and","the","previous","parameters","are","kept",",","equivalently","to","if","the","parameters","were","frozen",".","frozen",":","bool",",","optional","Whether","all","the","parameters","associated","with","this","distribution","are","frozen",".","If","you","want","to","freeze","individual","pameters",",","or","individual","values","in","those","parameters",",","you","must","modify","the","`","frozen","`","attribute","of","the","tensor","or","parameter","directly",".","Default","is","False",".","check_data",":","bool",",","optional","Whether","to","check","properties","of","the","data","and","potentially","recast","it","to","torch.tensors",".","This","does","not","prevent","checking","of","parameters","but","can","slightly","speed","up","computation","when","you","know","that","your","inputs","are","valid",".","Setting","this","to","False","is","also","necessary","for","compiling",".","Default","is","True","."]
docstr: Sample from the probability distribution.
  
  This method will return `n` samples generated from the underlying
  probability distribution. Because a HMM describes variable length
  sequences, a list will be returned where each element is one of
  the generated sequences.
  
  
  Parameters
  ----------
  n: int
          The number of samples to generate.
  
  
  Returns
  -------
  X: list of torch.tensor, shape=(n,)
          A list of randomly generated samples, where each sample of
          size (length, self.d).
docstr_tok: ["Sample","from","the","probability","distribution",".","This","method","will","return","`","n","`","samples","generated","from","the","underlying","probability","distribution",".","Because","a","HMM","describes","variable","length","sequences",",","a","list","will","be","returned","where","each","element","is","one","of","the","generated","sequences",".","Parameters","--","--","--","--","--","n",":","int","The","number","of","samples","to","generate",".","Returns","--","--","--","-","X",":","list","of","torch.tensor",",","shape=","(","n",",",")","A","list","of","randomly","generated","samples",",","where","each","sample","of","size","(","length",",","self.d",")","."]
code: def sample(self, n):
      """Sample from the probability distribution.
  
      This method will return `n` samples generated from the underlying
      probability distribution. Because a HMM describes variable length
      sequences, a list will be returned where each element is one of
      the generated sequences.
  
  
      Parameters
      ----------
      n: int
              The number of samples to generate.
  
  
      Returns
      -------
      X: list of torch.tensor, shape=(n,)
              A list of randomly generated samples, where each sample of
              size (length, self.d).
      """
  
      if self.sample_length is None and self.ends is None:
          raise ValueError(
              "Must specify a length or have explicit "
              + "end probabilities."
          )
  
      distributions, emissions = [], []
  
      edge_probs = torch.hstack([self.edges, self.ends.unsqueeze(1)])
      edge_probs = torch.exp(edge_probs).numpy()
  
      starts = torch.exp(self.starts).numpy()
  
      for _ in range(n):
          node_i = self.random_state.choice(
              self.n_distributions, p=starts
          )
          emission_i = self.distributions[node_i].sample(n=1)
          distributions_, emissions_ = [node_i], [emission_i]
  
          for i in range(1, self.sample_length or int(1e8)):
              node_i = self.random_state.choice(
                  self.n_distributions + 1, p=edge_probs[node_i]
              )
  
              if node_i == self.n_distributions:
                  break
  
              emission_i = self.distributions[node_i].sample(n=1)
  
              distributions_.append(node_i)
              emissions_.append(emission_i)
  
          distributions.append(distributions_)
          emissions.append(torch.vstack(emissions_))
  
      if self.return_sample_paths == True:
          return emissions, distributions
      return emissions
  
imports: import math
  import numpy
  import torch
  from .._utils import _cast_as_tensor
  from .._utils import _cast_as_parameter
  from .._utils import _update_parameter
  from .._utils import _check_parameter
  from ..distributions._distribution import Distribution
  from ._base import _BaseHMM
  from ._base import _check_inputs
label_desc: Use image node_id 5 for calling the DenseHMM obj's underlying member method code with example usage: obj.sample(n) and returns: emissions, emissions,  distributions