예제 #1
0
def vis_gauss_lanczos_mtx_size():
    n_repetitions = 30
    eig_max = 5

    mtx_sizes = list(range(2, 45))
    average_errs = []
    for mtx_size in mtx_sizes:
        np.random.seed(0)
        average_err = 0
        for seed in range(n_repetitions):
            mtx = rand_positive_definite_mtx(size=mtx_size,
                                             seed=seed,
                                             eig_max=eig_max).mtx
            tr_appr = tr_approx(mtx=mtx,
                                f=matrix_fun,
                                n_samples=mtx_size // 2 + 1,
                                seed=seed,
                                approx_method=ApproxMethod.gauss_lanczos_naive,
                                max_iter=mtx_size // 2 + 1)
            tr_precise = np.trace(matrix_fun(mtx))
            print("trace (approx): {}".format(tr_appr))
            print("trace (precise): {}".format(tr_precise))
            average_err += np.abs((tr_appr - tr_precise) / tr_appr)
        average_err /= n_repetitions
        average_errs.append(average_err)

    plt.figure()
    plt.plot(mtx_sizes, average_errs)
    plt.title(
        "Trace approximation with Gauss-Lanczos procedure: \n relative deviation"
    )
    plt.xlabel("matrix size")
    plt.ylabel("average relative error per {} runs".format(n_repetitions))
    plt.show()
예제 #2
0
def trace_approx_benchmark(n_lanczos_iter: int, n_hutchinson_iter: int,
                           eig_max: int, fig_file: Path):
    methods = (
        ApproxMethod.gauss_lanczos_naive,
        ApproxMethod.gauss_lanczos_memopt,
    )

    n_repeats = 100
    mtx_sizes = list(range(20, 121, 20))
    n_observ = len(mtx_sizes)
    times_exact = [0] * n_observ
    times, errs = ({method: [0] * n_observ
                    for method in methods} for _ in range(2))

    for i_obs, m_size in enumerate(mtx_sizes):
        for seed in range(n_repeats):
            r_mtx = rand_positive_definite_mtx(size=m_size,
                                               seed=seed,
                                               eig_max=eig_max)

            t_exact_start = time.perf_counter()
            tr_exact = np.trace(matrix_fun(r_mtx.mtx))
            t_exact_end = time.perf_counter()
            times_exact[i_obs] += t_exact_end - t_exact_start

            for method in methods:
                t_start = time.perf_counter()
                tr_appr = tr_approx(mtx=r_mtx.mtx,
                                    f=matrix_fun,
                                    n_samples=n_hutchinson_iter,
                                    max_iter=n_lanczos_iter,
                                    seed=seed,
                                    approx_method=method)
                t_end = time.perf_counter()

                times[method][i_obs] += t_end - t_start
                errs[method][i_obs] += np.abs((tr_appr - tr_exact) / tr_exact)

            def normalize(arr: List[int]):
                arr[i_obs] /= n_repeats

            map(normalize, [times_exact, *times.values(), *errs.values()])

    fig, (ax_top, ax_bottom) = plt.subplots(nrows=2, ncols=1)

    ax_top.plot(mtx_sizes, times_exact)
    for method in methods:
        ax_top.plot(mtx_sizes, times[method])
    ax_top.legend(["exact", *(str(method) for method in methods)])
    ax_top.set_title("time performance in seconds")
    ax_top.set_xlabel("mtx size")

    for method in methods:
        ax_bottom.plot(mtx_sizes, errs[method])
    ax_bottom.legend(list(map(str, methods)))
    ax_bottom.set_title("relative error")
    ax_bottom.set_xlabel("mtx size")

    plt.tight_layout()
    plt.savefig(fig_file)
예제 #3
0
def test_lanczos_vectorized():
    mtx_size, seed = 10, 0
    abs_tol = .1
    for mtx_size in range(10, 40, 5):
        rand_mtx_props = rand_positive_definite_mtx(size=mtx_size, seed=seed, eig_max=5)
        q1, max_iter = rand_unit_vector(size=mtx_size, seed=seed).reshape((mtx_size, 1)), mtx_size // 2 + 1
        res_vec = lanczos_memoptimized(a=rand_mtx_props.mtx, q1=q1, max_iter=max_iter)
        assert np.abs(np.max(res_vec.eigvals) - np.max(rand_mtx_props.eigvals)) < abs_tol
예제 #4
0
def test_lanczos_naive():
    eig_max = 10
    for mtx_size in (5, 10, 15, 20, 25, 30):
        rand_mtx_props = rand_positive_definite_mtx(mtx_size, seed=0, eig_max=eig_max)
        np.random.seed(0)

        q = rand_unit_vector(size=mtx_size, seed=0)
        eig_estimate = lanczos_naive(a=rand_mtx_props.mtx, q1=q.reshape((len(q), 1)), max_iter=mtx_size // 2 + 1)
        assert (0 <= eig_estimate.eigvals).all() and (eig_estimate.eigvals <= eig_max).all()
        print("test for n={} passed, k={}, deviation of max eig ={}"
              .format(mtx_size, len(eig_estimate.eigvals),
                      np.abs(np.max(rand_mtx_props.eigvals) - np.max(eig_estimate.eigvals))))
예제 #5
0
def test_gauss_lanzcos():
    mtx = rand_positive_definite_mtx(5, 0).mtx

    def f(x: np.ndarray) -> np.ndarray:
        return x**2

    tr_appr = tr_approx(mtx=mtx,
                        f=f,
                        n_samples=3,
                        seed=0,
                        approx_method=ApproxMethod.bruteforce)
    assert np.abs((tr_appr - np.trace(f(mtx))) / tr_appr) < .5
예제 #6
0
def test_hutchinson_trick():
    m = rand_positive_definite_mtx(10, 0).mtx

    def f(x: np.array) -> np.array:
        return np.log(np.abs(x) + .5)

    trace_precise = np.trace(f(m))
    residuals = [
        np.abs(
            tr_approx(m, f, n_samples, 0, ApproxMethod.bruteforce) -
            trace_precise) for n_samples in range(1, 20)
    ]
    assert np.median(residuals[:5]) > np.median(residuals[-5:])
예제 #7
0
def average_deviation(n_samples: int, eig_max: float, absolute: bool,
                      mtx_size: int, method: ApproxMethod,
                      max_iter: int) -> float:
    n_sample_runs = 15
    result = 0
    for seed in range(n_sample_runs):
        mtx = rand_positive_definite_mtx(size=mtx_size,
                                         seed=seed,
                                         eig_max=eig_max).mtx
        tr_precise = np.trace(matrix_fun(mtx))
        delta_tr = np.abs(tr_precise - tr_approx(mtx=mtx,
                                                 f=matrix_fun,
                                                 n_samples=n_samples,
                                                 seed=seed,
                                                 approx_method=method,
                                                 max_iter=max_iter))
        if not absolute:
            delta_tr /= np.abs(tr_precise)
        result += delta_tr
    return result / n_sample_runs
예제 #8
0
def test_rand_matrix():
    matrices: List[np.ndarray] = []
    size = 2
    max_eig = 20
    out_file_stem = "rand_matrices"
    for seed in range(200):
        matrices.append(rand_positive_definite_mtx(size=size, seed=seed, eig_max=max_eig).mtx)
    matrices_flat = np.array([mtx.flatten() for mtx in matrices])

    fig = plt.figure()
    ax = fig.add_subplot(projection="3d")
    ax.scatter(matrices_flat[:, 0], matrices_flat[:, 1], matrices_flat[:, 3], c=matrices_flat[:, 2])
    ax.set_xlabel("a[0,0]")
    ax.set_ylabel("a[0,1]")
    ax.set_zlabel("a[1,1]")
    plt.savefig(out_file_stem + ".png")

    px_fig = px.scatter_3d(x=matrices_flat[:, 0], y=matrices_flat[:, 1], z=matrices_flat[:, 3],
                           color=matrices_flat[:, 2])
    with open(out_file_stem + ".html", "w") as fout:
        fout.write(px_fig.to_html())
예제 #9
0
def test_rand_positive_definite():
    for seed in range(10):
        assert np.all(
            np.linalg.eigvals(rand_positive_definite_mtx(10, seed).mtx) > 0)