.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_example/plot_shi_xie_xuan_nocedal_forward_benchmark.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_example_plot_shi_xie_xuan_nocedal_forward_benchmark.py: Benchmark Shi, Xie, Xuan & Nocedal's forward method =================================================== The goal of this example is to benchmark the :class:`~numericalderivative.ShiXieXuanNocedalForward` class on a collection of test problems. These problems are created by the :meth:`~numericalderivative.build_benchmark()` static method, which returns a list of problems. .. GENERATED FROM PYTHON SOURCE LINES 16-21 .. code-block:: Python import numpy as np import pylab as pl import tabulate import numericalderivative as nd .. GENERATED FROM PYTHON SOURCE LINES 22-24 Compute the first derivative ---------------------------- .. GENERATED FROM PYTHON SOURCE LINES 24-71 .. code-block:: Python class ShiXieXuanNocedalForwardMethod: def __init__(self, relative_precision, initial_step): """ Create a ShiXieXuanNocedalForward method to compute the approximate first derivative Parameters ---------- relative_precision : float, > 0, optional The relative precision of evaluation of f. initial_step : float, > 0 The initial step in the algorithm. """ self.relative_precision = relative_precision self.initial_step = initial_step def compute_first_derivative(self, function, x): """ Compute the first derivative using ShiXieXuanNocedal Parameters ---------- function : function The function x : float The test point Returns ------- f_prime_approx : float The approximate value of the first derivative of the function at point x number_of_function_evaluations : int The number of function evaluations. """ absolute_precision = abs(function(x)) * self.relative_precision algorithm = nd.ShiXieXuanNocedalForward( function, x, absolute_precision, ) step, _ = algorithm.find_step(self.initial_step) f_prime_approx = algorithm.compute_first_derivative(step) number_of_function_evaluations = algorithm.get_number_of_function_evaluations() return f_prime_approx, number_of_function_evaluations .. GENERATED FROM PYTHON SOURCE LINES 72-74 The next example computes the approximate derivative on the :class:`~numericalderivative.ExponentialProblem`. .. GENERATED FROM PYTHON SOURCE LINES 76-109 .. code-block:: Python initial_step = 1.0e0 problem = nd.ExponentialProblem() print(problem) function = problem.get_function() x = problem.get_x() algorithm = nd.ShiXieXuanNocedalForward( function, x, verbose=True, ) second_derivative = problem.get_second_derivative() second_derivative_value = second_derivative(x) optimal_step, absolute_error = nd.FirstDerivativeForward.compute_step( second_derivative_value ) print("Exact h* = %.3e" % (optimal_step)) function = problem.get_function() first_derivative = problem.get_first_derivative() x = 1.0 relative_precision = 1.0e-15 absolute_precision = abs(function(x)) * relative_precision method = ShiXieXuanNocedalForwardMethod(absolute_precision, initial_step) ( f_prime_approx, number_of_function_evaluations, ) = method.compute_first_derivative(function, x) first_derivative_value = first_derivative(x) absolute_error = abs(f_prime_approx - first_derivative_value) print( "x = %.3f, error = %.3e, Func. eval. = %d" % (x, absolute_error, number_of_function_evaluations) ) .. rst-class:: sphx-glr-script-out .. code-block:: none DerivativeBenchmarkProblem name = exp x = 1.0 f(x) = 2.718281828459045 f'(x) = 2.718281828459045 f''(x) = 2.718281828459045 f^(3)(x) = 2.718281828459045 f^(4)(x) = 2.718281828459045 f^(5)(x) = 2.718281828459045 Exact h* = 1.213e-08 x = 1.000, error = 1.633e-07, Func. eval. = 19 .. GENERATED FROM PYTHON SOURCE LINES 110-112 Perform the benchmark --------------------- .. GENERATED FROM PYTHON SOURCE LINES 115-138 .. code-block:: Python print("+ Benchmark on several points") number_of_test_points = 21 # This number of test points is odd problem = nd.PolynomialProblem() print(problem) interval = problem.get_interval() function = problem.get_function() first_derivative = problem.get_first_derivative() initial_step = 1.0e2 test_points = np.linspace(interval[0], interval[1], number_of_test_points) relative_precision = 1.0e-15 absolute_precision = abs(function(x)) * relative_precision method = ShiXieXuanNocedalForwardMethod(absolute_precision, initial_step) average_relative_error, average_feval, data = nd.benchmark_method( function, first_derivative, test_points, method.compute_first_derivative, verbose=True, ) print("Average relative error =", average_relative_error) print("Average number of function evaluations =", average_feval) tabulate.tabulate(data, headers=["x", "Rel. err.", "F. Eval."], tablefmt="html") .. rst-class:: sphx-glr-script-out .. code-block:: none + Benchmark on several points DerivativeBenchmarkProblem name = polynomial x = 1.0 f(x) = 1.0 f'(x) = 2.0 f''(x) = 2.0 f^(3)(x) = 0.0 f^(4)(x) = 0.0 f^(5)(x) = 0.0 x = -12.000, abs. error = 7.629e-07, rel. error = 3.179e-08, Func. eval. = 21 x = -10.800, abs. error = 3.815e-07, rel. error = 1.766e-08, Func. eval. = 19 x = -9.600, abs. error = 3.815e-07, rel. error = 1.987e-08, Func. eval. = 19 x = -8.400, abs. error = 3.815e-07, rel. error = 2.271e-08, Func. eval. = 19 x = -7.200, abs. error = 3.624e-07, rel. error = 2.517e-08, Func. eval. = 19 x = -6.000, abs. error = 3.815e-07, rel. error = 3.179e-08, Func. eval. = 19 x = -4.800, abs. error = 1.907e-07, rel. error = 1.987e-08, Func. eval. = 22 x = -3.600, abs. error = 1.907e-07, rel. error = 2.649e-08, Func. eval. = 22 x = -2.400, abs. error = 9.537e-08, rel. error = 1.987e-08, Func. eval. = 20 x = -1.200, abs. error = 4.768e-08, rel. error = 1.987e-08, Func. eval. = 23 x = 0.000, abs. error = nan, rel. error = nan, Func. eval. = -1 x = 1.200, abs. error = 4.292e-08, rel. error = 1.788e-08, Func. eval. = 23 x = 2.400, abs. error = 8.583e-08, rel. error = 1.788e-08, Func. eval. = 20 x = 3.600, abs. error = 1.907e-07, rel. error = 2.649e-08, Func. eval. = 22 x = 4.800, abs. error = 1.907e-07, rel. error = 1.987e-08, Func. eval. = 22 x = 6.000, abs. error = 3.815e-07, rel. error = 3.179e-08, Func. eval. = 19 x = 7.200, abs. error = 3.815e-07, rel. error = 2.649e-08, Func. eval. = 19 x = 8.400, abs. error = 3.815e-07, rel. error = 2.271e-08, Func. eval. = 19 x = 9.600, abs. error = 3.815e-07, rel. error = 1.987e-08, Func. eval. = 19 x = 10.800, abs. error = 3.815e-07, rel. error = 1.766e-08, Func. eval. = 19 x = 12.000, abs. error = 7.629e-07, rel. error = 3.179e-08, Func. eval. = 21 Average relative error = nan Average number of function evaluations = 19.285714285714285 .. raw:: html
x Rel. err. F. Eval.
-12 3.17891e-08 21
-10.8 1.76606e-08 19
-9.6 1.98682e-08 19
-8.4 2.27065e-08 19
-7.2 2.51664e-08 19
-6 3.17891e-08 19
-4.8 1.98682e-08 22
-3.6 2.6491e-08 22
-2.4 1.98682e-08 20
-1.2 1.98682e-08 23
0 nan -1
1.2 1.78814e-08 23
2.4 1.78814e-08 20
3.6 2.6491e-08 22
4.8 1.98682e-08 22
6 3.17891e-08 19
7.2 2.6491e-08 19
8.4 2.27065e-08 19
9.6 1.98682e-08 19
10.8 1.76606e-08 19
12 3.17891e-08 21


.. GENERATED FROM PYTHON SOURCE LINES 139-152 Notice that the method does not perform correctly for the point :math:`x = 0` for the polynomial problem. This test point appears only if the number of test points is odd, because the test interval is symmetric with respect to :math:`x = 0`. For this problem, the method does not perform correctly because the value of the function is zero at :math:`x = 0`. The method can perform correctly in this case, if it is provided a consistent value of the absolute error of the function value. Here, we compute the absolute error depending on the relative error and the absolute value of the value of the function. If the value of the function is zero, then the computed absolute error is zero, which produces a failure of the method. .. GENERATED FROM PYTHON SOURCE LINES 154-155 Map from the problem name to the initial step. .. GENERATED FROM PYTHON SOURCE LINES 157-176 .. code-block:: Python initial_step_map = { "polynomial": 1.0, "inverse": 1.0e0, "exp": 1.0e-1, "log": 1.0e-3, # x > 0 "sqrt": 1.0e-3, # x > 0 "atan": 1.0e0, "sin": 1.0e0, "scaled exp": 1.0e5, "GMSW": 1.0e0, "SXXN1": 1.0e0, "SXXN2": 1.0e0, "SXXN3": 1.0e0, "SXXN4": 1.0e0, "Oliver1": 1.0e0, "Oliver2": 1.0e0, "Oliver3": 1.0e-3, } .. GENERATED FROM PYTHON SOURCE LINES 177-179 The next script evaluates a collection of benchmark problems using the :class:`~numericalderivative.ShiXieXuanNocedalForward` class. .. GENERATED FROM PYTHON SOURCE LINES 181-230 .. code-block:: Python number_of_test_points = 100 # This value can significantly change the results data = [] function_list = nd.build_benchmark() number_of_functions = len(function_list) average_absolute_error_list = [] average_feval_list = [] relative_precision = 1.0e-15 delta_x = 1.0e-9 for i in range(number_of_functions): problem = function_list[i] name = problem.get_name() initial_step = initial_step_map[name] function = problem.get_function() first_derivative = problem.get_first_derivative() interval = problem.get_interval() lower_x_bound, upper_x_bound = problem.get_interval() print(f"Function #{i}, {name}") if name == "sin": # Change the lower and upper bound so that the points +/-pi # are excluded (see below for details). lower_x_bound += delta_x upper_x_bound -= delta_x test_points = np.linspace(lower_x_bound, upper_x_bound, number_of_test_points) method = ShiXieXuanNocedalForwardMethod(relative_precision, initial_step) average_relative_error, average_feval, _ = nd.benchmark_method( function, first_derivative, test_points, method.compute_first_derivative ) average_absolute_error_list.append(average_relative_error) average_feval_list.append(average_feval) data.append( ( name, average_relative_error, average_feval, ) ) data.append( [ "Average", np.nanmean(average_absolute_error_list), np.nanmean(average_feval_list), ] ) tabulate.tabulate( data, headers=["Name", "Average rel. error", "Average func. eval"], tablefmt="html", ) .. rst-class:: sphx-glr-script-out .. code-block:: none Function #0, polynomial Function #1, inverse Function #2, exp Function #3, log Function #4, sqrt Function #5, atan Function #6, sin Function #7, scaled exp Function #8, GMSW Function #9, SXXN1 Function #10, SXXN2 Function #11, SXXN3 Function #12, SXXN4 Function #13, Oliver1 Function #14, Oliver2 Function #15, Oliver3 .. raw:: html
Name Average rel. error Average func. eval
polynomial 2.26555e-08 17.6
inverse 4.6337e-08 17.62
exp 2.72409e-08 18.68
log 4.03016e-08 11.89
sqrt 3.193e-08 11.49
atan 1.24809e-07 16.68
sin 1.02845e-07 17.02
scaled exp 2.38187e-08 18
GMSW 2.98893e-08 19.92
SXXN1 8.16797e-07 18.12
SXXN2 2.32017e-08 23
SXXN3 2.98696e-08 17.84
SXXN4 2.61695e-08 17.54
Oliver1 2.97327e-08 18
Oliver2 7.13647e-08 20.67
Oliver3 3.26823e-08 12.39
Average 9.24778e-08 17.2788


.. GENERATED FROM PYTHON SOURCE LINES 231-240 Notice that the method cannot perform correctly for the sin function at the point :math:`x = \pm \pi`. Indeed, this function is such that :math:`f''(x) = 0` if :math:`x = \pm \pi`. In this case, the test ratio is zero and the method cannot work. Therefore, we make so that the points :math:`\pm \pi` are excluded from the benchmark. The same problem appears at the point :math:`x = 0`. This point is not included in the test set if the number of points is even (e.g. with `number_of_test_points = 100`), but it might appear if the number of test points is odd. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.060 seconds) .. _sphx_glr_download_auto_example_plot_shi_xie_xuan_nocedal_forward_benchmark.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_shi_xie_xuan_nocedal_forward_benchmark.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_shi_xie_xuan_nocedal_forward_benchmark.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_shi_xie_xuan_nocedal_forward_benchmark.zip `