code: def _estimate_distribution_change_score(
      parent_original_data: np.ndarray,
      parent_new_data: np.ndarray,
      target_new_data: np.ndarray,
      causal_model_original: ConditionalStochasticModel,
      difference_estimation_func: Callable[
          [np.ndarray, np.ndarray], Union[np.ndarray, float]
      ],
      max_num_evaluation_samples: int,
      num_joint_samples: int,
      early_stopping_percentage: float,
  ) -> float:
      (
          parent_original_data,
          parent_new_data,
          target_new_data,
      ) = shape_into_2d(
          parent_original_data, parent_new_data, target_new_data
      )
      causal_model_new = causal_model_original.clone()
      causal_model_new.fit(X=parent_new_data, Y=target_new_data)
  
      joint_parent_samples = np.vstack(
          [parent_original_data, parent_new_data]
      )
      joint_parent_samples = joint_parent_samples[
          np.random.choice(
              joint_parent_samples.shape[0],
              min(
                  joint_parent_samples.shape[0],
                  max_num_evaluation_samples,
              ),
              replace=False,
          )
      ]
  
      result = 0
      run = 0
      for joint_parent_sample in joint_parent_samples:
          old_result = result
  
          samples = repmat(joint_parent_sample, num_joint_samples, 1)
          result += difference_estimation_func(
              causal_model_original.draw_samples(samples),
              causal_model_new.draw_samples(samples),
          )
  
          run += 1
          if (
              old_result != 0
              and (1 - result / old_result) <= early_stopping_percentage
          ):
              # If the relative change of the score is less than the given threshold, we stop the estimation early.
              _logger.info(
                  "Early stopping: Result only changed by %f percent and a threshold of %f is set."
                  % (1 - result / old_result, early_stopping_percentage)
              )
              break
  
      return result / run
  
imports: import logging
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import networkx
  import numpy
  import pandas
  from numpy.matlib import repmat
  from statsmodels.stats.multitest import multipletests
  from tqdm import tqdm
  from dowhy.gcm.auto import AssignmentQuality, assign_causal_mechanism_node, assign_causal_mechanisms
  from dowhy.gcm.causal_mechanisms import ConditionalStochasticModel
  from dowhy.gcm.causal_models import PARENTS_DURING_FIT, ProbabilisticCausalModel, clone_causal_models, validate_causal_dag
  from dowhy.gcm.divergence import auto_estimate_kl_divergence
  from dowhy.gcm.fitting_sampling import draw_samples, fit_causal_model_of_target
  from dowhy.gcm.independence_test.kernel import kernel_based
  from dowhy.gcm.shapley import ShapleyConfig, estimate_shapley_values
  from dowhy.gcm.util.general import shape_into_2d
  from dowhy.graph import DirectedGraph, get_ordered_predecessors, is_root_node, node_connected_subgraph_view
label_desc: Use image node_id 9 for calling a global function with example usage: _estimate_distribution_change_score(parent_original_data, parent_new_data, target_new_data, causal_model_original, difference_estimation_func, max_num_evaluation_samples, num_joint_samples, early_stopping_percentage) and returns: unknown