class_docstr: Lazy representation of :func:`sequential_sum_product` .
  
  :param AssociativeOp sum_op: A marginalization op.
  :param AssociativeOp prod_op: A Bayesian fusion op.
  :param Funsor trans: A sequence of transition factors,
      usually varying along the ``time`` input.
  :param time: A time dimension.
  :type time: str or Variable
  :param dict step: A str-to-str mapping of "previous" inputs of ``trans``
      to "current" inputs of ``trans``.
  :param dict step_names: Optional, for internal use by alpha conversion.
code: def __init__(self, sum_op, prod_op, trans, time, step, step_names):
      assert isinstance(sum_op, AssociativeOp)
      assert isinstance(prod_op, AssociativeOp)
      assert isinstance(trans, Funsor)
      assert isinstance(time, Variable)
      assert isinstance(step, frozenset)
      assert isinstance(step_names, frozenset)
      step = dict(step)
      step_names = dict(step_names)
      assert all(isinstance(k, str) for k in step_names.keys())
      assert all(isinstance(v, str) for v in step_names.values())
      assert set(step_names) == set(step).union(step.values())
      inputs = OrderedDict(
          (step_names.get(k, k), v)
          for k, v in trans.inputs.items()
          if k != time.name
      )
      output = trans.output
      fresh = frozenset(step_names.values())
      bound = {k: trans.inputs[k] for k in step_names}
      bound[time.name] = time.output
      super().__init__(inputs, output, fresh, bound)
      self.sum_op = sum_op
      self.prod_op = prod_op
      self.trans = trans
      self.time = time
      self.step = step
      self.step_names = step_names
  
imports: import re
  from collections import OrderedDict, defaultdict
  from functools import reduce
  from math import gcd
  import funsor
  import funsor.ops
  from funsor.cnf import Contraction
  from funsor.domains import Bint, Reals
  from funsor.interpreter import gensym
  from funsor.ops import PRODUCT_TO_POWER, UNITS, AssociativeOp
  from funsor.terms import Cat, Funsor, FunsorMeta, Number, Slice, Stack, Subs, Variable, eager, substitute, to_funsor
  from funsor.util import quote
label_desc: Use image node_id 1 to create a new MarkovProduct object from inherited base classes: Funsor with example: obj = MarkovProduct(sum_op, prod_op, trans, time, step, step_names)