code: def elkan_iter(
      X,
      sample_weight,
      centers_old,
      center_half_distances,
      distance_next_center,
      upper_bounds,
      lower_bounds,
      labels,
      center_shift,
      update_centers=True,
      session=None,
      run_kwargs=None,
  ):
      update_op = KMeansElkanUpdate(
          x=X,
          sample_weight=sample_weight,
          centers_old=centers_old,
          center_half_distances=center_half_distances,
          distance_next_center=distance_next_center,
          labels=labels,
          upper_bounds=upper_bounds,
          lower_bounds=lower_bounds,
          update_centers=update_centers,
          n_clusters=centers_old.shape[0],
      )
      to_run = []
      ret = update_op()
      to_run.extend(ret)
      (
          labels,
          upper_bounds,
          lower_bounds,
          centers_new,
          weight_in_clusters,
      ) = ret
  
      if update_centers:
          centers_new, weight_in_clusters = _relocate_empty_clusters(
              X,
              sample_weight,
              centers_old,
              centers_new,
              weight_in_clusters,
              labels,
              to_run=to_run,
              session=session,
              run_kwargs=run_kwargs,
          )
          postprocess = KMeansElkanPostprocess(
              centers_old=centers_old,
              centers_new=centers_new,
              center_shift=center_shift,
              lower_bounds=lower_bounds,
              upper_bounds=upper_bounds,
              labels=labels,
              weight_in_clusters=weight_in_clusters,
          )
          (
              centers_new,
              center_shift,
              upper_bounds,
              lower_bounds,
          ) = postprocess()
  
      return (
          centers_new,
          weight_in_clusters,
          upper_bounds,
          lower_bounds,
          labels,
          center_shift,
      )
  
imports: import numpy
  from ...None import opcodes
  from ...core import OutputType, recursive_tile
  from ...core.operand import OperandStage
  from ...serialization.serializables import KeyField, Int32Field, BoolField
  from ...tensor.array_utils import as_same_device, device, cp, sparse
  from ...tensor.core import TensorOrder
  from ...utils import has_unknown_shape
  from ..operands import LearnOperand, LearnOperandMixin
  from ._k_means_common import _execute_merge_update, _relocate_empty_clusters
  from ._k_means_elkan import init_bounds_dense, init_bounds_sparse, update_chunk_dense, update_chunk_sparse
  from ._k_means_fast import update_center, update_upper_lower_bounds
label_desc: Use image node_id 2 for calling a global function with example usage: elkan_iter(X, sample_weight, centers_old, center_half_distances, distance_next_center, upper_bounds, lower_bounds, labels, center_shift, update_centers, session, run_kwargs) and returns: centers_new,  weight_in_clusters,  upper_bounds,  lower_bounds,  labels,  center_shift