Пример #1
0
    def __init__(self, A, **kwargs):
        GenericPreconditioner.__init__(self, A, **kwargs)
        n = self.shape[0]
        self.bandwidth = kwargs.get('bandwidth', 5)
        self.threshold = kwargs.get('threshold', 1.0e-3)

        # See how many nonzeros are in the requested band of A
        nnz = 0
        sumrowelm = np.zeros(n, 'd')
        for j in range(n):
            for i in range(min(self.bandwidth, n - j - 1)):
                if A[j + i + 1, j] != 0.0:
                    nnz += 1
                    sumrowelm[j] += abs(A[j + i + 1, j])

        M = spmatrix.ll_mat_sym(n, nnz + n)

        # Assemble banded matrix --- ensure it is positive definite
        for j in range(n):
            M[j, j] = max(A[j, j], 2 * sumrowelm[j] + self.threshold)
            for i in range(min(self.bandwidth, n - j - 1)):
                if A[j + i + 1, j] != 0.0:
                    M[j + i + 1, j] = A[j + i + 1, j]

        # Factorize preconditioner
        self.lbl = LBLContext(M)

        # Only need factors of M --- can discard M itself
        del M
Пример #2
0
    def Factorize(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)

        if self.debug:
            msg = 'Factorizing projection matrix '
            msg += '(size %-d, nnz = %-d)...\n' % (P.shape[0], P.nnz)
            self._write(msg)
        self.t_fact = cputime()
        self.Proj = LBLContext(P)
        self.t_fact = cputime() - self.t_fact
        if self.debug:
            msg = ' done (%-5.2fs)\n' % self.t_fact
            self._write(msg)
        self.factorized = True
        return
Пример #3
0
Файл: lp.py Проект: b45ch1/nlpy
    def set_initial_guess(self, lp, **kwargs):
        """
        Compute initial guess according the Mehrotra's heuristic. Initial values
        of x are computed as the solution to the least-squares problem::

            minimize ||s||  subject to  A1 x + A2 s = b

        which is also the solution to the augmented system::

            [ 0   0   A1' ] [x]   [0]
            [ 0   I   A2' ] [s] = [0]
            [ A1  A2   0  ] [w]   [b].

        Initial values for (y,z) are chosen as the solution to the least-squares
        problem::

            minimize ||z||  subject to  A1' y = c,  A2' y + z = 0

        which can be computed as the solution to the augmented system::

            [ 0   0   A1' ] [w]   [c]
            [ 0   I   A2' ] [z] = [0]
            [ A1  A2   0  ] [y]   [0].

        To ensure stability and nonsingularity when A does not have full row
        rank, the (1,1) block is perturbed to 1.0e-4 * I and the (3,3) block is
        perturbed to -1.0e-4 * I.

        The values of s and z are subsequently adjusted to ensure they are
        positive. See [Methrotra, 1992] for details.
        """
        n = lp.n ; m = lp.m ; ns = self.nSlacks ; on = lp.original_n

        # Set up augmented system matrix and factorize it.
        self.H.put(1.0e-4, range(on))
        self.H.put(1.0, range(on,n))
        self.H.put(-1.0e-4, range(n,n+m))
        self.H[n:,:n] = self.A
        self.LBL = LBLContext(self.H, sqd=True)  # Perform analyze and factorize

        # Assemble first right-hand side and solve.
        rhs = np.zeros(n+m)
        rhs[n:] = self.b
        (step, nres, neig) = self.solveSystem(rhs)
        x = step[:n].copy()
        s = x[on:]  # Slack variables. Must be positive.

        # Assemble second right-hand side and solve.
        rhs[:on] = self.c
        rhs[on:] = 0.0

        (step, nres, neig) = self.solveSystem(rhs)
        y = step[n:].copy()
        z = step[on:n].copy()

        # Use Mehrotra's heuristic to ensure (s,z) > 0.
        if np.all(s >= 0):
            dp = 0.0
        else:
            dp = -1.5 * min(s[s < 0])
        if np.all(z >= 0):
            dd = 0.0
        else:
            dd = -1.5 * min(z[z < 0])

        if dp == 0.0: dp = 1.5
        if dd == 0.0: dd = 1.5

        es = sum(s+dp)
        ez = sum(z+dd)
        xs = sum((s+dp) * (z+dd))

        dp += 0.5 * xs/ez
        dd += 0.5 * xs/es
        s += dp
        z += dd

        if not np.all(s>0) or not np.all(z>0):
            raise ValueError, 'Initial point not strictly feasible'

        return (x,y,z)
Пример #4
0
    def set_initial_guess(self, **kwargs):
        """
        Compute initial guess according the Mehrotra's heuristic. Initial values
        of x are computed as the solution to the least-squares problem::

            minimize ||s||  subject to  A1 x + A2 s = b

        which is also the solution to the augmented system::

            [ Q   0   A1' ] [x]   [0]
            [ 0   I   A2' ] [s] = [0]
            [ A1  A2   0  ] [w]   [b].

        Initial values for (y,z) are chosen as the solution to the least-squares
        problem::

            minimize ||z||  subject to  A1' y = c,  A2' y + z = 0

        which can be computed as the solution to the augmented system::

            [ Q   0   A1' ] [w]   [c]
            [ 0   I   A2' ] [z] = [0]
            [ A1  A2   0  ] [y]   [0].

        To ensure stability and nonsingularity when A does not have full row
        rank, the (1,1) block is perturbed to 1.0e-4 * I and the (3,3) block is
        perturbed to -1.0e-4 * I.

        The values of s and z are subsequently adjusted to ensure they are
        positive. See [Methrotra, 1992] for details.
        """
        qp = self.qp
        n = qp.n
        m = qp.m
        ns = self.nSlacks
        on = qp.original_n

        self.log.debug('Computing initial guess')

        # Set up augmented system matrix and factorize it.
        self.set_initial_guess_system()
        self.LBL = LBLContext(self.H,
                              sqd=self.regdu > 0)  # Analyze + factorize

        # Assemble first right-hand side and solve.
        rhs = self.set_initial_guess_rhs()
        (step, nres, neig) = self.solveSystem(rhs)

        dx, _, _, _ = self.get_dxsyz(step, 0, 1, 0, 0, 0)

        # dx is just a reference; we need to make a copy.
        x = dx.copy()
        s = x[on:]  # Slack variables. Must be positive.

        # Assemble second right-hand side and solve.
        self.update_initial_guess_rhs(rhs)

        (step, nres, neig) = self.solveSystem(rhs)

        _, dz, dy, _ = self.get_dxsyz(step, 0, 1, 0, 0, 0)

        # dy and dz are just references; we need to make copies.
        y = dy.copy()
        z = -dz

        # If there are no inequality constraints, this is it.
        if n == on: return (x, y, z)

        # Use Mehrotra's heuristic to ensure (s,z) > 0.
        if np.all(s >= 0):
            dp = 0.0
        else:
            dp = -1.5 * min(s[s < 0])
        if np.all(z >= 0):
            dd = 0.0
        else:
            dd = -1.5 * min(z[z < 0])

        if dp == 0.0: dp = 1.5
        if dd == 0.0: dd = 1.5

        es = sum(s + dp)
        ez = sum(z + dd)
        xs = sum((s + dp) * (z + dd))

        dp += 0.5 * xs / ez
        dd += 0.5 * xs / es
        s += dp
        z += dd

        if not np.all(s > 0) or not np.all(z > 0):
            raise ValueError, 'Initial point not strictly feasible'

        return (x, y, z)
Пример #5
0
nC = C.shape[0]
K = spmatrix.ll_mat_sym(nA + nC, A.nnz + C.nnz + min(nA, nC))
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)

# Factorize and solve Kx = rhs, knowing K is sqd
t = cputime()
P = LBLContext(K, sqd=True)
t = cputime() - t
sys.stderr.write('Factorization time with sqd=True : %5.2fs   ' % t)
P.solve(rhs, get_resid=False)
sys.stderr.write('Error: %7.1e\n' % np.linalg.norm(P.x - e, ord=np.Inf))

# Do it all over again, pretending we don't know K is sqd
t = cputime()
P = LBLContext(K)
t = cputime() - t
sys.stderr.write('Factorization time with sqd=False: %5.2fs   ' % t)
P.solve(rhs, get_resid=False)
sys.stderr.write('Error: %7.1e\n' % np.linalg.norm(P.x - e, ord=np.Inf))

try:
    import pylab
Пример #6
0
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 = cputime()
LDL = LBLContext(K, sqd=True)
t = cputime() - 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 = cputime()
LBL = LBLContext(K)
t = cputime() - 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))

try:
    import pylab