code: def _rcit(
      X: np.ndarray,
      Y: np.ndarray,
      Z: np.ndarray,
      num_random_features_X: int,
      num_random_features_Y: int,
      num_random_features_Z: int,
      num_permutations: int,
      num_runs: int,
      num_max_samples_per_run: int,
      approx_kernel: Callable[[np.ndarray, int], np.ndarray],
      scale_data: bool,
      n_jobs: Optional[int],
      p_value_adjust_func: Callable[
          [Union[np.ndarray, List[float]]], float
      ],
  ) -> float:
      """
      Implementation of the Randomized Conditional Independence Test based on the work:
          Strobl, Eric V., Kun Zhang, and Shyam Visweswaran.
          Approximate kernel-based conditional independence tests for fast non-parametric causal discovery.
          Journal of Causal Inference 7.1 (2019).
      """
      n_jobs = config.default_n_jobs if n_jobs is None else n_jobs
  
      X, Y, Z = _convert_to_numeric(*shape_into_2d(X, Y, Z))
  
      if scale_data:
          X = scale(X)
          Y = scale(Y)
          Z = scale(Z)
  
      def parallel_job(parallel_random_seed: int):
          set_random_seed(parallel_random_seed)
  
          if X.shape[0] > num_max_samples_per_run:
              random_indices = np.random.choice(
                  X.shape[0], num_max_samples_per_run, replace=False
              )
              X_samples = X[random_indices]
              Y_samples = Y[random_indices]
              Z_samples = Z[random_indices]
          else:
              X_samples = X
              Y_samples = Y
              Z_samples = Z
  
          Y_samples = np.column_stack([Y_samples, Z_samples])
          random_features_x = scale(
              approx_kernel(X_samples, num_random_features_X)
          )
          random_features_y = scale(
              approx_kernel(Y_samples, num_random_features_Y)
          )
          random_features_z = scale(
              approx_kernel(Z_samples, num_random_features_Z)
          )
  
          cov_zz = _estimate_column_wise_covariances(
              random_features_z, random_features_z
          )
          inverse_cov_zz = scipy.linalg.cho_solve(
              scipy.linalg.cho_factor(
                  cov_zz + np.eye(cov_zz.shape[0]) * 10**-10,
                  lower=True,
              ),
              np.eye(cov_zz.shape[0]),
          )
          cov_xz = _estimate_column_wise_covariances(
              random_features_x, random_features_z
          )
          cov_zy = _estimate_column_wise_covariances(
              random_features_z, random_features_y
          )
  
          z_inverse_cov_zz = random_features_z @ inverse_cov_zz
  
          residual_x = random_features_x - z_inverse_cov_zz @ cov_xz.T
          residual_y = random_features_y - z_inverse_cov_zz @ cov_zy
  
          # Estimate test statistic multiple times on different permutations of the data. The p-value is then the
          # probability (i.e. fraction) of obtaining a test statistic that is greater than statistic on the non-permuted
          # data.
          permutation_results_of_statistic = []
          for i in range(num_permutations):
              permutation_results_of_statistic.append(
                  _estimate_rit_statistic(
                      residual_x[
                          np.random.choice(
                              residual_x.shape[0],
                              residual_x.shape[0],
                              replace=False,
                          )
                      ],
                      residual_y,
                  )
              )
  
          return 1 - (
              np.sum(
                  _estimate_rit_statistic(residual_x, residual_y)
                  > permutation_results_of_statistic
              )
              / len(permutation_results_of_statistic)
          )
  
      random_seeds = np.random.randint(
          np.iinfo(np.int32).max, size=num_runs
      )
      p_values = Parallel(n_jobs=n_jobs)(
          delayed(parallel_job)(int(random_seeds[i]))
          for i in range(num_runs)
      )
  
      return p_value_adjust_func(p_values)
  
file_path: dowhy/dowhy/gcm/independence_test/kernel.py
imports: from typing import Callable, List, Optional, Union
  import numpy
  import scipy
  from causallearn.utils.KCI.KCI import KCI_CInd, KCI_UInd
  from joblib import Parallel, delayed
  from sklearn.preprocessing import scale
  import dowhy.gcm.config
  from dowhy.gcm.independence_test.kernel_operation import approximate_rbf_kernel_features
  from dowhy.gcm.stats import quantile_based_fwer
  from dowhy.gcm.util.general import auto_apply_encoders, auto_fit_encoders, set_random_seed, shape_into_2d
label_desc: Use image node_id 4 for calling a global function with example usage: _rcit(X, Y, Z, num_random_features_X, num_random_features_Y, num_random_features_Z, num_permutations, num_runs, num_max_samples_per_run, approx_kernel, scale_data, n_jobs, p_value_adjust_func) and returns: p_value_adjust_func, unknown