Source code for netsalt.algorithm

"""Search algorighms for mode detections."""
import logging

import numpy as np
from skimage.feature import peak_local_max

from .quantum_graph import mode_quality

L = logging.getLogger(__name__)


[docs]def find_rough_modes_from_scan(ks, alphas, qualities, min_distance=2, threshold_abs=10): """Use scipy.ndimage algorithms to detect minima in the scan. Args: ks (list): list of real part of wavenumbers from the scan alphas (list): list of imaginary part of wavenumbers from the scan qualities (array): matrix with mode qualities for each pair of k/alpha min_distance (int): smallest distance between peaks (for skimage.feature.peak_local_max) threshold_abs (float): minimal intensity between peaks (for skimage.feature.peak_local_max) """ data = 1.0 / (1e-10 + qualities) rough_mode_ids = peak_local_max(data, min_distance=min_distance, threshold_abs=threshold_abs) return [[ks[rough_mode_id[0]], alphas[rough_mode_id[1]]] for rough_mode_id in rough_mode_ids]
[docs]def refine_mode_brownian_ratchet( initial_mode, graph, params, disp=False, save_mode_trajectories=False, seed=42, ): """Accurately find a mode from an initial guess, using brownian ratchet algorithm. This algorithm is quite complex, but generally randomly propose a move to a new mode location, and accept if the quality decreases. TODO: get rid of params, or better handling of them, and complete the doc on the small details Args: initial_mode (complex): initial gues for a mode graph (graph): quantum graph params (dict): includes search_stepsize, max_steps, quality_threhsold, max_tries_reduction reduction_factor disp (bool): to print some state of the search for debuing save_mode_trajectories (bool): true to save intermediate modes seed (int): seed for rng """ np.random.seed(seed) current_mode = initial_mode.copy() if save_mode_trajectories: mode_trajectories = [current_mode.copy()] initial_quality = mode_quality(current_mode, graph) current_quality = initial_quality search_stepsize = params["search_stepsize"] tries_counter = 0 step_counter = 0 while current_quality > params["quality_threshold"] and step_counter < params["max_steps"]: new_mode = ( current_mode + search_stepsize * current_quality / initial_quality * np.random.uniform(-1, 1, 2) ) new_quality = mode_quality(new_mode, graph) if disp: L.debug( "New quality: %s, Step size: %s, Current mode: %s, New mode: %s, step %s", new_quality, search_stepsize, current_mode, new_mode, step_counter, ) # if the quality improves, update the mode if new_quality < current_quality: current_quality = new_quality current_mode = new_mode tries_counter = 0 if save_mode_trajectories: mode_trajectories.append(current_mode.copy()) else: tries_counter += 1 # if no improvements after some iterations, multiply the steps by reduction factor if tries_counter > params["max_tries_reduction"]: search_stepsize *= params["reduction_factor"] tries_counter = 0 if search_stepsize < 1e-10: disp = True L.info("Warning: mode search stepsize under 1e-10 for mode: %s", current_mode) L.info("We retry from a larger one, but consider fine tuning search parameters.") search_stepsize = 1e-8 step_counter += 1 if current_quality < params["quality_threshold"]: if save_mode_trajectories: return np.array(mode_trajectories) return current_mode L.info("Maximum number of tries attained and no mode found, we retry from scratch!") params["search_stepsize"] *= 5 return refine_mode_brownian_ratchet( initial_mode, graph, params, disp=disp, save_mode_trajectories=save_mode_trajectories, )
[docs]def clean_duplicate_modes(all_modes, k_size, alpha_size): """Remave duplicate modes from a list of modes with a threshold in real/imag(k). Args: all_modes (list): list of modes k_size (float): minimal distance in real(k) alpha_size (float): minimal distance in imag(k) """ duplicate_mode_ids = [] for mode_id_0, mode_0 in enumerate(all_modes): for mode_id_1, mode_1 in enumerate(all_modes[mode_id_0 + 1 :]): if ( mode_id_1 + mode_id_0 + 1 not in duplicate_mode_ids and abs(mode_0[0] - mode_1[0]) < k_size and abs(mode_0[1] - mode_1[1]) < alpha_size ): duplicate_mode_ids.append(mode_id_0) break return np.delete(np.array(all_modes), duplicate_mode_ids, axis=0)