code: def forward_backward_algorithm(
      factors: List[Funsor],
      step: Dict[str, str],
  ) -> List[Tensor]:
      """
      Calculate marginal probabilities:
      p(x[t], x[t-1] | Y)
      """
      step = OrderedDict(sorted(step.items()))
      drop = tuple("_drop_{}".format(i) for i in range(len(step)))
      prev_to_drop = dict(zip(step.keys(), drop))
      curr_to_drop = dict(zip(step.values(), drop))
      reduce_vars = frozenset(drop)
  
      # Base cases
      alpha = factors[0]  # alpha[0] = p(y[0], x[0])
      beta = Tensor(
          ops.full_like(alpha.data, 0.0), alpha(x_curr="x_prev").inputs
      )  # beta[T] = 1
  
      # Backward algorithm
      # beta[t] = p(y[t+1:T] | x[t])
      # beta[t] = trans[t+1] @ beta[t+1]
      betas = [beta]
      for trans in factors[:0:-1]:
          beta = (trans(**curr_to_drop) + beta(**prev_to_drop)).reduce(
              ops.logaddexp, reduce_vars
          )
          betas.append(beta)
      else:
          init = factors[0]
          Z = (init(**curr_to_drop) + beta(**prev_to_drop)).reduce(
              ops.logaddexp, reduce_vars
          )
      betas.reverse()
  
      # Forward algorithm & Marginal computations
      marginal = (
          alpha + betas[0](**{"x_prev": "x_curr"}) - Z
      )  # p(x[0] | Y)
      marginals = [marginal]
      # inductive steps
      for trans, beta in zip(factors[1:], betas[1:]):
          # alpha[t-1] * trans[t] = p(y[0:t], x[t-1], x[t])
          alpha_trans = alpha(**{"x_curr": "x_prev"}) + trans
          # alpha[t] = p(y[0:t], x[t])
          alpha = alpha_trans.reduce(ops.logaddexp, "x_prev")
          # alpha[t-1] * trans[t] * beta[t] / Z = p(x[t-1], x[t] | Y)
          marginal = alpha_trans + beta(**{"x_prev": "x_curr"}) - Z
          marginals.append(marginal)
  
      return marginals
  
file_path: funsor/examples/forward_backward.py
imports: import argparse
  from collections import OrderedDict
  from typing import Dict, List, Tuple
  import funsor.ops
  from funsor import Funsor, Tensor
  from funsor.adjoint import AdjointTape
  from funsor.domains import Bint
  from funsor.testing import assert_close, random_tensor
label_desc: Use image node_id 2 for calling a global function with example usage: forward_backward_algorithm(factors, step) and returns: marginals