def solve_system(A, rhs, itref_threshold=1.0e-6, nitrefmax=5, **kwargs): # Obtain Sils context object t = timeit.default_timer() LBL = LBLContext(A, **kwargs) t_analyze = timeit.default_timer() - t # Solve system and compute residual t = timeit.default_timer() LBL.solve(rhs) t_solve = timeit.default_timer() - t # Compute residual norm nrhsp1 = norm(rhs, ord=np.infty) + 1 nr = norm(LBL.residual) / nrhsp1 # If residual not small, perform iterative refinement LBL.refine(rhs, tol=itref_threshold, nitref=nitrefmax) nr1 = norm(LBL.residual, ord=np.infty) / nrhsp1 return (LBL.x, LBL.residual, nr, nr1, t_analyze, t_solve, LBL.neig)
def perform_factorization(self): """Assemble projection matrix and factorize it. P = [ G A^T ] [ A 0 ], where G is the preconditioner, or the identity matrix if no preconditioner was given. """ if self.A is None: raise ValueError('No linear equality constraints were specified') # Form projection matrix P = spmatrix.ll_mat_sym(self.n + self.m, self.nnzA + self.n) if self.precon is not None: P[:self.n, :self.n] = self.precon else: r = range(self.n) P.put(1, r, r) # for i in range(self.n): # P[i,i] = 1 P[self.n:, :self.n] = self.A # Add regularization if requested. if self.dreg > 0.0: r = range(self.n, self.n + self.m) P.put(-self.dreg, r, r) msg = 'Factorizing projection matrix ' msg += '(size %-d, nnz = %-d)...' % (P.shape[0], P.nnz) self.log.debug(msg) self.t_fact = cputime() self.proj = LBLContext(P) self.t_fact = cputime() - self.t_fact self.log.debug('... done (%-5.2fs)' % self.t_fact) self.factorized = True return
nC = C.shape[0] # K = spmatrix.ll_mat_sym(nA + nC, A.nnz + C.nnz + min(nA,nC)) K = sp(size=nA + nC, sizeHint=A.nnz + C.nnz + min(nA, nC), symmetric=True) K[:nA, :nA] = A K[nA:, nA:] = -C # K[nA:,nA:].scale(-1.0) idx = np.arange(min(nA, nC), dtype=np.int) K.put(1, nA + idx, idx) # Create right-hand side rhs=K*e e = np.ones(nA + nC) # rhs = np.empty(nA+nC) # K.matvec(e,rhs) rhs = K * e # Factorize and solve Kx = rhs, knowing K is sqd t = timeit.default_timer() LDL = LBLContext(K, sqd=True) t = timeit.default_timer() - t sys.stderr.write('Factorization time with sqd=True : %5.2fs ', t) LDL.solve(rhs, get_resid=False) sys.stderr.write('Error: %7.1e\n', np.linalg.norm(LDL.x - e, ord=np.Inf)) # Do it all over again, pretending we don't know K is sqd t = timeit.default_timer() LBL = LBLContext(K) t = timeit.default_timer() - t sys.stderr.write('Factorization time with sqd=False: %5.2fs ', t) LBL.solve(rhs, get_resid=False) sys.stderr.write('Error: %7.1e\n', np.linalg.norm(LBL.x - e, ord=np.Inf))
class ProjectedKrylov(object): """Generic class for projected Krylov method.""" def __init__(self, c, H, **kwargs): """Instantiate a projected Krylov method. :parameters: :H: the operator in the leading block. Only matrix-vector products with ``H`` are required in projected Krylov methods. ``H`` can be given as a linear operator. :c: the first part of the right-hand side vector. :keywords: :A: the `constraint` matrix. Must be given as an explicit matrix. :b: the second part of the right-hand side vector (default: ``None``, meaning the vector of zeros). :abstol: absolute stopping tolerance (default: 1.0e-8). :reltol: relative stopping tolerance (default: 1.0e-6). :maxiter: maximum number of iterations of the Krylov method. :max_itref: maximum number of iterative refinement steps after a projection (default: 3). :itref_tol: acceptable residual tolerance during iterative refinement (default: 1.0e-6). :factorize: if set to ``True``, the projector will be factorized (this is the default). If set to ``False``, an existing factorization should be given in ``proj``. :proj: an existing factorization of the projector. If not ``None``, ``factorize`` will be set to ``False``. :precon: preconditioner. Normally this is a cheap approximation to ``H``. It must be specified as an explicit matrix. :logger_name: Name of a logger (Default: `None`). """ self.prefix = 'Generic PK: ' # Should be overridden in subclass self.name = 'Generic Projected Krylov Method (should be subclassed)' self.debug = kwargs.get('debug', False) self.abstol = kwargs.get('abstol', 1.0e-8) self.reltol = kwargs.get('reltol', 1.0e-6) self.max_itref = kwargs.get('max_itref', 3) self.itref_tol = kwargs.get('itref_tol', 1.0e-6) self.factorize = kwargs.get('factorize', True) self.precon = kwargs.get('precon', None) logger_name = kwargs.get('logger_name', None) self.log = logging.getLogger(logger_name) self.log.propagate = False # Optional keyword arguments self.A = kwargs.get('A', None) if self.A is not None: self.log.debug('Constraint matrix has shape (%d,%d)', self.A.shape[0], self.A.shape[1]) else: self.log.debug('No constraint matrix specified') self.b = kwargs.get('rhs', None) self.n = c.shape[0] # Number of variables if self.A is None: self.m = 0 self.nnzA = 0 else: self.m = self.A.shape[0] # Number of constraints self.nnzA = self.A.nnz # Number of nonzeros in constraint matrix self.nnzP = 0 # Number of nonzeros in projection matrix self.c = c self.H = H self.maxiter = kwargs.get('maxiter', 2 * self.n) self.proj = kwargs.get('proj', None) # Factorization already performed self.factorized = (self.proj is not None) self.dreg = kwargs.get('dreg', 0.0) # Dual regularization. # Initializations self.t_fact = 0.0 # Timing of factorization phase self.t_feasible = 0.0 # Timing of feasibility phase self.t_solve = 0.0 # Timing of iterative solution phase self.x_feasible = None self.converged = False def perform_factorization(self): """Assemble projection matrix and factorize it. P = [ G A^T ] [ A 0 ], where G is the preconditioner, or the identity matrix if no preconditioner was given. """ if self.A is None: raise ValueError('No linear equality constraints were specified') # Form projection matrix P = spmatrix.ll_mat_sym(self.n + self.m, self.nnzA + self.n) if self.precon is not None: P[:self.n, :self.n] = self.precon else: r = range(self.n) P.put(1, r, r) # for i in range(self.n): # P[i,i] = 1 P[self.n:, :self.n] = self.A # Add regularization if requested. if self.dreg > 0.0: r = range(self.n, self.n + self.m) P.put(-self.dreg, r, r) msg = 'Factorizing projection matrix ' msg += '(size %-d, nnz = %-d)...' % (P.shape[0], P.nnz) self.log.debug(msg) self.t_fact = cputime() self.proj = LBLContext(P) self.t_fact = cputime() - self.t_fact self.log.debug('... done (%-5.2fs)' % self.t_fact) self.factorized = True return def check_accurate(self): """Verify constraints consistency and residual accuracy.""" scale_factor = norms.norm_infty(self.proj.x[:self.n]) if self.b is not None: scale_factor = max(scale_factor, norms.norm_infty(self.b)) max_res = max(1.0e-6 * scale_factor, self.abstol) res = norms.norm_infty(self.proj.residual) if res > max_res: if self.proj.isFullRank: self.log.info(' Large residual. ' + 'Factorization likely inaccurate...') else: self.log.info(' Large residual. ' + 'Constraints likely inconsistent...') self.log.debug(' accurate to within %8.1e...' % res) return def find_feasible(self): """Obtain `x_feasible` satisfying the constraints. `rhs` must have been specified. """ n = self.n self.log.debug('Obtaining feasible solution...') self.t_feasible = cputime() self.rhs[n:] = self.b self.proj.solve(self.rhs) self.x_feasible = self.proj.x[:n].copy() self.t_feasible = cputime() - self.t_feasible self.check_accurate() self.log.debug('... done (%-5.2fs)' % self.t_feasible) return def solve(self): """Solve method of the abstract projectedKrylov class. The class must be specialized and this method overridden. """ raise NotImplementedError('This method must be overridden.')