def adjointness_error(op, its=100): """Check adjointness of op.A and op.As for 'its' instances of random data. For random unit-normed x and y, this finds the error in the adjoint identity <Ax, y> == <x, A*y>: err = abs( vdot(A(x), y) - vdot(x, Astar(y)) ). The type and shape of the input to A are specified by inshape and indtype. Returns a vector of the error magnitudes. """ inshape = op.inshape indtype = op.indtype outshape = op.outshape outdtype = op.outdtype x = get_random_normal(inshape, indtype) errs = np.zeros(its, dtype=indtype) for k in xrange(its): x = get_random_normal(inshape, indtype) x = x/np.linalg.norm(x) y = get_random_normal(outshape, outdtype) y = y/np.linalg.norm(y) ip_A = np.vdot(op.A(x), y) ip_Astar = np.vdot(x, op.As(y)) errs[k] = np.abs(ip_A - ip_Astar) return errs
def opnorm(op, reltol=1e-8, abstol=1e-6, maxits=100, printrate=None): """Estimate the l2-induced operator norm: sup_v ||A(v)||/||v|| for v != 0. Uses the power iteration method to estimate the operator norm of op.A and op.As. The type and shape of the input to A are specified by inshape and indtype. Returns a tuple: (norm of A, norm of As, vector inducing maximum scaling). """ inshape = op.inshape indtype = op.indtype v0 = get_random_normal(inshape, indtype) v = v0/np.linalg.norm(v0) norm_f0 = 1 norm_a0 = 1 for k in xrange(maxits): Av = op.A(v) norm_f = np.linalg.norm(Av) w = Av/norm_f Asw = op.As(w) norm_a = np.linalg.norm(Asw) v = Asw/norm_a delta_f = abs(norm_f - norm_f0) delta_a = abs(norm_a - norm_a0) if printrate is not None and (k % printrate) == 0: s = 'Iteration {0}, forward norm: {1}, adjoint norm: {2}' s = s.format(k, norm_f, norm_a) print(s) if (delta_f < abstol + reltol*max(norm_f, norm_f0) and delta_a < abstol + reltol*max(norm_a, norm_a0)): break norm_f0 = norm_f norm_a0 = norm_a return norm_f, norm_a, v