def do_no_stepsearch(self, obj, one, two, orb, **kwargs): '''Scale step size with factor self.alpha **Arguments:** obj A class instance containing the objective function. one, two One- and Two-electron integrals (TwoIndex and FourIndex/Cholesky instances) orb An Expansion instance. Contains the MO coefficients **Keywords:** :kappa: Initial step size (OneIndex instance) ''' kappa = kwargs.get('kappa') # # Scale current optimization step, rotate orbitals # kappa.iscale(self.alpha) rotation = obj.compute_rotation_matrix(kappa) rotate_orbitals(orb, rotation) # # Solve for wfn/population model # try: obj.solve_model(one, two, orb, **kwargs) except: pass
def do_trust_region(self, obj, one, two, orb, **kwargs): '''Do trust-region optimization. **Arguments:** obj A class instance containing the objective function. one/two One and Two-body Hamiltonian (TwoIndex and FourIndex/Cholesky instances) orb (Expansion instance) An MO expansion **Keywords:** :kappa: Initial step size (OneIndex instance) :gradient: Orbital gradient (OneIndex instance) :hessian: Orbital Hessian (OneIndex instance) ''' kappa = kwargs.get('kappa') gradient = kwargs.get('gradient') hessian = kwargs.get('hessian') iteri = 1 ofun_ref = obj.compute_objective_function() De = 0.0 stepn = kappa.copy() while True: norm = stepn.norm() # # If ||kappa||_2 is outside the trust region, find a new Newton # step inside the trust region: # if norm > self.trustradius: # # Preconditioned conjugate gradient # if self.optimizer == 'pcg': optimizer = TruncatedCG(self.lf, gradient, hessian, self.trustradius) optimizer(**{'niter': self.maxiterinner, 'abstol': self.threshold}) stepn = optimizer.step # # Powell's dogleg optimization: # elif self.optimizer == 'dogleg': optimizer = Dogleg(kappa, gradient, hessian, self.trustradius) optimizer() stepn = optimizer.step # # Powell's double dogleg optimization: # elif self.optimizer == 'ddl': optimizer = DoubleDogleg(kappa, gradient, hessian, self.trustradius) optimizer() stepn = optimizer.step # # New rotation # rotation = obj.compute_rotation_matrix(stepn) orb_ = orb.copy() rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function after rotation # ofun = obj.compute_objective_function() # # Determine ratio for a given step: # hstep = hessian.new() hessian.mult(stepn, hstep) Destimate = gradient.dot(stepn)+0.5*stepn.dot(hstep) De = ofun-ofun_ref rho = De/Destimate # # For a given ratio, adjust trust radius and accept or reject # Newton step: # if rho > self.maxeta and De <= 0.0: # # Enlarge trust radius: # new = min(self.upscale*self.trustradius,self.maxtrustradius) self.update_trustradius(new) orb.assign(orb_) break elif rho >= self.mineta and rho <= self.maxeta and De <= 0.0: # # Do nothing with trust radius: # orb.assign(orb_) break elif rho > 0 and rho < self.mineta and De <= 0.0: # # Decrease trust radius: # self.update_trustradius(self.downscale*self.trustradius) orb.assign(orb_) break else: # # Bad step! Reject Newton step and repeat with smaller trust # radius # self.update_trustradius(self.downscale*self.trustradius) iteri = iteri+1 if iteri > self.maxiterouter: log('Warning: Trust region search not converged after %i iterations. Trust region search aborted.' %self.maxiterouter) orb.assign(orb_) break
def do_backtracking(self, obj, one, two, orb, **kwargs): '''Backtracking line search. **Arguments:** obj A class instance containing the objctive function. one, two One- and Two-electron integrals (TwoIndex and FourIndex/Cholesky instances) orb An Expansion instance. Contains the MO coefficients **Keywords:** :kappa: Initial step size (OneIndex instance) :gradient: Orbital gradient (OneIndex instance) ''' kappa = kwargs.get('kappa') gradient = kwargs.get('gradient') # # Update scaling factor to initial value # self.update_alpha(self.alpha0) # # Calculate objective function # ofun_ref = obj.compute_objective_function() # # Copy current orbitals # orb_ = orb.copy() # # Initial rotation # kappa.iscale(self.alpha) rotation = obj.compute_rotation_matrix(kappa) rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function for rotated orbitals # ofun = obj.compute_objective_function() # # reduce step size until line search condition is satisfied # while self.check_line_search_condition(ofun, ofun_ref, kappa, gradient): self.update_alpha(self.alpha*self.downscale) # # New rotation # kappa.iscale(self.alpha) rotation = obj.compute_rotation_matrix(kappa) orb_ = orb.copy() rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function for scaled rotation # ofun = obj.compute_objective_function() # # Abort if scaling factor falls below threshold # if self.alpha < self.minalpha: break orb.assign(orb_)
def do_trust_region(self, obj, one, two, orb, **kwargs): '''Do trust-region optimization. **Arguments:** obj A class instance containing the objective function. one/two One and Two-body Hamiltonian (TwoIndex and FourIndex/Cholesky instances) orb (Expansion instance) An MO expansion **Keywords:** :kappa: Initial step size (OneIndex instance) :gradient: Orbital gradient (OneIndex instance) :hessian: Orbital Hessian (OneIndex instance) ''' kappa = kwargs.get('kappa') gradient = kwargs.get('gradient') hessian = kwargs.get('hessian') iteri = 1 ofun_ref = obj.compute_objective_function() De = 0.0 stepn = kappa.copy() while True: norm = stepn.norm() # # If ||kappa||_2 is outside the trust region, find a new Newton # step inside the trust region: # if norm > self.trustradius: # # Preconditioned conjugate gradient # if self.optimizer == 'pcg': optimizer = TruncatedCG(self.lf, gradient, hessian, self.trustradius) optimizer(**{ 'niter': self.maxiterinner, 'abstol': self.threshold }) stepn = optimizer.step # # Powell's dogleg optimization: # elif self.optimizer == 'dogleg': optimizer = Dogleg(kappa, gradient, hessian, self.trustradius) optimizer() stepn = optimizer.step # # Powell's double dogleg optimization: # elif self.optimizer == 'ddl': optimizer = DoubleDogleg(kappa, gradient, hessian, self.trustradius) optimizer() stepn = optimizer.step # # New rotation # rotation = obj.compute_rotation_matrix(stepn) orb_ = orb.copy() rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function after rotation # ofun = obj.compute_objective_function() # # Determine ratio for a given step: # hstep = hessian.new() hessian.mult(stepn, hstep) Destimate = gradient.dot(stepn) + 0.5 * stepn.dot(hstep) De = ofun - ofun_ref rho = De / Destimate # # For a given ratio, adjust trust radius and accept or reject # Newton step: # if rho > self.maxeta and De <= 0.0: # # Enlarge trust radius: # new = min(self.upscale * self.trustradius, self.maxtrustradius) self.update_trustradius(new) orb.assign(orb_) break elif rho >= self.mineta and rho <= self.maxeta and De <= 0.0: # # Do nothing with trust radius: # orb.assign(orb_) break elif rho > 0 and rho < self.mineta and De <= 0.0: # # Decrease trust radius: # self.update_trustradius(self.downscale * self.trustradius) orb.assign(orb_) break else: # # Bad step! Reject Newton step and repeat with smaller trust # radius # self.update_trustradius(self.downscale * self.trustradius) iteri = iteri + 1 if iteri > self.maxiterouter: log('Warning: Trust region search not converged after %i iterations. Trust region search aborted.' % self.maxiterouter) orb.assign(orb_) break
def do_backtracking(self, obj, one, two, orb, **kwargs): '''Backtracking line search. **Arguments:** obj A class instance containing the objctive function. one, two One- and Two-electron integrals (TwoIndex and FourIndex/Cholesky instances) orb An Expansion instance. Contains the MO coefficients **Keywords:** :kappa: Initial step size (OneIndex instance) :gradient: Orbital gradient (OneIndex instance) ''' kappa = kwargs.get('kappa') gradient = kwargs.get('gradient') # # Update scaling factor to initial value # self.update_alpha(self.alpha0) # # Calculate objective function # ofun_ref = obj.compute_objective_function() # # Copy current orbitals # orb_ = orb.copy() # # Initial rotation # kappa.iscale(self.alpha) rotation = obj.compute_rotation_matrix(kappa) rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function for rotated orbitals # ofun = obj.compute_objective_function() # # reduce step size until line search condition is satisfied # while self.check_line_search_condition(ofun, ofun_ref, kappa, gradient): self.update_alpha(self.alpha * self.downscale) # # New rotation # kappa.iscale(self.alpha) rotation = obj.compute_rotation_matrix(kappa) orb_ = orb.copy() rotate_orbitals(orb_, rotation) # # Solve for wfn/population model if required # try: obj.solve_model(one, two, orb_, **kwargs) except: pass # # Calculate objective function for scaled rotation # ofun = obj.compute_objective_function() # # Abort if scaling factor falls below threshold # if self.alpha < self.minalpha: break orb.assign(orb_)