def element_equals(self): """Verify `LinearSpaceElement.__eq__`.""" try: zero = self.space.zero() except NotImplementedError: print('*** SPACE HAS NO ZERO VECTOR ***') return try: zero == zero except NotImplementedError: self.log('Vector has no __eq__') return with fail_counter( test_name='Verify behavior of `element1 == element2`', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): if n_x == n_y: if not x == y: counter.fail('failed x == x with x={:25s}' ''.format(n_x)) if x != y: counter.fail('failed not x != x with x={:25s}' ''.format(n_x)) else: if x == y: counter.fail('failed not x == y with x={:25s}, ' 'x={:25s}'.format(n_x, n_y)) if not x != y: counter.fail('failed x != y with x={:25s}, x={:25s}' ''.format(n_x, n_y))
def equals(self): """Verify `LinearSpace.__eq__`.""" self.log('\n== Verifying __eq__ ==\n') if not self.space == self.space: print('** space == space failed ***') if self.space != self.space: print('** not space != space failed***') if self.space != copy(self.space): print('** space == copy(space) failed***') if self.space != deepcopy(self.space): print('** space == deepcopy(space) failed***') with fail_counter( test_name='Verify behavior of `space == obj` when `obj` ' 'is not a space', logger=self.log) as counter: for obj in [[1, 2], list(), tuple(), dict(), 5.0]: if self.space == obj: counter.fail('space == obj, with obj={}' ''.format(obj)) if not self.space != obj: counter.fail('not space != obj, with obj={}' ''.format(obj))
def _adjoint_of_adjoint(self): """Verify ``(A^*)^* == A``""" try: self.operator.adjoint.adjoint except AttributeError: print('A^* has no adjoint') return if self.operator.adjoint.adjoint is self.operator: self.log('(A^*)^* == A') return with fail_counter(test_name='\nVerifying the identity Ax = (A^*)^* x', err_msg='error = ||Ax - (A^*)^* x|| / ||A|| ||x||', logger=self.log) as counter: for [name_x, x] in self.operator.domain.examples: opx = self.operator(x) op_adj_adj_x = self.operator.adjoint.adjoint(x) denom = self.operator_norm * x.norm() if denom == 0: error = 0 else: error = (opx - op_adj_adj_x).norm() / denom if error > self.tol: counter.fail('x={:25s} : error={:6.5f}' ''.format(name_x, error))
def self_adjoint(self): """Verify ``<Ax, y> == <x, Ay>``.""" left_inner_vals = [] right_inner_vals = [] with fail_counter( test_name='Verifying the identity <Ax, y> = <x, Ay>', err_msg='error = |<Ax, y> - <x, Ay>| / ||A|| ||x|| ||y||', logger=self.log) as counter: for [name_x, x], [name_y, y] in samples(self.operator.domain, self.operator.range): x_norm = x.norm() y_norm = y.norm() l_inner = self.operator(x).inner(y) r_inner = x.inner(self.operator(y)) denom = self.operator_norm * x_norm * y_norm error = 0 if denom == 0 else abs(l_inner - r_inner) / denom if error > self.tol: counter.fail('x={:25s} y={:25s} : error={:6.5f}' ''.format(name_x, name_y, error)) left_inner_vals.append(l_inner) right_inner_vals.append(r_inner) scale = np.polyfit(left_inner_vals, right_inner_vals, 1)[0] self.log('\nThe adjoint seems to be scaled according to:') self.log('(x, Ay) / (Ax, y) = {}. Should be 1.0'.format(scale))
def element_space(self): """Verify `LinearSpaceElement.space`.""" with fail_counter(test_name='Verify `LinearSpaceElement.space`', logger=self.log) as counter: for [n_x, x] in samples(self.space): if x.space != self.space: counter.fail('failed with x={:25s}'.format(n_x))
def _commutativity_of_addition(self): """Verify addition commutativity.""" with fail_counter(test_name='Verifying commutativity of addition', err_msg='error = dist(x + y, y + x)', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): correct = _approx_equal(x + y, y + x, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s}' ''.format(n_x, n_y))
def _identity_of_mult(self): """Verify multiplicative neutral element ('one').""" with fail_counter( test_name='Verifying identity element of multiplication', err_msg='error = dist(1 * x, x)', logger=self.log) as counter: for [n_x, x] in samples(self.space): correct = _approx_equal(1 * x, x, self.tol) if not correct: counter.fail('failed with x={:25s}'.format(n_x))
def element_method(self): """Verify `LinearSpace.element`.""" with fail_counter(test_name='Verifying element method', logger=self.log) as counter: try: elem = self.space.element() except NotImplementedError: counter.fail('*** element failed ***') return if elem not in self.space: counter.fail('*** space.element() not in space ***')
def _inner_conjugate_symmetry(self): """Verify conjugate symmetry of the inner product.""" with fail_counter( test_name='Verifying conjugate symmetry of the inner product', err_msg='error = |<x, y> - <y, x>.conj()|', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): error = abs((x).inner(y) - y.inner(x).conjugate()) if error > self.tol: counter.fail('x={:25s}, y={:25s}: error={}' ''.format(n_x, n_y, error))
def element_assign(self): """Verify `LinearSpaceElement.assign`.""" with fail_counter( test_name='Verify behavior of `LinearSpaceElement.assign`', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): x.assign(y) correct = _approx_equal(x, y, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s}' ''.format(n_x, n_y))
def _division(self): """Verify scalar division as multiplication with mult. inverse.""" with fail_counter(test_name='Verifying scalar division', err_msg='error = dist(x / a, x * (1/a))', logger=self.log) as counter: for [n_x, x], [_, a] in samples(self.space, self.space.field): if a != 0: correct = _approx_equal(x / a, x * (1.0 / a), self.tol) if not correct: counter.fail('failed with x={:25s}, a={}' ''.format(n_x, a))
def _subtraction(self): """Verify element subtraction as addition of additive inverse.""" with fail_counter(test_name='Verifying element subtraction', err_msg='error = dist(x - y, x + (-1 * y))', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): correct = (_approx_equal(x - y, x + (-1 * y), self.tol) and _approx_equal(x - y, x + (-y), self.tol)) if not correct: counter.fail('failed with x={:25s}, y={:25s}' ''.format(n_x, n_y))
def _norm_homogeneity(self): """Verify positive homogeneity of the norm.""" with fail_counter( test_name='Verifying positive homogeneity of the norm', err_msg='error = | ||a*x|| - |a|*||x|| |', logger=self.log) as counter: for [n_x, x], [_, a] in samples(self.space, self.space.field): error = abs((a * x).norm() - abs(a) * x.norm()) if error > self.tol: counter.fail('x={:25s} a={}: error={}' ''.format(n_x, a, error))
def _associativity_of_addition(self): """Verify addition associativity.""" with fail_counter(test_name='Verifying associativity of addition', err_msg='error = dist(x + (y + z), (x + y) + z)', logger=self.log) as counter: for [n_x, x], [n_y, y], [n_z, z] in samples(self.space, self.space, self.space): correct = _approx_equal(x + (y + z), (x + y) + z, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s} z={:25s}' ''.format(n_x, n_y, n_z))
def _multiply_commutative(self): """Verify commutativity of vector multiplication.""" with fail_counter( test_name='Verifying commutativity of vector multiplication', err_msg='error = dist(x * y, y * x)', logger=self.log) as counter: for [n_x, x], [n_y, y], _ in samples(self.space, self.space, self.space): correct = _approx_equal(x * y, y * x, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s}' ''.format(n_x, n_y))
def _dist_symmetric(self): """Verify symmetry of the distance.""" with fail_counter(test_name='Verifying symmetry of the distance', err_msg='error = |d(x, y) - d(y, x)|', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): dist_1 = x.dist(y) dist_2 = y.dist(x) error = abs(dist_1 - dist_2) if error > self.tol: counter.fail('x={:25s}, y={:25s}: error={}' ''.format(n_x, n_y, error))
def _commutativity_of_scalar_mult(self): """Verify scalar multiplication commutativity.""" with fail_counter( test_name='Verifying commutativity of scalar multiplication', err_msg='error = dist(a * (b * x), (a * b) * x)', logger=self.log) as counter: for [n_x, x], [_, a], [_, b] in samples(self.space, self.space.field, self.space.field): correct = _approx_equal(a * (b * x), (a * b) * x, self.tol) if not correct: counter.fail('failed with x={:25s}, a={}, b={}' ''.format(n_x, a, b))
def _inner_linear_scalar(self): """Verify homogeneity of the inner product in the first argument.""" with fail_counter( test_name='Verifying homogeneity of the inner product in the ' 'first argument', err_msg='error = |<a*x, y> - a*<x, y>|', logger=self.log) as counter: for [n_x, x], [n_y, y], [_, a] in samples(self.space, self.space, self.space.field): error = abs((a * x).inner(y) - a * x.inner(y)) if error > self.tol: counter.fail('x={:25s}, y={:25s}, a={}: error={}' ''.format(n_x, n_y, a, error))
def _multiply_distributive_scalar(self): """Verify distributivity of scalar multiplication.""" with fail_counter( test_name='Verifying distributivity of vector multiplication ' 'under scalar multiplication', err_msg='error = dist(a * (x + y), a * x + a * y)', logger=self.log) as counter: for [n_x, x], [n_y, y], [_, a] in samples(self.space, self.space, self.space.field): correct = _approx_equal(a * (x + y), a * x + a * y, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s} a={}' ''.format(n_x, n_y, a))
def _multiply_associative(self): """Verify associativity of vector multiplication.""" with fail_counter( test_name='Verifying associativity of vector multiplication', err_msg='error = dist(x * (y * z), (x * y) * z)', logger=self.log) as counter: for [n_x, x], [n_y, y], [n_z, z] in samples(self.space, self.space, self.space): correct = _approx_equal(x * (y * z), (x * y) * z, self.tol) if not correct: counter.fail('failed with x={:25s} y={:25s} z={:25s}' ''.format(n_x, n_y, n_z))
def field(self): """Verify `LinearSpace.field`.""" with fail_counter(test_name='Verifying field property', logger=self.log) as counter: try: field = self.space.field except NotImplementedError: counter.fail('*** field failed ***') return if not isinstance(field, Field): counter.fail('*** space.field not a `Field` ***') return try: zero = field.element(0) except NotImplementedError: counter.fail('*** field.element(0) failed ***') zero = None if zero is not None and zero != 0: counter.fail('*** field.element(0) != 0 ***') if zero is not None and zero != 0.0: counter.fail('*** field.element(0) != 0.0 ***') try: one = field.element(1) except NotImplementedError: counter.fail('*** field.element(1) failed ***') one = None if one is not None and one != 1: counter.fail('*** field.element(1) != 1 ***') if one is not None and one != 1.0: counter.fail('*** field.element(1) != 1.0 ***') try: minus_one = field.element(-1) except NotImplementedError: counter.fail('field.element(-1) failed') minus_one = None if minus_one is not None and minus_one != -1: counter.fail('field.element(-1) != -1') if minus_one is not None and minus_one != -1.0: counter.fail('field.element(-1) != -1.0')
def _distributivity_of_mult_scalar(self): """Verify scalar multiplication distributivity wrt scalar addition.""" with fail_counter( test_name='Verifying distributivity of scalar multiplication ' 'under scalar addition', err_msg='error = dist((a + b) * x, a * x + b * x)', logger=self.log) as counter: for [n_x, x], [_, a], [_, b] in samples(self.space, self.space.field, self.space.field): correct = _approx_equal((a + b) * x, a * x + b * x, self.tol) if not correct: counter.fail('failed with x={:25s}, a={}, b={}' ''.format(n_x, a, b))
def _inner_linear_sum(self): """Verify distributivity of the inner product in the first argument.""" with fail_counter( test_name='Verifying distributivity of the inner product' 'in the first argument', err_msg='error = |<x+y, z> - (<x, z> + <y, z>)|', logger=self.log) as counter: for [n_x, x], [n_y, y], [n_z, z] in samples(self.space, self.space, self.space): error = abs((x + y).inner(z) - (x.inner(z) + y.inner(z))) if error > self.tol: counter.fail('x={:25s}, y={:25s}, z={:25s}: error={}' ''.format(n_x, n_y, n_z, error))
def _dist_positivity(self): """Verify nonnegativity of the distance.""" with fail_counter(test_name='Verifying nonnegativity of the distance', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): dist = x.dist(y) if n_x == n_y and dist != 0: counter.fail('d(x, x) != 0.0, x={:25s}: dist={}' ''.format(n_x, dist)) elif n_x != n_y and dist <= 0: counter.fail('d(x, y) <= 0, x={:25s} y={:25s}: dist={}' ''.format(n_x, n_y, dist))
def _inverse_element_of_addition(self): """Verify additive inverse.""" try: zero = self.space.zero() except (AttributeError, NotImplementedError): print('*** SPACE HAS NO ZERO VECTOR ***') return with fail_counter(test_name='Verifying inverse element of addition', err_msg='error = dist(x + (-x), 0)', logger=self.log) as counter: for [n_x, x] in samples(self.space): correct = _approx_equal(x + (-x), zero, self.tol) if not correct: counter.fail('failed with x={:25s}'.format(n_x))
def _norm_positive(self): """Verify positive definiteness of the norm.""" with fail_counter( test_name='Verifying positive definiteness of the norm', logger=self.log) as counter: for [n_x, x] in samples(self.space): norm = x.norm() if n_x == 'Zero' and norm != 0: counter.fail('||0|| != 0.0, x={:25s}: ||x||={}' ''.format(n_x, norm)) elif n_x != 'Zero' and norm <= 0: counter.fail('||x|| <= 0, x={:25s}: ||x||={}' ''.format(n_x, norm))
def _norm_subadditive(self): """Verify subadditivity of the norm.""" with fail_counter(test_name='Verifying sub-additivity of the norm', err_msg='error = max(||x+y|| - (||x|| + ||y||), 0)', logger=self.log) as counter: for [n_x, x], [n_y, y] in samples(self.space, self.space): norm_x = x.norm() norm_y = y.norm() norm_xy = (x + y).norm() error = norm_xy - norm_x - norm_y if error > 0: counter.fail('x={:25s} y={:25s}: error={}' ''.format(n_x, n_y, error))
def element_set_zero(self): """Verify `LinearSpaceElement.set_zero`.""" try: zero = self.space.zero() except NotImplementedError: print('*** SPACE HAS NO ZERO VECTOR ***') return with fail_counter( test_name='Verify behavior of `LinearSpaceElement.set_zero`', logger=self.log) as counter: for [n_x, x] in samples(self.space): x.set_zero() correct = _approx_equal(x, zero, self.tol) if not correct: counter.fail('failed with x={:25s}' ''.format(n_x))
def _multiply_zero(self): """Verify that vector multiplication with zero is zero.""" try: zero = self.space.zero() except NotImplementedError: print('*** SPACE HAS NO ZERO VECTOR ***') return with fail_counter( test_name='Verifying vector multiplication with zero', err_msg='error = ||x * 0||', logger=self.log) as counter: for [n_x, x] in samples(self.space): error = (zero * x).norm() if error > self.tol: counter.fail('x={:25s},: error={}' ''.format(n_x, error))
def _scale_invariance(self): """Verify ``A(c*x) = c * A(x)``.""" with fail_counter( test_name='Verifying homogeneity under scalar multiplication', err_msg='error = ||A(c*x)-c*A(x)|| / |c| ||A|| ||x||', logger=self.log) as counter: for [name_x, x], [_, scale] in samples(self.operator.domain, self.operator.domain.field): opx = self.operator(x) scaled_opx = self.operator(scale * x) denom = self.operator_norm * scale * x.norm() error = (0 if denom == 0 else (scaled_opx - opx * scale).norm() / denom) if error > self.tol: counter.fail('x={:25s} scale={:7.2f} error={:6.5f}' ''.format(name_x, scale, error))