class_docstr: Temporal Markov Random Field with Gaussian factors 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.
  
  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.distributions.MultivariateNormal transition_dist: A joint
      distribution factor over a pair of successive time steps. This should
      have batch_shape broadcastable to ``self.batch_shape + (num_steps,)``.
      This should have event_shape ``(hidden_dim + hidden_dim,)`` (old+new).
  :param ~torch.distributions.MultivariateNormal observation_dist: A joint
      distribution factor over a hidden and an observed state. This should
      have batch_shape broadcastable to ``self.batch_shape + (num_steps,)``.
      This should have event_shape ``(hidden_dim + obs_dim,)``.
class_docstr_tok: ["Temporal","Markov","Random","Field","with","Gaussian","factors","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",".","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.distributions.MultivariateNormal","transition_dist",":","A","joint","distribution","factor","over","a","pair","of","successive","time","steps",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","hidden_dim","+","hidden_dim",",",")","``","(","old+new",")",".",":","param","~torch.distributions.MultivariateNormal","observation_dist",":","A","joint","distribution","factor","over","a","hidden","and","an","observed","state",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","hidden_dim","+","obs_dim",",",")","``","."]
code: def __init__(
      self,
      initial_dist,
      transition_dist,
      observation_dist,
      validate_args=None,
  ):
      assert isinstance(
          initial_dist, torch.distributions.MultivariateNormal
      )
      assert isinstance(
          transition_dist, torch.distributions.MultivariateNormal
      )
      assert isinstance(
          observation_dist, torch.distributions.MultivariateNormal
      )
      hidden_dim = initial_dist.event_shape[0]
      assert transition_dist.event_shape[0] == hidden_dim + hidden_dim
      obs_dim = observation_dist.event_shape[0] - hidden_dim
  
      shape = broadcast_shape(
          initial_dist.batch_shape + (1,),
          transition_dist.batch_shape,
          observation_dist.batch_shape,
      )
      batch_shape, time_shape = shape[:-1], shape[-1:]
      event_shape = time_shape + (obs_dim,)
      super().__init__(
          batch_shape, event_shape, validate_args=validate_args
      )
      self.hidden_dim = hidden_dim
      self.obs_dim = obs_dim
      self._init = mvn_to_gaussian(initial_dist)
      self._trans = mvn_to_gaussian(transition_dist)
      self._obs = mvn_to_gaussian(observation_dist)
      self._support = constraints.independent(
          observation_dist.support, 1
      )
  
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 1 to create a new GaussianMRF object from inherited base classes: TorchDistribution with example: obj = GaussianMRF(initial_dist, transition_dist, observation_dist, validate_args)