class_docstr: Compare various KF EnKF versions.
  
  If the model is linear and Gaussian the EnKF sample mean/cov and marginal
  likelihood converges to that of a KF in the large ensemble limit.
  This class tests that they are the same. It does that by implementing a
  one-step KF. It also does some simple checks on the KF, to make sure we didn't
  just replicate misunderstanding in the EnKF.
  
  This class also checks that various flavors of the EnKF are the same.
docstr: Check that two sets of kwargs give same result.
docstr_tok: ["Check","that","two","sets","of","kwargs","give","same","result","."]
code: def test_cases_where_different_kwargs_give_same_enkf_result(
      self,
      kwargs_1,
      kwargs_2,
      n_states=5,
      n_observations=5,
      n_ensemble=10,
  ):
      """Check that two sets of kwargs give same result."""
      # In most cases, `test_kf_vs_enkf` is more complete, since it tests
      # correctness. However, `test_kf_vs_enkf` requires a huge ensemble.
      # This test is useful when you cannot use a huge ensemble and/or you want to
      # compare to a method already checked for correctness by `test_kf_vs_enkf`.
      salt = str(n_ensemble) + str(n_states) + str(n_observations)
      seed_stream = test_util.test_seed_stream(salt)
      dtype = tf.float64
  
      linear_model_params = self._get_linear_model_params(
          noise_level=0.1,
          n_states=n_states,
          n_observations=n_observations,
          seed_stream=seed_stream,
          dtype=dtype,
      )
  
      # Ensure that our observation comes from a state that ~ prior.
      prior_dist = mvn_tril.MultivariateNormalTriL(
          loc=linear_model_params.prior_mean,
          scale_tril=tf.linalg.cholesky(linear_model_params.prior_cov),
      )
      true_state = prior_dist.sample(seed=seed_stream())
      observation = tf.linalg.matvec(
          linear_model_params.observation_mat, true_state
      )
  
      enkf_params = self._get_enkf_params(
          n_ensemble,
          linear_model_params,
          prior_dist,
          seed_stream,
          dtype,
      )
  
      # Use the exact same seeds for each.
      enkf_soln_1 = self._enkf_solve(
          observation,
          enkf_params,
          kwargs_1["predict"],
          kwargs_1["update"],
          kwargs_1["log_marginal_likelihood"],
          test_util.test_seed_stream(salt),
      )
      enkf_soln_2 = self._enkf_solve(
          observation,
          enkf_params,
          kwargs_2["predict"],
          kwargs_2["update"],
          kwargs_2["log_marginal_likelihood"],
          test_util.test_seed_stream(salt),
      )
  
      # Evaluate at the same time, so both use the same randomness!
      # Do not use anything that was not evaluated here!
      enkf_soln_1, enkf_soln_2 = self.evaluate(
          [enkf_soln_1, enkf_soln_2]
      )
  
      # We used the same seed, so solutions should be identical up to tolerance of
      # different solver methods.
      self.assertAllCloseNested(enkf_soln_1, enkf_soln_2)
  
imports: import collections
  from absl.testing import parameterized
  import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.distributions import joint_distribution_named
  from tensorflow_probability.python.distributions import mvn_diag
  from tensorflow_probability.python.distributions import mvn_tril
  from tensorflow_probability.python.distributions import poisson
  from tensorflow_probability.python.experimental.sequential import ensemble_kalman_filter
  from tensorflow_probability.python.internal import test_combinations
  from tensorflow_probability.python.internal import test_util
  from tensorflow_probability.python.stats import sample_stats
label_desc: Use image node_id 7 for calling the ComparingMethodsTest obj's underlying member method code with example usage: obj.test_cases_where_different_kwargs_give_same_enkf_result(kwargs_1, kwargs_2, n_states, n_observations, n_ensemble) without return types