jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def _MatrixSufficientStatistics(
    x: ArrayLike,
    y: ArrayLike,
    epsilon: float,
    preproc: Optional[KendallPreproc],
    preproc_x: Optional[KendallPreproc],
    ) -> Tuple[int, int, int, int, int]:
  """Calculates tau sufficient statistics using matrices in NumPy.
  
  An absolute difference less than `epsilon` in x pairs is considered to be
  a tie.

  Args:
    x: Vector of numeric values.
    y: Vector of numeric values.
    epsilon: The threshold for which an absolute difference in x scores should
      be considered a tie.
    preproc: A `KendallPreproc` object that has been called on a vector of
      y values to be compared to the currrent x. If this is non-None, the y
      parameter is ignored.
    preproc_x: A `PairwiseDiffs` object that has been called on a vector of
      x values to be compared to the currrent y. If this is non-None, the x
      parameter is ignored.

  Returns:
    The number of concordant pairs, discordant pairs, pairs tied only in x,
    paired tied only in y, and pairs tied in both x and y.
  """
  if preproc_x is None:
    preproc_x = PairwiseDiffs(x, epsilon)
  x_diffs = preproc_x.x_diffs
  x_is_tie = preproc_x.x_is_tie

  if preproc is None:
    y1, y2 = np.meshgrid(y, y.T)
    y_diffs = y1 - y2
    y_is_tie = y_diffs == 0.0
  else:
    y_diffs = preproc.y_diffs
    y_is_tie = preproc.y_is_tie

  n = len(y) if preproc is None else len(preproc.y)
  num_pairs = int(scipy.special.comb(n, 2))
  # All of the counts are divided by 2 because each pair is double counted. The
  # double counted data will always be an even number, so dividing by 2 will
  # be an integer.
  con = int(
      ((x_diffs > 0) & (y_diffs > 0) | (x_diffs < 0) & (y_diffs < 0)).sum() / 2
  )
  t_x = int((x_is_tie & ~y_is_tie).sum() / 2)
  t_y = int((~x_is_tie & y_is_tie).sum() / 2)
  t_xy = int(((x_is_tie & y_is_tie).sum() - n) / 2)  # -n removes diagonal
  dis = num_pairs - (con + t_x + t_y + t_xy)
  return con, dis, t_x, t_y, t_xy
//  [python]
def test_n3_k2(self):
        # Get each ordered sequence of 2 numbers that sum to 3.
        n = 3
        k = 2
        compositions = list(restricted_weak_compositions(n, k))

        # Check the number of possible combinations.
        assert len(compositions) == s.comb(n + k - 1, n, exact=True)

        # Check unique combinations.
        assert set(compositions) == {
            (3, 0),
            (2, 1),
            (1, 2),
            (0, 3),
        }
//  [python]
def test_n3_k2(self):
        # Get each ordered sequence of 2 numbers that sum to 3.
        n = 3
        k = 2
        compositions = list(restricted_weak_compositions(n, k))

        # Check the number of possible combinations.
        assert len(compositions) == scipy.special.comb(n + k - 1, n, exact=True)

        # Check unique combinations.
        assert set(compositions) == {
            (3, 0),
            (2, 1),
            (1, 2),
            (0, 3),
        }
//  [python]
def test_n2_k3(self):
        # Get each ordered sequence of 3 numbers that sum to 2.
        n = 2
        k = 3
        compositions = list(restricted_weak_compositions(n, k))

        # Check the number of possible combinations.
        assert len(compositions) == s.comb(n + k - 1, n, exact=True)

        # Check unique combinations.
        assert set(compositions) == {
            (2, 0, 0),
            (0, 2, 0),
            (0, 0, 2),
            (1, 1, 0),
            (1, 0, 1),
            (0, 1, 1),
        }
//  [python]
def test_n2_k3(self):
        # Get each ordered sequence of 3 numbers that sum to 2.
        n = 2
        k = 3
        compositions = list(restricted_weak_compositions(n, k))

        # Check the number of possible combinations.
        assert len(compositions) == scipy.special.comb(n + k - 1, n, exact=True)

        # Check unique combinations.
        assert set(compositions) == {
            (2, 0, 0),
            (0, 2, 0),
            (0, 0, 2),
            (1, 1, 0),
            (1, 0, 1),
            (0, 1, 1),
        }
//  [python]
def smoothstep(x, x_min=0, x_max=1, N=1):
    x = np.clip((x - x_min) / (x_max - x_min), 0, 1)

    result = 0
    for n in range(0, N + 1):
        result += s.comb(N + n, n) * s.comb(2 * N + 1, N - n) * (-x)**n

    result *= x ** (N + 1)

    return result
//  [python]
def smoothstep(x, x_min=0, x_max=1, N=1):
    x = np.clip((x - x_min) / (x_max - x_min), 0, 1)

    result = 0
    for n in range(0, N + 1):
        result += comb(N + n, n) * comb(2 * N + 1, N - n) * (-x)**n

    result *= x ** (N + 1)

    return result
//  [python]
def test_comb(self):
        assert_allclose(s.comb([10, 10], [3, 4]), [120., 210.])
        assert_allclose(s.comb(10, 3), 120.)
        assert_equal(s.comb(10, 3, exact=True), 120)
        assert_equal(s.comb(10, 3, exact=True, repetition=True), 220)

        assert_allclose([s.comb(20, k, exact=True) for k in range(21)],
                        s.comb(20, list(range(21))), atol=1e-15)

        ii = np.iinfo(int).max + 1
        assert_equal(s.comb(ii, ii-1, exact=True), ii)

        expected = 100891344545564193334812497256
        assert s.comb(100, 50, exact=True) == expected
//  [python]
def test_comb(self):
        assert_allclose(special.comb([10, 10], [3, 4]), [120., 210.])
        assert_allclose(special.comb(10, 3), 120.)
        assert_equal(special.comb(10, 3, exact=True), 120)
        assert_equal(special.comb(10, 3, exact=True, repetition=True), 220)

        assert_allclose([special.comb(20, k, exact=True) for k in range(21)],
                        special.comb(20, list(range(21))), atol=1e-15)

        ii = np.iinfo(int).max + 1
        assert_equal(special.comb(ii, ii-1, exact=True), ii)

        expected = 100891344545564193334812497256
        assert special.comb(100, 50, exact=True) == expected
//  [python]
def _adjusted_rand_index(reference_indices, estimated_indices):
    """Compute the Rand index, adjusted for change.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    ari : float
        Adjusted Rand index

    .. note:: Based on sklearn.metrics.cluster.adjusted_rand_score

    """
    n_samples = len(reference_indices)
    ref_classes = np.unique(reference_indices)
    est_classes = np.unique(estimated_indices)
    # Special limit cases: no clustering since the data is not split;
    # or trivial clustering where each document is assigned a unique cluster.
    # These are perfect matches hence return 1.0.
    if (ref_classes.shape[0] == est_classes.shape[0] == 1 or
        ref_classes.shape[0] == est_classes.shape[0] == 0 or
        (ref_classes.shape[0] == est_classes.shape[0] ==
         len(reference_indices))):
        return 1.0

    contingency = _contingency_matrix(reference_indices, estimated_indices)

    # Compute the ARI using the contingency data
    sum_comb_c = sum(s.comb(n_c, 2, exact=1) for n_c in
                     contingency.sum(axis=1))
    sum_comb_k = sum(s.comb(n_k, 2, exact=1) for n_k in
                     contingency.sum(axis=0))

    sum_comb = sum((s.comb(n_ij, 2, exact=1) for n_ij in
                    contingency.flatten()))
    prod_comb = (sum_comb_c * sum_comb_k)/float(s.comb(n_samples,
                                                                   2))
    mean_comb = (sum_comb_k + sum_comb_c)/2.
    return (sum_comb - prod_comb)/(mean_comb - prod_comb)
//  [python]
def _adjusted_rand_index(reference_indices, estimated_indices):
    """Compute the Rand index, adjusted for change.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    ari : float
        Adjusted Rand index

    .. note:: Based on sklearn.metrics.cluster.adjusted_rand_score

    """
    n_samples = len(reference_indices)
    ref_classes = np.unique(reference_indices)
    est_classes = np.unique(estimated_indices)
    # Special limit cases: no clustering since the data is not split;
    # or trivial clustering where each document is assigned a unique cluster.
    # These are perfect matches hence return 1.0.
    if (ref_classes.shape[0] == est_classes.shape[0] == 1 or
        ref_classes.shape[0] == est_classes.shape[0] == 0 or
        (ref_classes.shape[0] == est_classes.shape[0] ==
         len(reference_indices))):
        return 1.0

    contingency = _contingency_matrix(reference_indices, estimated_indices)

    # Compute the ARI using the contingency data
    sum_comb_c = sum(scipy.special.comb(n_c, 2, exact=1) for n_c in
                     contingency.sum(axis=1))
    sum_comb_k = sum(scipy.special.comb(n_k, 2, exact=1) for n_k in
                     contingency.sum(axis=0))

    sum_comb = sum((scipy.special.comb(n_ij, 2, exact=1) for n_ij in
                    contingency.flatten()))
    prod_comb = (sum_comb_c * sum_comb_k)/float(scipy.special.comb(n_samples,
                                                                   2))
    mean_comb = (sum_comb_k + sum_comb_c)/2.
    return (sum_comb - prod_comb)/(mean_comb - prod_comb)
//  [python]
def _samlmularge(x, nmom=5):
    try:
        x = np.asarray(x, dtype=np.float64)
        n = len(x)
        x.sort()
    except ValueError:
        raise ValueError("Input data to estimate L-moments must be numeric.")

    if nmom <= 0:
        raise ValueError("Invalid number of sample L-moments")

    if n < nmom:
        raise ValueError("Insufficient length of data for specified nmoments")

    # Calculate first order
    l = [np.sum(x) / s.comb(n, 1, exact=True)]  # noqa: E741

    if nmom == 1:
        return l[0]

    # Setup comb table, where comb[i][x] refers to comb(x,i)
    comb = []
    for i in range(1, nmom):
        comb.append([])
        for j in range(n):
            comb[-1].append(s.comb(j, i, exact=True))

    for mom in range(2, nmom + 1):
        coefl = 1.0 / mom * 1.0 / s.comb(n, mom, exact=True)
        xtrans = []
        for i in range(0, n):
            coeftemp = []
            for j in range(0, mom):
                coeftemp.append(1)

            for j in range(0, mom - 1):
                coeftemp[j] = coeftemp[j] * comb[mom - j - 2][i]

            for j in range(1, mom):
                coeftemp[j] = coeftemp[j] * comb[j - 1][n - i - 1]

            for j in range(0, mom):
                coeftemp[j] = coeftemp[j] * s.comb(mom - 1, j, exact=True)

            for j in range(0, int(0.5 * mom)):
                coeftemp[j * 2 + 1] = -coeftemp[j * 2 + 1]
            coeftemp = sum(coeftemp)
            xtrans.append(x[i] * coeftemp)

        if mom > 2:
            l.append(coefl * sum(xtrans) / l[1])
        else:
            l.append(coefl * sum(xtrans))
    return l
//  [python]
def _samlmularge(x, nmom=5):
    try:
        x = np.asarray(x, dtype=np.float64)
        n = len(x)
        x.sort()
    except ValueError:
        raise ValueError("Input data to estimate L-moments must be numeric.")

    if nmom <= 0:
        raise ValueError("Invalid number of sample L-moments")

    if n < nmom:
        raise ValueError("Insufficient length of data for specified nmoments")

    # Calculate first order
    l = [np.sum(x) / scipy.special.comb(n, 1, exact=True)]  # noqa: E741

    if nmom == 1:
        return l[0]

    # Setup comb table, where comb[i][x] refers to comb(x,i)
    comb = []
    for i in range(1, nmom):
        comb.append([])
        for j in range(n):
            comb[-1].append(scipy.special.comb(j, i, exact=True))

    for mom in range(2, nmom + 1):
        coefl = 1.0 / mom * 1.0 / scipy.special.comb(n, mom, exact=True)
        xtrans = []
        for i in range(0, n):
            coeftemp = []
            for j in range(0, mom):
                coeftemp.append(1)

            for j in range(0, mom - 1):
                coeftemp[j] = coeftemp[j] * comb[mom - j - 2][i]

            for j in range(1, mom):
                coeftemp[j] = coeftemp[j] * comb[j - 1][n - i - 1]

            for j in range(0, mom):
                coeftemp[j] = coeftemp[j] * scipy.special.comb(mom - 1, j, exact=True)

            for j in range(0, int(0.5 * mom)):
                coeftemp[j * 2 + 1] = -coeftemp[j * 2 + 1]
            coeftemp = sum(coeftemp)
            xtrans.append(x[i] * coeftemp)

        if mom > 2:
            l.append(coefl * sum(xtrans) / l[1])
        else:
            l.append(coefl * sum(xtrans))
    return l
//  [python]
def prior(self, t):
        """Get prior at time `t`.

        Parameters
        ----------
        t : int
            Time point

        Returns
        -------
        float
            Prior probability for time point `t`
        """
        return (scipy.misc.comb(t - self.k, self.k - 1) *
                self.p**self.k * (1 - self.p)**(t - self.k))
//  [python]
def prior(self, t):
        """Get prior at time `t`.

        Parameters
        ----------
        t : int
            Time point

        Returns
        -------
        float
            Prior probability for time point `t`
        """
        return (scipy.special.comb(t - self.k, self.k - 1) *
                self.p**self.k * (1 - self.p)**(t - self.k))
//  [python]
def generateUniformLabelDistrib(size, componentCount, uniformLabelName, sample):
    all_ind = np.zeros(shape=(size, componentCount), dtype=int)
    label = sample.params.loc[:, uniformLabelName].to_numpy()
    if ML.isClassification(sample.params, uniformLabelName):
        label_values = np.unique(label)
        # print(label_values, label)
        inds_by_label_values = {lv:np.where(label == lv)[0] for lv in label_values}
        if componentCount > len(label_values):
            raise LabelValuesLackError(f'componentCount = {componentCount} > len(label_values) = {len(label_values)}')
        maxSize = s.comb(len(label_values), componentCount, repetition=True)
        index_combinations = utils.comb_index(len(label_values), componentCount, repetition=True)
        if maxSize <= size:
            # repeat combinations
            index_combinations = index_combinations[np.arange(size) % len(index_combinations), :]
        else:
            # take random subset
            index_combinations = index_combinations[np.random.choice(int(maxSize), size=size, replace=False), :]
        for i in range(size):
            for j in range(componentCount):
                label_value = label_values[index_combinations[i, j]]
                # take random spectrum from the set with same label
                all_ind[i, j] = np.random.choice(inds_by_label_values[label_value])
    else:
        # label is real but not integer or nominal
        mi = np.min(label)
        ma = np.max(label)
        random_labels = np.random.rand(size, componentCount) * (ma - mi) + mi
        sorted_label_ind = np.argsort(label)
        sorted_label = label[sorted_label_ind]
        for i in range(size):
            for j in range(componentCount):
                _, idx = utils.find_nearest_in_sorted_array(sorted_label, random_labels[i, j])
                initial_index = sorted_label_ind[idx]
                all_ind[i, j] = initial_index
    # print(label[all_ind])
    return all_ind
//  [python]
def generateUniformLabelDistrib(size, componentCount, uniformLabelName, sample):
    all_ind = np.zeros(shape=(size, componentCount), dtype=int)
    label = sample.params.loc[:, uniformLabelName].to_numpy()
    if ML.isClassification(sample.params, uniformLabelName):
        label_values = np.unique(label)
        # print(label_values, label)
        inds_by_label_values = {lv:np.where(label == lv)[0] for lv in label_values}
        if componentCount > len(label_values):
            raise LabelValuesLackError(f'componentCount = {componentCount} > len(label_values) = {len(label_values)}')
        maxSize = scipy.special.comb(len(label_values), componentCount, repetition=True)
        index_combinations = utils.comb_index(len(label_values), componentCount, repetition=True)
        if maxSize <= size:
            # repeat combinations
            index_combinations = index_combinations[np.arange(size) % len(index_combinations), :]
        else:
            # take random subset
            index_combinations = index_combinations[np.random.choice(int(maxSize), size=size, replace=False), :]
        for i in range(size):
            for j in range(componentCount):
                label_value = label_values[index_combinations[i, j]]
                # take random spectrum from the set with same label
                all_ind[i, j] = np.random.choice(inds_by_label_values[label_value])
    else:
        # label is real but not integer or nominal
        mi = np.min(label)
        ma = np.max(label)
        random_labels = np.random.rand(size, componentCount) * (ma - mi) + mi
        sorted_label_ind = np.argsort(label)
        sorted_label = label[sorted_label_ind]
        for i in range(size):
            for j in range(componentCount):
                _, idx = utils.find_nearest_in_sorted_array(sorted_label, random_labels[i, j])
                initial_index = sorted_label_ind[idx]
                all_ind[i, j] = initial_index
    # print(label[all_ind])
    return all_ind
//  [python]
def encoder(seed, x, k, epsilon, number_candidates):
  """This is the encoder used by the miracle algorithm.

  Args:
    seed: The random seed to be used by the encoder.
    x: The user input data.
    k: The dimension of the one-hot encoded x.
    epsilon: The privacy parameter epsilon.
    number_candidates: The number of candidates to be sampled.

  Returns:
    z: The set of candidates sampled at the encoder.
    index: The index sampled by the encoder.
    pi: The distribution over the candidates for the given input data x.
  """
  d = int(np.ceil(k / (np.exp(epsilon) + 1)))

  c1 = np.exp(epsilon) / (
      s.comb(k - 1, d - 1) * np.exp(epsilon) + s.comb(k - 1, d))
  c2 = 1 / (s.comb(k - 1, d - 1) * np.exp(epsilon) + s.comb(k - 1, d))

  # Proposal distribution is chosen to be uniform on all d-hot encoded vectors.
  z = np.zeros((k, number_candidates))
  z[:d, :] = 1
  rs = np.random.RandomState(seed)
  for i in range(number_candidates):
    rs.shuffle(z[:, i])

  pi = np.where(z[x, :] == 1, c1, c2)
  pi /= np.sum(pi)
  index = np.random.choice(number_candidates, 1, p=pi)[0]
  return z, pi, index
//  [python]
def encoder(seed, x, k, epsilon, number_candidates):
  """This is the encoder used by the miracle algorithm.

  Args:
    seed: The random seed to be used by the encoder.
    x: The user input data.
    k: The dimension of the one-hot encoded x.
    epsilon: The privacy parameter epsilon.
    number_candidates: The number of candidates to be sampled.

  Returns:
    z: The set of candidates sampled at the encoder.
    index: The index sampled by the encoder.
    pi: The distribution over the candidates for the given input data x.
  """
  d = int(np.ceil(k / (np.exp(epsilon) + 1)))

  c1 = np.exp(epsilon) / (
      sc.comb(k - 1, d - 1) * np.exp(epsilon) + sc.comb(k - 1, d))
  c2 = 1 / (sc.comb(k - 1, d - 1) * np.exp(epsilon) + sc.comb(k - 1, d))

  # Proposal distribution is chosen to be uniform on all d-hot encoded vectors.
  z = np.zeros((k, number_candidates))
  z[:d, :] = 1
  rs = np.random.RandomState(seed)
  for i in range(number_candidates):
    rs.shuffle(z[:, i])

  pi = np.where(z[x, :] == 1, c1, c2)
  pi /= np.sum(pi)
  index = np.random.choice(number_candidates, 1, p=pi)[0]
  return z, pi, index
//  [python]
def _samlmusmall(x, nmom=5):
    try:
        x = np.asarray(x, dtype=np.float64)
        n = len(x)
        x.sort()
    except ValueError:
        raise ValueError("Input data to estimate L-moments must be numeric.")

    if nmom <= 0 or nmom > 5:
        raise ValueError("Invalid number of sample L-moments")

    if n < nmom:
        raise ValueError("Insufficient length of data for specified nmoments")

    # First L-moment

    l1 = np.sum(x) / s.comb(n, 1, exact=True)

    if nmom == 1:
        return l1

    # Second L-moment

    comb1 = range(n)
    coefl2 = 0.5 / s.comb(n, 2, exact=True)
    sum_xtrans = sum([(comb1[i] - comb1[n - i - 1]) * x[i] for i in range(n)])
    l2 = coefl2 * sum_xtrans

    if nmom == 2:
        return [l1, l2]

    # Third L-moment

    comb3 = [s.comb(i, 2, exact=True) for i in range(n)]
    coefl3 = 1.0 / 3.0 / s.comb(n, 3, exact=True)
    sum_xtrans = sum(
        [
            (
                comb3[i] - 2 * comb1[i] * comb1[n - i - 1] + comb3[n - i - 1]
            )
            * x[i]
            for i in range(n)
        ]
    )
    l3 = coefl3 * sum_xtrans / l2

    if nmom == 3:
        return [l1, l2, l3]

    # Fourth L-moment

    comb5 = [s.comb(i, 3, exact=True) for i in range(n)]
    coefl4 = 0.25 / s.comb(n, 4, exact=True)
    sum_xtrans = sum(
        [
            (
                comb5[i]
                - 3 * comb3[i] * comb1[n - i - 1]
                + 3 * comb1[i] * comb3[n - i - 1]
                - comb5[n - i - 1]
            )
            * x[i]
            for i in range(n)
        ]
    )
    l4 = coefl4 * sum_xtrans / l2

    if nmom == 4:
        return [l1, l2, l3, l4]

    # Fifth L-moment

    comb7 = [s.comb(i, 4, exact=True) for i in range(n)]
    coefl5 = 0.2 / s.comb(n, 5, exact=True)
    sum_xtrans = sum(
        [
            (
                comb7[i]
                - 4 * comb5[i] * comb1[n - i - 1]
                + 6 * comb3[i] * comb3[n - i - 1]
                - 4 * comb1[i] * comb5[n - i - 1]
                + comb7[n - i - 1]
            )
            * x[i]
            for i in range(n)
        ]
    )
    l5 = coefl5 * sum_xtrans / l2

    return [l1, l2, l3, l4, l5]
//  [python]
def _samlmusmall(x, nmom=5):
    try:
        x = np.asarray(x, dtype=np.float64)
        n = len(x)
        x.sort()
    except ValueError:
        raise ValueError("Input data to estimate L-moments must be numeric.")

    if nmom <= 0 or nmom > 5:
        raise ValueError("Invalid number of sample L-moments")

    if n < nmom:
        raise ValueError("Insufficient length of data for specified nmoments")

    # First L-moment

    l1 = np.sum(x) / scipy.special.comb(n, 1, exact=True)

    if nmom == 1:
        return l1

    # Second L-moment

    comb1 = range(n)
    coefl2 = 0.5 / scipy.special.comb(n, 2, exact=True)
    sum_xtrans = sum([(comb1[i] - comb1[n - i - 1]) * x[i] for i in range(n)])
    l2 = coefl2 * sum_xtrans

    if nmom == 2:
        return [l1, l2]

    # Third L-moment

    comb3 = [scipy.special.comb(i, 2, exact=True) for i in range(n)]
    coefl3 = 1.0 / 3.0 / scipy.special.comb(n, 3, exact=True)
    sum_xtrans = sum(
        [
            (comb3[i] - 2 * comb1[i] * comb1[n - i - 1] + comb3[n - i - 1]) * x[i]
            for i in range(n)
        ]
    )
    l3 = coefl3 * sum_xtrans / l2

    if nmom == 3:
        return [l1, l2, l3]

    # Fourth L-moment

    comb5 = [scipy.special.comb(i, 3, exact=True) for i in range(n)]
    coefl4 = 0.25 / scipy.special.comb(n, 4, exact=True)
    sum_xtrans = sum(
        [
            (
                comb5[i]
                - 3 * comb3[i] * comb1[n - i - 1]
                + 3 * comb1[i] * comb3[n - i - 1]
                - comb5[n - i - 1]
            )
            * x[i]
            for i in range(n)
        ]
    )
    l4 = coefl4 * sum_xtrans / l2

    if nmom == 4:
        return [l1, l2, l3, l4]

    # Fifth L-moment

    comb7 = [scipy.special.comb(i, 4, exact=True) for i in range(n)]
    coefl5 = 0.2 / scipy.special.comb(n, 5, exact=True)
    sum_xtrans = sum(
        [
            (
                comb7[i]
                - 4 * comb5[i] * comb1[n - i - 1]
                + 6 * comb3[i] * comb3[n - i - 1]
                - 4 * comb1[i] * comb5[n - i - 1]
                + comb7[n - i - 1]
            )
            * x[i]
            for i in range(n)
        ]
    )
    l5 = coefl5 * sum_xtrans / l2

    return [l1, l2, l3, l4, l5]
//  [python]
def getUnlinkedStationary(self, popSize, theta):
        one_loc_probs = one_locus_probs(popSize=popSize, theta=theta, n=self.n)
        assertValidProbs(one_loc_probs)

        n = self.n
        leftOnes = self.numOnes(0)
        rightOnes = self.numOnes(1)
        bothOnes = self.hapCount((1, 1))
        joint = one_loc_probs[leftOnes] * one_loc_probs[rightOnes]
        if self.exact:
            joint[self.numC > 0] = 0
        else:
            joint *= (s.comb(rightOnes, bothOnes)
                      * s.comb(n-rightOnes, leftOnes-bothOnes)
                      / s.comb(n, leftOnes))

        joint *= self.n_unfolded_versions

        assertValidProbs(joint)
        return joint
//  [python]
def getUnlinkedStationary(self, popSize, theta):
        one_loc_probs = one_locus_probs(popSize=popSize, theta=theta, n=self.n)
        assertValidProbs(one_loc_probs)

        n = self.n
        leftOnes = self.numOnes(0)
        rightOnes = self.numOnes(1)
        bothOnes = self.hapCount((1, 1))
        joint = one_loc_probs[leftOnes] * one_loc_probs[rightOnes]
        if self.exact:
            joint[self.numC > 0] = 0
        else:
            joint *= (scipy.special.comb(rightOnes, bothOnes)
                      * scipy.special.comb(n-rightOnes, leftOnes-bothOnes)
                      / scipy.special.comb(n, leftOnes))

        joint *= self.n_unfolded_versions

        assertValidProbs(joint)
        return joint
//  [python]
def test_positional_deprecation(self):
        with pytest.deprecated_call(match="use keyword arguments"):
            # from test_comb
            s.comb([10, 10], [3, 4], False, False)
//  [python]
def test_positional_deprecation(self):
        with pytest.deprecated_call(match="use keyword arguments"):
            # from test_comb
            special.comb([10, 10], [3, 4], False, False)
//  [python]
def _ell(A, m):
    """
    A helper function for expm_2009.
    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator
    Returns
    -------
    value : int
        A value related to a bound.
    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    p = 2*m + 1

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2p_p = s.comb(2*p, p, exact=True)
    abs_c_recip = float(choose_2p_p * math.factorial(2*p + 1))

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2.**-53

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), p).item()

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0
    one_norm = A.norm(1).item()

    alpha = A_abs_onenorm / (one_norm * abs_c_recip)
    # Cut backprop
    log2_alpha_div_u = np.log2(alpha/u)
    value = int(np.ceil(log2_alpha_div_u / (2 * m)))
    return max(value, 0)
//  [python]
def _ell(A, m):
    """
    A helper function for expm_2009.
    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator
    Returns
    -------
    value : int
        A value related to a bound.
    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    p = 2*m + 1

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2p_p = scipy.special.comb(2*p, p, exact=True)
    abs_c_recip = float(choose_2p_p * math.factorial(2*p + 1))

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2.**-53

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), p).item()

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0
    one_norm = A.norm(1).item()

    alpha = A_abs_onenorm / (one_norm * abs_c_recip)
    # Cut backprop
    log2_alpha_div_u = np.log2(alpha/u)
    value = int(np.ceil(log2_alpha_div_u / (2 * m)))
    return max(value, 0)
//  [python]
def binomial(n, k):
    """
    Binomial coefficient returning an integer.

    Parameters
    ----------
    n : int
    k : int

    Returns
    -------
    int
         Binomial coefficient.
    """

    return s.comb(n, k)
//  [python]
def binomial(n, k):
    """
    Binomial coefficient returning an integer.

    Parameters
    ----------
    n : int
    k : int

    Returns
    -------
    int
         Binomial coefficient.
    """

    return sc_sp.comb(n, k, exact=True, repetition=False)
//  [python]
def test_comb_legacy(self, N, k, legacy, repetition):
        # test is only relevant for exact=True
        if legacy is not _NoValue:
            with pytest.warns(
                DeprecationWarning,
                match=r"Using 'legacy' keyword is deprecated"
            ):
                result = s.comb(N, k, exact=True, legacy=legacy,
                                      repetition=repetition)
        else:
            result = s.comb(N, k, exact=True, legacy=legacy,
                                  repetition=repetition)
        if legacy:
            # for exact=True and legacy=True, cast input arguments, else don't
            if repetition:
                # the casting in legacy mode happens AFTER transforming N & k,
                # so rounding can change (e.g. both floats, but sum to int);
                # hence we need to emulate the repetition-transformation here
                N, k = int(N + k - 1), int(k)
                repetition = False
            else:
                N, k = int(N), int(k)
        # expected result is the same as with exact=False
        with suppress_warnings() as sup:
            if legacy is not _NoValue:
                sup.filter(DeprecationWarning)
            expected = s.comb(N, k, legacy=legacy, repetition=repetition)
        assert_equal(result, expected)
//  [python]
def test_comb_legacy(self, N, k, legacy, repetition):
        # test is only relevant for exact=True
        if legacy is not _NoValue:
            with pytest.warns(
                DeprecationWarning,
                match=r"Using 'legacy' keyword is deprecated"
            ):
                result = special.comb(N, k, exact=True, legacy=legacy,
                                      repetition=repetition)
        else:
            result = special.comb(N, k, exact=True, legacy=legacy,
                                  repetition=repetition)
        if legacy:
            # for exact=True and legacy=True, cast input arguments, else don't
            if repetition:
                # the casting in legacy mode happens AFTER transforming N & k,
                # so rounding can change (e.g. both floats, but sum to int);
                # hence we need to emulate the repetition-transformation here
                N, k = int(N + k - 1), int(k)
                repetition = False
            else:
                N, k = int(N), int(k)
        # expected result is the same as with exact=False
        with suppress_warnings() as sup:
            if legacy is not _NoValue:
                sup.filter(DeprecationWarning)
            expected = special.comb(N, k, legacy=legacy, repetition=repetition)
        assert_equal(result, expected)
//  [python]
def bernstein_poly(n, i, t):
    """
    Bernstein polynom.

    :param n: (int) polynom degree
    :param i: (int)
    :param t: (float)
    :return: (float)
    """
    return s.comb(n, i) * t ** i * (1 - t) ** (n - i)
//  [python]
def bernstein_poly(n, i, t):
    """
    Bernstein polynom.

    :param n: (int) polynom degree
    :param i: (int)
    :param t: (float)
    :return: (float)
    """
    return scipy.special.comb(n, i) * t ** i * (1 - t) ** (n - i)
//  [python]
def hermite_triple_product (k,l,m):
        tripleproduct=0
        g=(k+l+m)/ 2
        if ((k+l+m)% 2) == 0 and m<=(k+l) and m>=abs(k-l):
            tripleproduct=np.sqrt(s.comb(k,g-m)*s.comb(l,g-m)*s.comb(m,g-k))
        else:
            tripleproduct=0
        return tripleproduct
//  [python]
def hermite_triple_product (k,l,m):
        tripleproduct=0
        g=(k+l+m)/ 2
        if ((k+l+m)% 2) == 0 and m<=(k+l) and m>=abs(k-l):
            tripleproduct=np.sqrt(special.comb(k,g-m)*special.comb(l,g-m)*special.comb(m,g-k))
        else:
            tripleproduct=0
        return tripleproduct
//  [python]
def encode_decode_modified_miracle_fast(seed, x, k, epsilon, number_candidates):
  """A fast implementation of the modified miracle protocol.

  Instead of generating number_candidates samples, generate one sample with true
  expectation.

  Args:
    seed: The random seed to be used by the encoder.
    x: The user input data.
    k: The dimension of the one-hot encoded x.
    epsilon: The privacy parameter epsilon.
    number_candidates: The number of candidates to be sampled.

  Returns:
    z: The candidate sampled at the decoder.
  """
  d = int(np.ceil(k / (np.exp(epsilon) + 1)))
  c1 = np.exp(epsilon) / (
      s.comb(k - 1, d - 1) * np.exp(epsilon) + s.comb(k - 1, d))
  c2 = 1 / (s.comb(k - 1, d - 1) * np.exp(epsilon) + s.comb(k - 1, d))

  num_cand_in_cap = np.random.binomial(number_candidates, d / k, size=None)

  beta = num_cand_in_cap / number_candidates
  expected_beta = np.ceil(k / (np.exp(epsilon) + 1)) / k

  pi_in = c1 / (
      num_cand_in_cap * c1 + (number_candidates - num_cand_in_cap) * c2)
  tilde_pi_in = pi_in * (1 + beta *
                         (np.exp(epsilon) - 1)) / ((1 + expected_beta *
                                                    (np.exp(epsilon) - 1)))
  if beta > expected_beta:
    tilde_pi_in = tilde_pi_in * (beta + expected_beta *
                                 (np.exp(epsilon) - 1)) / (
                                     beta * np.exp(epsilon))

  prob_sample_from_cap = num_cand_in_cap * tilde_pi_in

  if np.random.uniform(0, 1) <= prob_sample_from_cap:
    # Generate a sample uniformly from the cap
    z = [1] * (d - 1) + [0] * (k - d)
    rs = np.random.RandomState(seed)
    rs.shuffle(z)
    z = z[:x] + [1] + z[x:]
  else:
    # Generate a sample uniformly from outside the cap
    z = [1] * (d) + [0] * (k - d - 1)
    rs = np.random.RandomState(seed)
    rs.shuffle(z)
    z = z[:x] + [0] + z[x:]
  return np.array(z)
//  [python]
def encode_decode_modified_miracle_fast(seed, x, k, epsilon, number_candidates):
  """A fast implementation of the modified miracle protocol.

  Instead of generating number_candidates samples, generate one sample with true
  expectation.

  Args:
    seed: The random seed to be used by the encoder.
    x: The user input data.
    k: The dimension of the one-hot encoded x.
    epsilon: The privacy parameter epsilon.
    number_candidates: The number of candidates to be sampled.

  Returns:
    z: The candidate sampled at the decoder.
  """
  d = int(np.ceil(k / (np.exp(epsilon) + 1)))
  c1 = np.exp(epsilon) / (
      sc.comb(k - 1, d - 1) * np.exp(epsilon) + sc.comb(k - 1, d))
  c2 = 1 / (sc.comb(k - 1, d - 1) * np.exp(epsilon) + sc.comb(k - 1, d))

  num_cand_in_cap = np.random.binomial(number_candidates, d / k, size=None)

  beta = num_cand_in_cap / number_candidates
  expected_beta = np.ceil(k / (np.exp(epsilon) + 1)) / k

  pi_in = c1 / (
      num_cand_in_cap * c1 + (number_candidates - num_cand_in_cap) * c2)
  tilde_pi_in = pi_in * (1 + beta *
                         (np.exp(epsilon) - 1)) / ((1 + expected_beta *
                                                    (np.exp(epsilon) - 1)))
  if beta > expected_beta:
    tilde_pi_in = tilde_pi_in * (beta + expected_beta *
                                 (np.exp(epsilon) - 1)) / (
                                     beta * np.exp(epsilon))

  prob_sample_from_cap = num_cand_in_cap * tilde_pi_in

  if np.random.uniform(0, 1) <= prob_sample_from_cap:
    # Generate a sample uniformly from the cap
    z = [1] * (d - 1) + [0] * (k - d)
    rs = np.random.RandomState(seed)
    rs.shuffle(z)
    z = z[:x] + [1] + z[x:]
  else:
    # Generate a sample uniformly from outside the cap
    z = [1] * (d) + [0] * (k - d - 1)
    rs = np.random.RandomState(seed)
    rs.shuffle(z)
    z = z[:x] + [0] + z[x:]
  return np.array(z)
//  [python]
def k_array_rank(a):
    """
    Given an array `a` of k distinct nonnegative integers, sorted in
    ascending order, return its ranking in the lexicographic ordering of
    the descending sequences of the elements [1]_.

    Parameters
    ----------
    a : ndarray(int, ndim=1)
        Array of length k.

    Returns
    -------
    idx : scalar(int)
        Ranking of `a`.

    References
    ----------
    .. [1] `Combinatorial number system
       <https://en.wikipedia.org/wiki/Combinatorial_number_system>`_,
       Wikipedia.

    """
    k = len(a)
    idx = int(a[0])  # Convert to Python int
    for i in range(1, k):
        idx += s.comb(a[i], i+1, exact=True)
    return idx
//  [python]
def k_array_rank(a):
    """
    Given an array `a` of k distinct nonnegative integers, sorted in
    ascending order, return its ranking in the lexicographic ordering of
    the descending sequences of the elements [1]_.

    Parameters
    ----------
    a : ndarray(int, ndim=1)
        Array of length k.

    Returns
    -------
    idx : scalar(int)
        Ranking of `a`.

    References
    ----------
    .. [1] `Combinatorial number system
       <https://en.wikipedia.org/wiki/Combinatorial_number_system>`_,
       Wikipedia.

    """
    k = len(a)
    idx = int(a[0])  # Convert to Python int
    for i in range(1, k):
        idx += comb(a[i], i+1, exact=True)
    return idx
//  [python]
def prob (k):
  p = s.comb(M,k)* (1/Num_slots)**k * (1- (1/Num_slots))**(M-k)
  return p
//  [python]
def prob (k):
  p = scipy.special.comb(M,k)* (1/Num_slots)**k * (1- (1/Num_slots))**(M-k)
  return p
//  [python]
def __divergency_cpu(W):
    """
    Calculates the graph divergency. Its the entropic distance (as euclidean
    distance) between a uniform weight distribution (random graph) and the 
    network under study using CPU
    
    Parameters
    ----------
    W : numpy 2D matrix
        Graph matrix. ChannelsXChannels.

    Returns
    -------
    D : numpy array
        Network divergency.
        
    """    
    N = W.shape[0]
    ind = np.argwhere(np.triu(np.ones((N,N)),k=1))
    W_wei = np.sum(W[ind[:,0],ind[:,1]]) # Tri Up indices
    
    if not W.all() == 0:
        p = W[ind[:,0],ind[:,1]] / W_wei # Weights normalising
    
        p_sort = np.sort(p,axis=0)[::-1] # Weight sorting (descending)
        
        p_equi_sort = 1 / len(p_sort) * np.ones((1,len(p_sort))) # Full network is the
        #equilibrium network (same weight for all the edges)
        
        # Normalised euclidean distance
        c = s.comb(N,2) # Number of connections without autoloops
        D = np.sqrt(c / (c - 1)) * np.sqrt(np.nansum(
                np.power(np.squeeze(np.asarray(p_equi_sort))-np.squeeze(np.asarray(p_sort)),2)))
    else: # Empty graph
        D = 0 
        
    return D
//  [python]
def __divergency_cpu(W):
    """
    Calculates the graph divergency. Its the entropic distance (as euclidean
    distance) between a uniform weight distribution (random graph) and the 
    network under study using CPU
    
    Parameters
    ----------
    W : numpy 2D matrix
        Graph matrix. ChannelsXChannels.

    Returns
    -------
    D : numpy array
        Network divergency.
        
    """    
    N = W.shape[0]
    ind = np.argwhere(np.triu(np.ones((N,N)),k=1))
    W_wei = np.sum(W[ind[:,0],ind[:,1]]) # Tri Up indices
    
    if not W.all() == 0:
        p = W[ind[:,0],ind[:,1]] / W_wei # Weights normalising
    
        p_sort = np.sort(p,axis=0)[::-1] # Weight sorting (descending)
        
        p_equi_sort = 1 / len(p_sort) * np.ones((1,len(p_sort))) # Full network is the
        #equilibrium network (same weight for all the edges)
        
        # Normalised euclidean distance
        c = sps.comb(N,2) # Number of connections without autoloops
        D = np.sqrt(c / (c - 1)) * np.sqrt(np.nansum(
                np.power(np.squeeze(np.asarray(p_equi_sort))-np.squeeze(np.asarray(p_sort)),2)))
    else: # Empty graph
        D = 0 
        
    return D
//  [python]
def expected_entropy_estimate(probabilities, sample_count):
    """Compute the expected entropy estimate sampling N elements underlying
    probabilities `p`


    Arguments:
        probabilities (numpy.ndarray): probabilities (p)
                                       (assumed to sum to 1.0)
        sample_count (int): number of samples (N)

    Returns:
        entropy (float): expected entropy
    """
    entropy = 0.0
    for probability in probabilities:
        sample_array = np.arange(1, sample_count)
        entropy += np.sum(
            s.comb(sample_count, sample_array)
            * np.power(probability, sample_array)
            * np.power(1 - probability, sample_count - sample_array)
            # should be sample_array/sample_count
            # but we moved the 1/sample_count out:
            * sample_array
            * np.log(sample_array / sample_count)
        )
    return -entropy / sample_count
//  [python]
def expected_entropy_estimate(probabilities, sample_count):
    """Compute the expected entropy estimate sampling N elements underlying
    probabilities `p`


    Arguments:
        probabilities (numpy.ndarray): probabilities (p)
                                       (assumed to sum to 1.0)
        sample_count (int): number of samples (N)

    Returns:
        entropy (float): expected entropy
    """
    entropy = 0.0
    for probability in probabilities:
        sample_array = np.arange(1, sample_count)
        entropy += np.sum(
            scipy.special.comb(sample_count, sample_array)
            * np.power(probability, sample_array)
            * np.power(1 - probability, sample_count - sample_array)
            # should be sample_array/sample_count
            # but we moved the 1/sample_count out:
            * sample_array
            * np.log(sample_array / sample_count)
        )
    return -entropy / sample_count
//  [python]
def choose(n: int, k: int) -> int:
    r"""The binomial coefficient n choose k.

    :math:`\binom{n}{k}` describes the number of possible choices of
    :math:`k` elements from a set of :math:`n` elements.

    References
    ----------
    - https://en.wikipedia.org/wiki/Combination
    - https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html
    """
    return s.comb(n, k, exact=True)
//  [python]
def choose(n: int, k: int) -> int:
    r"""The binomial coefficient n choose k.

    :math:`\binom{n}{k}` describes the number of possible choices of
    :math:`k` elements from a set of :math:`n` elements.

    References
    ----------
    - https://en.wikipedia.org/wiki/Combination
    - https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html
    """
    return special.comb(n, k, exact=True)
//  [python]
def _ell(A, m):
    """A helper function for expm_2009.

    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator

    Returns
    -------
    value : int
        A value related to a bound.

    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    p = 2*m + 1

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2p_p = s.comb(2*p, p, exact=True)
    abs_c_recip = float(choose_2p_p * math.factorial(2*p + 1))

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2.**-24

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), p)

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0

    alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip)
    return max(int(np.ceil(np.log2(alpha/u) / (2 * m))), 0)
//  [python]
def _ell(A, m):
    """A helper function for expm_2009.

    Parameters
    ----------
    A : linear operator
        A linear operator whose norm of power we care about.
    m : int
        The power of the linear operator

    Returns
    -------
    value : int
        A value related to a bound.

    """
    if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
        raise ValueError('expected A to be like a square matrix')

    p = 2*m + 1

    # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper.
    # They are coefficients of terms of a generating function series expansion.
    choose_2p_p = scipy.special.comb(2*p, p, exact=True)
    abs_c_recip = float(choose_2p_p * math.factorial(2*p + 1))

    # This is explained after Eq. (1.2) of the 2009 expm paper.
    # It is the "unit roundoff" of IEEE double precision arithmetic.
    u = 2.**-24

    # Compute the one-norm of matrix power p of abs(A).
    A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), p)

    # Treat zero norm as a special case.
    if not A_abs_onenorm:
        return 0

    alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip)
    return max(int(np.ceil(np.log2(alpha/u) / (2 * m))), 0)
//  [python]
def compute_rep(args):
    """
    Compute path representation as function of k
    """
    rep_ar = np.zeros((args.depth,))
    alpha = args.alpha
    for i, k in enumerate(range(args.depth)):
        m_choose_k = s.comb(args.depth, k)
        rep_ar[i] = (
            m_choose_k
            * args.width ** k
            * args.alpha ** (args.depth - k)
            * (1 - alpha) ** k
            * args.R0
            / (args.c ** (3 ** k - 1))
        )

        print(k, rep_ar[i])
//  [python]
def compute_rep(args):
    """
    Compute path representation as function of k
    """
    rep_ar = np.zeros((args.depth,))
    alpha = args.alpha
    for i, k in enumerate(range(args.depth)):
        m_choose_k = scipy.special.comb(args.depth, k)
        rep_ar[i] = (
            m_choose_k
            * args.width ** k
            * args.alpha ** (args.depth - k)
            * (1 - alpha) ** k
            * args.R0
            / (args.c ** (3 ** k - 1))
        )

        print(k, rep_ar[i])
//  [python]
def utilde(n):
    res = defaultdict(float)

    if n == 0:
        return {(0, 0, 0): 1.0}

    for k in range(n + 1):
        c1 = s.comb(n, k) * (-1) ** k
        k2 = k // 2
        for j in range(k2 + 1):
            c2 = s.comb(k2, j) * (-1) ** j
            for l in range(j + 1):
                c3 = s.comb(j, l)
                res[(2 * (j - l), 2 * l, k % 2)] += -c1 * c2 * c3

    return res
//  [python]
def utilde(n):
    res = defaultdict(float)

    if n == 0:
        return {(0, 0, 0): 1.0}

    for k in range(n + 1):
        c1 = comb(n, k) * (-1) ** k
        k2 = k // 2
        for j in range(k2 + 1):
            c2 = comb(k2, j) * (-1) ** j
            for l in range(j + 1):
                c3 = comb(j, l)
                res[(2 * (j - l), 2 * l, k % 2)] += -c1 * c2 * c3

    return res
//  [python]
def probDiffs(readsf, pos_ascf, pos_allf, chrm, fout_prob, fout_idDiff, fout_pshap, fout_idhap):

    reads=pd.read_csv(readsf, sep=',',index_col=0,header=0)
    pos_asc=np.loadtxt(pos_ascf,dtype='float', delimiter = ",")
    pos_all=np.loadtxt(pos_allf,dtype='float', delimiter = ",")

    l=int(np.shape(reads)[1])

    reads['chrm']=chrm
    reads['pos']=pos_all

    xx=reads['pos'].isin(pos_asc)

    reads=reads.loc[xx,:]
    reads.reset_index(drop=True, inplace=True)


    cols=list(map(str, list(range(l))))
    r1=reads[cols].to_numpy()
    r3=np.array(np.hsplit(r1,int(np.shape(r1)[1]/4)))


    p_ae=r3[:,:,0]
    p_de=r3[:,:,1]
    p_ac=r3[:,:,2]
    p_dc=r3[:,:,3]


    der= p_de + p_dc
    anc= p_ae + p_ac

    total=der+anc

    prob_ar= der / total


    idDiff=s.comb(der,1) * s.comb(anc,1)/ s.comb(total, 2)



    pshap=np.random.binomial(1,prob_ar)
    pshap[pshap<0]=-9

    idhap=np.random.binomial(1, idDiff)
    idhap[total<2]=-9

    prob_ar[total==0]=-9
    idDiff[total<2]=-9

    np.savetxt(fname=fout_prob, X=prob_ar.T, delimiter=",")
    np.savetxt(fname=fout_idDiff, X=idDiff.T, delimiter=",")
    np.savetxt(fname=fout_pshap, X=pshap.T, delimiter=",")
    np.savetxt(fname=fout_idhap, X=idhap.T, delimiter=",")