Exemplo n.º 1
0
def initialize_AED_sampler(kernel, random_state=None):
    """
    .. seealso::
        - :func:`add_delete_sampler <add_delete_sampler>`
        - :func:`basis_exchange_sampler <basis_exchange_sampler>`
        - :func:`initialize_AED_sampler <initialize_AED_sampler>`
        - :func:`add_exchange_delete_sampler <add_exchange_delete_sampler>`
    """
    rng = check_random_state(random_state)

    N = kernel.shape[0]
    ground_set = np.arange(N)

    S0, det_S0 = [], 0.0
    nb_trials = 100
    tol = 1e-9

    for _ in range(nb_trials):
        if det_S0 > tol:
            break
        else:
            T = rng.choice(2 * N, size=N, replace=False)
            S0 = np.intersect1d(T, ground_set, assume_unique=True)
            det_S0 = det_ST(kernel, S0)
    else:
        err_str = [
            'Initialization terminated unsuccessfully.',
            'After {} random trials, no initial set S0 satisfies det L_S0 > {}.'
            .format(nb_trials, tol),
            'You may consider passing your own initial state **{"s_init": S0}.'
        ]
        raise ValueError('\n'.join(err_str))

    return S0.tolist()
Exemplo n.º 2
0
def initialize_AD_and_E_sampler(kernel, size=None):
    """
    .. seealso::

        - :func:`add_delete_sampler <add_delete_sampler>`
        - :func:`basis_exchange_sampler <basis_exchange_sampler>`
        - :func:`initialize_AED_sampler <initialize_AED_sampler>`
        - :func:`add_exchange_delete_sampler <add_exchange_delete_sampler>`
    """

    N = kernel.shape[0]

    S0, det_S0 = [], 0.0
    it_max = 100
    tol = 1e-9

    for _ in range(it_max):
        if det_S0 > tol:
            break
        else:
            sz = size if size else np.random.randint(1, N + 1)
            S0 = np.random.choice(N, size=sz, replace=False).tolist()
            det_S0 = det_ST(kernel, S0)
    else:
        raise ValueError('Initialization problem, you may be using a size `k` > rank of the kernel')

    return S0
Exemplo n.º 3
0
    def doubleton_adequation(dpp, samples, tol=0.05):
        """Perform chi-square test to check that
        P[{i, j} C X] = det [[K_ii, K_ij], [K_ji, K_jj]]
        """
        samples = list(map(set, samples))
        dpp.compute_K()
        N = len(dpp.K)

        nb_doubletons = 10
        doubletons = [
            set(rndm.choice(N, size=2, replace=False))
            for _ in range(nb_doubletons)
        ]

        # det [[K_ii, K_ij], [K_ji, K_jj]]
        marginal_th = [det_ST(dpp.K, list(d)) for d in doubletons]

        counts = [
            sum([doubl.issubset(sampl) for sampl in samples])
            for doubl in doubletons
        ]
        marginal_emp = np.array(counts) / len(samples)

        _, pval = chisquare(f_obs=marginal_emp, f_exp=marginal_th)

        msg = 'pval = {}, emp = {}, th = {}'.format(pval, marginal_emp,
                                                    marginal_th)

        return pval > tol, msg
Exemplo n.º 4
0
    def __init__(self, *args, **kwargs):
        super(UniformityOfSamplerForUniformSpanningTree,
              self).__init__(*args, **kwargs)

        # Sample a connected Erdos-Renyi graph
        n, p = 5, 0.4
        nb_st_min, nb_st_max = 5, 10

        it_max = 100
        for _ in range(it_max):

            g = erdos_renyi_graph(n, p)

            if is_connected(g):
                A = incidence_matrix(g, oriented=True)[:-1, :].toarray()

                potential_st = itt.combinations(range(g.number_of_edges()),
                                                n - 1)
                list_st = [
                    st for st in potential_st if det_ST(A, range(n - 1), st)
                ]

                if nb_st_min <= len(list_st) <= nb_st_max:
                    break
        else:
            raise ValueError('No satisfactory Erdos-Renyi graph found')

        self.nb_spanning_trees = len(list_st)

        self.ust = UST(g)

        self.nb_samples = 1000
Exemplo n.º 5
0
    def doubleton_adequation(self, dpp, samples, tol=0.05):
        """Perform chi-square test"""

        samples = list(map(set, samples))
        dpp.compute_K()

        nb_doubletons_to_check = 10
        doubletons = [
            set(
                rndm.choice(self.N,
                            size=2,
                            p=np.diag(dpp.K) / self.rank,
                            replace=False))
            for _ in range(nb_doubletons_to_check)
        ]

        counts = [
            sum([doubl.issubset(sampl) for sampl in samples])
            for doubl in doubletons
        ]
        freq = np.array(counts) / len(samples)
        marg_theo = [det_ST(dpp.K, list(d)) for d in doubletons]

        print(freq)
        print(marg_theo)

        _, pval = chisquare(f_obs=freq, f_exp=marg_theo)

        return pval > tol
Exemplo n.º 6
0
def initialize_AED_sampler(kernel):
    """
    .. seealso::
        - :func:`add_delete_sampler <add_delete_sampler>`
        - :func:`basis_exchange_sampler <basis_exchange_sampler>`
        - :func:`initialize_AED_sampler <initialize_AED_sampler>`
        - :func:`add_exchange_delete_sampler <add_exchange_delete_sampler>`
    """

    N = kernel.shape[0]
    ground_set = np.arange(N)

    S0, det_S0 = [], 0.0
    nb_iter = 100
    tol = 1e-9

    for _ in range(nb_iter):
        if det_S0 > tol:
            break
        else:
            T = np.random.choice(2 * N, size=N, replace=False)
            S0 = np.intersect1d(T, ground_set).tolist()
            det_S0 = det_ST(kernel, S0)
    else:
        raise ValueError('Initialization problem, you may be using a size `k` > rank of the kernel')

    return S0
Exemplo n.º 7
0
    def test_det_ST(self):
        """Test determinant
            - det_ST(arr, S) = det(arr[S, S])
            - det_ST(arr, S, T) = det(arr[S, T])
        """

        shapes = [10, 50, 100, 300]
        nb_minors = 10

        for sh in shapes:

            arr = rndm.rand(sh, sh)
            size_minors = sh // 3

            for _ in range(nb_minors):
                S, T = rndm.choice(sh, size=(2, size_minors))

                self.assertTrue(
                    np.allclose(utils.det_ST(arr, S), la.det(arr[np.ix_(S,
                                                                        S)])))

                self.assertTrue(
                    np.allclose(utils.det_ST(arr, S, T),
                                la.det(arr[np.ix_(S, T)])))
Exemplo n.º 8
0
    def test_det_ST(self):
        """Test determinant
            - det_ST(arr, S) = det(arr[S, S])
            - det_ST(arr, S, T) = det(arr[S, T])
        """

        shapes = [10, 50, 100, 300]
        nb_minors = 10

        for sh in shapes:
            with self.subTest(axis=sh):

                arr = rndm.rand(sh, sh)
                size_minors = sh // 3

                for idx in range(nb_minors):
                    with self.subTest(idx=idx):

                        S, T = rndm.choice(sh,
                                           size=(2, size_minors),
                                           replace=False)

                        for test_det_ST in ['SS', 'ST']:
                            with self.subTest(test_det_ST=test_det_ST):

                                if test_det_ST == 'SS':

                                    self.assertTrue(
                                        np.allclose(utils.det_ST(arr, S),
                                                    la.det(arr[np.ix_(S, S)])))

                                if test_det_ST == 'ST':

                                    self.assertTrue(
                                        np.allclose(utils.det_ST(arr, S, T),
                                                    la.det(arr[np.ix_(S, T)])))
Exemplo n.º 9
0
    def doubleton_adequation(self, tol=0.05):
        """Perform chi-square test"""

        samples = list(map(set, self.list_of_samples))

        nb_doubletons_to_check = 10
        doubletons = [set(choice(self.N, size=2, p=diag(self.K) / self.rank,
                                 replace=False))
                      for _ in range(nb_doubletons_to_check)]

        counts = [sum([doubl.issubset(sampl) for sampl in samples])
                  for doubl in doubletons]
        freq = array(counts) / self.nb_samples
        marg_theo = [det_ST(self.K, list(d)) for d in doubletons]

        _, pval = chisquare(f_obs=freq, f_exp=marg_theo)

        return pval > tol
Exemplo n.º 10
0
def initialize_AD_and_E_sampler(kernel, size=None, random_state=None):
    """
    .. seealso::

        - :func:`add_delete_sampler <add_delete_sampler>`
        - :func:`basis_exchange_sampler <basis_exchange_sampler>`
        - :func:`initialize_AED_sampler <initialize_AED_sampler>`
        - :func:`add_exchange_delete_sampler <add_exchange_delete_sampler>`
    """
    rng = check_random_state(random_state)

    N = kernel.shape[0]

    S0, det_S0 = [], 0.0
    nb_trials = 100
    tol = 1e-9

    for _ in range(nb_trials):
        if det_S0 > tol:
            break
        else:
            S0 = rng.choice(N,
                            size=size if size else rng.randint(1, N + 1),
                            replace=False)
            det_S0 = det_ST(kernel, S0)
    else:
        err_str = [
            'Initialization terminated unsuccessfully.',
            'After {} random trials, no initial set S0 satisfies det L_S0 > {}.'
            .format(nb_trials, tol),
            'If you are sampling from a k-DPP, make sure k <= rank(L).'
            if size else '',
            'You may consider passing your own initial state **{"s_init": S0}.'
        ]
        raise ValueError('\n'.join(err_str))

    return S0.tolist()
Exemplo n.º 11
0
def basis_exchange_sampler(kernel,
                           s_init,
                           nb_iter=10,
                           T_max=None,
                           random_state=None):
    """ MCMC sampler for projection DPPs, based on the basis exchange property.

    :param kernel:
        Feature vector matrix, feature vectors are stacked columnwise.
        It is assumed to be full row rank.
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
        Default is None.
    :type T_max:
        float

    :param random_state:
    :type random_state:
        None, np.random, int, np.random.RandomState

    :return:
        MCMC chain of approximate sample (stacked row_wise i.e. nb_iter rows).
    :rtype:
        array_like

    .. seealso::

        Algorithm 2 in :cite:`LiJeSr16c`
    """
    rng = check_random_state(random_state)

    # Initialization
    N = kernel.shape[0]  # Number of elements
    ground_set = np.arange(N)  # Ground set

    size = len(s_init)  # Size of the sample (cardinality is fixed)
    # Initialization
    S0, det_S0 = s_init, det_ST(kernel, s_init)

    chain = np.zeros((nb_iter, size), dtype=int)
    chain[0] = S0

    # Evaluate running time...
    t_start = time.time() if T_max else 0

    for it in range(1, nb_iter):

        # With proba 1/2 try to swap 2 elements
        if rng.rand() < 0.5:

            # Perform the potential exchange move S1 = S0 - s + t
            S1 = S0.copy()  # S1 = S0
            # Pick one element s in S0 by index uniformly at random
            s_ind = rng.choice(size)
            # Pick one element t in [N]\S0 uniformly at random
            t = rng.choice(np.delete(ground_set, S0))
            S1[s_ind] = t  # S_1 = S0 - S0[s_ind] + t

            det_S1 = det_ST(kernel, S1)  # det K_S1

            # Accept_reject the move w. proba
            if rng.rand() < det_S1 / det_S0:
                S0, det_S0 = S1, det_S1
                chain[it] = S1

            else:  # if reject, stay in the same state
                chain[it] = S0

        else:
            chain[it] = S0

        if T_max:
            if time.time() - t_start < T_max:
                break

    return chain.tolist()
Exemplo n.º 12
0
def add_delete_sampler(kernel,
                       s_init,
                       nb_iter=10,
                       T_max=None,
                       random_state=None):
    """ MCMC sampler for generic DPP(kernel), it performs local moves by removing/adding one element at a time.

    :param kernel:
        Kernel martrix
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
        Default is None.
    :type T_max:
        float

    :param random_state:
    :type random_state:
        None, np.random, int, np.random.RandomState

    :return:
        list of `nb_iter` approximate sample of DPP(kernel)
    :rtype:
        array_like

    .. seealso::

        Algorithm 1 in :cite:`LiJeSr16c`
    """
    rng = check_random_state(random_state)

    # Initialization
    N = kernel.shape[0]  # Number of elements

    # Initialization
    S0, det_S0 = s_init, det_ST(kernel, s_init)
    chain = [S0]  # Initialize the collection (list) of sample

    # Evaluate running time...
    t_start = time.time() if T_max else 0

    for _ in range(1, nb_iter):

        # With proba 1/2 try to add/delete an element
        if rng.rand() < 0.5:

            # Perform the potential add/delete move S1 = S0 +/- s
            S1 = S0.copy()  # S1 = S0
            s = rng.choice(N)  # Uniform item in [N]
            if s in S1:
                S1.remove(s)  # S1 = S0 - s
            else:
                S1.append(s)  # S1 = SO + s

            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if rng.rand() < det_S1 / det_S0:
                S0, det_S0 = S1, det_S1
                chain.append(S1)

            else:
                chain.append(S0)

        else:
            chain.append(S0)

        if T_max:
            if time.time() - t_start < T_max:
                break

    return chain
Exemplo n.º 13
0
def add_exchange_delete_sampler(kernel,
                                s_init=None,
                                nb_iter=10,
                                T_max=None,
                                random_state=None):
    """ MCMC sampler for generic DPPs, it is a mix of add/delete and basis exchange MCMC samplers.

    :param kernel:
        Kernel martrix
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
    :type T_max:
        float

    :param random_state:
    :type random_state:
        None, np.random, int, np.random.RandomState

    :return:
        list of `nb_iter` approximate sample of DPP(kernel)
    :rtype:
        array_like

    .. seealso::

        Algorithm 3 in :cite:`LiJeSr16c`
    """
    rng = check_random_state(random_state)

    # Initialization
    N = kernel.shape[0]
    ground_set = np.arange(N)

    S0, det_S0 = s_init, det_ST(kernel, s_init)
    size_S0 = len(S0)  # Size of the current sample
    chain = [S0]  # Initialize the collection (list) of sample

    # Evaluate running time...
    t_start = time.time() if T_max else 0

    for _ in range(1, nb_iter):

        S1 = S0.copy()  # S1 = S0
        # Pick one element s in S_0 by index uniformly at random
        s_ind = rng.choice(size_S0 if size_S0 else N)  # , size=1)[0]
        # Unif t in [N]-S0
        t = rng.choice(np.delete(ground_set, S0))

        U = rng.rand()
        ratio = size_S0 / N  # Proportion of items in current sample

        # Add: S1 = S0 + t
        if U < 0.5 * (1 - ratio)**2:
            S1.append(t)  # S1 = S0 + t
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if rng.rand() < det_S1 / det_S0 * (size_S0 + 1) / (N - size_S0):
                S0, det_S0 = S1, det_S1
                chain.append(S1)
                size_S0 += 1
            else:
                chain.append(S0)

        # Exchange: S1 = S0 - s + t
        elif (0.5 * (1 - ratio)**2 <= U) & (U < 0.5 * (1 - ratio)):
            del S1[s_ind]  # S1 = S0 - s
            S1.append(t)  # S1 = S1 + t = S0 - s + t
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if rng.rand() < (det_S1 / det_S0):
                S0, det_S0 = S1, det_S1
                chain.append(S1)
                # size_S0 stays the same
            else:
                chain.append(S0)

        # Delete: S1 = S0 - s
        elif (0.5 * (1 - ratio) <= U) & (U < 0.5 * (ratio**2 + (1 - ratio))):
            del S1[s_ind]  # S0 - s
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if rng.rand() < det_S1 / det_S0 * size_S0 / (N - (size_S0 - 1)):
                S0, det_S0 = S1, det_S1
                chain.append(S1)
                size_S0 -= 1
            else:
                chain.append(S0)

        else:
            chain.append(S0)

        if T_max:
            if time.time() - t_start < T_max:
                break

    return chain
Exemplo n.º 14
0
def basis_exchange_sampler(kernel, s_init, nb_iter=10, T_max=10):
    """ MCMC sampler for projection DPPs, based on the basis exchange property.

    :param kernel:
        Feature vector matrix, feature vectors are stacked columnwise.
        It is assumed to be full row rank.
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
        Default is 10s.
    :type T_max:
        float

    :return:
        MCMC chain of approximate sample (stacked row_wise i.e. nb_iter rows).
    :rtype:
        array_like

    .. seealso::

        Algorithm 2 in :cite:`LiJeSr16c`
    """

    # Initialization
    N = kernel.shape[0]  # Number of elements
    ground_set = np.arange(N)  # Ground set

    size = len(s_init)  # Size of the sample (cardinality is fixed)
    # Initialization
    S0, det_S0 = s_init, det_ST(kernel, s_init)
    samples = [S0]  # Initialize the collection (list) of sample

    # Evaluate running time...
    flag = True
    it = 1
    t_start = time.time() if T_max else 0

    while flag:

        # With proba 1/2 try to swap 2 elements
        if np.random.rand() < 0.5:

            # Perform the potential exchange move S1 = S0 - s + t
            S1 = S0.copy()  # S1 = S0
            # Pick one element s in S0 by index uniformly at random
            s_ind = np.random.choice(size, size=1)[0]
            # Pick one element t in [N]\S0 uniformly at random
            t = np.random.choice(np.delete(ground_set, S0), size=1)[0]
            S1[s_ind] = t  # S_1 = S0 - S0[s_ind] + t

            det_S1 = det_ST(kernel, S1)  # det K_S1

            # Accept_reject the move w. proba
            if np.random.rand() < det_S1 / det_S0:
                S0, det_S0 = S1, det_S1
                samples.append(S1)

            else:  # if reject, stay in the same state
                samples.append(S0)

        else:
            samples.append(S0)

        it += 1
        flag = (it < nb_iter) if not T_max else ((time.time()-t_start) < T_max)

    return samples
Exemplo n.º 15
0
def add_delete_sampler(kernel, s_init, nb_iter=10, T_max=10):
    """ MCMC sampler for generic DPP(kernel), it performs local moves by removing/adding one element at a time.

    :param kernel:
        Kernel martrix
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
        Default is 10s.
    :type T_max:
        float

    :return:
        list of `nb_iter` approximate sample of DPP(kernel)
    :rtype:
        array_like

    .. seealso::

        Algorithm 1 in :cite:`LiJeSr16c`
    """

    # Initialization
    N = kernel.shape[0]  # Number of elements

    # Initialization
    S0, det_S0 = s_init, det_ST(kernel, s_init)
    samples = [S0]  # Initialize the collection (list) of sample

    # Evaluate running time...
    flag = True
    it = 1
    t_start = time.time() if T_max else 0

    while flag:

        # With proba 1/2 try to add/delete an element
        if np.random.rand() < 0.5:

            # Perform the potential add/delete move S1 = S0 +/- s
            S1 = S0.copy()  # S1 = S0
            s = np.random.choice(N, size=1)[0]  # Uniform item in [N]
            if s in S1:
                S1.remove(s)  # S1 = S0 - s
            else:
                S1.extend([s])  # S1 = SO + s

            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if np.random.rand() < det_S1 / det_S0:
                S0, det_S0 = S1, det_S1
                samples.append(S1)

            else:
                samples.append(S0)

        else:
            samples.append(S0)

        it += 1
        flag = (it < nb_iter) if not T_max else ((time.time()-t_start) < T_max)

    return samples
Exemplo n.º 16
0
def add_exchange_delete_sampler(kernel, s_init=None, nb_iter=10, T_max=None):
    """ MCMC sampler for generic DPPs, it is a mix of add/delete and basis exchange MCMC samplers.

    :param kernel:
        Kernel martrix
    :type kernel:
        array_like

    :param s_init:
        Initial sample.
    :type s_init:
        list

    :param nb_iter:
        Maximum number of iterations performed by the the algorithm.
        Default is 10.
    :type nb_iter:
        int

    :param T_max:
        Maximum running time of the algorithm (in seconds).
    :type T_max:
        float

    :return:
        list of `nb_iter` approximate sample of DPP(kernel)
    :rtype:
        array_like

    .. seealso::

        Algorithm 3 in :cite:`LiJeSr16c`
    """

    N = kernel.shape[0]
    ground_set = np.arange(N)

    # Initialization
    S0, det_S0 = s_init, det_ST(kernel, s_init)
    sampl_size = len(S0)  # Size of the current sample
    samples = [S0]  # Initialize the collection (list) of sample

    # Evaluate running time...
    flag = True
    it = 1
    t_start = time.time() if T_max else 0

    while flag:

        S1 = S0.copy()  # S1 = S0
        # Pick one element s in S_0 by index uniformly at random
        s_ind = np.random.choice(sampl_size, size=1)[0]
        # Unif t in [N]-S0
        t = np.random.choice(np.delete(ground_set, S0), size=1)[0]

        unif_01 = np.random.rand()
        ratio = sampl_size / N  # Proportion of items in current sample

        # Add: S1 = S0 + t
        if unif_01 < 0.5 * (1 - ratio)**2:
            S1.extend([t])  # S1 = S0 + t
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if np.random.rand() < det_S1/det_S0*(sampl_size+1)/(N-sampl_size):
                S0, det_S0 = S1, det_S1
                samples.append(S1)
                sampl_size += 1
            else:
                samples.append(S0)

        # Exchange: S1 = S0 - s + t
        elif (0.5 * (1 - ratio)**2 <= unif_01) & (unif_01 < 0.5 * (1 - ratio)):
            del S1[s_ind]  # S1 = S0 - s
            S1.extend([t])  # S1 = S1 + t = S0 - s + t
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if np.random.rand() < (det_S1 / det_S0):
                S0, det_S0 = S1, det_S1
                samples.append(S1)
                # sampl_size stays the same
            else:
                samples.append(S0)

        # Delete: S1 = S0 - s
        elif (0.5*(1-ratio) <= unif_01) & (unif_01 < 0.5*(ratio**2+(1-ratio))):
            del S1[s_ind] # S0 - s
            # Accept_reject the move
            det_S1 = det_ST(kernel, S1)  # det K_S1
            if np.random.rand() < det_S1/det_S0*sampl_size/(N-(sampl_size-1)):
                S0, det_S0 = S1, det_S1
                samples.append(S1)
                sampl_size -= 1
            else:
                samples.append(S0)

        else:
            samples.append(S0)

        it += 1
        flag = (it < nb_iter) if not T_max else ((time.time()-t_start) < T_max)

    return samples