def test_RingOscillator(): # problem in section 4.3 of [DSZ] from cxroots import Rectangle, findRoots def A(z): t = 2. return np.array([[-0.0166689-2.12e-14*z, 1/60. + 6e-16*exp(-t*z)*z], [0.0166659+exp(-t*z)*(-0.000037485+6e-16*z), -0.0166667-6e-16*z]]) def dA(z): t = 2. return np.array([[-2.12e-14*np.ones_like(z), 6e-16*exp(-t*z) - t*6e-16*exp(-t*z)*z], [-t*exp(-t*z)*(-0.000037485+6e-16*z)+exp(-t*z)*6e-16, -6e-16*np.ones_like(z)]]) def f(z): AVal = np.rollaxis(A(z),-1,0) return np.linalg.det(AVal) def df(z): AVal = A(z) dAVal = dA(z) return dAVal[0,0]*AVal[1,1] + AVal[0,0]*dAVal[1,1] - dAVal[0,1]*AVal[1,0] - AVal[0,1]*dAVal[1,0] box = Rectangle([-12,0], [-40,40]) # roots_fdf = findRoots(box, f, df) # roots_f = findRoots(box, f) # XXX: No roots are recorded within the initial contour. # Perhaps because the coefficents of z are very small? # Perhaps need higher precision? assert box.count_enclosed_roots(f, df) != 0 assert box.count_enclosed_roots(f) != 0
class TestRootfinding_151(unittest.TestCase, RootfindingTests, MultiplicityTests): def setUp(self): # Ex 1.5.1 from [KB] self.C = Rectangle([-2, 2], [-2, 3]) self.f = lambda z: exp(3 * z) + 2 * z * cos(z) - 1 self.df = lambda z: 3 * exp(3 * z) + 2 * cos(z) - 2 * z * sin(z) self.roots = np.array([ -1.84423395326221337491592440, 0, 0.5308949302929305274642203840 - 1.331791876751120981651544228j, 0.5308949302929305274642203840 + 1.331791876751120981651544228j ], dtype=complex) self.multiplicities = [1, 1, 1, 1] def test_rootfinding_b_df(self): roots_approx_equal(self.C.roots(self.f, self.df, verbose=True, M=2), (self.roots, self.multiplicities), decimal=12) def test_rootfinding_b_f(self): roots_approx_equal(self.C.roots(self.f, verbose=True, M=2), (self.roots, self.multiplicities), decimal=12)
def setUp(self): # Ex 1.5.1 from [KB] self.C = Rectangle([-2, 2], [-2, 3]) self.f = lambda z: exp(3 * z) + 2 * z * cos(z) - 1 self.df = lambda z: 3 * exp(3 * z) + 2 * cos(z) - 2 * z * sin(z) self.roots = np.array([ -1.84423395326221337491592440, 0, 0.5308949302929305274642203840 - 1.331791876751120981651544228j, 0.5308949302929305274642203840 + 1.331791876751120981651544228j ], dtype=complex) self.multiplicities = [1, 1, 1, 1]
def test_count_roots(useDerivative): """ Example from "Locating all the Zeros of an Analytic Function in one Complex Variable" M.Dellnitz, O.Schutze, Q.Zheng, J. Compu. and App. Math. (2002), Vol.138, Issue 2 There should be 424 roots inside this contour """ C = Rectangle([-20.3,20.7], [-20.3,20.7]) f = lambda z: z**50 + z**12 - 5*sin(20*z)*cos(12*z) - 1 df = lambda z: 50*z**49 + 12*z**11 + 60*sin(12*z)*sin(20*z) - 100*cos(12*z)*cos(20*z) if not useDerivative: df = None assert C.count_roots(f, df, verbose=True) == 424
def setUp(self): self.C = Rectangle([-2, 2], [-2, 2]) self.f = lambda z: z**3 * (z - 1.2)**2 self.df = lambda z: 3 * (z)**2 * (z - 1.2)**2 + 2 * z**3 * (z - 1.2) self.roots = [0, 1.2] self.multiplicities = [3, 2]
def setUp(self): self.roots = roots = [0, -1.234, 1 + 1j, 1 - 1j, 2.345] self.multiplicities = [1, 1, 1, 1, 1] self.f = lambda z: (z - roots[0]) * (z - roots[1]) * (z - roots[2]) * ( z - roots[3]) * (z - roots[4]) self.df = lambda z: (z - roots[1]) * (z - roots[2]) * (z - roots[ 3]) * (z - roots[4]) + (z - roots[0]) * (z - roots[2]) * ( z - roots[3]) * (z - roots[4]) + (z - roots[0]) * (z - roots[ 1]) * (z - roots[3]) * (z - roots[4]) + (z - roots[0]) * ( z - roots[1]) * (z - roots[2]) * (z - roots[4]) + ( z - roots[0]) * (z - roots[1]) * (z - roots[2]) * ( z - roots[3]) self.Circle = Circle(0, 3) self.Rectangle = Rectangle([-2, 2], [-2, 2]) self.halfAnnulus = AnnulusSector(0, [0.5, 3], [-pi / 2, pi / 2]) self.Annulus = Annulus(0, [1, 2])
def test_annular_combustion(): from numpy import exp from cxroots import Rectangle A = -0.19435 B = 1000.41 C = 522463 T = 0.005 f = lambda z: z**2 + A * z + B * exp(-T * z) + C df = lambda z: 2 * z + A - B * T * exp(-T * z) rectangle = Rectangle([-15000, 5000], [-15000, 15000]) import warnings warnings.filterwarnings('error') roots = rectangle.roots(f, df, verbose=True, rootErrTol=1e-6) assert len(roots.roots) == 24
def setUp(self): # Ex 1.4.2 from [KB] with a rectangular initial contour self.C = Rectangle([-2, 2], [-2, 2]) self.f = lambda z: exp(3 * z) + 2 * z * cos(z) - 1 self.df = lambda z: 3 * exp(3 * z) + 2 * cos(z) - 2 * z * sin(z) self.roots = [ 0, -1.844233953262213, 0.5308949302929305 + 1.33179187675112098j, 0.5308949302929305 - 1.33179187675112098j ] self.multiplicities = [1, 1, 1, 1]
def setUp(self): # Ex 1.4.5 from [KB] with a rectangular initial contour self.C = Rectangle([-1, 11], [-1, 1]) self.f = lambda z: np.prod([z - k for k in range(1, 11)], axis=0) self.df = lambda z: np.sum([ np.prod([z - k for k in range(1, 11) if k != m], axis=0) for m in range(1, 11) ], axis=0) self.roots = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] self.multiplicities = np.ones(10)
def setUp(self): # Ex 1.5.2 from [KB] self.C = Rectangle([-0.5, 5.5], [-0.5, 1.5]) self.f = lambda z: z**2 * (z - 1) * (z - 2) * (z - 3) * (z - 4 ) + z * sin(z) self.df = lambda z: 2 * z * (3 * z**4 - 25 * z**3 + 70 * z**2 - 75 * z + 24) + sin(z) + z * cos(z) self.roots = [ 0, 1.18906588973011365517521756, 1.72843498616506284043592924, 3.01990732809571222812005354, 4.03038191606046844562845941 ] self.multiplicities = [2, 1, 1, 1, 1]
def setUp(self): # Ex 1.5.3 from [KB] self.C = Rectangle([-1, 3], [-1, 1]) self.f = lambda z: (z * (z - 2))**2 * (exp(2 * z) * cos(z) + z**3 - 1 - sin(z)) self.df = lambda z: 2 * z * (z - 2)**2 * (exp(2 * z) * cos( z) + z**3 - 1 - sin(z)) + 2 * z**2 * (z - 2) * (exp(2 * z) * cos( z) + z**3 - 1 - sin(z)) + (z * (z - 2))**2 * (2 * exp( 2 * z) * cos(z) - exp(2 * z) * sin(z) + 3 * z**2 - cos(z)) self.roots = [ 0, 2, 1.66468286974551654134568653, -0.4607141197289707542294459477 - 0.6254277693477682516688207854j, -0.4607141197289707542294459477 + 0.6254277693477682516688207854j ] self.multiplicities = [3, 2, 1, 1, 1]
from numpy import pi from cxroots import Circle, Annulus, AnnulusSector, Rectangle # make the contours for the tutorial Circle(0, 2).show('circle.png') Rectangle([-2,2],[-1,1]).show('rectangle.png') Annulus(0, [1,2]).show('annulus.png') AnnulusSector(0, [1,2], [0,pi]).show('annulussefig.png')
id='cluster_10^-3'), pytest.param([3, 3.0001, 3.0002, 8, 8.0002, 8 + 0.0001j], [1, 1, 1, 1, 1, 1], id='cluster_10^-4', marks=pytest.mark.slow), pytest.param([3, 3.00001, 3.00002, 8, 8.00002, 8 + 0.00001j], [1, 1, 1, 1, 1, 1], id='cluster_10^-5', marks=[ pytest.mark.slow, pytest.mark.xfail(reason='Cluster of roots too tight') ]) ] contours = [ pytest.param(Rectangle([2, 9], [-1, 1]), id='rect'), pytest.param(Circle(0, 8.5), id='circle') ] @pytest.mark.parametrize('C', contours) @pytest.mark.parametrize('roots,multiplicities', funcs) def test_rootfinding_df(C, roots, multiplicities): f = lambda z: np.prod([z - r for r in roots], axis=0) df = lambda z: np.sum([ np.prod([z - r for r in np.delete(roots, i)], axis=0) for i in range(len(roots)) ], axis=0) roots_approx_equal(C.roots(f, df, verbose=True), (roots, multiplicities))
import pytest import numpy as np from scipy import cos, sin from cxroots import Circle, Rectangle from cxroots import CxDerivative @pytest.mark.parametrize('C', [ pytest.param(Circle(0, 2), id='circle'), pytest.param(Rectangle([-1.5, 1.5], [-2, 2]), id='rect'), pytest.param(None, id='default') ]) def test_CxDerivative(C): f = lambda z: z**10 - 2 * z**5 + sin(z) * cos(z / 2) df = lambda z: 10 * (z**9 - z**4) + cos(z) * cos(z / 2) - 0.5 * sin( z) * sin(z / 2) z = np.array([-1.234, 0.3 + 1j, 0.1j, -0.9 - 0.5j]) assert CxDerivative(f, z, n=1, contour=C) == pytest.approx(df(z))
from cxroots import Rectangle rect = Rectangle(xRange=(-2, 2), yRange=(-1, 1)) rect.show()
class TestRootfindingContours(unittest.TestCase): def setUp(self): self.roots = roots = [0, -1.234, 1 + 1j, 1 - 1j, 2.345] self.multiplicities = [1, 1, 1, 1, 1] self.f = lambda z: (z - roots[0]) * (z - roots[1]) * (z - roots[2]) * ( z - roots[3]) * (z - roots[4]) self.df = lambda z: (z - roots[1]) * (z - roots[2]) * (z - roots[ 3]) * (z - roots[4]) + (z - roots[0]) * (z - roots[2]) * ( z - roots[3]) * (z - roots[4]) + (z - roots[0]) * (z - roots[ 1]) * (z - roots[3]) * (z - roots[4]) + (z - roots[0]) * ( z - roots[1]) * (z - roots[2]) * (z - roots[4]) + ( z - roots[0]) * (z - roots[1]) * (z - roots[2]) * ( z - roots[3]) self.Circle = Circle(0, 3) self.Rectangle = Rectangle([-2, 2], [-2, 2]) self.halfAnnulus = AnnulusSector(0, [0.5, 3], [-pi / 2, pi / 2]) self.Annulus = Annulus(0, [1, 2]) def test_rootfinding_circle_fdf(self): roots_approx_equal(self.Circle.roots(self.f, self.df, verbose=True), (self.roots, self.multiplicities), decimal=7) def test_rootfinding_circle_f(self): roots_approx_equal(self.Circle.roots(self.f, self.df, verbose=True), (self.roots, self.multiplicities), decimal=7) def test_rootfinding_rectangle_fdf(self): roots_approx_equal(self.Rectangle.roots(self.f, self.df, verbose=True), (self.roots[:-1], self.multiplicities[:-1]), decimal=7) def test_rootfinding_rectangle_f(self): roots_approx_equal(self.Rectangle.roots(self.f, self.df, verbose=True), (self.roots[:-1], self.multiplicities[:-1]), decimal=7) def test_rootfinding_halfAnnulus_fdf(self): roots_approx_equal(self.halfAnnulus.roots(self.f, self.df, verbose=True), (self.roots[2:], self.multiplicities[2:]), decimal=7) def test_rootfinding_halfAnnulus_f(self): roots_approx_equal(self.halfAnnulus.roots(self.f, self.df, verbose=True), (self.roots[2:], self.multiplicities[2:]), decimal=7) def test_rootfinding_Annulus_fdf(self): roots_approx_equal(self.Annulus.roots(self.f, self.df, verbose=True), (self.roots[1:-1], self.multiplicities[1:-1]), decimal=7) def test_rootfinding_Annulus_f(self): roots_approx_equal(self.Annulus.roots(self.f, self.df, verbose=True), (self.roots[1:-1], self.multiplicities[1:-1]), decimal=7)
def test_rect_contains(): C = Rectangle([-2355, -1860], [-8810, -8616]) assert C.contains(-2258 - 8694j) assert not C.contains(-2258 - 8500j)
from cxroots import Rectangle rect = Rectangle([0,2], [0,1]) rect.show()
from numpy import exp from cxroots import Rectangle A = -0.19435 B = 1000.41 C = 522463 T = 0.005 f = lambda z: z**2 + A * z + B * exp(-T * z) + C df = lambda z: 2 * z + A - B * T * exp(-T * z) rectangle = Rectangle([-15000, 5000], [-15000, 15000]) roots = rectangle.roots(f, df, rootErrTol=1e-6) roots.show()
from cxroots import Rectangle C = Rectangle([-1.5, 1.5], [-1.5, 1.5]) f = lambda z: z**26 - 2 * z**10 + 0.5 * z**6 - 1 df = lambda z: 26 * z**25 - 20 * z**9 + 3 * z**5 C.demo_roots(f, df, guessRootSymmetry=lambda z: [z.conjugate(), -z], saveFile='ex_rootSymmetry.gif', writer='imagemagick')