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
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
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
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()
def test_interpolation(func): """ Проверяем, что значит буква "И" в названии ИКФ Интегрируем интерполяционный многочлен, затем сравниваем результат с quad() """ x0, x1 = 0, 1 n_nodes = 5 xs = np.linspace(x0, x1, n_nodes) ys = func(xs) # numpy poly = np.polyfit(xs, ys, deg=n_nodes - 1) polyint = np.polyint(poly) int_v = np.polyval(polyint, x1) - np.polyval(polyint, x0) # our num_v = quad(func, x0, x1, xs) delta = np.abs(int_v - num_v) assert delta < 1e-6 print( f'interpolate+integrate: {int_v:8.3f}, quad: {num_v:8.3f}, delta: {delta:e}' )
def test_quad_vs_cq(): """ Проверяем, как работают ИКФ и СКФ при одинакомом количестве обращений к функции """ x0, x1 = 0, np.pi/2 p = Harmonic(0, 1) y0 = p[x0, x1] n_nodes = 2 ys_nt_ct = [] ys_gauss = [] ys_cquad = [] n_intervals = 2 ** np.arange(8) for n in n_intervals: n_evals = n * n_nodes ys_nt_ct.append(quad(p, x0, x1, np.linspace(0, 1, n_evals) * (x1-x0) + x0)) ys_gauss.append(quad_gauss(p, x0, x1, n_evals)) ys_cquad.append(composite_quad(p, x0, x1, n, n_nodes)) for ys, label in zip((ys_nt_ct, ys_gauss, ys_cquad), (f'newton-cotes', f'gauss', f'{n_nodes}-node CQ')): acc = get_accuracy(ys, y0 * np.ones_like(ys)) acc[acc > 17] = 17 plt.plot(np.log10(n_intervals), acc, '.:', label=label) plt.legend() plt.ylabel('accuracy') plt.xlabel('log10(n_evals)') plt.suptitle(f'test quad vs composite quad') plt.show()
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()