Ejemplo n.º 1
0
def _simulate(algorithm, ij_tuple, seeds, path):
    """
    Run a number of monte carlo simulations in a single delta-rho point.

    The result of a simulation is the simulation error distance, i.e., the
    ratio between the energy of the coefficient residual and the energy of the
    coefficient vector. The time of the simulation is the execution time of the
    reconstruction attempt.

    Parameters
    ----------
    algorithm : function
        A function handle to the reconstruction algorithm.
    ij_tuple : tuple
        A tuple (i, j) containing the parameters i, j as listed below.
    i : int
        The delta-index of the point in the delta-rho grid.
    j : int
        The rho-index of the point in the delta-rho grid.
    seeds : ndarray
        The seeds to pass to numpy.random when generating the problem suite
        instances.
    path : str
        The path of the HDF5 backup database.

    See Also
    --------
    magni.cs.phase_transition._data.generate_matrix : Matrix generation.
    magni.cs.phase_transition._data.generate_vector : Coefficient vector
        generation.

    """

    i, j = ij_tuple

    n = _config.get('n')
    m = int(np.round(n * _config.get('delta')[i]))
    k = int(np.round(m * _config.get('rho')[j]))

    stat_time = np.zeros(_config.get('monte_carlo'), dtype=np.float64)
    stat_dist = stat_time.copy()

    if k > 0:
        for l in range(_config.get('monte_carlo')):
            np.random.seed(seeds[l])
            A = _data.generate_matrix(m, n)
            x = _data.generate_vector(n, k)
            y = A.dot(x)

            start = time.time()
            x_hat = algorithm(y, A)
            end = time.time()
            x_res = x_hat - x

            stat_time[l] = end - start
            stat_dist[l] = (np.linalg.norm(x_res) / np.linalg.norm(x))**2

    _backup.set(path, (i, j), stat_time, stat_dist)
Ejemplo n.º 2
0
def run(algorithm, path, label):
    """
    Simulate a reconstruction algorithm.

    The simulation results are stored in a HDF5 database rather than returned
    by the function.

    Parameters
    ----------
    algorithm : function
        A function handle to the reconstruction algorithm.
    path : str
        The path of the HDF5 database where the results should be stored.
    label : str
        The label assigned to the simulation results.

    """

    tmp_dir = _split_path(path)[0] + '.tmp' + os.sep
    tmp_file = tmp_dir + label.replace('/', '#') + '.hdf5'

    if not os.path.isdir(tmp_dir):
        os.mkdir(tmp_dir)

    if not os.path.isfile(tmp_file):
        _backup.create(tmp_file)

    done = _backup.get(tmp_file)
    shape = _config.get()
    shape = [len(shape['delta']), len(shape['rho']), shape['monte_carlo']]
    np.random.seed(_config.get('seed'))
    seeds = np.random.randint(0, 2**30, shape)

    tasks = [(algorithm, (i, j), seeds[i, j], tmp_file)
             for i in range(shape[0]) for j in range(shape[1])
             if not done[i, j]]

    _process(_simulate, args_list=tasks)

    with _File(tmp_file, 'r') as f:
        stat_time = f.root.time[:]
        stat_dist = f.root.dist[:]

    with _File(path, 'a') as f:
        f.create_array('/' + label, 'time', stat_time, createparents=True)
        f.create_array('/' + label, 'dist', stat_dist, createparents=True)

    os.remove(tmp_file)

    if len(os.listdir(tmp_dir)) == 0:
        os.removedirs(tmp_dir)
Ejemplo n.º 3
0
def create(path):
    """
    Create the HDF5 backup database with the required arrays.

    The required arrays are an array for the simulation results, an array for
    the simulation timings, and an array for tracking the status.

    Parameters
    ----------
    path : str
        The path of the HDF5 backup database.

    See Also
    --------
    magni.cs.phase_transition.config : Configuration options.

    """

    shape = [_config.get(key) for key in ["delta", "rho", "monte_carlo"]]
    shape = [len(shape[0]), len(shape[1]), shape[2]]
    time = dist = np.zeros(shape)
    status = np.zeros(shape[:2], np.bool8)

    try:
        with _File(path, "w") as f:
            f.create_array("/", "time", time)
            f.create_array("/", "dist", dist)
            f.create_array("/", "status", status)
    except BaseException as e:
        if os.path.exists(path):
            os.remove(path)

        raise e
Ejemplo n.º 4
0
def run(path, label):
    """
    Determine the phase transition from the simulation results.

    The simulation results should be present in the HDF5 database specified by
    `path` in the pytables group specified by `label` in an array named 'dist'.
    The determined phase transition is stored in the same HDF5 database, in the
    same pytables group in an array named 'phase_transition'.

    Parameters
    ----------
    path : str
        The path of the HDF5 database.
    label : str
        The path of the pytables group in the HDF5 database.

    See Also
    --------
    _estimate_PT : The actual phase transition estimation.

    Notes
    -----
    A simulation is considered successful if the simulation result is less than
    10 to the power of -4.

    """

    _conf = _config.get()

    with _File(path, 'a') as f:
        if not '/' + label + '/phase_transition' in f:
            points = len(_conf['rho']) * _conf['monte_carlo']

            z = np.zeros(points)
            y = np.zeros(points)

            rho = np.zeros(len(_conf['delta']))

            dist = f.get_node('/' + label + '/dist')[:]

            for i in range(len(_conf['delta'])):
                n = np.round(_conf['delta'][i] * _conf['n'])

                for j in range(len(_conf['rho'])):
                    if n > 0:
                        var = _conf['rho'][j]
                        var = np.round(var * n) / n
                    else:
                        var = 0.

                    for m in range(_conf['monte_carlo']):
                        z[j * _conf['monte_carlo'] + m] = var
                        y[j * _conf['monte_carlo'] + m] = dist[i, j, m] < 1e-4

                rho[i] = _estimate_PT(z, y)

            f.create_array('/' + label, 'phase_transition', rho)
Ejemplo n.º 5
0
def generate_vector(n, k):
    """
    Generate a vector belonging to a specific problem suite.

    The available ensembles are the Gaussian ensemble and the Rademacher
    ensemble. See Notes for a description of the ensembles. Which of the
    available ensembles is used, is specified as a configuration option. Note,
    that the non-zero `k` non-zero coefficients are the `k` first entries.

    Parameters
    ----------
    n : int
        The length of the vector.
    k : int
        The number of non-zero coefficients.

    Returns
    -------
    alpha : ndarray
        The generated vector.

    See Also
    --------
    magni.cs.phase_transition.config : Configuration options.

    Notes
    -----
    The Gaussian ensemble :
        The non-zero coefficients are drawn from the normal Gaussian
        distribution.
    The Rademacher ensemble:
        The non-zero coefficients are drawn from the constant amplitude with
        random signs ensemble.

    """

    x = np.zeros((n, 1))
    coefficients = _config.get('coefficients')

    if coefficients == 'rademacher':
        x[:k, 0] = np.random.randint(0, 2, k) * 2 - 1
    elif coefficients == 'gaussian':
        x[:k, 0] = np.random.randn(k)

    return x