Beispiel #1
0
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)
Beispiel #2
0
    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
Beispiel #3
0
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))
Beispiel #4
0
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.')