def _solveKKTAndUpdatePD(x, func, grad, fx, g, gOrig, Haug, z, G, h, y, A, b, t): p = len(x) step = 1.0 deltaX = None deltaZ = None deltaY = None # standard log barrier, \nabla f(x) / -f(x) if G is not None: s = h - G.dot(x) Gs = G/s zs = z/s # now find the matrix/vector of our qp Haug += numpy.einsum('ji,ik->jk', G.T, G*zs) Dphi = Gs.sum(axis=0).reshape(p, 1) g += Dphi / t # find the solution to a Newton step to get the descent direction if A is not None: bTemp = _rPriFunc(x, A, b) g += A.T.dot(y) # print "here" LHS = scipy.sparse.bmat([ [Haug, A.T], [A, None] ],'csc') RHS = numpy.append(g, bTemp, axis=0) # print LHS # print RHS # if the total number of elements (in sparse format) is # more than half total possible elements, it is a dense matrix if LHS.size>= (LHS.shape[0] * LHS.shape[1])/2: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) # print deltaTemp deltaX = deltaTemp[:p] deltaY = deltaTemp[p::] else: deltaX = scipy.linalg.solve(Haug, -g).reshape(p, 1) # store the information for the next iteration oldFx = fx oldGrad = gOrig.copy() if G is None: maxStep = 1 barrierFunc = _logBarrier(x, func, t, G, h) lineFunc = lineSearch(maxStep, x, deltaX, barrierFunc) searchScale = deltaX.ravel().dot(g.ravel()) else: maxStep = _maxStepSizePD(z, x, deltaX, t, G, h) lineFunc = _residualLineSearchPD(maxStep, x, deltaX, grad, t, z, _deltaZFunc, G, h, y, deltaY, A, b) searchScale = -lineFunc(0.0) # perform a line search. Because the minimization routine # in scipy can sometimes be a bit weird, we assume that the # exact line search can sometimes fail, so we do a # back tracking line search if that is the case step, fx = exactLineSearch2(maxStep, lineFunc, searchScale, oldFx) # step, fx = exactLineSearch(maxStep, lineFunc) # if fx >= oldFx or step <=0: # step, fx = backTrackingLineSearch(maxStep, lineFunc, searchScale) # found one iteration, now update the information if z is not None: z += step * _deltaZFunc(x, deltaX, t, z, G, h) if y is not None: y += step * deltaY x += step * deltaX return x, y, z, fx, step, oldFx, oldGrad, deltaX
def _solveKKTAndUpdatePDC(x, func, grad, fx, g, gOrig, Haug, z, G, h, y, A, b, t): p = len(x) step = 1 deltaX = None deltaZ = None deltaY = None rDual = _rDualFunc(x, grad, z, G, y, A) RHS = rDual if G is not None: s = h - G.dot(x) Gs = G/s zs = z/s # now find the matrix/vector of our qp rCent = _rCentFunc(z, s, t) RHS = numpy.append(RHS, rCent, axis=0) ## solving the QP to get the descent direction if A is not None: bTemp = b - A.dot(x) g += A.T.dot(y) rPri = _rPriFunc(x, A, b) RHS = numpy.append(RHS, rPri, axis=0) if G is not None: LHS = scipy.sparse.bmat([ [Haug, G.T, A.T], [G*-z, scipy.sparse.diags(s.ravel(),0), None], [A, None, None] ],'csc') if LHS.size>= (LHS.shape[0] * LHS.shape[1])/2: deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape(len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) deltaX = deltaTemp[:p] deltaZ = deltaTemp[p:-len(A)] deltaY = deltaTemp[-len(A):] else: # G is None LHS = scipy.sparse.bmat([ [Haug, A.T], [A, None] ],'csc') if LHS.size>= (LHS.shape[0] * LHS.shape[1])/2: deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape(len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS),1) deltaX = deltaTemp[:p] deltaY = deltaTemp[p::] else: # A is None if G is not None: LHS = scipy.sparse.bmat([ [Haug, G.T], [G*-z, scipy.sparse.diags(s.ravel(),0)], ],'csc') deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape(len(RHS), 1) deltaX = deltaTemp[:p] deltaZ = deltaTemp[p::] else: deltaX = scipy.linalg.solve(Haug, -RHS).reshape(len(RHS), 1) # store the information for the next iteration oldFx = fx oldGrad = gOrig.copy() if G is None: # print "obj" maxStep = 1 barrierFunc = _logBarrier(x, func, t, G, h) lineFunc = lineSearch(maxStep, x, deltaX, barrierFunc) searchScale = deltaX.ravel().dot(g.ravel()) else: maxStep = _maxStepSizePDC(z, deltaZ, x, deltaX, G, h) lineFunc = _residualLineSearchPDC(step, x, deltaX, grad, t, z, deltaZ, G, h, y, deltaY, A, b) searchScale = -lineFunc(0.0) # perform a line search. Because the minimization routine # in scipy can sometimes be a bit weird, we assume that the # exact line search can sometimes fail, so we do a # back tracking line search if that is the case step, fx = exactLineSearch2(maxStep, lineFunc, searchScale, oldFx) # step, fx = exactLineSearch(maxStep, lineFunc) # if fx >= oldFx or step <= 0 or step>=maxStep: # step, fx = backTrackingLineSearch(maxStep, lineFunc, searchScale, oldFx) if z is not None: z += step * deltaZ if y is not None: y += step * deltaY x += step * deltaX return x, y, z, fx, step, oldFx, oldGrad, deltaX
def _solveKKTAndUpdatePDC(x, func, grad, fx, g, gOrig, Haug, z, G, h, y, A, b, t): p = len(x) step = 1 deltaX = None deltaZ = None deltaY = None rDual = _rDualFunc(x, grad, z, G, y, A) RHS = rDual if G is not None: s = h - G.dot(x) Gs = G / s zs = z / s # now find the matrix/vector of our qp rCent = _rCentFunc(z, s, t) RHS = numpy.append(RHS, rCent, axis=0) ## solving the QP to get the descent direction if A is not None: bTemp = b - A.dot(x) g += A.T.dot(y) rPri = _rPriFunc(x, A, b) RHS = numpy.append(RHS, rPri, axis=0) if G is not None: LHS = scipy.sparse.bmat( [[Haug, G.T, A.T], [G * -z, scipy.sparse.diags(s.ravel(), 0), None], [A, None, None]], 'csc') if LHS.size >= (LHS.shape[0] * LHS.shape[1]) / 2: deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape( len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) deltaX = deltaTemp[:p] deltaZ = deltaTemp[p:-len(A)] deltaY = deltaTemp[-len(A):] else: # G is None LHS = scipy.sparse.bmat([[Haug, A.T], [A, None]], 'csc') if LHS.size >= (LHS.shape[0] * LHS.shape[1]) / 2: deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape( len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) deltaX = deltaTemp[:p] deltaY = deltaTemp[p::] else: # A is None if G is not None: LHS = scipy.sparse.bmat([ [Haug, G.T], [G * -z, scipy.sparse.diags(s.ravel(), 0)], ], 'csc') deltaTemp = scipy.sparse.linalg.spsolve(LHS, -RHS).reshape(len(RHS), 1) deltaX = deltaTemp[:p] deltaZ = deltaTemp[p::] else: deltaX = scipy.linalg.solve(Haug, -RHS).reshape(len(RHS), 1) # store the information for the next iteration oldFx = fx oldGrad = gOrig.copy() if G is None: # print "obj" maxStep = 1 barrierFunc = _logBarrier(x, func, t, G, h) lineFunc = lineSearch(maxStep, x, deltaX, barrierFunc) searchScale = deltaX.ravel().dot(g.ravel()) else: maxStep = _maxStepSizePDC(z, deltaZ, x, deltaX, G, h) lineFunc = _residualLineSearchPDC(step, x, deltaX, grad, t, z, deltaZ, G, h, y, deltaY, A, b) searchScale = -lineFunc(0.0) # perform a line search. Because the minimization routine # in scipy can sometimes be a bit weird, we assume that the # exact line search can sometimes fail, so we do a # back tracking line search if that is the case step, fx = exactLineSearch2(maxStep, lineFunc, searchScale, oldFx) # step, fx = exactLineSearch(maxStep, lineFunc) # if fx >= oldFx or step <= 0 or step>=maxStep: # step, fx = backTrackingLineSearch(maxStep, lineFunc, searchScale, oldFx) if z is not None: z += step * deltaZ if y is not None: y += step * deltaY x += step * deltaX return x, y, z, fx, step, oldFx, oldGrad, deltaX
def _solveKKTAndUpdatePD(x, func, grad, fx, g, gOrig, Haug, z, G, h, y, A, b, t): p = len(x) step = 1.0 deltaX = None deltaZ = None deltaY = None # standard log barrier, \nabla f(x) / -f(x) if G is not None: s = h - G.dot(x) Gs = G / s zs = z / s # now find the matrix/vector of our qp Haug += numpy.einsum('ji,ik->jk', G.T, G * zs) Dphi = Gs.sum(axis=0).reshape(p, 1) g += Dphi / t # find the solution to a Newton step to get the descent direction if A is not None: bTemp = _rPriFunc(x, A, b) g += A.T.dot(y) # print "here" LHS = scipy.sparse.bmat([[Haug, A.T], [A, None]], 'csc') RHS = numpy.append(g, bTemp, axis=0) # print LHS # print RHS # if the total number of elements (in sparse format) is # more than half total possible elements, it is a dense matrix if LHS.size >= (LHS.shape[0] * LHS.shape[1]) / 2: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) else: deltaTemp = scipy.linalg.solve(LHS.todense(), -RHS).reshape(len(RHS), 1) # print deltaTemp deltaX = deltaTemp[:p] deltaY = deltaTemp[p::] else: deltaX = scipy.linalg.solve(Haug, -g).reshape(p, 1) # store the information for the next iteration oldFx = fx oldGrad = gOrig.copy() if G is None: maxStep = 1 barrierFunc = _logBarrier(x, func, t, G, h) lineFunc = lineSearch(maxStep, x, deltaX, barrierFunc) searchScale = deltaX.ravel().dot(g.ravel()) else: maxStep = _maxStepSizePD(z, x, deltaX, t, G, h) lineFunc = _residualLineSearchPD(maxStep, x, deltaX, grad, t, z, _deltaZFunc, G, h, y, deltaY, A, b) searchScale = -lineFunc(0.0) # perform a line search. Because the minimization routine # in scipy can sometimes be a bit weird, we assume that the # exact line search can sometimes fail, so we do a # back tracking line search if that is the case step, fx = exactLineSearch2(maxStep, lineFunc, searchScale, oldFx) # step, fx = exactLineSearch(maxStep, lineFunc) # if fx >= oldFx or step <=0: # step, fx = backTrackingLineSearch(maxStep, lineFunc, searchScale) # found one iteration, now update the information if z is not None: z += step * _deltaZFunc(x, deltaX, t, z, G, h) if y is not None: y += step * deltaY x += step * deltaX return x, y, z, fx, step, oldFx, oldGrad, deltaX