class_docstr: Policy Gradient with Parameter-based Exploration (PGPE) algorithm.
  
  Ref: https://people.idsia.ch/~juergen/icann2008sehnke.pdf
docstr: Initialization function.
  
  Args:
      pop_size - Population size.
      param_size - Parameter size.
      init_params - Initial parameters, all zeros if not given.
      optimizer - Possible values are {None, 'adam', 'clipup'}.
      optimizer_config - Configurations specific to the optimizer.
                         For None: No configuration is required.
                         For Adam: {'epsilon', 'beta1', 'beta2'}.
                         For ClipUp: {'momentum', 'max_speed'}.
      center_learning_rate - Learning rate for the Gaussian mean.
      stdev_learning_rate - Learning rate for the Gaussian stdev.
      init_stdev - Initial stdev for the Gaussian distribution.
      stdev_max_change - Maximum allowed change for stdev in abs values.
      solution_ranking - Should we treat the fitness as rankings or not.
      seed - Random seed for parameters sampling.
docstr_tok: ["Initialization","function",".","Args",":","pop_size","-","Population","size",".","param_size","-","Parameter","size",".","init_params","-","Initial","parameters",",","all","zeros","if","not","given",".","optimizer","-","Possible","values","are","{","None",",","'adam","'",",","'clipup","'","}",".","optimizer_config","-","Configurations","specific","to","the","optimizer",".","For","None",":","No","configuration","is","required",".","For","Adam",":","{","'epsilon","'",",","'beta1","'",",","'beta2","'","}",".","For","ClipUp",":","{","'momentum","'",",","'max_speed","'","}",".","center_learning_rate","-","Learning","rate","for","the","Gaussian","mean",".","stdev_learning_rate","-","Learning","rate","for","the","Gaussian","stdev",".","init_stdev","-","Initial","stdev","for","the","Gaussian","distribution",".","stdev_max_change","-","Maximum","allowed","change","for","stdev","in","abs","values",".","solution_ranking","-","Should","we","treat","the","fitness","as","rankings","or","not",".","seed","-","Random","seed","for","parameters","sampling","."]
code: def __init__(
      self,
      pop_size: int,
      param_size: int,
      init_params: Optional[Union[jnp.ndarray, np.ndarray]] = None,
      optimizer: Optional[str] = None,
      optimizer_config: Optional[dict] = None,
      center_learning_rate: float = 0.15,
      stdev_learning_rate: float = 0.1,
      init_stdev: Union[float, jnp.ndarray, np.ndarray] = 0.1,
      stdev_max_change: float = 0.2,
      solution_ranking: bool = True,
      seed: int = 0,
      logger: logging.Logger = None,
  ):
      """Initialization function.
  
      Args:
          pop_size - Population size.
          param_size - Parameter size.
          init_params - Initial parameters, all zeros if not given.
          optimizer - Possible values are {None, 'adam', 'clipup'}.
          optimizer_config - Configurations specific to the optimizer.
                             For None: No configuration is required.
                             For Adam: {'epsilon', 'beta1', 'beta2'}.
                             For ClipUp: {'momentum', 'max_speed'}.
          center_learning_rate - Learning rate for the Gaussian mean.
          stdev_learning_rate - Learning rate for the Gaussian stdev.
          init_stdev - Initial stdev for the Gaussian distribution.
          stdev_max_change - Maximum allowed change for stdev in abs values.
          solution_ranking - Should we treat the fitness as rankings or not.
          seed - Random seed for parameters sampling.
      """
  
      if logger is None:
          self._logger = create_logger(name="PGPE")
      else:
          self._logger = logger
  
      self.pop_size = abs(pop_size)
      if self.pop_size % 2 == 1:
          self.pop_size += 1
          self._logger.info(
              "Population size should be an even number, set to {}".format(
                  self.pop_size
              )
          )
      self._num_directions = self.pop_size // 2
  
      if init_params is None:
          self._center = np.zeros(abs(param_size))
      else:
          self._center = init_params
      self._center = jnp.array(self._center)
      if isinstance(init_stdev, float):
          self._stdev = np.ones(abs(param_size)) * abs(init_stdev)
      self._stdev = jnp.array(self._stdev)
  
      self._center_lr = abs(center_learning_rate)
      self._stdev_lr = abs(stdev_learning_rate)
      self._stdev_max_change = abs(stdev_max_change)
      self._solution_ranking = solution_ranking
  
      if optimizer_config is None:
          optimizer_config = {}
      decay_coef = optimizer_config.get("center_lr_decay_coef", 1.0)
      self._lr_decay_steps = optimizer_config.get(
          "center_lr_decay_steps", 1000
      )
  
      if optimizer == "adam":
          opt_init, opt_update, get_params = optimizers.adam(
              step_size=lambda x: self._center_lr
              * jnp.power(decay_coef, x),
              b1=optimizer_config.get("beta1", 0.9),
              b2=optimizer_config.get("beta2", 0.999),
              eps=optimizer_config.get("epsilon", 1e-8),
          )
      elif optimizer == "clipup":
          opt_init, opt_update, get_params = clipup(
              step_size=lambda x: self._center_lr
              * jnp.power(decay_coef, x),
              momentum=optimizer_config.get("momentum", 0.9),
              max_speed=optimizer_config.get("max_speed", 0.15),
              fix_gradient_size=optimizer_config.get(
                  "fix_gradient_size", True
              ),
          )
      else:
          opt_init, opt_update, get_params = optimizers.sgd(
              step_size=lambda x: self._center_lr
              * jnp.power(decay_coef, x),
          )
      self._t = 0
      self._opt_state = jax.jit(opt_init)(self._center)
      self._opt_update = jax.jit(opt_update)
      self._get_params = jax.jit(get_params)
  
      self._key = random.PRNGKey(seed=seed)
      self._solutions = None
      self._scaled_noises = None
  
imports: import numpy
  import logging
  from typing import Optional
  from typing import Union
  from typing import Tuple
  from functools import partial
  import jax
  import jax.numpy
  from jax import random
  from evojax.algo.base import NEAlgorithm
  from evojax.util import create_logger
label_desc: Use image node_id 1 to create a new PGPE object from inherited base classes: NEAlgorithm with example: obj = PGPE(pop_size, param_size, init_params, optimizer, optimizer_config, center_learning_rate, stdev_learning_rate, init_stdev, stdev_max_change, solution_ranking, seed, logger)