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
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
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)
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)
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
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