diff --git a/.circleci/run_linux.sh b/.circleci/run_linux.sh index 5bdaaef..9effe07 100755 --- a/.circleci/run_linux.sh +++ b/.circleci/run_linux.sh @@ -12,6 +12,7 @@ bash run-all.sh cd .. # Run the examples -cd examples +cd doc/examples bash run_examples.sh -cd .. +cd ../.. + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..05f27f8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,33 @@ +name: Build +on: [push, pull_request] +jobs: + conda-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: conda-incubator/setup-miniconda@v2 + with: + miniforge-version: latest + - name: Build + shell: bash -l {0} + run: | + conda install -y openturns pytest sphinx sphinx-gallery numpydoc pandoc + conda install -c conda-forge sphinx_rtd_theme setuptools matplotlib + python setup.py install + pytest + sudo apt install -y texlive-latex-recommended texlive-fonts-recommended texlive-latex-extra + make html -C doc + - name: Upload + if: ${{ github.ref == 'refs/heads/main' }} + run: | + git clone --depth 1 https://${{ secrets.GH_TOKEN }}@github.com/mbaudin47/mbaudin47.github.io.git /tmp/io + mkdir -p /tmp/io/numericalderivative/main + cp -r doc/build/html/* /tmp/io/numericalderivative/main + cd /tmp/io + touch .nojekyll + git config user.email "support@gh.com" + git config user.name "GitHub Actions" + git add -A . + if test `git diff HEAD | wc -c` -eq 0; then exit 0; fi + git commit -a -m "GitHub Actions build ${GITHUB_REPOSITORY} ${GITHUB_RUN_ID}" + git push --quiet origin main > /dev/null 2>&1 diff --git a/README.md b/README.md index 1d8aaff..7bdb054 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ h_optimal, iterations = algorithm.compute_step(h0) f_prime_approx = algorithm.compute_first_derivative(h_optimal) ``` +## Documentation & references + +- [Package documentation](https://mbaudin47.github.io/numericalderivative/main/index.html) + ## Authors * Michaël Baudin, 2024 @@ -76,5 +80,3 @@ https://github.com/mbaudin47/menum_code/blob/cec64dea8d205da796d1f578b4294811525 - Implement the method of: Shi, H. J. M., Xie, Y., Xuan, M. Q., & Nocedal, J. (2022). Adaptive finite-difference interval estimation for noisy derivative-free optimization. _SIAM Journal on Scientific Computing_, _44_(4), A2302-A2321. - - diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..00464d9 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,4 @@ +auto_example/* +build/* +sg_execution_times.rst +user_manual/_generated/* diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..10cb2dc --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,222 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build +PDFBUILDDIR = /tmp +PDF = $(BUILDDIR) + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/otfmi.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/otfmi.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/otfmi" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/otfmi" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(PDFBUILDDIR)/latex + # ^^^ + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(PDFBUILDDIR)/latex all-pdf + # ^^^ + cp $(PDFBUILDDIR)/latex/*.pdf $(PDF) + #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + @echo "pdflatex finished; see PDF files in $(PDF)." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/doc/_static/Icon.ico b/doc/_static/Icon.ico new file mode 100644 index 0000000..5285ad7 --- /dev/null +++ b/doc/_static/Icon.ico @@ -0,0 +1,1417 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + otfmi/Icon.ico at master · openturns/otfmi · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+ + + + + Permalink + + +
+ +
+
+ + + master + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + + + +
+
+
+ + + + + + + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + +
+ +
+ + +
+ + 3.56 KB +
+ +
+ + + + +
+ + + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+ View raw +
+
+ +
+ + + + +
+ + +
+ + +
+
+ + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css new file mode 100644 index 0000000..2b05290 --- /dev/null +++ b/doc/_static/css/custom.css @@ -0,0 +1,32 @@ +img.padimg { + padding-bottom: 5px; + cursor: pointer; +} + +li.hide { + display: none !important; +} + +li.show { + display: list-item !important; +} + +div.sphx-glr-clear { + clear: left; +} + +/* hide the top link */ +div.sphx-glr-download-link-note { + height: 0px; + visibility: hidden; +} + +/* Remove big whitespace to solve #1642 */ +pre, div[class*="highlight-"] { + clear: left; +} + +div.sphx-glr-download-link-note { + height: 0px; + visibility: hidden; +} diff --git a/doc/_static/error_vs_h.png b/doc/_static/error_vs_h.png new file mode 100644 index 0000000..a76ca64 Binary files /dev/null and b/doc/_static/error_vs_h.png differ diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000..f27017a --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,129 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +import sys +import os +import subprocess +from distutils.version import LooseVersion +import sphinx +import sphinx_gallery + +sys.path.insert(0, os.path.abspath('../../..')) +# -- Project information ----------------------------------------------------- + +project = 'numericalderivative' +copyright = 'M. Baudin' +author = 'M. Baudin' + +# The full version, including alpha/beta/rc tags +release = '0.1' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.todo', + 'sphinx.ext.intersphinx', + 'sphinx.ext.autosummary', + 'numpydoc', + 'sphinx_gallery.gen_gallery', +] + + +sphinx_gallery_conf = { + 'examples_dirs': ['examples'], # # path to + # example scripts + 'gallery_dirs': ['auto_example'], + #path to where to save gallery gen. output + 'run_stale_examples':True, + 'show_signature': False + } + +if LooseVersion(sphinx.__version__) >= '1.8': + autodoc_default_options = {'members': None, 'inherited-members': None} +else: + autodoc_default_flags = ['members', 'inherited-members'] + +autosummary_generate = True + +numpydoc_show_class_members = True +numpydoc_class_members_toctree = False + +# The suffix(es) of source filenames. +source_suffix = ['.rst'] + +# The master toctree document. +master_doc = 'index' + + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'python' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ---------------------------------------------- + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = '_static/Icon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +html_show_sourcelink = True + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = '_static/Icon.ico' + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + 'papersize': 'a4paper', + # The font size ('10pt', '11pt' or '12pt'). + 'pointsize': '10pt', +} + + +# The suffix(es) of source filenames. +source_suffix = ['.rst'] + +man_pages = [ + ('index', 'numericalderivative', u'numericalderivative Documentation', + [u'Michaël Baudin'], 1) +] + +texinfo_documents = [ + ('index', 'numericalderivative', u'numericalderivative Documentation', + u'Michaël Baudin', 'numericalderivative', 'Numerical Differentiation', + 'Miscellaneous'), +] diff --git a/doc/examples/README.rst b/doc/examples/README.rst new file mode 100644 index 0000000..e69de29 diff --git a/doc/examples/examples.rst b/doc/examples/examples.rst new file mode 100644 index 0000000..9e9f37e --- /dev/null +++ b/doc/examples/examples.rst @@ -0,0 +1,16 @@ +Examples +======== + +This section illustrates how to use the numericalderivative algorithms. + +.. toctree:: + + ../auto_example/plot_numericalderivative + ../auto_example/plot_dumontet_vignes + ../auto_example/plot_gill_murray_saunders_wright + ../auto_example/plot_stepleman_winarsky_benchmark + ../auto_example/plot_openturns + ../auto_example/plot_stepleman_winarsky_plots + ../auto_example/plot_dumontet_vignes_benchmark + ../auto_example/plot_gill_murray_saunders_wright_benchmark + ../auto_example/plot_stepleman_winarsky diff --git a/examples/dumontet_vignes.py b/doc/examples/plot_dumontet_vignes.py similarity index 98% rename from examples/dumontet_vignes.py rename to doc/examples/plot_dumontet_vignes.py index 51d6fed..f11bbdd 100644 --- a/examples/dumontet_vignes.py +++ b/doc/examples/plot_dumontet_vignes.py @@ -2,11 +2,12 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ +Experiments with Dumontet & Vignes method +========================================= + References ---------- -- Dumontet, J., & Vignes, J. (1977). - Détermination du pas optimal dans le calcul des dérivées sur ordinateur. - RAIRO. Analyse numérique, 11 (1), 13-25. +- Dumontet, J., & Vignes, J. (1977). Détermination du pas optimal dans le calcul des dérivées sur ordinateur. RAIRO. Analyse numérique, 11 (1), 13-25. """ # %% diff --git a/examples/dumontet_vignes_benchmark.py b/doc/examples/plot_dumontet_vignes_benchmark.py similarity index 96% rename from examples/dumontet_vignes_benchmark.py rename to doc/examples/plot_dumontet_vignes_benchmark.py index cd63b77..8f20ef0 100644 --- a/examples/dumontet_vignes_benchmark.py +++ b/doc/examples/plot_dumontet_vignes_benchmark.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & ùWinarsky method. +Benchmark Dumontet & Vignes method +================================== + Find a step which is near to optimal for a centered finite difference formula. References ---------- -- Adaptive numerical differentiation - R. S. Stepleman and N. D. Winarsky - Journal: Math. Comp. 33 (1979), 1257-1264 +- Dumontet, J., & Vignes, J. (1977). Détermination du pas optimal dans le calcul des dérivées sur ordinateur. RAIRO. Analyse numérique, 11 (1), 13-25. """ # %% import numpy as np diff --git a/examples/gill_murray_saunders_wright.py b/doc/examples/plot_gill_murray_saunders_wright.py similarity index 96% rename from examples/gill_murray_saunders_wright.py rename to doc/examples/plot_gill_murray_saunders_wright.py index fb439f1..7114a6b 100644 --- a/examples/gill_murray_saunders_wright.py +++ b/doc/examples/plot_gill_murray_saunders_wright.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Gill, Murray, Saunders and Wright method. +Experiment with Gill, Murray, Saunders and Wright method +======================================================== + Find a step which is near to optimal for a centered finite difference formula. References ---------- -- Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). - Computing forward-difference intervals for numerical optimization. - SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. +- Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). Computing forward-difference intervals for numerical optimization. SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. """ # %% @@ -237,7 +237,7 @@ def plot_error_vs_h_with_GMSW_steps( [step] * 2, [minimum_error, maximum_error], "--", - label="$\hat{h}$", + label=r"$\hat{h}$", ) pl.title(f"(GMS & W). {name} at point x = {x}") pl.xlabel("h") diff --git a/examples/gill_murray_saunders_wright_benchmark.py b/doc/examples/plot_gill_murray_saunders_wright_benchmark.py similarity index 94% rename from examples/gill_murray_saunders_wright_benchmark.py rename to doc/examples/plot_gill_murray_saunders_wright_benchmark.py index 0f3befb..cc73cd3 100644 --- a/examples/gill_murray_saunders_wright_benchmark.py +++ b/doc/examples/plot_gill_murray_saunders_wright_benchmark.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & Winarsky method. +Experiment with Gill, Murray, Saunders and Wright method +======================================================== + Find a step which is near to optimal for a centered finite difference formula. References ---------- -- Adaptive numerical differentiation - R. S. Stepleman and N. D. Winarsky - Journal: Math. Comp. 33 (1979), 1257-1264 +- Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). Computing forward-difference intervals for numerical optimization. SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. """ # %% diff --git a/examples/demo_numericalderivative.py b/doc/examples/plot_numericalderivative.py similarity index 95% rename from examples/demo_numericalderivative.py rename to doc/examples/plot_numericalderivative.py index 518585a..59d67d5 100644 --- a/examples/demo_numericalderivative.py +++ b/doc/examples/plot_numericalderivative.py @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -A simple demonstration of the methods. +A simple demonstration of the methods +===================================== + Finds a step which is near to optimal for a centered finite difference formula. References ---------- -- Adaptive numerical differentiation - R. S. Stepleman and N. D. Winarsky - Journal: Math. Comp. 33 (1979), 1257-1264 +- Adaptive numerical differentiation. R. S. Stepleman and N. D. Winarsky. Journal: Math. Comp. 33 (1979), 1257-1264 """ # %% import numpy as np diff --git a/examples/demo_openturns.py b/doc/examples/plot_openturns.py similarity index 99% rename from examples/demo_openturns.py rename to doc/examples/plot_openturns.py index eb3785a..63e58cd 100644 --- a/examples/demo_openturns.py +++ b/doc/examples/plot_openturns.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & Winarsky method. -Applies it to an OpenTURNS function. +Applies Stepleman & Winarsky method to an OpenTURNS function +============================================================ """ # %% diff --git a/examples/stepleman_winarsky.py b/doc/examples/plot_stepleman_winarsky.py similarity index 98% rename from examples/stepleman_winarsky.py rename to doc/examples/plot_stepleman_winarsky.py index cec8f1c..f476011 100644 --- a/examples/stepleman_winarsky.py +++ b/doc/examples/plot_stepleman_winarsky.py @@ -2,7 +2,9 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & Winarsky method. +Experiment with Stepleman & Winarsky method +=========================================== + Find a step which is near to optimal for a centered finite difference formula. diff --git a/examples/stepleman_winarsky_benchmark.py b/doc/examples/plot_stepleman_winarsky_benchmark.py similarity index 98% rename from examples/stepleman_winarsky_benchmark.py rename to doc/examples/plot_stepleman_winarsky_benchmark.py index 6e787cd..5dbd540 100644 --- a/examples/stepleman_winarsky_benchmark.py +++ b/doc/examples/plot_stepleman_winarsky_benchmark.py @@ -2,7 +2,9 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & Winarsky method. +Benchmark Stepleman & Winarsky's method +======================================= + Find a step which is near to optimal for a centered finite difference formula. diff --git a/examples/stepleman_winarsky_plots.py b/doc/examples/plot_stepleman_winarsky_plots.py similarity index 97% rename from examples/stepleman_winarsky_plots.py rename to doc/examples/plot_stepleman_winarsky_plots.py index 53d7237..96d1742 100644 --- a/examples/stepleman_winarsky_plots.py +++ b/doc/examples/plot_stepleman_winarsky_plots.py @@ -2,7 +2,9 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Experiment with Stepleman & Winarsky method. +Plot Stepleman & Winarsky's method +================================== + Find a step which is near to optimal for a centered finite difference formula. @@ -31,7 +33,7 @@ h = h_array[i] n_digits_array[i] = algorithm.number_of_lost_digits(h) -pl.figure(figsize=(3.0, 2.0)) +pl.figure(figsize=(4.0, 3.0)) pl.plot(h_array, n_digits_array) pl.title(r"Number of digits lost by F.D.. $f(x) = \exp(x)$") pl.xlabel("h") @@ -49,13 +51,14 @@ n_digits_array[i] = algorithm.number_of_lost_digits(h) # %% -pl.figure(figsize=(3.0, 2.0)) +pl.figure(figsize=(4.0, 3.0)) pl.plot(h_array, n_digits_array) pl.title(r"Number of digits lost by F.D.. $f(x) = \sin(x)$") pl.xlabel("h") pl.ylabel("$N(h)$") pl.xscale("log") +# %% # For each function, at point x = 1, plot the error vs the step computed # by the method @@ -95,7 +98,7 @@ def plot_error_vs_h_with_SW_steps( minimum_error = np.nanmin(error_array) maximum_error = np.nanmax(error_array) - pl.figure(figsize=(3.0, 2.0)) + pl.figure(figsize=(5.0, 3.0)) pl.plot(h_array, error_array) pl.plot( [bisection_h0_step] * 2, @@ -116,6 +119,7 @@ def plot_error_vs_h_with_SW_steps( pl.xscale("log") pl.yscale("log") pl.legend(bbox_to_anchor=(1.0, 1.0)) + pl.subplots_adjust(right=0.8) return diff --git a/doc/examples/run_examples.sh b/doc/examples/run_examples.sh new file mode 100644 index 0000000..9445fa5 --- /dev/null +++ b/doc/examples/run_examples.sh @@ -0,0 +1,9 @@ +# Copyright 2024 - Michaël Baudin. +set -xe +python3 plot_numericalderivative.py +python3 plot_openturns.py +python3 plot_dumontet_vignes_benchmark.py +python3 plot_dumontet_vignes.py +python3 plot_gill_murray_saunders_wright.py +python3 plot_stepleman_winarsky_benchmark.py +python3 plot_stepleman_winarsky.py diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..6a685dd --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,53 @@ +.. numericalderivative documentation master file, created by + sphinx-quickstart on Mon Feb 14 09:17:40 2022. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +numericalderivative documentation +================================= + +.. image:: _static/error_vs_h.png + :align: left + :scale: 50% + +numericalderivative is a module for numerical differentiation. + +The goal of this project is to compute the first derivative of a function using finite difference formulas. +The difficulty with these formulas is that it must use a finite difference +step which must be neither too large (otherwise truncation error dominates +the error) nor too small (otherwise condition error dominates). +To solve this issue, the module provides algorithms to compute an approximate +optimal finite difference step. + +Furthermore, this package provides benchmark problems for numerical +differentiation. + +Documentation about numericalderivative can be found `here `_ + +User documentation +------------------ + +.. toctree:: + :maxdepth: 3 + + user_manual/user_manual + +Examples +-------- + +.. toctree:: + :maxdepth: 2 + + examples/examples + +References +---------- +- Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). Computing forward-difference intervals for numerical optimization. SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. +- Adaptive numerical differentiation. R. S. Stepleman and N. D. Winarsky. Journal: Math. Comp. 33 (1979), 1257-1264 +- Dumontet, J., & Vignes, J. (1977). Détermination du pas optimal dans le calcul des dérivées sur ordinateur. RAIRO. Analyse numérique, 11 (1), 13-25. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..9534b01 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/user_manual/user_manual.rst b/doc/user_manual/user_manual.rst new file mode 100644 index 0000000..164c457 --- /dev/null +++ b/doc/user_manual/user_manual.rst @@ -0,0 +1,40 @@ +User manual +=========== + +.. currentmodule:: numericalderivative + +Algorithms +---------- + +.. autosummary:: + :toctree: _generated/ + + NumericalDerivative + DumontetVignes + GillMurraySaundersWright + SteplemanWinarsky + +Finite Differences +------------------ + +.. autosummary:: + :toctree: _generated/ + + FiniteDifferenceFormula + FiniteDifferenceOptimalStep + +Benchmark problems +------------------ + +.. autosummary:: + :toctree: _generated/ + + DerivativeBenchmark + ExponentialDerivativeBenchmark + LogarithmicDerivativeBenchmark + SquareRootDerivativeBenchmark + AtanDerivativeBenchmark + SinDerivativeBenchmark + ScaledExponentialDerivativeBenchmark + GillMurraySaundersWrightExponentialDerivativeBenchmark + BuildBenchmarkList diff --git a/examples/run_examples.sh b/examples/run_examples.sh deleted file mode 100644 index cf8d593..0000000 --- a/examples/run_examples.sh +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2024 - Michaël Baudin. -set -xe -python3 demo_numericalderivative.py -python3 demo_openturns.py -python3 dumontet_vignes_benchmark.py -python3 dumontet_vignes.py -python3 gill_murray_saunders_wright.py -python3 stepleman_winarsky_benchmark.py -python3 stepleman_winarsky.py diff --git a/numericalderivative/DerivativeBenchmark.py b/numericalderivative/DerivativeBenchmark.py index 3513c72..b4be9d4 100644 --- a/numericalderivative/DerivativeBenchmark.py +++ b/numericalderivative/DerivativeBenchmark.py @@ -8,6 +8,24 @@ class DerivativeBenchmark: + """ + Create a benchmark for numerical derivatives of a function + + Parameters + ---------- + function : function + The function + first_derivative : function + The first derivative of the function + second_derivative : function + The second derivative of the function + third_derivative : function + The third derivative of the function + fourth_derivative : function + The fourth derivative of the function + x : float + The point where the derivative should be computed + """ def __init__( self, name, @@ -18,24 +36,6 @@ def __init__( fourth_derivative, x, ): - """ - Create a benchmark for numerical derivatives of a function - - Parameters - ---------- - function : function - The function - first_derivative : function - The first derivative of the function - second_derivative : function - The second derivative of the function - third_derivative : function - The third derivative of the function - fourth_derivative : function - The fourth derivative of the function - x : float - The point where the derivative should be computed - """ self.name = name self.function = function self.first_derivative = first_derivative @@ -46,16 +46,16 @@ def __init__( class ExponentialDerivativeBenchmark(DerivativeBenchmark): - def __init__(self): - """ - Create an exponential derivative benchmark + """ + Create an exponential derivative benchmark - The function is: + The function is: - f(x) = exp(x) + f(x) = exp(x) - for any x. - """ + for any x. + """ + def __init__(self): def my_exp(x): return np.exp(x) @@ -85,16 +85,16 @@ def my_exp_4th_derivative(x): class LogarithmicDerivativeBenchmark(DerivativeBenchmark): - def __init__(self): - """ - Create a logarithmic derivative benchmark + """ + Create a logarithmic derivative benchmark - The function is: + The function is: - f(x) = log(x) + f(x) = log(x) - for any x > 0. - """ + for any x > 0. + """ + def __init__(self): def my_log(x): return np.log(x) @@ -125,16 +125,16 @@ def my_log_4th_derivative(x): class SquareRootDerivativeBenchmark(DerivativeBenchmark): - def __init__(self): - """ - Create a square root derivative benchmark + """ + Create a square root derivative benchmark - The function is: + The function is: - f(x) = log(x) + f(x) = log(x) - for any x >= 0. - """ + for any x >= 0. + """ + def __init__(self): def my_squareroot(x): return np.sqrt(x) @@ -164,16 +164,16 @@ def my_square_root_4th_derivative(x): class AtanDerivativeBenchmark(DerivativeBenchmark): - def __init__(self): - """ - Create an arctangent derivative benchmark + """ + Create an arctangent derivative benchmark - The function is: + The function is: - f(x) = atan(x) + f(x) = atan(x) - for any x. - """ + for any x. + """ + def __init__(self): def my_atan(x): return np.arctan(x) @@ -204,16 +204,16 @@ def my_atan_4th_derivative(x): class SinDerivativeBenchmark(DerivativeBenchmark): - def __init__(self): - """ - Create a sine derivative benchmark + """ + Create a sine derivative benchmark - The function is: + The function is: - f(x) = sin(x) + f(x) = sin(x) - for any x. - """ + for any x. + """ + def __init__(self): def my_sin(x): return np.sin(x) @@ -243,21 +243,21 @@ def my_sin_4th_derivative(x): class ScaledExponentialDerivativeBenchmark(DerivativeBenchmark): - def __init__(self, alpha=1.0e6): - """ - Create a scaled exponential derivative benchmark + """ + Create a scaled exponential derivative benchmark - The function is: + The function is: - f(x) = exp(-x / alpha) + f(x) = exp(-x / alpha) - for any x. + for any x. - Parameters - ---------- - alpha : float, > 0 - The parameter - """ + Parameters + ---------- + alpha : float, > 0 + The parameter + """ + def __init__(self, alpha=1.0e6): if alpha <= 0.0: raise ValueError(f"alpha = {alpha} should be > 0") self.alpha = alpha @@ -290,25 +290,25 @@ def scaled_exp_4th_derivative(x): class GillMurraySaundersWrightExponentialDerivativeBenchmark(DerivativeBenchmark): - def __init__(self, alpha=1.0e6): - """ - Create an exponential derivative benchmark + """ + Create an exponential derivative benchmark - See eq. 4 page 312 in (Gill, Murray, Saunders & Wright, 1983) + See eq. 4 page 312 in (Gill, Murray, Saunders & Wright, 1983) - f(x) = (exp(x) - 1)^2 + (1 / sqrt(1 + x^2) - 1)^2 + f(x) = (exp(x) - 1)^2 + (1 / sqrt(1 + x^2) - 1)^2 - Parameters - ---------- - alpha : float, > 0 - The parameter + Parameters + ---------- + alpha : float, > 0 + The parameter - References - ---------- - - Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). - Computing forward-difference intervals for numerical optimization. - SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. - """ + References + ---------- + - Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). + Computing forward-difference intervals for numerical optimization. + SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. + """ + def __init__(self, alpha=1.0e6): if alpha <= 0.0: raise ValueError(f"alpha = {alpha} should be > 0") self.alpha = alpha diff --git a/numericalderivative/DumontetVignes.py b/numericalderivative/DumontetVignes.py index 82ace04..b4662a0 100644 --- a/numericalderivative/DumontetVignes.py +++ b/numericalderivative/DumontetVignes.py @@ -1,20 +1,51 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -References ----------- -- Dumontet, J., & Vignes, J. (1977). - Détermination du pas optimal dans le calcul des dérivées sur ordinateur. - RAIRO. Analyse numérique, 11 (1), 13-25. +Class to define Dumontet and Vignes algorithm """ import numpy as np -from .NumericalDerivative import NumericalDerivative -from .FiniteDifferenceFormula import FiniteDifferenceFormula -from .FiniteDifferenceOptimalStep import FiniteDifferenceOptimalStep - - -class DumontetVignes(NumericalDerivative): +import numericalderivative as nd + + +class DumontetVignes(nd.NumericalDerivative): + """ + Use Dumontet & Vignes method to compute the optimum step size. + + Uses centered finite difference for f'. + The method is based on computing the third derivative. + Then the optimal step for the central formula for the first derivative is computed + from the third derivative. + + Parameters + ---------- + function : function + The function to differentiate. + x : float + The point where the derivative is to be evaluated. + relative_precision : float, > 0, optional + The relative precision of evaluation of f. The default is 1.0e-16. + number_of_digits : int + The maximum number of digits of the floating point system. + ell_1 : float + The minimum bound of the L ratio. + ell_2 : float + The maximum bound of the L ratio. + args : list + A list of optional arguments that the function takes as inputs. + By default, there is no extra argument and calling sequence of + the function must be y = function(x). + If there are extra arguments, then the calling sequence of + the function must be y = function(x, arg1, arg2, ...) where + arg1, arg2, ..., are the items in the args list. + verbose : bool, optional + Set to True to print intermediate messages. The default is False. + + References + ---------- + - Dumontet, J., & Vignes, J. (1977). Détermination du pas optimal dans le calcul des dérivées sur ordinateur. RAIRO. Analyse numérique, 11 (1), 13-25. + + """ def __init__( self, function, @@ -26,43 +57,6 @@ def __init__( args=None, verbose=False, ): - """ - Use Dumontet & Vignes method to compute the optimum step size. - - Uses centered finite difference for f'. - The method is based on computing the third derivative. - Then the optimal step for the central formula for the first derivative is computed - from the third derivative. - - Parameters - ---------- - function : function - The function to differentiate. - x : float - The point where the derivative is to be evaluated. - relative_precision : float, > 0, optional - The relative precision of evaluation of f. The default is 1.0e-16. - number_of_digits : int - The maximum number of digits of the floating point system. - ell_1 : float - The minimum bound of the L ratio. - ell_2 : float - The maximum bound of the L ratio. - args : list - A list of optional arguments that the function takes as inputs. - By default, there is no extra argument and calling sequence of - the function must be y = function(x). - If there are extra arguments, then the calling sequence of - the function must be y = function(x, arg1, arg2, ...) where - arg1, arg2, ..., are the items in the args list. - verbose : bool, optional - Set to True to print intermediate messages. The default is False. - - Returns - ------- - None. - - """ self.relative_precision = relative_precision self.number_of_digits = number_of_digits # Eq. 34, fixed @@ -71,7 +65,7 @@ def __init__( self.ell_3 = 1.0 / ell_2 self.ell_4 = 1.0 / ell_1 self.verbose = verbose - self.finite_difference = FiniteDifferenceFormula(function, x, args) + self.finite_difference = nd.FiniteDifferenceFormula(function, x, args) super().__init__(function, x, args) def compute_ell(self, k): @@ -87,6 +81,10 @@ def compute_ell(self, k): ------- ell : float The ratio f'''sup(x0) / f'''inf(x0). + f3inf : float + The lower bound of the third derivative + f3sup + The upper bound of the third derivative """ t = np.zeros(4) @@ -327,7 +325,7 @@ def compute_step( # Compute the approximate optimal step for the first derivative function_value = self.function_eval(self.x) absolute_precision = self.relative_precision * abs(function_value) - fd_optimal_step = FiniteDifferenceOptimalStep(absolute_precision) + fd_optimal_step = nd.FiniteDifferenceOptimalStep(absolute_precision) step, _ = fd_optimal_step.compute_step_first_derivative_central( third_derivative_value ) @@ -359,7 +357,7 @@ def get_number_of_function_evaluations(self): Returns the number of function evaluations. Returns - ---------- + ------- number_of_function_evaluations : int The number of function evaluations. """ diff --git a/numericalderivative/FiniteDifferenceFormula.py b/numericalderivative/FiniteDifferenceFormula.py index 89f75be..0e851d1 100644 --- a/numericalderivative/FiniteDifferenceFormula.py +++ b/numericalderivative/FiniteDifferenceFormula.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -Provides various finite difference formulas. +Various finite difference formulas. """ import numpy as np @@ -9,29 +9,29 @@ class FiniteDifferenceFormula(NumericalDerivative): + """ + Compute a derivative of the function using finite difference formula + + Parameters + ---------- + function : function + The function to differentiate. + x : float + The point where the derivative is to be evaluated. + args : list + A list of optional arguments that the function takes as inputs. + By default, there is no extra argument and calling sequence of + the function must be y = function(x). + If there are extra arguments, then the calling sequence of + the function must be y = function(x, arg1, arg2, ...) where + arg1, arg2, ..., are the items in the args list. + + Returns + ------- + None. + + """ def __init__(self, function, x, args=None) -> None: - """ - Compute a derivative of the function using finite difference formula - - Parameters - ---------- - function : function - The function to differentiate. - x : float - The point where the derivative is to be evaluated. - args : list - A list of optional arguments that the function takes as inputs. - By default, there is no extra argument and calling sequence of - the function must be y = function(x). - If there are extra arguments, then the calling sequence of - the function must be y = function(x, arg1, arg2, ...) where - arg1, arg2, ..., are the items in the args list. - - Returns - ------- - None. - - """ super().__init__(function, x, args) def function_eval(self, x): @@ -46,7 +46,7 @@ def function_eval(self, x): The input point. Returns - ---------- + ------- y : float The output point. """ @@ -62,7 +62,7 @@ def get_number_of_function_evaluations(self): Returns the number of function evaluations. Returns - ---------- + ------- number_of_function_evaluations : int The number of function evaluations. """ diff --git a/numericalderivative/FiniteDifferenceOptimalStep.py b/numericalderivative/FiniteDifferenceOptimalStep.py index 60a3baa..cd7b055 100644 --- a/numericalderivative/FiniteDifferenceOptimalStep.py +++ b/numericalderivative/FiniteDifferenceOptimalStep.py @@ -1,28 +1,30 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -References -Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). -Computing forward-difference intervals for numerical optimization. -SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. +Compute the optimum step for finite differences """ import numpy as np class FiniteDifferenceOptimalStep: + """ + Compute the optimum step for finite differences + + Parameters + ---------- + absolute_precision : float, optional + The absolute error of the function f at the point x. + This is equal to abs(relative_precision * f(x)) where + relative_precision is the relative accuracy and f(x) is the function + value of f at point x. + + References + ---------- + - Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). Computing forward-difference intervals for numerical optimization. SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. + + """ def __init__(self, absolute_precision=1.0e-16): - """ - Compute the optimum step for finite differences - - Parameters - ---------- - absolute_precision : float, optional - The absolute error of the function f at the point x. - This is equal to abs(relative_precision * f(x)) where - relative_precision is the relative accuracy and f(x) is the function - value of f at point x. - """ if absolute_precision <= 0.0: raise ValueError( f"The absolute precision = {absolute_precision} " "but it must be > 0" diff --git a/numericalderivative/GillMurraySaundersWright.py b/numericalderivative/GillMurraySaundersWright.py index f169a09..fc6e2ea 100644 --- a/numericalderivative/GillMurraySaundersWright.py +++ b/numericalderivative/GillMurraySaundersWright.py @@ -1,11 +1,7 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -References ----------- -- Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). - Computing forward-difference intervals for numerical optimization. - SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. +Class to define Gill, Murray, Saunders and Wright algorithm """ import numpy as np @@ -15,6 +11,56 @@ class GillMurraySaundersWright(NumericalDerivative): + """ + Compute an approximately optimal step for the forward finite difference first derivative. + + The method is based on three steps: + + - compute an approximate optimal step for the second derivative using central finite difference formula, + - compute the approximate second derivative using central finite difference formula, + - compute the approximate optimal step for the first derivative using the forward finite difference formula. + + Finally, this approximately optimal step can be use to compute the + first derivative using the forward finite difference formula. + + This algorithm is a simplified version of the algorithm published in + (Gill, Murray, Saunders & Wright, 1983) section 3.2 page 316. + While (Gill, Murray, Saunders & Wright, 1983) simultaneously considers + the finite difference step of the forward, backward formula for the + first derivative and the central formula for the second derivative, + this algorithm only searches for the optimal step for the central + formula for the second derivative. + + Parameters + ---------- + function : function + The function to differentiate. + x : float + The point where the derivative is approximated. + absolute_precision : float, optional + The absolute error of the function f at the point x. + c_threshold_min : float, optional, > 0 + The minimum value of the condition error. + c_threshold_max : float, optional, > c_threshold_min + The maximum value of the condition error. + args : list + A list of optional arguments that the function takes as inputs. + By default, there is no extra argument and calling sequence of + the function must be y = function(x). + If there are extra arguments, then the calling sequence of + the function must be y = function(x, arg1, arg2, ...) where + arg1, arg2, ..., are the items in the args list. + verbose : bool + Set to True to print intermediate messages + + Returns + ------- + None. + + References + ---------- + - Gill, P. E., Murray, W., Saunders, M. A., & Wright, M. H. (1983). Computing forward-difference intervals for numerical optimization. SIAM Journal on Scientific and Statistical Computing, 4(2), 310-321. + """ def __init__( self, function, @@ -25,55 +71,6 @@ def __init__( args=None, verbose=False, ): - """ - Compute an approximately optimal step for the forward finite difference first derivative. - - The method is based on three steps: - - compute an approximate optimal step for the second derivative using - central finite difference formula, - - compute the approximate second derivative using - central finite difference formula, - - compute the approximate optimal step for the first derivative using - the forward finite difference formula. - - Finally, this approximately optimal step can be use to compute the - first derivative using the forward finite difference formula. - - This algorithm is a simplified version of the algorithm published in - (Gill, Murray, Saunders & Wright, 1983) section 3.2 page 316. - While (Gill, Murray, Saunders & Wright, 1983) simultaneously considers - the finite difference step of the forward, backward formula for the - first derivative and the central formula for the second derivative, - this algorithm only searches for the optimal step for the central - formula for the second derivative. - - Parameters - ---------- - function : function - The function to differentiate. - x : float - The point where the derivative is approximated. - absolute_precision : float, optional - The absolute error of the function f at the point x. - c_threshold_min : float, optional, > 0 - The minimum value of the condition error. - c_threshold_max : float, optional, > c_threshold_min - The maximum value of the condition error. - args : list - A list of optional arguments that the function takes as inputs. - By default, there is no extra argument and calling sequence of - the function must be y = function(x). - If there are extra arguments, then the calling sequence of - the function must be y = function(x, arg1, arg2, ...) where - arg1, arg2, ..., are the items in the args list. - verbose : bool - Set to True to print intermediate messages - - Returns - ------- - None. - - """ if c_threshold_max <= c_threshold_min: raise ValueError( f"c_threshold_max = {c_threshold_max} must be greater than " @@ -295,7 +292,7 @@ def get_number_of_function_evaluations(self): Returns the number of function evaluations. Returns - ---------- + ------- number_of_function_evaluations : int The number of function evaluations. """ diff --git a/numericalderivative/NumericalDerivative.py b/numericalderivative/NumericalDerivative.py index c7bb3ac..bf3adc2 100644 --- a/numericalderivative/NumericalDerivative.py +++ b/numericalderivative/NumericalDerivative.py @@ -6,38 +6,42 @@ class NumericalDerivative: + """ + Compute an approximately optimal step for the forward finite difference first derivative. + + This is the root class and can only be used from its children. + + Parameters + ---------- + function : function + The function to differentiate. + x : float + The point where the derivative is approximated. + args : list + A list of optional arguments that the function takes as inputs. + By default, there is no extra argument and calling sequence of + the function must be y = function(x). + If there are extra arguments, then the calling sequence of + the function must be y = function(x, arg1, arg2, ...) where + arg1, arg2, ..., are the items in the args list. + verbose : bool, optional + Set to True to print intermediate messages. The default is False. + + Returns + ------- + None. + + See also + -------- + FiniteDifferenceFormula, SteplemanWinarsky, GillMurraySaundersWright, DumontetVignes + + """ def __init__( self, function, x, args=None, ): - """ - Compute an approximately optimal step for the forward finite difference first derivative. - - This is the root class and can only be used from its children. - - Parameters - ---------- - function : function - The function to differentiate. - x : float - The point where the derivative is approximated. - args : list - A list of optional arguments that the function takes as inputs. - By default, there is no extra argument and calling sequence of - the function must be y = function(x). - If there are extra arguments, then the calling sequence of - the function must be y = function(x, arg1, arg2, ...) where - arg1, arg2, ..., are the items in the args list. - verbose : bool, optional - Set to True to print intermediate messages. The default is False. - - Returns - ------- - None. - - """ self.function = function self.x = x self.args = args @@ -55,7 +59,7 @@ def function_eval(self, x): The input point. Returns - ---------- + ------- y : float The output point. """ @@ -71,7 +75,7 @@ def get_number_of_function_evaluations(self): Returns the number of function evaluations. Returns - ---------- + ------- number_of_function_evaluations : int The number of function evaluations. """ @@ -87,7 +91,7 @@ def compute_first_derivative(self, step): The finite difference step Returns - ---------- + ------- f_prime_approx : float, > 0 The approximate first derivative of the function """ @@ -100,7 +104,7 @@ def compute_step(self): Compute an approximate optimal step Returns - ---------- + ------- step : float, > 0 The finite difference step for the first derivative number_of_iterations : int diff --git a/numericalderivative/SteplemanWinarsky.py b/numericalderivative/SteplemanWinarsky.py index c133cdc..ad301e0 100644 --- a/numericalderivative/SteplemanWinarsky.py +++ b/numericalderivative/SteplemanWinarsky.py @@ -1,11 +1,7 @@ # -*- coding: utf-8 -*- # Copyright 2024 - Michaël Baudin. """ -References ----------- -Adaptive numerical differentiation -R. S. Stepleman and N. D. Winarsky -Journal: Math. Comp. 33 (1979), 1257-1264 +Class to define Stepleman and Winarsky algorithm """ import numpy as np @@ -14,42 +10,45 @@ class SteplemanWinarsky(NumericalDerivative): + """ + Use Stepleman & Winarsky method to compute the optimum step size for the first derivative. + + Uses centered finite difference to compute an approximate value of f'(x). + The approximate optimal step for f'(x) is computed using a monotony property. + + The central F.D. is: + + f'(x) ~ (f(x + h) - f(x - h)) / (2 * h) + + Parameters + ---------- + function : function + The function to differentiate. + x : float + The point where the derivative is to be evaluated. + relative_precision : float, > 0, optional + The relative precision of evaluation of f. The default is 1.0e-16. + args : list + A list of optional arguments that the function takes as inputs. + By default, there is no extra argument and calling sequence of + the function must be y = function(x). + If there are extra arguments, then the calling sequence of + the function must be y = function(x, arg1, arg2, ...) where + arg1, arg2, ..., are the items in the args list. + verbose : bool, optional + Set to True to print intermediate messages. The default is False. + + Returns + ------- + None. + + References + ---------- + - Adaptive numerical differentiation. R. S. Stepleman and N. D. Winarsky. Journal: Math. Comp. 33 (1979), 1257-1264 + """ def __init__( self, function, x, relative_precision=1.0e-16, args=None, verbose=False ): - """ - Use Stepleman & Winarsky method to compute the optimum step size for the first derivative. - - Uses centered finite difference to compute an approximate value of f'(x). - The approximate optimal step for f'(x) is computed using a monotony property. - - The central F.D. is: - - f'(x) ~ (f(x + h) - f(x - h)) / (2 * h) - - Parameters - ---------- - function : function - The function to differentiate. - x : float - The point where the derivative is to be evaluated. - relative_precision : float, > 0, optional - The relative precision of evaluation of f. The default is 1.0e-16. - args : list - A list of optional arguments that the function takes as inputs. - By default, there is no extra argument and calling sequence of - the function must be y = function(x). - If there are extra arguments, then the calling sequence of - the function must be y = function(x, arg1, arg2, ...) where - arg1, arg2, ..., are the items in the args list. - verbose : bool, optional - Set to True to print intermediate messages. The default is False. - - Returns - ------- - None. - - """ if relative_precision <= 0.0: raise ValueError( f"The absolute precision must be > 0. " @@ -334,7 +333,7 @@ def get_number_of_function_evaluations(self): Returns the number of function evaluations. Returns - ---------- + ------- number_of_function_evaluations : int The number of function evaluations. """