Exemple #1
0
def test_step_fast_perf() -> None:
    step_fasts, step_slows, step_corrects = [], [], []
    for _ in range(5):
        eigs = np.sort(np.random.uniform(-10000, 10000, 10000))
        x = np.linspace(eigs[0], eigs[-1], 5000)

        start = time.time()
        for _ in range(100):
            _step_function_fast(eigs, x)
        step_fast = time.time() - start

        start = time.time()
        for _ in range(100):
            _step_function_slow(eigs, x)
        step_slow = time.time() - start

        start = time.time()
        for _ in range(100):
            _step_function_correct(eigs, x)
        step_correct = time.time() - start

        step_fasts.append(step_fast)
        step_slows.append(step_slow)
        step_corrects.append(step_correct)

    print("Smaller values are better (seconds)")
    print(
        "_step_function_fast:       ",
        np.mean(step_fasts),
        "+-",
        3 * np.std(step_fasts, ddof=1),
    )
    print(
        "_step_function_slow: ",
        np.mean(step_slows),
        "+-",
        3 * np.std(step_slows, ddof=1),
    )
    print(
        "_step_function_correct:    ",
        np.mean(step_corrects),
        "+-",
        3 * np.std(step_corrects, ddof=1),
    )
Exemple #2
0
def _step_function(
    eigs: ndarray,
    gridsize: int = 100000,
    title: str = "Eigenvalue Step Function",
    mode: PlotMode = "block",
    outfile: Path = None,
    fig: Figure = None,
    axes: Axes = None,
) -> PlotResult:
    """Compute the step function vaues over a grid, and plot the resulting curve.

    Parameters
    ----------
    eigs: ndarray
        The eigenvalues to plot.

    gridsize: int
        The number of points to evaluate the step function over. The grid will be
        generated as np.linspace(eigs.min(), eigs.max(), gridsize).

    title: string
        The plot title string

    mode: "block" (default) | "noblock" | "save" | "return"
        If "block", call plot.plot() and display plot in a blocking fashion.
        If "noblock", attempt to generate plot in nonblocking fashion.
        If "save", save plot to pathlib Path specified in `outfile` argument
        If "return", return (fig, axes), the matplotlib figure and axes object
        for modification.

    outfile: Path
        If mode="save", save generated plot to Path specified in `outfile` argument.
        Intermediate directories will be created if needed.

    fig: Figure
        If provided with `axes`, configure plotting with the provided `fig`
        object instead of creating a new figure. Useful for creating subplots.

    axes: Axes
        If provided with `fig`, plot to the provided `axes` object. Useful for
        creating subplots.


    Returns
    -------
    (fig, axes): (Figure, Axes)
        The handles to the matplotlib objects, only if `mode` is "return".
    """
    _configure_sbn_style()
    fig, axes = _setup_plotting(fig, axes)
    grid = np.linspace(eigs.min(), eigs.max(), gridsize)
    steps = _step_function_fast(eigs, grid)
    df = pd.DataFrame({"Cumulative Value": steps, "Raw eigenvalues λ": grid})
    axes = sbn.lineplot(data=df, x="Raw eigenvalues λ", y="Cumulative Value", ax=axes)
    axes.set(title=title)
    return _handle_plot_mode(mode, fig, axes, outfile)
Exemple #3
0
def _spectral_iter(
    unfolded: ndarray,
    delta3_L_vals: ndarray,
    L: float,
    c_iters: int = 10000,
    interval_gridsize:
    int = 10000,  # does not tend to effect performance significantly
    use_simpsons: bool = True,
) -> ndarray:
    """Compute c_iters values of L and save them in delta3_L_vals.

    Parameters
    ----------
    unfolded: ndarray
        The sorted unfolded eigenvalues.

    delta3_L_vals: ndarray
        The array to store all the c_iters computed L values.

    L: float
        The current L value for which the spectral rigidity is being calculated.

    c_iters: int
        The number of centre-points (c) to choose (i.e. the number of L values to
        compute).

    interval_gridsize: int
        The number of points for which to evaluate the deviation from a straight
        line on [c - L/2, c + L/2].
    """
    # make each iteration centred at a random value on the unfolded spectrum
    starts = np.random.uniform(unfolded[0], unfolded[-1], c_iters)
    for i in prange(len(starts)):
        # c_start is in space of unfolded, not unfolded
        grid = np.linspace(starts[i] - L / 2, starts[i] + L / 2,
                           interval_gridsize)
        steps = _step_function_fast(unfolded, grid)  # performance bottleneck
        K = _slope(grid, steps)
        w = _intercept(grid, steps, K)
        y_vals = _sq_lin_deviation(unfolded, steps, K, w, grid)
        if use_simpsons:
            delta3 = _int_simps_nonunif(grid, y_vals)  # O(len(grid))
        else:
            delta3 = _integrate_fast(grid, y_vals)  # O(len(grid))
        delta3_L_vals[i] = delta3 / L
Exemple #4
0
 def step_function(self, x: ndarray) -> ndarray:
     return _step_function_fast(eigs=self.vals, x=x)
Exemple #5
0
 def steps(self) -> ndarray:
     if self._steps is None:
         self._steps = _step_function_fast(self._vals, self._vals)
     return self._steps
Exemple #6
0
 def is_close(eigs: ndarray, vals: ndarray) -> bool:
     computed = _step_function_fast(eigs, vals)
     correct = _step_function_correct(eigs, vals)
     diffs = np.sum(np.abs(computed - correct)) / len(vals)
     return bool(diffs < 1e-5)
Exemple #7
0
 def is_correct(eigs: ndarray, vals: ndarray) -> Any:
     return np.allclose(
         np.array(_step_function_fast(eigs, vals), dtype=int),
         np.array(_step_function_correct(eigs, vals), dtype=int),
         atol=1e-5,
     )
Exemple #8
0
def test_step_fast() -> None:
    def is_correct(eigs: ndarray, vals: ndarray) -> Any:
        return np.allclose(
            np.array(_step_function_fast(eigs, vals), dtype=int),
            np.array(_step_function_correct(eigs, vals), dtype=int),
            atol=1e-5,
        )

    def is_close(eigs: ndarray, vals: ndarray) -> bool:
        computed = _step_function_fast(eigs, vals)
        correct = _step_function_correct(eigs, vals)
        diffs = np.sum(np.abs(computed - correct)) / len(vals)
        return bool(diffs < 1e-5)

    # readable cases
    reigs = np.array([-2, -1, 0, 1, 2], dtype=float)
    x = np.array([-3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0])
    assert np.allclose(
        np.array(_step_function_fast(reigs, x), dtype=int),
        np.array([0, 0, 1, 1, 2, 2, 3], dtype=int),
    )
    assert is_correct(reigs, x)
    x = np.array([-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5])
    assert np.allclose(
        np.array(_step_function_fast(reigs, x), dtype=int),
        np.array([1, 1, 2, 2, 3, 3, 4, 4, 5, 5], dtype=int),
    )
    assert is_correct(reigs, x)
    x = np.array([-3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5])
    assert np.allclose(
        np.array(_step_function_fast(reigs, x), dtype=int),
        np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5], dtype=int),
    )
    assert is_correct(reigs, x)
    # this input is causing a segfault
    x = np.array([0.0, 0.5, 1.0, 1.5, 2.0, 2.5])
    assert np.allclose(
        np.array(_step_function_fast(reigs, x), dtype=int),
        np.array([3, 3, 4, 4, 5, 5], dtype=int),
    )
    assert is_correct(reigs, x)

    for _ in range(1000):
        eigs = np.sort(np.random.uniform(-1000, 1000, 1000))
        # for i in range(len(eigs) - 1):
        #     if np.allclose(eigs[i], eigs[i + 1]):
        #         raise ValueError("Non-unique eigenvalues!")

        # degenerate cases
        x_0 = np.linspace(eigs[-1] + 1000, eigs[-1] + 2000, 10000)
        x_1 = np.linspace(eigs[0] - 1000, eigs[0] - 2000, 10000)
        assert is_close(eigs, x_0)
        assert is_close(eigs, x_1)

        # differing overlaps
        x_2 = np.linspace(eigs[0], eigs[-1], 10000)
        x_3 = np.linspace(eigs[0] - 500, eigs[-1], 10000)
        x_4 = np.linspace(eigs[0] - 500, eigs[-1] + 500, 10000)
        x_5 = np.linspace(eigs[0], eigs[-1] + 500, 10000)
        assert is_close(eigs, x_2)
        assert is_close(eigs, x_3)
        assert is_close(eigs, x_4)
        assert is_close(eigs, x_5)