code: def one_step(
      objective_function,
      population,
      population_values=None,
      differential_weight=0.5,
      crossover_prob=0.9,
      seed=None,
      name=None,
  ):
      """Performs one step of the differential evolution algorithm.
  
      Args:
        objective_function:  A Python callable that accepts a batch of possible
          solutions and returns the values of the objective function at those
          arguments as a rank 1 real `Tensor`. This specifies the function to be
          minimized. The input to this callable may be either a single `Tensor`
          or a Python `list` of `Tensor`s. The signature must match the format of
          the argument `population`. (i.e., objective_function(*population) must
          return the value of the function to be minimized).
        population:  `Tensor` or Python `list` of `Tensor`s representing the
          current population vectors. Each `Tensor` must be of the same real dtype.
          The first dimension indexes individual population members while the
          rest of the dimensions are consumed by the value function. For example,
          if the population is a single `Tensor` of shape [n, m1, m2], then `n` is
          the population size and the output of `objective_function` applied to the
          population is a `Tensor` of shape [n]. If the population is a python
          list of `Tensor`s then each `Tensor` in the list should have the first
          axis of a common size, say `n` and `objective_function(*population)`
          should return a `Tensor` of shape [n]. The population must have at least
          4 members for the algorithm to work correctly.
        population_values: A `Tensor` of rank 1 and real dtype. The result of
          applying `objective_function` to the `population`. If not supplied it is
          computed using the `objective_function`.
          Default value: None.
        differential_weight: Real scalar `Tensor`. Must be positive and less than
          2.0. The parameter controlling the strength of mutation.
          Default value: 0.5
        crossover_prob: Real scalar `Tensor`. Must be between 0 and 1. The
          probability of recombination per site.
          Default value: 0.9
        seed: `int` or None. The random seed for this `Op`. If `None`, no seed is
          applied.
          Default value: None.
        name: (Optional) Python str. The name prefixed to the ops created by this
          function. If not supplied, the default name 'one_step' is
          used.
          Default value: None
  
      Returns:
        A sequence containing the following elements (in order):
        next_population: A `Tensor` or Python `list` of `Tensor`s of the same
          structure as the input population. The population at the next generation.
        next_population_values: A `Tensor` of same shape and dtype as input
          `population_values`. The function values for the `next_population`.
      """
      with tf.name_scope(name or "one_step"):
          population, _ = _ensure_list(population)
          if population_values is None:
              population_values = objective_function(*population)
          population_size = tf.shape(population[0])[0]
          stream = seed_stream.SeedStream(seed, salt="one_step")
          mixing_indices = _get_mixing_indices(
              population_size, seed=stream()
          )
          # Construct the mutated solution vectors. There is one for each member of
          # the population.
          mutants = _get_mutants(
              population,
              population_size,
              mixing_indices,
              differential_weight,
          )
          # Perform recombination between the parents and the mutants.
          candidates = _binary_crossover(
              population,
              population_size,
              mutants,
              crossover_prob,
              seed=stream(),
          )
          candidate_values = objective_function(*candidates)
          if population_values is None:
              population_values = objective_function(*population)
  
          population_values = tf.where(
              tf.math.is_nan(population_values),
              dtype_util.as_numpy_dtype(population_values.dtype)(
                  np.inf
              ),
              population_values,
          )
  
          to_replace = candidate_values < population_values
  
          def _replace(c_part, p_part):
              to_replace_reshaped = tf.reshape(
                  to_replace,
                  shape=ps.concat(
                      [
                          [population_size],
                          ps.ones(
                              [ps.size(ps.shape(c_part)[:-1])],
                              dtype=np.int32,
                          ),
                      ],
                      axis=0,
                  ),
              )
              return tf.where(to_replace_reshaped, c_part, p_part)
  
          next_population = tf.nest.map_structure(
              _replace, candidates, population
          )
          next_values = tf.where(
              to_replace, candidate_values, population_values
          )
  
      return next_population, next_values
  
imports: import collections
  import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.distributions import categorical
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.util import seed_stream
label_desc: Use image node_id 1 for calling a global function with example usage: one_step(objective_function, population, population_values, differential_weight, crossover_prob, seed, name) and returns: next_population,  next_values, tf