class_docstr: Independent Metropolis-Hastings SMC_kernel
docstr: Independent Metropolis-Hastings perturbation.
docstr_tok: ["Independent","Metropolis-Hastings","perturbation","."]
code: def mutate(self):
      """Independent Metropolis-Hastings perturbation."""
      self.n_steps = 1
      old_corr = 2
      corr = Pearson(self.tempered_posterior)
      ac_ = []
      while True:
          log_R = np.log(self.rng.random(self.draws))
          # The proposal is independent from the current point.
          # We have to take that into account to compute the Metropolis-Hastings acceptance
          # We first compute the logp of proposing a transition to the current points.
          # This variable is updated at the end of the loop with the entries from the accepted
          # transitions, which is equivalent to recomputing it in every iteration of the loop.
          proposal = floatX(
              self.proposal_dist.rvs(
                  size=self.draws, random_state=self.rng
              )
          )
          proposal = proposal.reshape(len(proposal), -1)
          # To do that we compute the logp of moving to a new point
          forward_logp = self.proposal_dist.logpdf(proposal)
          # And to going back from that new point
          backward_logp = self.proposal_dist.logpdf(
              self.tempered_posterior
          )
          ll = np.array(
              [self.likelihood_logp_func(prop) for prop in proposal]
          )
          pl = np.array(
              [self.prior_logp_func(prop) for prop in proposal]
          )
          proposal_logp = pl + ll * self.beta
          accepted = log_R < (
              (proposal_logp + backward_logp)
              - (self.tempered_posterior_logp + forward_logp)
          )
  
          self.tempered_posterior[accepted] = proposal[accepted]
          self.tempered_posterior_logp[accepted] = proposal_logp[
              accepted
          ]
          self.prior_logp[accepted] = pl[accepted]
          self.likelihood_logp[accepted] = ll[accepted]
          ac_.append(accepted)
          self.n_steps += 1
  
          pearson_r = corr.get(self.tempered_posterior)
          if (
              np.mean(
                  (old_corr - pearson_r) > self.correlation_threshold
              )
              > 0.9
          ):
              old_corr = pearson_r
          else:
              break
  
      self.acc_rate = np.mean(ac_)
  
imports: import abc
  import sys
  import warnings
  from abc import ABC
  from typing import Dict, Union, cast
  import numpy
  import pytensor.tensor
  from pytensor.graph.replace import clone_replace
  from scipy.special import logsumexp
  from scipy.stats import multivariate_normal
  from typing_extensions import TypeAlias
  from pymc.backends.ndarray import NDArray
  from pymc.blocking import DictToArrayBijection
  from pymc.initial_point import make_initial_point_expression
  from pymc.model import Point, modelcontext
  from pymc.pytensorf import compile_pymc, floatX, join_nonshared_inputs, make_shared_replacements
  from pymc.sampling.forward import draw
  from pymc.step_methods.metropolis import MultivariateNormalProposal
  from pymc.vartypes import discrete_types
label_desc: Use image node_id 3 for calling the IMH obj's underlying member method code with example usage: obj.mutate() without return types