def test_brentsroot(): for fmt in D.available_float_fmt(): print("Set dtype to:", fmt) D.set_float_fmt(fmt) for _ in range(10): ac_prod = D.array(np.random.uniform(0.9, 1.1)) a = D.array(np.random.uniform(-1, 1)) a = D.to_float(-1 * (a <= 0) + 1 * (a > 0)) c = ac_prod / a b = D.sqrt(0.01 + 4 * ac_prod) gt_root = -b / (2 * a) - 0.1 / (2 * a) ub = -b / (2 * a) lb = -b / (2 * a) - 1.0 / (2 * a) fun = lambda x: a * x**2 + b * x + c assert (D.to_numpy(D.to_float(D.abs(fun(gt_root)))) <= 32 * D.epsilon()) root, success = de.utilities.optimizer.brentsroot(fun, [lb, ub], 4 * D.epsilon(), verbose=True) assert (success) assert (np.allclose(D.to_numpy(D.to_float(gt_root)), D.to_numpy(D.to_float(root)), 32 * D.epsilon(), 32 * D.epsilon())) assert (D.to_numpy(D.to_float(D.abs(fun(root)))) <= 32 * D.epsilon())
def test_integration_and_nearestfloat_no_dense_output(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0],[-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, k, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.stack([ c2 * D.sin(D.to_float(D.asarray(t))) + c1 * D.cos(D.to_float(D.asarray(t))) + D.asarray(t), c2 * D.cos(D.to_float(D.asarray(t))) - c1 * D.sin(D.to_float(D.asarray(t))) + 1 ]) y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=False, t=(0, 2*D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5, constants=dict(k=1.0)) assert(a.integration_status() == "Integration has not been run.") a.integrate() assert(a.integration_status() == "Integration completed successfully.") assert(D.abs(a.t[-2] - a[2*D.pi].t) <= D.abs(a.dt))
def test_non_callable_rhs(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0],[-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, k, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.stack([ c2 * D.sin(D.to_float(D.asarray(t))) + c1 * D.cos(D.to_float(D.asarray(t))) + D.asarray(t), c2 * D.cos(D.to_float(D.asarray(t))) - c1 * D.sin(D.to_float(D.asarray(t))) + 1 ]) y_init = D.array([1., 0.]) a = de.OdeSystem(de_mat, y0=y_init, dense_output=False, t=(0, 2*D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5, constants=dict(k=1.0)) a.tf = 0.0
class PyAudiTestCase: @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_double' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_double(self): D.set_float_fmt('gdual_double') x1 = D.gdual_double(-0.5, 'x', 5) x2 = D.gdual_double(0.5, 'y', 5) self.do(x1, x2) @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_vdouble' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_vdouble(self): D.set_float_fmt('gdual_vdouble') x1 = D.gdual_vdouble([-0.5, -0.5], 'x', 5) x2 = D.gdual_vdouble([0.5, 0.5], 'y', 5) self.do(x1, x2)
def test_integration_and_representation(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0], [-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, k, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.stack([ c2 * D.sin(D.to_float(D.asarray(t))) + c1 * D.cos(D.to_float(D.asarray(t))) + D.asarray(t), c2 * D.cos(D.to_float(D.asarray(t))) - c1 * D.sin(D.to_float(D.asarray(t))) + 1 ]) def kbinterrupt_cb(ode_sys): if ode_sys[-1][0] > D.pi: raise KeyboardInterrupt("Test Interruption and Catching") y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, 2 * D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5, constants=dict(k=1.0)) a.integrate() try: print(str(a)) print(repr(a)) assert (D.max(D.abs(a.sol(a.t[0]) - y_init)) <= 8 * D.epsilon()**0.5) assert (D.max( D.abs(a.sol(a.t[-1]) - analytic_soln(a.t[-1], y_init))) <= 8 * D.epsilon()**0.5) assert (D.max(D.abs(a.sol(a.t).T - analytic_soln(a.t, y_init))) <= 8 * D.epsilon()**0.5) except: raise
class PyAudiMatrixTestCase: @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_double' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_double_matrix(self): D.set_float_fmt('gdual_double') A = D.array([ [D.gdual_double(-1.0, 'a11', 5), D.gdual_double(3 / 2, 'a12', 5)], [D.gdual_double(1.0, 'a21', 5), D.gdual_double(-1.0, 'a22', 5)], ]) self.do(A) @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_double' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_double_matrix_big(self): D.set_float_fmt('gdual_double') np.random.seed(23) A1 = self.generate_random_nondegenerate_matrix(4) A = [] for idx in range(A1.shape[0]): A.append([]) for jdx in range(A1.shape[1]): A[idx].append( D.gdual_double(A1[idx, jdx], 'a{}{}'.format(idx + 1, jdx + 1), 1)) A = D.array(A) self.do(A) def generate_random_nondegenerate_matrix(self, size): A = np.random.normal(size=(size, size)) while np.abs(np.linalg.det(D.to_float(A))) <= 1e-5: A = np.random.normal(size=(size, size), std=250.0) return A def do(self, A): pass
def test_event_detection(): for ffmt in D.available_float_fmt(): if ffmt == 'float16': continue D.set_float_fmt(ffmt) print("Testing event detection for float format {}".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0],[-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.array([ c2 * D.sin(t) + c1 * D.cos(t) + t, c2 * D.cos(t) - c1 * D.sin(t) + 1 ]) y_init = D.array([1., 0.]) def time_event(t, y, **kwargs): return t - D.pi/8 time_event.is_terminal = True time_event.direction = 0 a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, D.pi/4), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) with de.utilities.BlockTimer(section_label="Integrator Tests") as sttimer: for i in sorted(set(de.available_methods(False).values()), key=lambda x:x.__name__): try: a.set_method(i) print("Testing {}".format(a.integrator)) a.integrate(eta=True, events=time_event) if D.abs(a.t[-1] - D.pi/8) > 10*D.epsilon(): print("Event detection with integrator {} failed with t[-1] = {}".format(a.integrator, a.t[-1])) raise RuntimeError("Failed to detect event for integrator {}".format(str(i))) else: print("Event detection with integrator {} succeeded with t[-1] = {}".format(a.integrator, a.t[-1])) a.reset() except Exception as e: raise e raise RuntimeError("Test failed for integration method: {}".format(a.integrator)) print("") print("{} backend test passed successfully!".format(D.backend()))
def test_integration_and_representation(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0],[-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, k, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.stack([ c2 * D.sin(D.to_float(D.asarray(t))) + c1 * D.cos(D.to_float(D.asarray(t))) + D.asarray(t), c2 * D.cos(D.to_float(D.asarray(t))) - c1 * D.sin(D.to_float(D.asarray(t))) + 1 ]) y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, 2*D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5, constants=dict(k=1.0)) assert(a.integration_status() == "Integration has not been run.") a.integrate() assert(a.integration_status() == "Integration completed successfully.") try: print(str(a)) print(repr(a)) assert(D.max(D.abs(a.sol(a.t[0]) - y_init)) <= 8*D.epsilon()**0.5) assert(D.max(D.abs(a.sol(a.t[-1]) - analytic_soln(a.t[-1], y_init))) <= 8*D.epsilon()**0.5) assert(D.max(D.abs(a.sol(a.t).T - analytic_soln(a.t, y_init))) <= 8*D.epsilon()**0.5) except: raise for i in a: assert(D.max(D.abs(i.y - analytic_soln(i.t, y_init))) <= 8*D.epsilon()**0.5) assert(len(a.y) == len(a)) assert(len(a.t) == len(a))
def test_brentsrootvec(): for fmt in D.available_float_fmt(): print("Set dtype to:", fmt) D.set_float_fmt(fmt) if fmt == 'gdual_vdouble': continue for _ in range(10): slope_list = D.array( np.copysign(np.random.uniform(0.9, 1.1, size=25), np.random.uniform(-1, 1, size=25))) intercept_list = slope_list gt_root_list = -intercept_list / slope_list fun_list = [(lambda m, b: lambda x: m * x + b)(m, b) for m, b in zip(slope_list, intercept_list)] assert (all( map((lambda i: D.to_numpy(D.to_float(D.abs(i))) <= 32 * D. epsilon()), map((lambda x: x[0](x[1])), zip(fun_list, gt_root_list))))) root_list, success = de.utilities.optimizer.brentsrootvec( fun_list, [D.min(gt_root_list) - 1., D.max(gt_root_list) + 1.], 4 * D.epsilon(), verbose=True) assert (np.all(D.to_numpy(success))) assert (np.allclose(D.to_numpy(D.to_float(gt_root_list)), D.to_numpy(D.to_float(root_list)), 32 * D.epsilon(), 32 * D.epsilon())) assert (all( map((lambda i: D.to_numpy(D.to_float(D.abs(i))) <= 32 * D. epsilon()), map((lambda x: x[0](x[1])), zip(fun_list, root_list)))))
def test_getter_setters(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0],[-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.array([ c2 * D.sin(t) + c1 * D.cos(t) + t, c2 * D.cos(t) - c1 * D.sin(t) + 1 ]) def kbinterrupt_cb(ode_sys): if ode_sys[-1][0] > D.pi: raise KeyboardInterrupt("Test Interruption and Catching") y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, 2*D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) assert(a.t0 == 0) assert(a.tf == 2 * D.pi) assert(a.dt == 0.01) assert(a.get_current_time() == a.t0) assert(a.rtol == D.epsilon()**0.5) assert(a.atol == D.epsilon()**0.5) assert(D.norm(a.y[0] - y_init) <= 2 * D.epsilon()) assert(D.norm(a.y[-1] - y_init) <= 2 * D.epsilon()) a.set_kick_vars([True, False]) assert(a.staggered_mask == [True, False]) pval = 3 * D.pi a.tf = pval assert(a.tf == pval) pval = -1.0 a.t0 = pval assert(a.t0 == pval) assert(a.dt == 0.01) a.rtol = 1e-3 assert(a.rtol == 1e-3) a.atol = 1e-3 assert(a.atol == 1e-3) for method in de.available_methods(): a.set_method(method) assert(isinstance(a.integrator, de.available_methods(False)[method])) for method in de.available_methods(): a.method = method assert(isinstance(a.integrator, de.available_methods(False)[method])) a.constants['k'] = 5.0 assert(a.constants['k'] == 5.0) a.constants.pop('k') assert('k' not in a.constants.keys()) new_constants = dict(k=10.0) a.constants = new_constants assert(a.constants['k'] == 10.0) del a.constants assert(not bool(a.constants))
def test_float_formats(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0], [-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.array([ c2 * D.sin(t) + c1 * D.cos(t) + t, c2 * D.cos(t) - c1 * D.sin(t) + 1 ]) def kbinterrupt_cb(ode_sys): if ode_sys[-1][0] > D.pi: raise KeyboardInterrupt("Test Interruption and Catching") y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, 2 * D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) with de.utilities.BlockTimer( section_label="Integrator Tests") as sttimer: for i in sorted(set(de.available_methods(False).values()), key=lambda x: x.__name__): if "Heun-Euler" in i.__name__ and D.float_fmt( ) == "gdual_real128": print( "skipping {} due to ridiculous timestep requirements.". format(i)) continue try: a.set_method(i) print("Testing {}".format(a.integrator)) try: a.integrate(callback=kbinterrupt_cb, eta=True) except KeyboardInterrupt as e: pass try: a.integrate(eta=True) except: raise max_diff = D.max( D.abs(analytic_soln(a.t[-1], a.y[0]) - a.y[-1])) if a.method.__adaptive__ and max_diff >= a.atol * 10 + D.epsilon( ): print( "{} Failed with max_diff from analytical solution = {}" .format(a.integrator, max_diff)) raise RuntimeError( "Failed to meet tolerances for adaptive integrator {}" .format(str(i))) else: print( "{} Succeeded with max_diff from analytical solution = {}" .format(a.integrator, max_diff)) a.reset() except Exception as e: print(e) raise RuntimeError( "Test failed for integration method: {}".format( a.integrator)) print("") print("{} backend test passed successfully!".format(D.backend()))
def test_backend(): try: import desolver as de import desolver.backend as D import numpy as np import scipy if "DES_BACKEND" in os.environ: assert(D.backend() == os.environ['DES_BACKEND']) if D.backend() not in ['torch']: # Default datatype test for i in D.available_float_fmt(): D.set_float_fmt(i) assert(D.array(1.0).dtype == D.float_fmts[D.float_fmt()]) expected_eps = {'float16': 5e-3, 'float32': 5e-7, 'float64': 5e-16, 'gdual_double': 5e-16, 'gdual_vdouble': 5e-16, 'gdual_real128': 5e-16} test_array = np.array([1], dtype=np.int64) # Test Function Evals for i in D.available_float_fmt(): D.set_float_fmt(i) assert(D.float_fmt() == str(i)) assert(D.epsilon() == expected_eps[str(i)]) assert(isinstance(D.available_float_fmt(), list)) if not i.startswith('gdual'): assert(D.cast_to_float_fmt(test_array).dtype == str(i)) arr1 = D.array([[2.0, 1.0],[1.0, 0.0]]) arr2 = D.array([[1.0, 1.0],[-1.0, 1.0]]) if not i.startswith('gdual'): arr3 = D.contract_first_ndims(arr1, arr2, 1) arr4 = D.contract_first_ndims(arr1, arr2, 2) true_arr3 = D.array([1.0, 1.0]) true_arr4 = D.array(2.) assert(D.norm(arr3 - true_arr3) <= 2 * D.epsilon()) assert(D.norm(arr4 - true_arr4) <= 2 * D.epsilon()) de.utilities.warning("Testing float format {}".format(D.float_fmt())) pi = D.to_float(D.pi) assert(np.pi - 2*D.epsilon() <= pi <= np.pi + 2*D.epsilon()) assert(np.e - 2*D.epsilon() <= D.to_float(D.e) <= np.e + 2*D.epsilon()) assert(np.euler_gamma - 2*D.epsilon() <= D.to_float(D.euler_gamma) <= np.euler_gamma + 2*D.epsilon()) assert(-2*D.epsilon() <= D.sin(pi) <= 2*D.epsilon()) assert(-2*D.epsilon() <= D.cos(pi)+1 <= 2*D.epsilon()) assert(-2*D.epsilon() <= D.tan(pi) <= 2*D.epsilon()) assert(D.asin(D.to_float(1)) == pi/2) assert(D.acos(D.to_float(1)) == 0) assert(D.atan(D.to_float(1)) == pi/4) assert(D.atan2(D.to_float(1), D.to_float(1)) == pi/4) assert(D.sinh(pi) == np.sinh(pi)) assert(D.cosh(pi) == np.cosh(pi)) assert(D.tanh(pi) == np.tanh(pi)) assert(-3.141592653589793 - 2*D.epsilon() <= D.neg(pi) <= -3.141592653589793 + 2*D.epsilon()) assert(31.00627668029982 - 10*D.epsilon() <= D.pow(pi,3) <= 31.00627668029982 + 10*D.epsilon()) assert(3.141592653589793 - 2*D.epsilon() <= D.abs(pi) <= 3.141592653589793 + 2*D.epsilon()) assert(1.77245385090551603 - 2*D.epsilon() <= D.sqrt(pi) <= 1.77245385090551603 + 2*D.epsilon()) assert(23.1406926327792690 - 10*D.epsilon()<= D.exp(pi) <= 23.1406926327792690 + 10*D.epsilon()) assert(22.1406926327792690 - 10*D.epsilon()<= D.expm1(pi) <= 22.1406926327792690 + 10*D.epsilon()) assert(1.14472988584940017 - 2*D.epsilon() <= D.log(pi) <= 1.14472988584940017 + 2*D.epsilon()) assert(1.14472988584940017 - 2*D.epsilon() <= D.log(pi) <= 1.14472988584940017 + 2*D.epsilon()) assert(0.49714987269413385 - 2*D.epsilon() <= D.log10(pi) <= 0.49714987269413385 + 2*D.epsilon()) assert(1.42108041279429263 - 2*D.epsilon() <= D.log1p(pi) <= 1.42108041279429263 + 2*D.epsilon()) assert(1.65149612947231880 - 2*D.epsilon() <= D.log2(pi) <= 1.65149612947231880 + 2*D.epsilon()) assert(4.14159265358979324 - 2*D.epsilon() <= D.add(pi,1) <= 4.14159265358979324 + 2*D.epsilon()) assert(2.14159265358979324 - 2*D.epsilon() <= D.sub(pi,1) <= 2.14159265358979324 + 2*D.epsilon()) assert(D.div(pi,1) == pi) assert(D.mul(pi,1) == pi) assert(0.31830988618379067 - 2*D.epsilon() <= D.reciprocal(pi) <= 0.31830988618379067 + 2*D.epsilon()) if not i.startswith('gdual'): assert(0.14159265358979324 - 2*D.epsilon() <= D.remainder(pi,3) <= 0.14159265358979324 + 2*D.epsilon()) assert(D.ceil(pi) == 4) assert(D.floor(pi) == 3) assert(D.round(pi) == 3) assert(1.1415926535897931 - 2*D.epsilon() <= D.fmod(pi,2) <= 1.1415926535897931 + 2*D.epsilon()) assert(D.clip(pi,1,2) == 2) assert(D.sign(pi) == 1) assert(D.trunc(pi) == 3) assert(0.9772133079420067 - 2*D.epsilon() <= D.digamma(pi) <= 0.9772133079420067 + 2*D.epsilon()) assert(0.4769362762044699 - 2*D.epsilon() <= D.erfinv(D.to_float(0.5)) <= 0.4769362762044699 + 2*D.epsilon()) assert(1.7891115385869942 - 2*D.epsilon() <= D.mvlgamma(pi, 2) <= 1.7891115385869942 + 2*D.epsilon()) assert(D.frac(pi) == pi - 3) assert(0.9999911238536324 - 2*D.epsilon() <= D.erf(pi) <= 0.9999911238536324 + 2*D.epsilon()) assert(8.8761463676416054e-6 - 2*D.epsilon() <= D.erfc(pi) <= 8.8761463676416054e-6 + 2*D.epsilon()) assert(0.9585761678336372 - 2*D.epsilon() <= D.sigmoid(pi) <= 0.9585761678336372 + 2*D.epsilon()) assert(0.5641895835477563 - 2*D.epsilon() <= D.rsqrt(pi) <= 0.5641895835477563 + 2*D.epsilon()) assert(pi + 0.5 - 2*D.epsilon() <= D.lerp(pi,pi+1,0.5) <= pi + 0.5 + 2*D.epsilon()) assert(D.addcdiv(pi,1,D.to_float(3),D.to_float(2)) == pi + (1 * (3 / 2))) assert(D.addcmul(pi,1,D.to_float(3),D.to_float(2)) == pi + (1 * (3 * 2))) if not i.startswith('gdual'): assert(-2*D.epsilon() <= D.einsum("nm->", D.array([[1.0, 2.0], [-2.0, -1.0]])) <= 2*D.epsilon()) except: print("{} Backend Test Failed".format(D.backend())) raise print("{} Backend Test Succeeded".format(D.backend()))
def test_available_float_fmt_return_type(): assert (isinstance(D.available_float_fmt(), list))
class PyAudiLinearSystemTestCase: @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_double' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_double_solve_linear(self): D.set_float_fmt('gdual_double') A = D.array([ [D.gdual_double(-1.0, 'a11', 5), D.gdual_double(3 / 2, 'a12', 5)], [D.gdual_double(1.0, 'a21', 5), D.gdual_double(-1.0, 'a22', 5)], ]) b = D.array([[D.gdual_double(1.0, 'b1', 5)], [D.gdual_double(1.0, 'b2', 5)]]) self.do(A, b) @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_vdouble' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_vdouble_solve_linear(self): D.set_float_fmt('gdual_vdouble') A = D.array([ [ D.gdual_vdouble([-1.0, 1 / 2], 'a11', 5), D.gdual_vdouble([3 / 2, 3 / 2], 'a12', 5) ], [ D.gdual_vdouble([1.0, 1.0], 'a21', 5), D.gdual_vdouble([-1.0, -1.0], 'a22', 5) ], ]) b = D.array([[D.gdual_vdouble([1.0, -1.0], 'b1', 5)], [D.gdual_vdouble([1.0, 1.0], 'b2', 5)]]) self.do(A, b) @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_double' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_double_solve_linear_big(self): D.set_float_fmt('gdual_double') np.random.seed(22) A1 = self.generate_random_nondegenerate_matrix(60) A = [] b = [] for idx in range(A1.shape[0]): A.append([]) for jdx in range(A1.shape[1]): A[idx].append( D.gdual_double(A1[idx, jdx], 'a{}{}'.format(idx + 1, jdx + 1), 1)) b.append([D.gdual_double(1.0, 'b{}'.format(idx + 1), 1)]) A = D.array(A) b = D.array(b) self.do(A, b) @pytest.mark.skipif(D.backend() != 'numpy' or 'gdual_vdouble' not in D.available_float_fmt(), reason="PyAudi Tests") def test_gdual_vdouble_solve_linear_big(self): D.set_float_fmt('gdual_vdouble') np.random.seed(22) A1 = self.generate_random_nondegenerate_matrix(12) A2 = self.generate_random_nondegenerate_matrix(12) A = [] b = [] for idx in range(A1.shape[0]): A.append([]) for jdx in range(A1.shape[1]): A[idx].append( D.gdual_vdouble([A1[idx, jdx], A2[idx, jdx]], 'a{}{}'.format(idx + 1, jdx + 1), 1)) b.append([D.gdual_vdouble([1.0, -1.0], 'b{}'.format(idx + 1), 1)]) A = D.array(A) b = D.array(b) self.do(A, b) def generate_random_nondegenerate_matrix(self, size): A = np.random.normal(size=(size, size)) while np.abs(np.linalg.det(D.to_float(A))) <= 1e-5: A = np.random.normal(size=(size, size), std=250.0) return A def do(self, A, b): pass
] implicit_integrator_set = [ pytest.param(intg, marks=pytest.mark.implicit) for intg in integrator_set if intg.__implicit__ ] if D.backend() == 'torch': devices_set = [pytest.param('cpu', marks=pytest.mark.cpu)] import torch if torch.cuda.is_available(): devices_set.insert(0, pytest.param('cuda', marks=pytest.mark.gpu)) else: devices_set = [None] dt_set = [D.pi / 307, D.pi / 512] ffmt_set = D.available_float_fmt() ffmt_param = pytest.mark.parametrize('ffmt', ffmt_set) integrator_param = pytest.mark.parametrize('integrator', explicit_integrator_set + implicit_integrator_set) richardson_param = pytest.mark.parametrize('use_richardson_extrapolation', [True, False]) device_param = pytest.mark.parametrize('device', devices_set) dt_param = pytest.mark.parametrize('dt', dt_set) dense_output_param = pytest.mark.parametrize('dense_output', [True, False]) def set_up_basic_system(integrator=None, hook_jacobian=False): de_mat = D.array([[0.0, 1.0], [-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, **kwargs): nonlocal de_mat if D.backend() == 'torch':
def test_gradients(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) import torch torch.set_printoptions(precision=17) torch.set_num_threads(1) torch.autograd.set_detect_anomaly(True) class NNController(torch.nn.Module): def __init__(self, in_dim=2, out_dim=2, inter_dim=50, append_time=False): super().__init__() self.append_time = append_time self.net = torch.nn.Sequential( torch.nn.Linear(in_dim + (1 if append_time else 0), inter_dim), torch.nn.Softplus(), torch.nn.Linear(inter_dim, out_dim), torch.nn.Sigmoid()) for idx, m in enumerate(self.net.modules()): if isinstance(m, torch.nn.Linear): torch.nn.init.xavier_normal_(m.weight, gain=1.0) torch.nn.init.constant_(m.bias, 0.0) def forward(self, t, y, dy): if self.append_time: return self.net( torch.cat([y.view(-1), dy.view(-1), t.view(-1)])) else: return self.net(torch.cat([y, dy])) class SimpleODE(torch.nn.Module): def __init__(self, inter_dim=10, k=1.0): super().__init__() self.nn_controller = NNController(in_dim=4, out_dim=1, inter_dim=inter_dim) self.A = torch.tensor([[0.0, 1.0], [-k, -1.0]], requires_grad=True) def forward(self, t, y, params=None): if not isinstance(t, torch.Tensor): torch_t = torch.tensor(t) else: torch_t = t if not isinstance(y, torch.Tensor): torch_y = torch.tensor(y) else: torch_y = y if params is not None: if not isinstance(params, torch.Tensor): torch_params = torch.tensor(params) else: torch_params = params dy = torch.matmul(self.A, torch_y) controller_effect = self.nn_controller( torch_t, torch_y, dy) if params is None else params return dy + torch.cat( [torch.tensor([0.0]), (controller_effect * 2.0 - 1.0)]) with de.utilities.BlockTimer(section_label="Integrator Tests"): for i in sorted(set(de.available_methods(False).values()), key=lambda x: x.__name__): try: yi1 = D.array([1.0, 0.0], requires_grad=True) df = SimpleODE(k=1.0) a = de.OdeSystem(df, yi1, t=(0, 1.), dt=0.0675, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) a.set_method(i) a.integrate(eta=True) dyfdyi = D.jacobian(a.y[-1], a.y[0]) dyi = D.array([0.0, 1.0]) * D.epsilon()**0.5 dyf = D.einsum("nk,k->n", dyfdyi, dyi) yi2 = yi1 + dyi b = de.OdeSystem(df, yi2, t=(0, 1.), dt=0.0675, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) b.set_method(i) b.integrate(eta=True) true_diff = b.y[-1] - a.y[-1] print(D.norm(true_diff - dyf), D.epsilon()**0.5) assert (D.allclose(true_diff, dyf, rtol=4 * D.epsilon()**0.5, atol=4 * D.epsilon()**0.5)) print("{} method test succeeded!".format(a.integrator)) except: raise RuntimeError( "Test failed for integration method: {}".format( a.integrator)) print("") print("{} backend test passed successfully!".format(D.backend()))
def test_getter_setters(): for ffmt in D.available_float_fmt(): D.set_float_fmt(ffmt) print("Testing {} float format".format(D.float_fmt())) de_mat = D.array([[0.0, 1.0], [-1.0, 0.0]]) @de.rhs_prettifier("""[vx, -x+t]""") def rhs(t, state, **kwargs): return de_mat @ state + D.array([0.0, t]) def analytic_soln(t, initial_conditions): c1 = initial_conditions[0] c2 = initial_conditions[1] - 1 return D.array([ c2 * D.sin(t) + c1 * D.cos(t) + t, c2 * D.cos(t) - c1 * D.sin(t) + 1 ]) def kbinterrupt_cb(ode_sys): if ode_sys[-1][0] > D.pi: raise KeyboardInterrupt("Test Interruption and Catching") y_init = D.array([1., 0.]) a = de.OdeSystem(rhs, y0=y_init, dense_output=True, t=(0, 2 * D.pi), dt=0.01, rtol=D.epsilon()**0.5, atol=D.epsilon()**0.5) assert (a.get_end_time() == 2 * D.pi) assert (a.get_start_time() == 0) assert (a.dt == 0.01) assert (a.rtol == D.epsilon()**0.5) assert (a.atol == D.epsilon()**0.5) assert (D.norm(a.y[0] - y_init) <= 2 * D.epsilon()) assert (D.norm(a.y[-1] - y_init) <= 2 * D.epsilon()) try: a.set_kick_vars([True, False]) except Exception as e: raise RuntimeError("set_kick_vars failed with: {}".format(e)) assert (a.staggered_mask == [True, False]) pval = 3 * D.pi try: a.set_end_time(pval) except Exception as e: raise RuntimeError("set_end_time failed with: {}".format(e)) assert (a.get_end_time() == pval) pval = -1.0 try: a.set_start_time(pval) except Exception as e: raise RuntimeError("set_start_time failed with: {}".format(e)) assert (a.get_start_time() == pval) assert (a.get_step_size() == 0.01) try: a.set_rtol(1e-3) except Exception as e: raise RuntimeError("set_rtol failed with: {}".format(e)) assert (a.get_rtol() == 1e-3) try: a.set_atol(1e-3) except Exception as e: raise RuntimeError("set_atol failed with: {}".format(e)) assert (a.get_atol() == 1e-3) try: a.set_method("RK45CK") except Exception as e: raise RuntimeError("set_method failed with: {}".format(e)) assert (isinstance(a.integrator, de.available_methods(False)["RK45CK"])) try: a.add_constants(k=5.0) except Exception as e: raise RuntimeError("add_constants failed with: {}".format(e)) assert (a.consts['k'] == 5.0) try: a.remove_constants('k') except Exception as e: raise RuntimeError("remove_constants failed with: {}".format(e)) assert ('k' not in a.consts.keys())
def test_bisection_search_vec(): l1 = [0.0, 1.0, 2.0, 3.0, 5.0, 10.0] l2 = [0.2, 1.2, 2.2, 3.2, 5.2, 9.2] expected_l2 = [0, 1, 2, 3, 4, 4] l3 = [0.9, 1.9, 2.9, 3.9, 5.9, 9.9] expected_l3 = [0, 1, 2, 3, 4, 4] l4 = [0.2, 9.9, 2.3, 5.5] expected_l4 = [0, 4, 2, 4] assert (D.all(de.utilities.search_bisection_vec(l1, l2) == D.asarray(expected_l2))) assert (D.all(de.utilities.search_bisection_vec(l1, l3) == D.asarray(expected_l3))) assert (D.all(de.utilities.search_bisection_vec(l1, l4) == D.asarray(expected_l4))) @pytest.mark.parametrize('ffmt', D.available_float_fmt()) def test_jacobian_wrapper_non_callable(ffmt): D.set_float_fmt(ffmt) rhs = 5.0 jac_rhs = de.utilities.JacobianWrapper(rhs) with pytest.raises(TypeError): print(jac_rhs(0.1)) @pytest.mark.parametrize('ffmt', D.available_float_fmt()) def test_jacobian_wrapper_exact(ffmt): D.set_float_fmt(ffmt) rhs = lambda x: D.exp(-x) drhs_exact = lambda x: -D.exp(-x)
import pytest import os import numpy as np import desolver as de import desolver.backend as D @pytest.mark.parametrize('ffmt', list(i for i in D.available_float_fmt() if not i.startswith('gdual'))) def test_contract_first_ndims_case_1(ffmt): arr1 = D.array([[2.0, 1.0], [1.0, 0.0]]) arr2 = D.array([[1.0, 1.0], [-1.0, 1.0]]) arr3 = D.contract_first_ndims(arr1, arr2, 1) true_arr3 = D.array([1.0, 1.0]) assert (D.norm(arr3 - true_arr3) <= 2 * D.epsilon()) @pytest.mark.parametrize('ffmt', list(i for i in D.available_float_fmt() if not i.startswith('gdual'))) def test_contract_first_ndims_case_2(ffmt): arr1 = D.array([[2.0, 1.0], [1.0, 0.0]]) arr2 = D.array([[1.0, 1.0], [-1.0, 1.0]]) arr4 = D.contract_first_ndims(arr1, arr2, 2) true_arr4 = D.array(2.)