code: def check_backends_agree(model):
      guide1 = AutoGaussian(model, backend="dense")
      guide2 = AutoGaussian(model, backend="funsor")
      guide1()
      with xfail_if_not_implemented():
          guide2()
  
      # Inject random noise into all unconstrained parameters.
      params1 = dict(guide1.named_parameters())
      params2 = dict(guide2.named_parameters())
      assert set(params1) == set(params2)
      for k, v in params1.items():
          v.data.add_(torch.zeros_like(v).normal_())
          params2[k].data.copy_(v.data)
      names = sorted(params1)
  
      # Check densities agree between backends.
      with torch.no_grad(), poutine.trace() as tr:
          aux = guide2._sample_aux_values(temperature=1.0)
          flat = guide1._dense_flatten(aux)
          tr.trace.compute_log_prob()
      log_prob_funsor = tr.trace.nodes["_AutoGaussianFunsor_latent"][
          "log_prob"
      ]
      with torch.no_grad(), poutine.trace() as tr:
          with poutine.condition(
              data={"_AutoGaussianDense_latent": flat}
          ):
              guide1._sample_aux_values(temperature=1.0)
          tr.trace.compute_log_prob()
      log_prob_dense = tr.trace.nodes["_AutoGaussianDense_latent"][
          "log_prob"
      ]
      assert_equal(log_prob_funsor, log_prob_dense)
  
      # Check Monte Carlo estimate of entropy.
      entropy1 = guide1._dense_get_mvn().entropy()
      with pyro.plate(
          "particle", 100000, dim=-3
      ), poutine.trace() as tr:
          guide2._sample_aux_values(temperature=1.0)
          tr.trace.compute_log_prob()
      entropy2 = -tr.trace.nodes["_AutoGaussianFunsor_latent"][
          "log_prob"
      ].mean()
      assert_close(entropy1, entropy2, atol=1e-2)
      grads1 = torch.autograd.grad(
          entropy1, [params1[k] for k in names], allow_unused=True
      )
      grads2 = torch.autograd.grad(
          entropy2, [params2[k] for k in names], allow_unused=True
      )
      for name, grad1, grad2 in zip(names, grads1, grads2):
          # Gradients should agree to very high precision.
          if grad1 is None and grad2 is not None:
              grad1 = torch.zeros_like(grad2)
          elif grad2 is None and grad1 is not None:
              grad2 = torch.zeros_like(grad1)
          assert_close(grad1, grad2, msg=f"{name}:\n{grad1} vs {grad2}")
  
      # Check elbos agree between backends.
      elbo = Trace_ELBO(num_particles=1000000, vectorize_particles=True)
      loss1 = elbo.differentiable_loss(model, guide1)
      loss2 = elbo.differentiable_loss(model, guide2)
      assert_close(loss1, loss2, atol=1e-2, rtol=0.05)
      grads1 = torch.autograd.grad(
          loss1, [params1[k] for k in names], allow_unused=True
      )
      grads2 = torch.autograd.grad(
          loss2, [params2[k] for k in names], allow_unused=True
      )
      for name, grad1, grad2 in zip(names, grads1, grads2):
          assert_close(
              grad1,
              grad2,
              atol=0.05,
              rtol=0.05,
              msg=f"{name}:\n{grad1} vs {grad2}",
          )
  
imports: from collections import OrderedDict, namedtuple
  import pytest
  import torch
  import pyro
  import pyro.distributions
  import pyro.poutine
  from pyro.infer import SVI, JitTrace_ELBO, Predictive, Trace_ELBO
  from pyro.infer.autoguide import AutoGaussian, AutoGuideList
  from pyro.infer.autoguide.gaussian import AutoGaussianDense, AutoGaussianFunsor, _break_plates
  from pyro.infer.reparam import LocScaleReparam
  from pyro.optim import ClippedAdam
  from tests.common import assert_close, assert_equal, xfail_if_not_implemented
label_desc: Use image node_id 4 for calling a global function with example usage: check_backends_agree(model) without return types