//  [python]
def NewSmarterSeparate(self, num_samples, args_K, regu):
        """Default mask sampler
        Generates feature mask and node mask independently
        Favours masks with a high weight + smart space allocation algorithm

        Args:
            num_samples (int): number of masks desired
            args_K (int): maximum size of masks favoured
            regu (binary): nodes or features

        Returns:
            tensor: dataset of samples
        """
        if regu == None:
            z_ = self.Smarter(num_samples, args_K, regu)
            return z_

        # Favour features - special coalitions don't study node's effect
        elif regu > 0.5:
            M = self.F
            z_ = torch.ones(num_samples, M)
            z_[1::2] = torch.zeros(num_samples // 2, M)  # case k = 0
            i = 2
            k = 1
            P = num_samples * 9 / 10
            while i < P and k <= min(args_K, M - 1):

                # All coalitions of order k can be sampled
                if i + 2 * scipy.special.comb(M, k) <= P:
                    L = list(combinations(range(M), k))
                    for c in L:
                        z_[i, c] = torch.zeros(k)
                        z_[i + 1, c] = torch.ones(k)
                        i += 2

                # All coalitions of order k cannot be sampled
                else:
                    weight = torch.ones(M)
                    L = list(combinations(range(M), k))
                    random.shuffle(L)
                    while i < min(P, len(L)):
                        cw = torch.tensor([sum(weight[list(c)]) for c in L])
                        c_idx = torch.argmax(cw).item()
                        c = list(L[c_idx])
                        p = float(random.randint(0, 1))
                        z_[i, :] = torch.tensor(p).repeat(M)
                        z_[i, c] = torch.tensor(1 - p).repeat(len(c))
                        weight[list(c)] = torch.tensor(
                            [1 / (1 + 1 / el.item()) for el in weight[list(c)]]
                        )
                        i += 1
                    k += 1

            # Random coal
            z_[i:, :] = torch.empty(max(0, num_samples - i), M).random_(2)
            return z_

        # Favour features - special coalitions don't study node's effect
        elif regu < 0.5:
            M = self.M - self.F
            z_ = torch.ones(num_samples, M)
            z_[1::2] = torch.zeros(num_samples // 2, M)  # case k = 0
            i = 2
            k = 1
            P = int(num_samples * 9 / 10)
            while i < P and k <= min(args_K, M - 1):

                # All coalitions of order k can be sampled
                if i + 2 * scipy.special.comb(M, k) <= P:
                    L = list(combinations(range(M), k))
                    for c in L:
                        z_[i, c] = torch.zeros(k)
                        z_[i + 1, c] = torch.ones(k)
                        i += 2
                    k += 1

                # All coalitions of order k cannot be sampled
                else:
                    weight = torch.ones(M)
                    L = list(combinations(range(M), k))
                    random.shuffle(L)
                    while i < min(P, len(L)):
                        cw = torch.tensor([sum(weight[list(c)]) for c in L])
                        c_idx = torch.argmax(cw).item()
                        c = list(L[c_idx])
                        p = float(random.randint(0, 1))
                        z_[i, :] = torch.tensor(p).repeat(M)
                        z_[i, c] = torch.tensor(1 - p).repeat(len(c))
                        weight[list(c)] = torch.tensor(
                            [1 / (1 + 1 / el.item()) for el in weight[list(c)]]
                        )
                        i += 1
                    k += 1

            # Random coal
            z_[i:, :] = torch.empty(max(0, num_samples - i), M).random_(2)
            return z_