123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- r"""
- Parameters used in test and benchmark methods.
- Collections of test cases suitable for testing 1-D root-finders
- 'original': The original benchmarking functions.
- Real-valued functions of real-valued inputs on an interval
- with a zero.
- f1, .., f3 are continuous and infinitely differentiable
- f4 has a left- and right- discontinuity at the root
- f5 has a root at 1 replacing a 1st order pole
- f6 is randomly positive on one side of the root,
- randomly negative on the other.
- f4 - f6 are not continuous at the root.
- 'aps': The test problems in the 1995 paper
- TOMS "Algorithm 748: Enclosing Zeros of Continuous Functions"
- by Alefeld, Potra and Shi. Real-valued functions of
- real-valued inputs on an interval with a zero.
- Suitable for methods which start with an enclosing interval, and
- derivatives up to 2nd order.
- 'complex': Some complex-valued functions of complex-valued inputs.
- No enclosing bracket is provided.
- Suitable for methods which use one or more starting values, and
- derivatives up to 2nd order.
- The test cases are provided as a list of dictionaries. The dictionary
- keys will be a subset of:
- ["f", "fprime", "fprime2", "args", "bracket", "smoothness",
- "a", "b", "x0", "x1", "root", "ID"]
- """
- # Sources:
- # [1] Alefeld, G. E. and Potra, F. A. and Shi, Yixun,
- # "Algorithm 748: Enclosing Zeros of Continuous Functions",
- # ACM Trans. Math. Softw. Volume 221(1995)
- # doi = {10.1145/210089.210111},
- from random import random
- import numpy as np
- from scipy.optimize import _zeros_py as cc
- # "description" refers to the original functions
- description = """
- f2 is a symmetric parabola, x**2 - 1
- f3 is a quartic polynomial with large hump in interval
- f4 is step function with a discontinuity at 1
- f5 is a hyperbola with vertical asymptote at 1
- f6 has random values positive to left of 1, negative to right
- Of course, these are not real problems. They just test how the
- 'good' solvers behave in bad circumstances where bisection is
- really the best. A good solver should not be much worse than
- bisection in such circumstance, while being faster for smooth
- monotone sorts of functions.
- """
- def f1(x):
- r"""f1 is a quadratic with roots at 0 and 1"""
- return x * (x - 1.)
- def f1_fp(x):
- return 2 * x - 1
- def f1_fpp(x):
- return 2
- def f2(x):
- r"""f2 is a symmetric parabola, x**2 - 1"""
- return x**2 - 1
- def f2_fp(x):
- return 2 * x
- def f2_fpp(x):
- return 2
- def f3(x):
- r"""A quartic with roots at 0, 1, 2 and 3"""
- return x * (x - 1.) * (x - 2.) * (x - 3.) # x**4 - 6x**3 + 11x**2 - 6x
- def f3_fp(x):
- return 4 * x**3 - 18 * x**2 + 22 * x - 6
- def f3_fpp(x):
- return 12 * x**2 - 36 * x + 22
- def f4(x):
- r"""Piecewise linear, left- and right- discontinuous at x=1, the root."""
- if x > 1:
- return 1.0 + .1 * x
- if x < 1:
- return -1.0 + .1 * x
- return 0
- def f5(x):
- r"""Hyperbola with a pole at x=1, but pole replaced with 0. Not continuous at root."""
- if x != 1:
- return 1.0 / (1. - x)
- return 0
- # f6(x) returns random value. Without memoization, calling twice with the
- # same x returns different values, hence a "random value", not a
- # "function with random values"
- _f6_cache = {}
- def f6(x):
- v = _f6_cache.get(x, None)
- if v is None:
- if x > 1:
- v = random()
- elif x < 1:
- v = -random()
- else:
- v = 0
- _f6_cache[x] = v
- return v
- # Each Original test case has
- # - a function and its two derivatives,
- # - additional arguments,
- # - a bracket enclosing a root,
- # - the order of differentiability (smoothness) on this interval
- # - a starting value for methods which don't require a bracket
- # - the root (inside the bracket)
- # - an Identifier of the test case
- _ORIGINAL_TESTS_KEYS = ["f", "fprime", "fprime2", "args", "bracket", "smoothness", "x0", "root", "ID"]
- _ORIGINAL_TESTS = [
- [f1, f1_fp, f1_fpp, (), [0.5, np.sqrt(3)], np.inf, 0.6, 1.0, "original.01.00"],
- [f2, f2_fp, f2_fpp, (), [0.5, np.sqrt(3)], np.inf, 0.6, 1.0, "original.02.00"],
- [f3, f3_fp, f3_fpp, (), [0.5, np.sqrt(3)], np.inf, 0.6, 1.0, "original.03.00"],
- [f4, None, None, (), [0.5, np.sqrt(3)], -1, 0.6, 1.0, "original.04.00"],
- [f5, None, None, (), [0.5, np.sqrt(3)], -1, 0.6, 1.0, "original.05.00"],
- [f6, None, None, (), [0.5, np.sqrt(3)], -np.inf, 0.6, 1.0, "original.05.00"]
- ]
- _ORIGINAL_TESTS_DICTS = [dict(zip(_ORIGINAL_TESTS_KEYS, testcase)) for testcase in _ORIGINAL_TESTS]
- # ##################
- # "APS" test cases
- # Functions and test cases that appear in [1]
- def aps01_f(x):
- r"""Straightforward sum of trigonometric function and polynomial"""
- return np.sin(x) - x / 2
- def aps01_fp(x):
- return np.cos(x) - 1.0 / 2
- def aps01_fpp(x):
- return -np.sin(x)
- def aps02_f(x):
- r"""poles at x=n**2, 1st and 2nd derivatives at root are also close to 0"""
- ii = np.arange(1, 21)
- return -2 * np.sum((2 * ii - 5)**2 / (x - ii**2)**3)
- def aps02_fp(x):
- ii = np.arange(1, 21)
- return 6 * np.sum((2 * ii - 5)**2 / (x - ii**2)**4)
- def aps02_fpp(x):
- ii = np.arange(1, 21)
- return 24 * np.sum((2 * ii - 5)**2 / (x - ii**2)**5)
- def aps03_f(x, a, b):
- r"""Rapidly changing at the root"""
- return a * x * np.exp(b * x)
- def aps03_fp(x, a, b):
- return a * (b * x + 1) * np.exp(b * x)
- def aps03_fpp(x, a, b):
- return a * (b * (b * x + 1) + b) * np.exp(b * x)
- def aps04_f(x, n, a):
- r"""Medium-degree polynomial"""
- return x**n - a
- def aps04_fp(x, n, a):
- return n * x**(n - 1)
- def aps04_fpp(x, n, a):
- return n * (n - 1) * x**(n - 2)
- def aps05_f(x):
- r"""Simple Trigonometric function"""
- return np.sin(x) - 1.0 / 2
- def aps05_fp(x):
- return np.cos(x)
- def aps05_fpp(x):
- return -np.sin(x)
- def aps06_f(x, n):
- r"""Exponential rapidly changing from -1 to 1 at x=0"""
- return 2 * x * np.exp(-n) - 2 * np.exp(-n * x) + 1
- def aps06_fp(x, n):
- return 2 * np.exp(-n) + 2 * n * np.exp(-n * x)
- def aps06_fpp(x, n):
- return -2 * n * n * np.exp(-n * x)
- def aps07_f(x, n):
- r"""Upside down parabola with parametrizable height"""
- return (1 + (1 - n)**2) * x - (1 - n * x)**2
- def aps07_fp(x, n):
- return (1 + (1 - n)**2) + 2 * n * (1 - n * x)
- def aps07_fpp(x, n):
- return -2 * n * n
- def aps08_f(x, n):
- r"""Degree n polynomial"""
- return x * x - (1 - x)**n
- def aps08_fp(x, n):
- return 2 * x + n * (1 - x)**(n - 1)
- def aps08_fpp(x, n):
- return 2 - n * (n - 1) * (1 - x)**(n - 2)
- def aps09_f(x, n):
- r"""Upside down quartic with parametrizable height"""
- return (1 + (1 - n)**4) * x - (1 - n * x)**4
- def aps09_fp(x, n):
- return (1 + (1 - n)**4) + 4 * n * (1 - n * x)**3
- def aps09_fpp(x, n):
- return -12 * n * (1 - n * x)**2
- def aps10_f(x, n):
- r"""Exponential plus a polynomial"""
- return np.exp(-n * x) * (x - 1) + x**n
- def aps10_fp(x, n):
- return np.exp(-n * x) * (-n * (x - 1) + 1) + n * x**(n - 1)
- def aps10_fpp(x, n):
- return np.exp(-n * x) * (-n * (-n * (x - 1) + 1) + -n * x) + n * (n - 1) * x**(n - 2)
- def aps11_f(x, n):
- r"""Rational function with a zero at x=1/n and a pole at x=0"""
- return (n * x - 1) / ((n - 1) * x)
- def aps11_fp(x, n):
- return 1 / (n - 1) / x**2
- def aps11_fpp(x, n):
- return -2 / (n - 1) / x**3
- def aps12_f(x, n):
- r"""nth root of x, with a zero at x=n"""
- return np.power(x, 1.0 / n) - np.power(n, 1.0 / n)
- def aps12_fp(x, n):
- return np.power(x, (1.0 - n) / n) / n
- def aps12_fpp(x, n):
- return np.power(x, (1.0 - 2 * n) / n) * (1.0 / n) * (1.0 - n) / n
- _MAX_EXPABLE = np.log(np.finfo(float).max)
- def aps13_f(x):
- r"""Function with *all* derivatives 0 at the root"""
- if x == 0:
- return 0
- # x2 = 1.0/x**2
- # if x2 > 708:
- # return 0
- y = 1 / x**2
- if y > _MAX_EXPABLE:
- return 0
- return x / np.exp(y)
- def aps13_fp(x):
- if x == 0:
- return 0
- y = 1 / x**2
- if y > _MAX_EXPABLE:
- return 0
- return (1 + 2 / x**2) / np.exp(y)
- def aps13_fpp(x):
- if x == 0:
- return 0
- y = 1 / x**2
- if y > _MAX_EXPABLE:
- return 0
- return 2 * (2 - x**2) / x**5 / np.exp(y)
- def aps14_f(x, n):
- r"""0 for negative x-values, trigonometric+linear for x positive"""
- if x <= 0:
- return -n / 20.0
- return n / 20.0 * (x / 1.5 + np.sin(x) - 1)
- def aps14_fp(x, n):
- if x <= 0:
- return 0
- return n / 20.0 * (1.0 / 1.5 + np.cos(x))
- def aps14_fpp(x, n):
- if x <= 0:
- return 0
- return -n / 20.0 * (np.sin(x))
- def aps15_f(x, n):
- r"""piecewise linear, constant outside of [0, 0.002/(1+n)]"""
- if x < 0:
- return -0.859
- if x > 2 * 1e-3 / (1 + n):
- return np.e - 1.859
- return np.exp((n + 1) * x / 2 * 1000) - 1.859
- def aps15_fp(x, n):
- if not 0 <= x <= 2 * 1e-3 / (1 + n):
- return np.e - 1.859
- return np.exp((n + 1) * x / 2 * 1000) * (n + 1) / 2 * 1000
- def aps15_fpp(x, n):
- if not 0 <= x <= 2 * 1e-3 / (1 + n):
- return np.e - 1.859
- return np.exp((n + 1) * x / 2 * 1000) * (n + 1) / 2 * 1000 * (n + 1) / 2 * 1000
- # Each APS test case has
- # - a function and its two derivatives,
- # - additional arguments,
- # - a bracket enclosing a root,
- # - the order of differentiability of the function on this interval
- # - a starting value for methods which don't require a bracket
- # - the root (inside the bracket)
- # - an Identifier of the test case
- #
- # Algorithm 748 is a bracketing algorithm so a bracketing interval was provided
- # in [1] for each test case. Newton and Halley methods need a single
- # starting point x0, which was chosen to be near the middle of the interval,
- # unless that would have made the problem too easy.
- _APS_TESTS_KEYS = ["f", "fprime", "fprime2", "args", "bracket", "smoothness", "x0", "root", "ID"]
- _APS_TESTS = [
- [aps01_f, aps01_fp, aps01_fpp, (), [np.pi / 2, np.pi], np.inf, 3, 1.89549426703398094e+00, "aps.01.00"],
- [aps02_f, aps02_fp, aps02_fpp, (), [1 + 1e-9, 4 - 1e-9], np.inf, 2, 3.02291534727305677e+00, "aps.02.00"],
- [aps02_f, aps02_fp, aps02_fpp, (), [4 + 1e-9, 9 - 1e-9], np.inf, 5, 6.68375356080807848e+00, "aps.02.01"],
- [aps02_f, aps02_fp, aps02_fpp, (), [9 + 1e-9, 16 - 1e-9], np.inf, 10, 1.12387016550022114e+01, "aps.02.02"],
- [aps02_f, aps02_fp, aps02_fpp, (), [16 + 1e-9, 25 - 1e-9], np.inf, 17, 1.96760000806234103e+01, "aps.02.03"],
- [aps02_f, aps02_fp, aps02_fpp, (), [25 + 1e-9, 36 - 1e-9], np.inf, 26, 2.98282273265047557e+01, "aps.02.04"],
- [aps02_f, aps02_fp, aps02_fpp, (), [36 + 1e-9, 49 - 1e-9], np.inf, 37, 4.19061161952894139e+01, "aps.02.05"],
- [aps02_f, aps02_fp, aps02_fpp, (), [49 + 1e-9, 64 - 1e-9], np.inf, 50, 5.59535958001430913e+01, "aps.02.06"],
- [aps02_f, aps02_fp, aps02_fpp, (), [64 + 1e-9, 81 - 1e-9], np.inf, 65, 7.19856655865877997e+01, "aps.02.07"],
- [aps02_f, aps02_fp, aps02_fpp, (), [81 + 1e-9, 100 - 1e-9], np.inf, 82, 9.00088685391666701e+01, "aps.02.08"],
- [aps02_f, aps02_fp, aps02_fpp, (), [100 + 1e-9, 121 - 1e-9], np.inf, 101, 1.10026532748330197e+02, "aps.02.09"],
- [aps03_f, aps03_fp, aps03_fpp, (-40, -1), [-9, 31], np.inf, -2, 0, "aps.03.00"],
- [aps03_f, aps03_fp, aps03_fpp, (-100, -2), [-9, 31], np.inf, -2, 0, "aps.03.01"],
- [aps03_f, aps03_fp, aps03_fpp, (-200, -3), [-9, 31], np.inf, -2, 0, "aps.03.02"],
- [aps04_f, aps04_fp, aps04_fpp, (4, 0.2), [0, 5], np.inf, 2.5, 6.68740304976422006e-01, "aps.04.00"],
- [aps04_f, aps04_fp, aps04_fpp, (6, 0.2), [0, 5], np.inf, 2.5, 7.64724491331730039e-01, "aps.04.01"],
- [aps04_f, aps04_fp, aps04_fpp, (8, 0.2), [0, 5], np.inf, 2.5, 8.17765433957942545e-01, "aps.04.02"],
- [aps04_f, aps04_fp, aps04_fpp, (10, 0.2), [0, 5], np.inf, 2.5, 8.51339922520784609e-01, "aps.04.03"],
- [aps04_f, aps04_fp, aps04_fpp, (12, 0.2), [0, 5], np.inf, 2.5, 8.74485272221167897e-01, "aps.04.04"],
- [aps04_f, aps04_fp, aps04_fpp, (4, 1), [0, 5], np.inf, 2.5, 1, "aps.04.05"],
- [aps04_f, aps04_fp, aps04_fpp, (6, 1), [0, 5], np.inf, 2.5, 1, "aps.04.06"],
- [aps04_f, aps04_fp, aps04_fpp, (8, 1), [0, 5], np.inf, 2.5, 1, "aps.04.07"],
- [aps04_f, aps04_fp, aps04_fpp, (10, 1), [0, 5], np.inf, 2.5, 1, "aps.04.08"],
- [aps04_f, aps04_fp, aps04_fpp, (12, 1), [0, 5], np.inf, 2.5, 1, "aps.04.09"],
- [aps04_f, aps04_fp, aps04_fpp, (8, 1), [-0.95, 4.05], np.inf, 1.5, 1, "aps.04.10"],
- [aps04_f, aps04_fp, aps04_fpp, (10, 1), [-0.95, 4.05], np.inf, 1.5, 1, "aps.04.11"],
- [aps04_f, aps04_fp, aps04_fpp, (12, 1), [-0.95, 4.05], np.inf, 1.5, 1, "aps.04.12"],
- [aps04_f, aps04_fp, aps04_fpp, (14, 1), [-0.95, 4.05], np.inf, 1.5, 1, "aps.04.13"],
- [aps05_f, aps05_fp, aps05_fpp, (), [0, 1.5], np.inf, 1.3, np.pi / 6, "aps.05.00"],
- [aps06_f, aps06_fp, aps06_fpp, (1,), [0, 1], np.inf, 0.5, 4.22477709641236709e-01, "aps.06.00"],
- [aps06_f, aps06_fp, aps06_fpp, (2,), [0, 1], np.inf, 0.5, 3.06699410483203705e-01, "aps.06.01"],
- [aps06_f, aps06_fp, aps06_fpp, (3,), [0, 1], np.inf, 0.5, 2.23705457654662959e-01, "aps.06.02"],
- [aps06_f, aps06_fp, aps06_fpp, (4,), [0, 1], np.inf, 0.5, 1.71719147519508369e-01, "aps.06.03"],
- [aps06_f, aps06_fp, aps06_fpp, (5,), [0, 1], np.inf, 0.4, 1.38257155056824066e-01, "aps.06.04"],
- [aps06_f, aps06_fp, aps06_fpp, (20,), [0, 1], np.inf, 0.1, 3.46573590208538521e-02, "aps.06.05"],
- [aps06_f, aps06_fp, aps06_fpp, (40,), [0, 1], np.inf, 5e-02, 1.73286795139986315e-02, "aps.06.06"],
- [aps06_f, aps06_fp, aps06_fpp, (60,), [0, 1], np.inf, 1.0 / 30, 1.15524530093324210e-02, "aps.06.07"],
- [aps06_f, aps06_fp, aps06_fpp, (80,), [0, 1], np.inf, 2.5e-02, 8.66433975699931573e-03, "aps.06.08"],
- [aps06_f, aps06_fp, aps06_fpp, (100,), [0, 1], np.inf, 2e-02, 6.93147180559945415e-03, "aps.06.09"],
- [aps07_f, aps07_fp, aps07_fpp, (5,), [0, 1], np.inf, 0.4, 3.84025518406218985e-02, "aps.07.00"],
- [aps07_f, aps07_fp, aps07_fpp, (10,), [0, 1], np.inf, 0.4, 9.90000999800049949e-03, "aps.07.01"],
- [aps07_f, aps07_fp, aps07_fpp, (20,), [0, 1], np.inf, 0.4, 2.49375003906201174e-03, "aps.07.02"],
- [aps08_f, aps08_fp, aps08_fpp, (2,), [0, 1], np.inf, 0.9, 0.5, "aps.08.00"],
- [aps08_f, aps08_fp, aps08_fpp, (5,), [0, 1], np.inf, 0.9, 3.45954815848242059e-01, "aps.08.01"],
- [aps08_f, aps08_fp, aps08_fpp, (10,), [0, 1], np.inf, 0.9, 2.45122333753307220e-01, "aps.08.02"],
- [aps08_f, aps08_fp, aps08_fpp, (15,), [0, 1], np.inf, 0.9, 1.95547623536565629e-01, "aps.08.03"],
- [aps08_f, aps08_fp, aps08_fpp, (20,), [0, 1], np.inf, 0.9, 1.64920957276440960e-01, "aps.08.04"],
- [aps09_f, aps09_fp, aps09_fpp, (1,), [0, 1], np.inf, 0.5, 2.75508040999484394e-01, "aps.09.00"],
- [aps09_f, aps09_fp, aps09_fpp, (2,), [0, 1], np.inf, 0.5, 1.37754020499742197e-01, "aps.09.01"],
- [aps09_f, aps09_fp, aps09_fpp, (4,), [0, 1], np.inf, 0.5, 1.03052837781564422e-02, "aps.09.02"],
- [aps09_f, aps09_fp, aps09_fpp, (5,), [0, 1], np.inf, 0.5, 3.61710817890406339e-03, "aps.09.03"],
- [aps09_f, aps09_fp, aps09_fpp, (8,), [0, 1], np.inf, 0.5, 4.10872918496395375e-04, "aps.09.04"],
- [aps09_f, aps09_fp, aps09_fpp, (15,), [0, 1], np.inf, 0.5, 2.59895758929076292e-05, "aps.09.05"],
- [aps09_f, aps09_fp, aps09_fpp, (20,), [0, 1], np.inf, 0.5, 7.66859512218533719e-06, "aps.09.06"],
- [aps10_f, aps10_fp, aps10_fpp, (1,), [0, 1], np.inf, 0.9, 4.01058137541547011e-01, "aps.10.00"],
- [aps10_f, aps10_fp, aps10_fpp, (5,), [0, 1], np.inf, 0.9, 5.16153518757933583e-01, "aps.10.01"],
- [aps10_f, aps10_fp, aps10_fpp, (10,), [0, 1], np.inf, 0.9, 5.39522226908415781e-01, "aps.10.02"],
- [aps10_f, aps10_fp, aps10_fpp, (15,), [0, 1], np.inf, 0.9, 5.48182294340655241e-01, "aps.10.03"],
- [aps10_f, aps10_fp, aps10_fpp, (20,), [0, 1], np.inf, 0.9, 5.52704666678487833e-01, "aps.10.04"],
- [aps11_f, aps11_fp, aps11_fpp, (2,), [0.01, 1], np.inf, 1e-02, 1.0 / 2, "aps.11.00"],
- [aps11_f, aps11_fp, aps11_fpp, (5,), [0.01, 1], np.inf, 1e-02, 1.0 / 5, "aps.11.01"],
- [aps11_f, aps11_fp, aps11_fpp, (15,), [0.01, 1], np.inf, 1e-02, 1.0 / 15, "aps.11.02"],
- [aps11_f, aps11_fp, aps11_fpp, (20,), [0.01, 1], np.inf, 1e-02, 1.0 / 20, "aps.11.03"],
- [aps12_f, aps12_fp, aps12_fpp, (2,), [1, 100], np.inf, 1.1, 2, "aps.12.00"],
- [aps12_f, aps12_fp, aps12_fpp, (3,), [1, 100], np.inf, 1.1, 3, "aps.12.01"],
- [aps12_f, aps12_fp, aps12_fpp, (4,), [1, 100], np.inf, 1.1, 4, "aps.12.02"],
- [aps12_f, aps12_fp, aps12_fpp, (5,), [1, 100], np.inf, 1.1, 5, "aps.12.03"],
- [aps12_f, aps12_fp, aps12_fpp, (6,), [1, 100], np.inf, 1.1, 6, "aps.12.04"],
- [aps12_f, aps12_fp, aps12_fpp, (7,), [1, 100], np.inf, 1.1, 7, "aps.12.05"],
- [aps12_f, aps12_fp, aps12_fpp, (9,), [1, 100], np.inf, 1.1, 9, "aps.12.06"],
- [aps12_f, aps12_fp, aps12_fpp, (11,), [1, 100], np.inf, 1.1, 11, "aps.12.07"],
- [aps12_f, aps12_fp, aps12_fpp, (13,), [1, 100], np.inf, 1.1, 13, "aps.12.08"],
- [aps12_f, aps12_fp, aps12_fpp, (15,), [1, 100], np.inf, 1.1, 15, "aps.12.09"],
- [aps12_f, aps12_fp, aps12_fpp, (17,), [1, 100], np.inf, 1.1, 17, "aps.12.10"],
- [aps12_f, aps12_fp, aps12_fpp, (19,), [1, 100], np.inf, 1.1, 19, "aps.12.11"],
- [aps12_f, aps12_fp, aps12_fpp, (21,), [1, 100], np.inf, 1.1, 21, "aps.12.12"],
- [aps12_f, aps12_fp, aps12_fpp, (23,), [1, 100], np.inf, 1.1, 23, "aps.12.13"],
- [aps12_f, aps12_fp, aps12_fpp, (25,), [1, 100], np.inf, 1.1, 25, "aps.12.14"],
- [aps12_f, aps12_fp, aps12_fpp, (27,), [1, 100], np.inf, 1.1, 27, "aps.12.15"],
- [aps12_f, aps12_fp, aps12_fpp, (29,), [1, 100], np.inf, 1.1, 29, "aps.12.16"],
- [aps12_f, aps12_fp, aps12_fpp, (31,), [1, 100], np.inf, 1.1, 31, "aps.12.17"],
- [aps12_f, aps12_fp, aps12_fpp, (33,), [1, 100], np.inf, 1.1, 33, "aps.12.18"],
- [aps13_f, aps13_fp, aps13_fpp, (), [-1, 4], np.inf, 1.5, 1.54720911915117165e-02, "aps.13.00"],
- [aps14_f, aps14_fp, aps14_fpp, (1,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.00"],
- [aps14_f, aps14_fp, aps14_fpp, (2,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.01"],
- [aps14_f, aps14_fp, aps14_fpp, (3,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.02"],
- [aps14_f, aps14_fp, aps14_fpp, (4,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.03"],
- [aps14_f, aps14_fp, aps14_fpp, (5,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.04"],
- [aps14_f, aps14_fp, aps14_fpp, (6,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.05"],
- [aps14_f, aps14_fp, aps14_fpp, (7,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.06"],
- [aps14_f, aps14_fp, aps14_fpp, (8,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.07"],
- [aps14_f, aps14_fp, aps14_fpp, (9,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.08"],
- [aps14_f, aps14_fp, aps14_fpp, (10,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.09"],
- [aps14_f, aps14_fp, aps14_fpp, (11,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.10"],
- [aps14_f, aps14_fp, aps14_fpp, (12,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.11"],
- [aps14_f, aps14_fp, aps14_fpp, (13,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.12"],
- [aps14_f, aps14_fp, aps14_fpp, (14,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.13"],
- [aps14_f, aps14_fp, aps14_fpp, (15,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.14"],
- [aps14_f, aps14_fp, aps14_fpp, (16,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.15"],
- [aps14_f, aps14_fp, aps14_fpp, (17,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.16"],
- [aps14_f, aps14_fp, aps14_fpp, (18,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.17"],
- [aps14_f, aps14_fp, aps14_fpp, (19,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.18"],
- [aps14_f, aps14_fp, aps14_fpp, (20,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.19"],
- [aps14_f, aps14_fp, aps14_fpp, (21,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.20"],
- [aps14_f, aps14_fp, aps14_fpp, (22,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.21"],
- [aps14_f, aps14_fp, aps14_fpp, (23,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.22"],
- [aps14_f, aps14_fp, aps14_fpp, (24,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.23"],
- [aps14_f, aps14_fp, aps14_fpp, (25,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.24"],
- [aps14_f, aps14_fp, aps14_fpp, (26,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.25"],
- [aps14_f, aps14_fp, aps14_fpp, (27,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.26"],
- [aps14_f, aps14_fp, aps14_fpp, (28,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.27"],
- [aps14_f, aps14_fp, aps14_fpp, (29,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.28"],
- [aps14_f, aps14_fp, aps14_fpp, (30,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.29"],
- [aps14_f, aps14_fp, aps14_fpp, (31,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.30"],
- [aps14_f, aps14_fp, aps14_fpp, (32,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.31"],
- [aps14_f, aps14_fp, aps14_fpp, (33,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.32"],
- [aps14_f, aps14_fp, aps14_fpp, (34,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.33"],
- [aps14_f, aps14_fp, aps14_fpp, (35,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.34"],
- [aps14_f, aps14_fp, aps14_fpp, (36,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.35"],
- [aps14_f, aps14_fp, aps14_fpp, (37,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.36"],
- [aps14_f, aps14_fp, aps14_fpp, (38,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.37"],
- [aps14_f, aps14_fp, aps14_fpp, (39,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.38"],
- [aps14_f, aps14_fp, aps14_fpp, (40,), [-1000, np.pi / 2], 0, 1, 6.23806518961612433e-01, "aps.14.39"],
- [aps15_f, aps15_fp, aps15_fpp, (20,), [-1000, 1e-4], 0, -2, 5.90513055942197166e-05, "aps.15.00"],
- [aps15_f, aps15_fp, aps15_fpp, (21,), [-1000, 1e-4], 0, -2, 5.63671553399369967e-05, "aps.15.01"],
- [aps15_f, aps15_fp, aps15_fpp, (22,), [-1000, 1e-4], 0, -2, 5.39164094555919196e-05, "aps.15.02"],
- [aps15_f, aps15_fp, aps15_fpp, (23,), [-1000, 1e-4], 0, -2, 5.16698923949422470e-05, "aps.15.03"],
- [aps15_f, aps15_fp, aps15_fpp, (24,), [-1000, 1e-4], 0, -2, 4.96030966991445609e-05, "aps.15.04"],
- [aps15_f, aps15_fp, aps15_fpp, (25,), [-1000, 1e-4], 0, -2, 4.76952852876389951e-05, "aps.15.05"],
- [aps15_f, aps15_fp, aps15_fpp, (26,), [-1000, 1e-4], 0, -2, 4.59287932399486662e-05, "aps.15.06"],
- [aps15_f, aps15_fp, aps15_fpp, (27,), [-1000, 1e-4], 0, -2, 4.42884791956647841e-05, "aps.15.07"],
- [aps15_f, aps15_fp, aps15_fpp, (28,), [-1000, 1e-4], 0, -2, 4.27612902578832391e-05, "aps.15.08"],
- [aps15_f, aps15_fp, aps15_fpp, (29,), [-1000, 1e-4], 0, -2, 4.13359139159538030e-05, "aps.15.09"],
- [aps15_f, aps15_fp, aps15_fpp, (30,), [-1000, 1e-4], 0, -2, 4.00024973380198076e-05, "aps.15.10"],
- [aps15_f, aps15_fp, aps15_fpp, (31,), [-1000, 1e-4], 0, -2, 3.87524192962066869e-05, "aps.15.11"],
- [aps15_f, aps15_fp, aps15_fpp, (32,), [-1000, 1e-4], 0, -2, 3.75781035599579910e-05, "aps.15.12"],
- [aps15_f, aps15_fp, aps15_fpp, (33,), [-1000, 1e-4], 0, -2, 3.64728652199592355e-05, "aps.15.13"],
- [aps15_f, aps15_fp, aps15_fpp, (34,), [-1000, 1e-4], 0, -2, 3.54307833565318273e-05, "aps.15.14"],
- [aps15_f, aps15_fp, aps15_fpp, (35,), [-1000, 1e-4], 0, -2, 3.44465949299614980e-05, "aps.15.15"],
- [aps15_f, aps15_fp, aps15_fpp, (36,), [-1000, 1e-4], 0, -2, 3.35156058778003705e-05, "aps.15.16"],
- [aps15_f, aps15_fp, aps15_fpp, (37,), [-1000, 1e-4], 0, -2, 3.26336162494372125e-05, "aps.15.17"],
- [aps15_f, aps15_fp, aps15_fpp, (38,), [-1000, 1e-4], 0, -2, 3.17968568584260013e-05, "aps.15.18"],
- [aps15_f, aps15_fp, aps15_fpp, (39,), [-1000, 1e-4], 0, -2, 3.10019354369653455e-05, "aps.15.19"],
- [aps15_f, aps15_fp, aps15_fpp, (40,), [-1000, 1e-4], 0, -2, 3.02457906702100968e-05, "aps.15.20"],
- [aps15_f, aps15_fp, aps15_fpp, (100,), [-1000, 1e-4], 0, -2, 1.22779942324615231e-05, "aps.15.21"],
- [aps15_f, aps15_fp, aps15_fpp, (200,), [-1000, 1e-4], 0, -2, 6.16953939044086617e-06, "aps.15.22"],
- [aps15_f, aps15_fp, aps15_fpp, (300,), [-1000, 1e-4], 0, -2, 4.11985852982928163e-06, "aps.15.23"],
- [aps15_f, aps15_fp, aps15_fpp, (400,), [-1000, 1e-4], 0, -2, 3.09246238772721682e-06, "aps.15.24"],
- [aps15_f, aps15_fp, aps15_fpp, (500,), [-1000, 1e-4], 0, -2, 2.47520442610501789e-06, "aps.15.25"],
- [aps15_f, aps15_fp, aps15_fpp, (600,), [-1000, 1e-4], 0, -2, 2.06335676785127107e-06, "aps.15.26"],
- [aps15_f, aps15_fp, aps15_fpp, (700,), [-1000, 1e-4], 0, -2, 1.76901200781542651e-06, "aps.15.27"],
- [aps15_f, aps15_fp, aps15_fpp, (800,), [-1000, 1e-4], 0, -2, 1.54816156988591016e-06, "aps.15.28"],
- [aps15_f, aps15_fp, aps15_fpp, (900,), [-1000, 1e-4], 0, -2, 1.37633453660223511e-06, "aps.15.29"],
- [aps15_f, aps15_fp, aps15_fpp, (1000,), [-1000, 1e-4], 0, -2, 1.23883857889971403e-06, "aps.15.30"]
- ]
- _APS_TESTS_DICTS = [dict(zip(_APS_TESTS_KEYS, testcase)) for testcase in _APS_TESTS]
- # ##################
- # "complex" test cases
- # A few simple, complex-valued, functions, defined on the complex plane.
- def cplx01_f(z, n, a):
- r"""z**n-a: Use to find the nth root of a"""
- return z**n - a
- def cplx01_fp(z, n, a):
- return n * z**(n - 1)
- def cplx01_fpp(z, n, a):
- return n * (n - 1) * z**(n - 2)
- def cplx02_f(z, a):
- r"""e**z - a: Use to find the log of a"""
- return np.exp(z) - a
- def cplx02_fp(z, a):
- return np.exp(z)
- def cplx02_fpp(z, a):
- return np.exp(z)
- # Each "complex" test case has
- # - a function and its two derivatives,
- # - additional arguments,
- # - the order of differentiability of the function on this interval
- # - two starting values x0 and x1
- # - the root
- # - an Identifier of the test case
- #
- # Algorithm 748 is a bracketing algorithm so a bracketing interval was provided
- # in [1] for each test case. Newton and Halley need a single starting point
- # x0, which was chosen to be near the middle of the interval, unless that
- # would make the problem too easy.
- _COMPLEX_TESTS_KEYS = ["f", "fprime", "fprime2", "args", "smoothness", "x0", "x1", "root", "ID"]
- _COMPLEX_TESTS = [
- [cplx01_f, cplx01_fp, cplx01_fpp, (2, -1), np.inf, (1 + 1j), (0.5 + 0.5j), 1j, "complex.01.00"],
- [cplx01_f, cplx01_fp, cplx01_fpp, (3, 1), np.inf, (-1 + 1j), (-0.5 + 2.0j), (-0.5 + np.sqrt(3) / 2 * 1.0j),
- "complex.01.01"],
- [cplx01_f, cplx01_fp, cplx01_fpp, (3, -1), np.inf, 1j, (0.5 + 0.5j), (0.5 + np.sqrt(3) / 2 * 1.0j),
- "complex.01.02"],
- [cplx01_f, cplx01_fp, cplx01_fpp, (3, 8), np.inf, 5, 4, 2, "complex.01.03"],
- [cplx02_f, cplx02_fp, cplx02_fpp, (-1,), np.inf, (1 + 2j), (0.5 + 0.5j), np.pi * 1.0j, "complex.02.00"],
- [cplx02_f, cplx02_fp, cplx02_fpp, (1j,), np.inf, (1 + 2j), (0.5 + 0.5j), np.pi * 0.5j, "complex.02.01"],
- ]
- _COMPLEX_TESTS_DICTS = [dict(zip(_COMPLEX_TESTS_KEYS, testcase)) for testcase in _COMPLEX_TESTS]
- def _add_a_b(tests):
- r"""Add "a" and "b" keys to each test from the "bracket" value"""
- for d in tests:
- for k, v in zip(['a', 'b'], d.get('bracket', [])):
- d[k] = v
- _add_a_b(_ORIGINAL_TESTS_DICTS)
- _add_a_b(_APS_TESTS_DICTS)
- _add_a_b(_COMPLEX_TESTS_DICTS)
- def get_tests(collection='original', smoothness=None):
- r"""Return the requested collection of test cases, as an array of dicts with subset-specific keys
- Allowed values of collection:
- 'original': The original benchmarking functions.
- Real-valued functions of real-valued inputs on an interval with a zero.
- f1, .., f3 are continuous and infinitely differentiable
- f4 has a single discontinuity at the root
- f5 has a root at 1 replacing a 1st order pole
- f6 is randomly positive on one side of the root, randomly negative on the other
- 'aps': The test problems in the TOMS "Algorithm 748: Enclosing Zeros of Continuous Functions"
- paper by Alefeld, Potra and Shi. Real-valued functions of
- real-valued inputs on an interval with a zero.
- Suitable for methods which start with an enclosing interval, and
- derivatives up to 2nd order.
- 'complex': Some complex-valued functions of complex-valued inputs.
- No enclosing bracket is provided.
- Suitable for methods which use one or more starting values, and
- derivatives up to 2nd order.
- The dictionary keys will be a subset of
- ["f", "fprime", "fprime2", "args", "bracket", "a", b", "smoothness", "x0", "x1", "root", "ID"]
- """
- collection = collection or "original"
- subsets = {"aps": _APS_TESTS_DICTS,
- "complex": _COMPLEX_TESTS_DICTS,
- "original": _ORIGINAL_TESTS_DICTS}
- tests = subsets.get(collection, [])
- if smoothness is not None:
- tests = [tc for tc in tests if tc['smoothness'] >= smoothness]
- return tests
- # Backwards compatibility
- methods = [cc.bisect, cc.ridder, cc.brenth, cc.brentq]
- mstrings = ['cc.bisect', 'cc.ridder', 'cc.brenth', 'cc.brentq']
- functions = [f2, f3, f4, f5, f6]
- fstrings = ['f2', 'f3', 'f4', 'f5', 'f6']
|