def find_root(self): L_alpha = [1.0, 10.0] L_lam = [[1.0, 2.0, 3.0], [1.0, 1.0], [0.0], [-1.0, 1.0], [-1.0, 0.0, 1.0], [1.0, -2.0, -3.0], [-3.0, -4.0, -5.0, -6.0]] L_rho = [1e-2, 1e-1, 1e0, 1e1] L_tol = [1e-3, 1e-5, 1e-10, 1e-14] for alpha_r, lam, rho, tol in product(L_alpha, L_lam, L_rho, L_tol): alpha = ones(len(lam)) * alpha_r lam = array(lam) tol = rho * tol if min(lam) > 0: if calculate_distance(alpha, lam, 0.0) < rho: continue print 'alpha', alpha, 'lam', lam, 'rho', rho, 'tol', tol nu = find_step_size(alpha, lam, rho, tol) f_nu = calculate_distance(alpha, lam, nu) print 'nu', nu, 'f(nu)', f_nu abs(rho - calculate_distance(alpha, lam, nu)) < Assert(tol)
def main(): parser = argparse.ArgumentParser( description="Test root-finding method to find step size in trust region optimization methods." ) parser.add_argument("--alpha", type=float) parser.add_argument("--lam", type=float, nargs="+") parser.add_argument("--rho", type=float) args = parser.parse_args() alpha = args.alpha lam = array(args.lam) rho = args.rho print "α:", alpha print "λ:", lam print "ρ:", rho print "f(0)=", calculate_distance(alpha, lam, 0) nu = find_step_size(alpha, lam, rho, 1e-14) print "nu=", nu print "f(nu)-rho=", calculate_distance(alpha, lam, nu) - rho rez = 0.01 xx = mgrid[nu / 100.0 : nu * 100 : rez] yy = array([calculate_distance(alpha, lam, x) for x in xx]) ion() plot(xx, yy) plot([nu / 10.0, nu * 10.0], [rho, rho], "r-") plot(nu, calculate_distance(alpha, lam, nu), "rd") grid() code.interact()
def trust_region_step(G, g, rho, rho_tol): Nv = g.shape #number of dimensions ## Eigen decomposition of the matrix. try: lam, v = np.linalg.eig(G) except: # print '*** ERROR, invalid Hessian matrix' # print G raise Exception ## lam, v = svd_eig(G) ## This is WRONG! (?) # print '==lam',lam # print '==v',v ln = lam.min() lni = nonzero(lam==ln)[0] lok = nonzero(1-(lam==ln))[0] ## Gradient projectin on the eigenvectors. alpha = dot(v.T, g) # print 'New QP problem:' # print 'lam:', lam # print 'rho:', rho # print lni, lok # print 'alpha:', alpha ## A plane. Just use the gradient... if (np.abs(lam)<1e-10).all(): # print 'case 0' if norm(g) > 0: return -rho * g / norm(g) else: #print "joga pro santo" return rho * v[0] ## Test for case i -> Newton step (nu=0) if ln > 0: # print 'case 1' ## Matrix is positive definite. ## Test norm for the nu=0 case. beta = -alpha / lam nd = norm(beta) if nd <= rho + rho_tol: ## If norm is smaller than radius, this is "case i". The ## Newton step is feasible, so we just return it. delta = dot(v,beta) return delta if ln <= 0: ## This may be case iii or ii. Test alpha. if (np.abs(alpha[lni]) < 1e-10).all(): # print "case 3" ## This is case iii. First we test if the saddle point is ## outside the trust region, in which case we perofrm the ## normal calculation in the end. If not, we calculate the ## saddle point position, and return a vector stemming ## from it up to the trust region boundary. beta = zeros(Nv) if lok.shape[0]>0: beta[lok] = -alpha[lok] / (lam[lok] - ln) nd = norm(beta) ## this is h_bar from Fletcher's book, pg. 104 if nd <= rho + rho_tol: # print "saddle in" ## If norm is smaller than radius, this is "case iii" ## with hk>=h_bar. We return the newton step plus a ## vector in the direction of the smallest eigenvalue. db = dot(v,beta) ## delta_bar from Fletcher's book mv = v[:,lni[0]] # print db, mv ## Solve to find the sum that touches the region border. # print '----', rho, nd delta = db + mv * np.sqrt((rho + rho_tol) ** 2 - nd ** 2) # print "Return some crazy vector", delta return delta # print "saddle out", nd, rho # print 'case 2' ################################################################## ## Perform an iterative root-finding procedure (secant method) to ## find nu. nu_opt = find_step_size(alpha, lam, rho, rho_tol) beta = -alpha / (lam + nu_opt) delta = dot(v,beta) return delta