Beispiel #1
0
def test_quad_degree():
    """
    Проверяем АСТ для ИКФ
    Q: почему в  некоторых случаях x^n интегрируется почти без ошибок при n узлах ИКФ?
    """
    x0, x1 = 0, 1

    max_degree = 7
    max_nodes = 7

    for deg in range(max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        node_counts = range(1, max_nodes+1)

        Y = [quad(p, x0, x1, np.linspace(x0, x1, node_count)) for node_count in node_counts]
        # Y = [quad(p, x0, x1, x0 + (x1-x0) * np.random.random(node_count)) for node_count in max_node_count]
        accuracy = get_accuracy(Y, y0 * np.ones_like(Y))

        # Проверяем точность
        for node_count, acc in zip(node_counts, accuracy):
            if node_count >= deg + 1:
                assert acc > 6

        plt.plot(node_counts, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node_count')
    plt.suptitle(f'test quad')
    plt.show()
Beispiel #2
0
def test_weighted_quad_degree():
    """
    Проверяем АСТ для ИКФ с весами
    Посчитаем n-ый момент весовой функции двумя способами:
        - через moments()
        - численно через quad()
    """
    x0, x1 = 1, 3
    alpha = 0.14
    beta = 0.88

    max_degree = 7
    for deg in range(1, max_degree):
        p = Monome(deg)
        xs = np.linspace(x0, x1, 6)[1:-1]  # 4 points => accuracy degree is 3

        res = quad(p, x0, x1, xs, a=x0, alpha=alpha)
        ans = moments(deg, x0, x1, a=x0, alpha=alpha)[-1]
        d = abs(res - ans)
        print(f'{deg:2}-a: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6

        res = quad(p, x0, x1, xs, b=x1, beta=beta)
        ans = moments(deg, x0, x1, b=x1, beta=beta)[-1]
        d = abs(res - ans)
        print(f'{deg:2}-b: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6
Beispiel #3
0
def test_quad_gauss_degree():
    """
    check gaussian quadrature degree
    """
    x0, x1 = 0, 1

    max_degree = 8

    for deg in range(2, max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        max_node_count = range(2, 6)
        Y = [
            quad_gauss(p, x0, x1, node_count) for node_count in max_node_count
        ]
        accuracy = get_log_error(Y, y0 * np.ones_like(Y))
        accuracy[np.isinf(accuracy)] = 17

        # check accuracy is good enough
        for node_count, acc in zip(max_node_count, accuracy):
            if 2 * node_count >= deg + 1:
                assert acc > 6

        plt.plot(max_node_count, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node count')
    plt.suptitle(f'test quad gauss')
    plt.show()
Beispiel #4
0
def test_quad_gauss_degree():
    """
    Проверяем АСТ для ИКФ Гаусса
    """
    x0, x1 = 0, 1

    max_degree = 8

    for deg in range(max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        node_counts = range(1, 6)
        Y = [quad_gauss(p, x0, x1, node_count) for node_count in node_counts]
        accuracy = get_accuracy(Y, y0 * np.ones_like(Y))

        # Проверяем точность
        for node_count, acc in zip(node_counts, accuracy):
            if 2 * node_count >= deg + 1:
                assert acc > 6

        plt.plot(node_counts, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node count')
    plt.suptitle(f'test quad gauss')
    plt.show()
Beispiel #5
0
def test_composite_quad(n_nodes):
    """
    Проверяем 2-, 3-, 5-узловые СКФ
    Q: объясните скорость сходимости для каждого случая
    """
    fig, ax = plt.subplots(1, 2)

    x0, x1 = 0, 1
    L = 2
    n_intervals = [L ** q for q in range(0, 8)]

    for i, degree in enumerate((5, 6)):
        p = Monome(degree)
        Y = [composite_quad(p, x0, x1, n_intervals=n, n_nodes=n_nodes) for n in n_intervals]
        accuracy = get_accuracy(Y, p[x0, x1] * np.ones_like(Y))
        x = np.log10(n_intervals)

        # оценка сходимости
        ind = np.isfinite(x) & np.isfinite(accuracy)
        k, b = np.polyfit(x[ind], accuracy[ind], 1)
        aitken_degree = aitken(*Y[0:6:2], L ** 2)

        ax[i].plot(x, k*x+b, 'b:', label=f'{k:.2f}*x+{b:.2f}')
        ax[i].plot(x, aitken_degree*x+b, 'm:', label=f'aitken ({aitken_degree:.2f})')
        ax[i].plot(x, accuracy, 'kh', label=f'accuracy for x^{degree}')
        ax[i].set_title(f'{n_nodes}-node CQ for x^{degree}')
        ax[i].set_xlabel('log10(n_intervals)')
        ax[i].set_ylabel('accuracy')
        ax[i].legend()

        if n_nodes < degree:
            assert np.abs(aitken_degree - k) < 0.5, \
                f'Aitken estimation {aitken_degree:.2f} is too far from actual {k:.2f}'

    plt.show()
Beispiel #6
0
def test_weighted_quad_degree():
    """
    check weighted quadrature degree
    we compare n-th moment of weight function calculated in two ways:
        - by moments()
        - numerically by quad()
    """
    x0, x1 = 1, 3
    alpha = 0.14
    beta = 0.88

    max_degree = 7
    for deg in range(1, max_degree):
        p = Monome(deg)
        xs = np.linspace(x0, x1, 6)[1:-1]  # 4 points => accuracy degree is 3

        res = quad(p, x0, x1, xs, a=x0, alpha=alpha)
        ans = moments(deg, x0, x1, a=x0, alpha=alpha)[-1]
        d = abs(res - ans)
        print(f'{deg:2}-a: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6

        res = quad(p, x0, x1, xs, b=x1, beta=beta)
        ans = moments(deg, x0, x1, b=x1, beta=beta)[-1]
        d = abs(res - ans)
        print(f'{deg:2}-b: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6
Beispiel #7
0
def tes_quad_degree():
    """
    check quadrature degree
    Q: why in some cases x^n integrated perfectly with only n nodes?
    """
    x0, x1 = 0, 1

    max_degree = 7

    for deg in range(1, max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        max_node_count = range(1, max_degree + 1)

        Y = [
            quad(p, x0, x1, np.linspace(x0, x1, node_count))
            for node_count in max_node_count
        ]
        # Y = [quad(p, x0, x1, x0 + (x1-x0) * np.random.random(node_count)) for node_count in max_node_count]
        accuracy = get_log_error(Y, y0 * np.ones_like(Y))
        accuracy[np.isinf(accuracy)] = 17

        # check accuracy is good enough
        for node_count, acc in zip(max_node_count, accuracy):
            if node_count >= deg + 1:
                assert acc > 6

        plt.plot(max_node_count, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node_count')
    plt.suptitle(f'test quad')
    plt.show()
Beispiel #8
0
def test_weighted_quad_degree():
    """
    check weighed quadrature degree
    """
    x0, x1 = 1, 3
    alpha = 0.14
    beta = 0.88

    max_degree = 7
    for deg in range(1, max_degree):
        p = Monome(deg)
        xs = np.linspace(x0, x1, 6)[1:-1]  # 4 points => accuracy degree is 3

        res = quad(p, x0, x1, xs, alpha=alpha)
        ans = weight(deg, x0, x1, alpha=alpha)
        d = abs(res - ans)
        print(f'{deg:2}-a: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6

        res = quad(p, x0, x1, xs, beta=beta)
        ans = weight(deg, x0, x1, beta=beta)
        d = abs(res - ans)
        print(f'{deg:2}-b: {res:8.3f} vs {ans:8.3f}, delta = {d:e}')
        if deg < len(xs):
            assert d < 1e-6
Beispiel #9
0
def test_composite_quad():
    plt.figure()

    x0, x1 = 0, 1
    L = 2
    n_intervals = [L**q for q in range(0, 8)]
    n_nodes = 3

    for i, degree in enumerate((5, 6)):
        p = Monome(degree)
        Y = [
            composite_quad(p, x0, x1, n_intervals=n, n_nodes=n_nodes)
            for n in n_intervals
        ]
        accuracy = get_log_error(Y, p[x0, x1] * np.ones_like(Y))
        x = np.log10(n_intervals)

        # check convergence
        ind = np.isfinite(x) & np.isfinite(accuracy)
        k, b = np.polyfit(x[ind], accuracy[ind], 1)
        aitken_degree = aitken(*Y[0:6:2], L**2)

        plt.subplot(1, 2, i + 1)
        plt.plot(x, k * x + b, 'b:', label=f'{k:.2f}*x+{b:.2f}')
        plt.plot(x, aitken_degree * x + b, 'm:', label=f'aitken estimation')
        plt.plot(x, accuracy, 'kh', label=f'accuracy for x^{degree}')
        plt.xlabel('log10(node count)')
        plt.ylabel('accuracy')
        plt.legend()

        assert np.abs(aitken_degree - k) < 0.5, \
            f'Aitken estimation {aitken_degree:.2f} is too far from actual {k:.2f}'

    plt.show()
Beispiel #10
0
def test_composite_quad(n_nodes):
    """
    test composite 2-, 3-, 5-node quads
    Q: explain converge speed for each case
    """
    fig, ax = plt.subplots(1, 2)

    x0, x1 = 0, 1
    L = 2
    n_intervals = [L ** q for q in range(0, 8)]

    for i, degree in enumerate((5, 6)):
        p = Monome(degree)
        Y = [composite_quad(p, x0, x1, n_intervals=n, n_nodes=n_nodes) for n in n_intervals]
        accuracy = get_log_error(Y, p[x0, x1] * np.ones_like(Y))
        x = np.log10(n_intervals)

        # check convergence
        ind = np.isfinite(x) & np.isfinite(accuracy)
        k, b = np.polyfit(x[ind], accuracy[ind], 1)
        aitken_degree = aitken(*Y[0:6:2], L ** 2)

        ax[i].plot(x, k*x+b, 'b:', label=f'{k:.2f}*x+{b:.2f}')
        ax[i].plot(x, aitken_degree*x+b, 'm:', label=f'aitken ({aitken_degree:.2f})')
        ax[i].plot(x, accuracy, 'kh', label=f'accuracy for x^{degree}')
        ax[i].set_title(f'{n_nodes}-node CQ for x^{degree}')
        ax[i].set_xlabel('log10(n_intervals)')
        ax[i].set_ylabel('accuracy')
        ax[i].legend()

        if n_nodes < degree:
            assert np.abs(aitken_degree - k) < 0.5, \
                f'Aitken estimation {aitken_degree:.2f} is too far from actual {k:.2f}'

    plt.show()
Beispiel #11
0
def test_quad_degree():
    """
    Проверяем АСТ для ИКФ
    Q: почему в некоторых случаях x^n интегрируется почти без ошибок при n узлах ИКФ?

    A: Поскольку многочлен Лагранжа Ln является алгебраическим многочленом степени n − 1, то по построению, он имеет
       алгебраический порядок точности не ниже n − 1. Однако если n нечетно, т.е. когда середина отрезка [a, b] входит
       в состав сетки, то формула оказывается точна и для многочленов степени n.
    """
    x0, x1 = 0, 1

    max_degree = 7
    max_nodes = 7

    for deg in range(max_degree):
        p = Monome(deg)
        y0 = p[x0, x1]

        node_counts = range(1, max_nodes + 1)

        Y = [
            quad(p, x0, x1, np.linspace(x0, x1, node_count))
            for node_count in node_counts
        ]
        # Y = [quad(p, x0, x1, x0 + (x1-x0) * np.random.random(node_count)) for node_count in node_counts]
        accuracy = get_accuracy(Y, y0 * np.ones_like(Y))

        # Проверяем точность
        for node_count, acc in zip(node_counts, accuracy):
            if node_count >= deg + 1:
                assert acc > 6

        plt.plot(node_counts, accuracy, '.:', label=f'x^{deg}')

    plt.legend()
    plt.ylabel('accuracy')
    plt.xlabel('node_count')
    plt.suptitle(f'test quad')
    plt.show()