class_docstr: Hidden Markov Model with Gaussians for initial, transition, and observation
  distributions. This adapts [1] to parallelize over time to achieve
  O(log(time)) parallel complexity, however it differs in that it tracks the
  log normalizer to ensure :meth:`log_prob` is differentiable.
  
  This corresponds to the generative model::
  
      z = initial_distribution.sample()
      x = []
      for t in range(num_events):
          z = z @ transition_matrix + transition_dist.sample()
          x.append(z @ observation_matrix + observation_dist.sample())
  
  The event_shape of this distribution includes time on the left::
  
      event_shape = (num_steps,) + observation_dist.event_shape
  
  This distribution supports any combination of homogeneous/heterogeneous
  time dependency of ``transition_dist`` and ``observation_dist``. However,
  because time is included in this distribution's event_shape, the
  homogeneous+homogeneous case will have a broadcastable event_shape with
  ``num_steps = 1``, allowing :meth:`log_prob` to work with arbitrary length
  data::
  
      event_shape = (1, obs_dim)  # homogeneous + homogeneous case
  
  **References:**
  
  [1] Simo Sarkka, Angel F. Garcia-Fernandez (2019)
      "Temporal Parallelization of Bayesian Filters and Smoothers"
      https://arxiv.org/pdf/1905.13002.pdf
  
  :ivar int hidden_dim: The dimension of the hidden state.
  :ivar int obs_dim: The dimension of the observed state.
  :param ~torch.distributions.MultivariateNormal initial_dist: A distribution
      over initial states. This should have batch_shape broadcastable to
      ``self.batch_shape``.  This should have event_shape ``(hidden_dim,)``.
  :param ~torch.Tensor transition_matrix: A linear transformation of hidden
      state. This should have shape broadcastable to
      ``self.batch_shape + (num_steps, hidden_dim, hidden_dim)`` where the
      rightmost dims are ordered ``(old, new)``.
  :param ~torch.distributions.MultivariateNormal transition_dist: A process
      noise distribution. This should have batch_shape broadcastable to
      ``self.batch_shape + (num_steps,)``.  This should have event_shape
      ``(hidden_dim,)``.
  :param ~torch.Tensor observation_matrix: A linear transformation from hidden
      to observed state. This should have shape broadcastable to
      ``self.batch_shape + (num_steps, hidden_dim, obs_dim)``.
  :param observation_dist: An observation noise distribution. This should
      have batch_shape broadcastable to ``self.batch_shape + (num_steps,)``.
      This should have event_shape ``(obs_dim,)``.
  :type observation_dist: ~torch.distributions.MultivariateNormal or
      ~torch.distributions.Independent of ~torch.distributions.Normal
  :param int duration: Optional size of the time axis ``event_shape[0]``.
      This is required when sampling from homogeneous HMMs whose parameters
      are not expanded along the time axis.
class_docstr_tok: ["Hidden","Markov","Model","with","Gaussians","for","initial",",","transition",",","and","observation","distributions",".","This","adapts","[","1","]","to","parallelize","over","time","to","achieve","O","(","log","(","time",")",")","parallel","complexity",",","however","it","differs","in","that","it","tracks","the","log","normalizer","to","ensure",":","meth",":","`","log_prob","`","is","differentiable",".","This","corresponds","to","the","generative","model",":",":","z","=","initial_distribution.sample","(",")","x","=","[","]","for","t","in","range","(","num_events",")",":","z","=","z","@","transition_matrix","+","transition_dist.sample","(",")","x.append","(","z","@","observation_matrix","+","observation_dist.sample","(",")",")","The","event_shape","of","this","distribution","includes","time","on","the","left",":",":","event_shape","=","(","num_steps",",",")","+","observation_dist.event_shape","This","distribution","supports","any","combination","of","homogeneous\/heterogeneous","time","dependency","of","``","transition_dist","``","and","``","observation_dist","``",".","However",",","because","time","is","included","in","this","distribution","'s","event_shape",",","the","homogeneous+homogeneous","case","will","have","a","broadcastable","event_shape","with","``","num_steps","=","1","``",",","allowing",":","meth",":","`","log_prob","`","to","work","with","arbitrary","length","data",":",":","event_shape","=","(","1",",","obs_dim",")","#","homogeneous","+","homogeneous","case","*","*","References",":","*","*","[","1","]","Simo","Sarkka",",","Angel","F.","Garcia-Fernandez","(","2019",")","``","Temporal","Parallelization","of","Bayesian","Filters","and","Smoothers","''","https",":","\/\/arxiv.org\/pdf\/1905.13002.pdf",":","ivar","int","hidden_dim",":","The","dimension","of","the","hidden","state",".",":","ivar","int","obs_dim",":","The","dimension","of","the","observed","state",".",":","param","~torch.distributions.MultivariateNormal","initial_dist",":","A","distribution","over","initial","states",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","``",".","This","should","have","event_shape","``","(","hidden_dim",",",")","``",".",":","param","~torch.Tensor","transition_matrix",":","A","linear","transformation","of","hidden","state",".","This","should","have","shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",","hidden_dim",",","hidden_dim",")","``","where","the","rightmost","dims","are","ordered","``","(","old",",","new",")","``",".",":","param","~torch.distributions.MultivariateNormal","transition_dist",":","A","process","noise","distribution",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","hidden_dim",",",")","``",".",":","param","~torch.Tensor","observation_matrix",":","A","linear","transformation","from","hidden","to","observed","state",".","This","should","have","shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",","hidden_dim",",","obs_dim",")","``",".",":","param","observation_dist",":","An","observation","noise","distribution",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","obs_dim",",",")","``",".",":","type","observation_dist",":","~torch.distributions.MultivariateNormal","or","~torch.distributions.Independent","of","~torch.distributions.Normal",":","param","int","duration",":","Optional","size","of","the","time","axis","``","event_shape","[","0","]","``",".","This","is","required","when","sampling","from","homogeneous","HMMs","whose","parameters","are","not","expanded","along","the","time","axis","."]
code: def log_prob(self, value):
      if self._validate_args:
          self._validate_sample(value)
  
      # Combine observation and transition factors.
      result = self._trans + self._obs.condition(value).event_pad(
          left=self.hidden_dim
      )
  
      # Eliminate time dimension.
      result = sequential_gaussian_tensordot(
          result.expand(result.batch_shape)
      )
  
      # Combine initial factor.
      result = gaussian_tensordot(
          self._init, result, dims=self.hidden_dim
      )
  
      # Marginalize out final state.
      result = result.event_logsumexp()
      return result
  
imports: import torch
  import torch.nn.functional
  from pyro.ops.gamma_gaussian import GammaGaussian, gamma_and_mvn_to_gamma_gaussian, gamma_gaussian_tensordot, matrix_and_mvn_to_gamma_gaussian
  from pyro.ops.gaussian import Gaussian, gaussian_tensordot, matrix_and_mvn_to_gaussian, mvn_to_gaussian, sequential_gaussian_filter_sample, sequential_gaussian_tensordot
  from pyro.ops.indexing import Vindex
  from pyro.ops.special import safe_log
  from pyro.ops.tensor_utils import cholesky_solve, safe_cholesky
  from .None import constraints
  from .torch import Categorical, Gamma, Independent, MultivariateNormal
  from .torch_distribution import TorchDistribution
  from .util import broadcast_shape, torch_jit_script_if_tracing
label_desc: Use image node_id 3 for calling the GaussianHMM obj's underlying member method code with example usage: obj.log_prob(value) and returns: result