def line_search(f, myfprime, xk, pk, gfk, old_fval, old_old_fval, args=(), c1=1e-4, c2=0.9, amax=50): fc = 0 gc = 0 phi0 = old_fval derphi0 = numpy.dot(gfk, pk) alpha1 = pymin(1.0, 1.01 * 2 * (phi0 - old_old_fval) / derphi0) # trevor: added this test alpha1 = pymin(alpha1, amax) if isinstance(myfprime, type(())): eps = myfprime[1] fprime = myfprime[0] newargs = (f, eps) + args gradient = False else: fprime = myfprime newargs = args gradient = True xtol = 1e-14 amin = 1e-8 isave = numpy.zeros((2, ), numpy.intc) dsave = numpy.zeros((13, ), float) task = 'START' fval = old_fval gval = gfk while 1: stp, fval, derphi, task = minpack2.dcsrch(alpha1, phi0, derphi0, c1, c2, xtol, task, amin, amax, isave, dsave) #print 'minpack2.dcsrch', alpha1, phi0, derphi0, c1, c2, xtol, task, amin, amax,isave,dsave #print 'returns', stp,fval,derphi,task if task[:2] == 'FG': alpha1 = stp fval = f(xk + stp * pk, *args) fc += 1 gval = fprime(xk + stp * pk, *newargs) if gradient: gc += 1 else: fc += len(xk) + 1 phi0 = fval derphi0 = numpy.dot(gval, pk) else: break if task[:5] == 'ERROR' or task[1:4] == 'WARN': stp = None # failed return stp, fc, gc, fval, old_fval, gval
def _lineSearchStep(self, lastStepInfo, curObjVal): """ Determine the next action to take in the line search process @ In, lastStepInfo, dict, dictionary of past and present relevant information @ In, curObjVal, float, current objective value obtained during line search @ Out, stepSize, float, new suggested step size @ Out, task, binary string, task of line search """ # determine next task in line search stepSize = lastStepInfo['stepSize'] lineObjDerivative = lastStepInfo['line']['objDerivative'] task = lastStepInfo['task'] iSave = lastStepInfo['fortranParams']['iSave'] dSave = lastStepInfo['fortranParams']['dSave'] stepSize, _, _, task = minpack2.dcsrch(stepSize, curObjVal, lineObjDerivative, ftol=1e-4, gtol=0.4, xtol=1e-14, task=task, stpmin=1e-100, stpmax=1e100, isave=iSave, dsave=dSave) return stepSize, task
def _line_search_minpack(self, maxiter: int, amin: float, amax: float): phi0 = self._p['fval'] old_phi0 = self._p['old_fval'] derphi0 = self._derphi(0.0) if derphi0 != 0.0: alpha1 = min(1.0, 2.02 * (phi0 - old_phi0) / derphi0) else: alpha1 = 1.0 if alpha1 <= amin: alpha1 = 1.0 phi1 = phi0 derphi1 = derphi0 isave = np.zeros((2,), np.intc) dsave = np.zeros((13,), float) task = b'START' for _ in range(maxiter): stp, phi1, derphi1, task = dcsrch(alpha1, phi1, derphi1, self._p['c1'], self._p['c2'], self._p['xtol'], task, amin, amax, isave, dsave) if task[:2] == b'FG': alpha1 = stp phi1 = self._phi(stp) derphi1 = self._derphi(stp) else: break self._p['alpha_k'] = stp self._p['fval'] = phi1 self._p['old_fval'] = phi0
def line_search(f, myfprime, xk, pk, gfk, old_fval, old_old_fval, args=(), c1=1e-4, c2=0.9, amax=50): fc = 0 gc = 0 phi0 = old_fval derphi0 = numpy.dot(gfk,pk) alpha1 = pymin(1.0,1.01*2*(phi0-old_old_fval)/derphi0) # trevor: added this test alpha1 = pymin(alpha1,amax) if isinstance(myfprime,type(())): eps = myfprime[1] fprime = myfprime[0] newargs = (f,eps) + args gradient = False else: fprime = myfprime newargs = args gradient = True xtol = 1e-14 amin = 1e-8 isave = numpy.zeros((2,), numpy.intc) dsave = numpy.zeros((13,), float) task = 'START' fval = old_fval gval = gfk while 1: stp,fval,derphi,task = minpack2.dcsrch(alpha1, phi0, derphi0, c1, c2, xtol, task, amin, amax,isave,dsave) #print 'minpack2.dcsrch', alpha1, phi0, derphi0, c1, c2, xtol, task, amin, amax,isave,dsave #print 'returns', stp,fval,derphi,task if task[:2] == 'FG': alpha1 = stp fval = f(xk+stp*pk,*args) fc += 1 gval = fprime(xk+stp*pk,*newargs) if gradient: gc += 1 else: fc += len(xk) + 1 phi0 = fval derphi0 = numpy.dot(gval,pk) else: break if task[:5] == 'ERROR' or task[1:4] == 'WARN': stp = None # failed return stp, fc, gc, fval, old_fval, gval
def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=1e-4, c2=0.9, amax=50, amin=1e-8, xtol=1e-14): if phi0 is None: phi0 = phi(0.) if derphi0 is None: derphi0 = derphi(0.) if old_phi0 is not None and derphi0 != 0: alpha1 = min(1.0, 1.01 * 2 * (phi0 - old_phi0) / derphi0) if alpha1 < 0: alpha1 = 1.0 else: alpha1 = 1.0 phi1 = phi0 derphi1 = derphi0 isave = np.zeros((2, ), np.intc) dsave = np.zeros((13, ), float) task = b'START' maxiter = 100 for i in xrange(maxiter): stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) if task[:2] == b'FG': alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp) else: break else: # maxiter reached, the line search did not converge stp = None if task[:5] == b'ERROR' or task[:4] == b'WARN': stp = None # failed return stp, phi1, phi0
def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=1e-4, c2=0.9, amax=50, amin=1e-8, xtol=1e-14): if phi0 is None: phi0 = phi(0.) if derphi0 is None: derphi0 = derphi(0.) if old_phi0 is not None and derphi0 != 0: alpha1 = min(1.0, 1.01*2*(phi0 - old_phi0)/derphi0) if alpha1 < 0: alpha1 = 1.0 else: alpha1 = .01 phi1 = phi0 derphi1 = derphi0 isave = numpy.zeros((2,), numpy.intc) dsave = numpy.zeros((13,), float) task = b'START' maxiter = 15 for i in xrange(maxiter): stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) #print "alpha1 = ", alpha1 if task[:2] == b'FG': alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp) else: break else: # maxiter reached, the line search did not converge stp = None if task[:5] == b'ERROR' or task[:4] == b'WARN': stp = None # failed return stp, phi1, phi0
def line_search(self,x0,f0,g0,d,above_iter,max_steplength,func,alpha=1e-4,\ beta=0.9,xtol_minpack=1e-5,max_iter=30): steplength_0 = 1 if max_steplength > 1 else 0.5 * max_steplength f_m1 = f0 dphi = g0.dot(d) dphi_m1 = dphi idx = 0 if (above_iter == 0): max_steplength = 1.0 steplength_0 = min(1.0 / np.sqrt(d.dot(d)), 1.0) isave = np.zeros((2, ), np.intc) dsave = np.zeros((13, ), float) task = b'START' while idx < max_iter: steplength,f0,dphi,task=minpack2.dcsrch(steplength_0,f_m1,dphi_m1,\ alpha,beta,xtol_minpack,task,\ 0,max_steplength,isave,dsave) if task[:2] == b'FG': steplength_0 = steplength f_m1, g_m1 = func(x0 + steplength * d) dphi_m1 = g_m1.dot(d) # print(f_m1) else: break else: # max_iter reached, the line search did not converge steplength = None if task[:5] == b'ERROR' or task[:4] == b'WARN': if task[:21] != b'WARNING: STP = STPMAX': print(task) steplength = None # failed return steplength
def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=1e-4, c2=0.9, amax=50, amin=1e-8, xtol=1e-14): """ Scalar function search for alpha that satisfies strong Wolfe conditions alpha > 0 is assumed to be a descent direction. Parameters ---------- phi : callable phi(alpha) Function at point `alpha` derphi : callable dphi(alpha) Derivative `d phi(alpha)/ds`. Returns a scalar. phi0 : float, optional Value of `f` at 0 old_phi0 : float, optional Value of `f` at the previous point derphi0 : float, optional Value `derphi` at 0 c1, c2 : float, optional Wolfe parameters amax, amin : float, optional Maximum and minimum step size xtol : float, optional Relative tolerance for an acceptable step. Returns ------- alpha : float Step size, or None if no suitable step was found phi : float Value of `phi` at the new point `alpha` phi0 : float Value of `phi` at `alpha=0` Notes ----- Uses routine DCSRCH from MINPACK. """ if phi0 is None: phi0 = phi(0.) if derphi0 is None: derphi0 = derphi(0.) if old_phi0 is not None and derphi0 != 0: alpha1 = min(1.0, 1.01*2*(phi0 - old_phi0)/derphi0) if alpha1 < 0: alpha1 = 1.0 else: alpha1 = 1.0 phi1 = phi0 derphi1 = derphi0 isave = np.zeros((2,), np.intc) dsave = np.zeros((13,), float) task = b'START' maxiter = 100 for i in xrange(maxiter): stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) if task[:2] == b'FG': alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp) else: break else: # maxiter reached, the line search did not converge stp = None if task[:5] == b'ERROR' or task[:4] == b'WARN': stp = None # failed return stp, phi1, phi0
def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=1e-4, c2=0.9, amax=50, amin=1e-8, xtol=1e-14): """ Scalar function search for alpha that satisfies strong Wolfe conditions alpha > 0 is assumed to be a descent direction. Parameters ---------- phi : callable phi(alpha) Function at point `alpha` derphi : callable dphi(alpha) Derivative `d phi(alpha)/ds`. Returns a scalar. phi0 : float, optional Value of `f` at 0 old_phi0 : float, optional Value of `f` at the previous point derphi0 : float, optional Value `derphi` at 0 amax : float, optional Maximum step size c1, c2 : float, optional Wolfe parameters Returns ------- alpha : float Step size, or None if no suitable step was found phi : float Value of `phi` at the new point `alpha` phi0 : float Value of `phi` at `alpha=0` Notes ----- Uses routine DCSRCH from MINPACK. """ if phi0 is None: phi0 = phi(0.) if derphi0 is None: derphi0 = derphi(0.) if old_phi0 is not None and derphi0 != 0: alpha1 = min(1.0, 1.01*2*(phi0 - old_phi0)/derphi0) if alpha1 < 0: alpha1 = 1.0 else: alpha1 = 1.0 phi1 = phi0 derphi1 = derphi0 isave = np.zeros((2,), np.intc) dsave = np.zeros((13,), float) task = b'START' maxiter = 30 for i in xrange(maxiter): stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) if task[:2] == b'FG': alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp) else: break else: # maxiter reached, the line search did not converge stp = None if task[:5] == b'ERROR' or task[:4] == b'WARN': stp = None # failed return stp, phi1, phi0
def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=1e-4, c2=0.9, amax=50, amin=1e-8, xtol=1e-14): """ Scalar function search for alpha that satisfies strong Wolfe conditions alpha > 0 is assumed to be a descent direction. Parameters ---------- phi : callable phi(alpha) Function at point `alpha` derphi : callable dphi(alpha) Derivative `d phi(alpha)/ds`. Returns a scalar. phi0 : float, optional Value of `f` at 0 old_phi0 : float, optional Value of `f` at the previous point derphi0 : float, optional Value `derphi` at 0 amax : float, optional Maximum step size c1, c2 : float, optional Wolfe parameters Returns ------- alpha : float Step size, or None if no suitable step was found phi : float Value of `phi` at the new point `alpha` phi0 : float Value of `phi` at `alpha=0` Notes ----- Uses routine DCSRCH from MINPACK. """ if phi0 is None: phi0 = phi(0.) if derphi0 is None: derphi0 = derphi(0.) if old_phi0 is not None: alpha1 = min(1.0, 1.01 * 2 * (phi0 - old_phi0) / derphi0) if alpha1 < 0: alpha1 = 1.0 else: alpha1 = 1.0 phi1 = phi0 derphi1 = derphi0 isave = np.zeros((2, ), np.intc) dsave = np.zeros((13, ), float) task = asbytes('START') while 1: stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) if task[:2] == asbytes('FG'): alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp) else: break if task[:5] == asbytes('ERROR') or task[:4] == asbytes('WARN'): stp = None # failed return stp, phi1, phi0
def find_geodesic_midpoint(start_point, end_point, number_of_inner_points, basis_rotation_matrix, tangent_direction, codimension, metric_server_addresses, mass_matrix, authkey, gtol=1e-5): """ This function computes the local geodesic curve joining start_point to end_point using a modified BFGS method. The modification arises from taking the implementation of BFGS and re-writing it to minimise the number of times the metric function is called. Args: start_point (numpy.array) : The first end point of the curve. end_point (numpy.array) : The last end point of the curve. number_of_inner_points (int) : The number of nodes along the curve, less the end points. basis_rotation_matrix (numpy.array) : The matrix computed as a result of the orthogonal_tangent_basis function. tangent_direction (numpy.array) : The tangent direction as computed by the SimulationClient. codimension (int) : The dimension of the problem minus 1. Computed from the atomistic simulation environment. metric_server_addresses : A list of tuples of the form (str, int) containing the hostnames and port numbers of the SimulationPotential instances. mass_matrix (numpy.array) : A diagonal NumPy array containing the masses of the molecular system as computed in the SimulationClient object. authkey (str) : The password used in order to communicate with the SimulationPotential instances. gtol (optional float) : The tolerance threshold for the BGFS method. Returns: numpy.array: The midpoint along the local geodesic curve. """ # Determine the number of variable the BFGS method will be applied to number_of_variables = number_of_inner_points * codimension # Produce an initial guess for the minimum, in this case it will be that the straight line segment joining # start_point to end_point is the initial guess x0 = np.zeros(number_of_variables) # Allocate memory for the kth iterate xk = x0 # Convert the description of the curve as shifts in the orthonormal hyperspace along the initial line to points in # the full space. See LinearAlgebra.shifts_to_curve for more details. curve = la.shifts_to_curve(start_point, end_point, xk, number_of_inner_points, basis_rotation_matrix, tangent_direction, codimension) # Get the initial metric values along the starting curve. metric = get_metric(curve, number_of_inner_points, metric_server_addresses, authkey) # If the SimulationPotential couldn't be contacted then return None to close the SimulationClient if metric is None: return None # Obtain the initial gradient of the length functional along the curve gfk = GradLength(curve, metric, number_of_inner_points, mass_matrix, basis_rotation_matrix) # Create an identity matrix object I = np.eye(number_of_variables, dtype=int) # Initialise the memory to store the approximate Hessian matrix Hk = I # Compute the norm of the gradient in the L^{\infty} norm gnorm = np.amax(np.abs(gfk)) # The main body of the BFGS calculation: # Repeat the method until the norm of the gradient of the length is sufficiently small. while gnorm > gtol: alpha1 = 1.0 pk = -np.dot(Hk, gfk) phi0 = Length(curve, metric, number_of_inner_points, mass_matrix) phi1 = phi0 derphi0 = np.dot(gfk, pk) derphi1 = derphi0 isave = np.zeros((2,), np.intc) dsave = np.zeros((13,), float) task = b'START' # Perform the linesearch for i in xrange(30): stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, 1e-4, 0.9, 1e-14, task, 1e-8, 50, isave, dsave) if task[:2] == b'FG': alpha1 = stp # Convert the description of the curve as shifts in the orthonormal hyperspace along the initial line # to points in the full space. See LinearAlgebra.shifts_to_curve for more details. curve = la.shifts_to_curve(start_point, end_point, xk + stp*pk, number_of_inner_points, basis_rotation_matrix, tangent_direction, codimension) # Get the initial metric values along the current trial. metric = get_metric(curve, number_of_inner_points, metric_server_addresses, authkey) # If the SimulationPotential couldn't be reached then return None to close SimulationClient if metric is None: return None phi1 = Length(curve, metric, number_of_inner_points, mass_matrix) gfkp1 = GradLength(curve, metric, number_of_inner_points, mass_matrix, basis_rotation_matrix) derphi1 = np.dot(gfkp1, pk) else: break else: break if task[:5] == b'ERROR' or task[:4] == b'WARN': break alpha_k = stp xkp1 = xk + alpha_k * pk sk = xkp1 - xk xk = xkp1 yk = gfkp1 - gfk gfk = gfkp1 gnorm = np.amax(np.abs(gfk)) if gnorm <= gtol: break rhok = 1.0 / (np.dot(yk, sk)) if np.isinf(rhok): rhok = 1000.0 # this is patch for numpy Hk = np.dot(I - sk[:, np.newaxis] * yk[np.newaxis, :] * rhok, np.dot(Hk, I - yk[:, np.newaxis] * sk[np.newaxis, :] * rhok)) + (rhok * sk[:, np.newaxis] * sk[np.newaxis, :]) # Return the midpoint return curve[(number_of_inner_points + 1) / 2]
def line_search(x0, f0, g0, d, above_iter, max_steplength,\ fct_f, fct_grad,\ alpha = 1e-4, beta = 0.9,\ xtol_minpack = 1e-5, max_iter = 30): """ Finds a step that satisfies a sufficient decrease condition and a curvature condition. The algorithm is designed to find a step that satisfies the sufficient decrease condition f(x0+stp*d) <= f(x0) + alpha*stp*\langle f'(x0),d\rangle, and the curvature condition abs(f'(x0+stp*d)) <= beta*abs(\langle f'(x0),d\rangle). If alpha is less than beta and if, for example, the functionis bounded below, then there is always a step which satisfies both conditions. :param x0: starting point :type x0: np.array :param f0: f(x0) :type f0: float :param g0: f'(x0), gradient :type g0: np.array :param d: search direction :type d: np.array :param above_iter: current iteration in optimization process :type above_iter: integer :param max_steplength: maximum steplength allowed :type max_steplength: float :param fct_f: callable, function f(x) :type fct_f: function returning float :param fct_grad: callable, function f'(x) :type fct_grad: function returning np.array :param alpha, beta: parameters of the decrease and curvature conditions :type alpha, beta: floats :param xtol_minpack: tolerance used in minpack2.dcsrch :type xtol_minpack: float :param max_iter: number of iteration allowed for finding a steplength :type max_iter: integer :return: optimal steplength meeting both decrease and curvature condition :rtype: float .. seealso:: [minpack] scipy.optimize.minpack2.dcsrch [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited memory algorithm for bound constrained optimization'', SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN Subroutines for Large Scale Bound Constrained Optimization'' Tech. Report, NAM-11, EECS Department, Northwestern University, 1994. """ steplength_0 = 1 if max_steplength > 1 else 0.5 * max_steplength f_m1 = f0 dphi = g0.dot(d) dphi_m1 = dphi i = 0 if (above_iter == 0): max_steplength = 1.0 steplength_0 = min(1.0 / np.sqrt(d.dot(d)), 1.0) isave = np.zeros((2, ), np.intc) dsave = np.zeros((13, ), float) task = b'START' while i < max_iter: steplength, f0, dphi, task = minpack2.dcsrch(steplength_0, f_m1, dphi_m1, alpha, beta, xtol_minpack, task, 0, max_steplength, isave, dsave) if task[:2] == b'FG': steplength_0 = steplength f_m1 = fct_f(x0 + steplength * d) dphi_m1 = fct_grad(x0 + steplength * d).dot(d) else: break else: # max_iter reached, the line search did not converge steplength = None if task[:5] == b'ERROR' or task[:4] == b'WARN': if task[:21] != b'WARNING: STP = STPMAX': print(task) steplength = None # failed return steplength
def localFinalizeActualSampling(self,jobObject,model,myInput): """ Overwrite only if you need something special at the end of each run.... This function is used by optimizers that need to collect information from the just ended run @ In, jobObject, instance, an instance of a Runner @ In, model, Model, instance of a RAVEN model @ In, myInput, list, the generating input @ Out, None """ #collect first output prefix = jobObject.getMetadata()['prefix'] traj, step, identifier = [int(x) for x in prefix.split('_')] self.raiseADebug('Collected sample "{}"'.format(prefix)) category, number, _, cdId = self._identifierToLabel(identifier) done, index = self._checkModelFinish(str(traj), str(step), str(identifier)) if not done: self.raiseAnError(RuntimeError,'Trying to collect "{}" but identifies as not done!'.format(prefix)) number = number + (cdId * len(self.fullOptVars)) self.realizations[traj]['collect'][category][number].append(index) if len(self.realizations[traj]['collect'][category][number]) == self.realizations[traj]['need']: outputs = self._averageCollectedOutputs(self.realizations[traj]['collect'][category][number]) self.realizations[traj]['denoised'][category][number] = outputs if category == 'opt': converged = self._finalizeOptimalCandidate(traj,outputs) else: converged = False optDone = bool(len(self.realizations[traj]['denoised']['opt'][0])) gradDone = all( len(self.realizations[traj]['denoised']['grad'][i]) for i in range(self.paramDict['pertSingleGrad'])) if not converged and optDone and gradDone: optCandidate = self.normalizeData(self.realizations[traj]['denoised']['opt'][0]) if self.writeSolnExportOn == 'every': self.writeToSolutionExport(traj, optCandidate, self.realizations[traj]['accepted']) # whether we wrote to solution export or not, update the counter self.counter['solutionUpdate'][traj] += 1 self.counter['varsUpdate'][traj] += 1 if self.counter['task'][traj][:5] == b'START': ## since accepted, update history try: self.counter['recentOptHist'][traj][1] = copy.deepcopy(self.counter['recentOptHist'][traj][0]) except KeyError: # this means we don't have an entry for this trajectory yet, so don't copy anything pass # store realization of most recent developments self.counter['recentOptHist'][traj][0] = optCandidate # change xk into array with index matching the index map xk = dict((var,self.realizations[traj]['denoised']['opt'][0][var]) for var in self.getOptVars()) self.counter['xk'][traj] = np.asarray(list(xk.values())) self.counter['oldGradK'][traj] = self.counter['gfk'][traj] gfk = dict((var,self.localEvaluateGradient(traj,gradHist = True)[var][0]) for var in self.getOptVars()) self.counter['gfk'][traj] = np.asarray(list(gfk.values())) if self.useGradHist and self.counter['oldFVal'][traj]: self.counter['oldOldFVal'][traj] = self.counter['oldFVal'][traj] self.counter['oldFVal'][traj] = self.realizations[traj]['denoised']['opt'][0][self.objVar] self.counter['gNorm'][traj] = self.polakRibierePowellStep(traj,self.counter['lastStepSize'][traj], self.counter['gfk'][traj]) else: self.counter['oldFVal'][traj] = self.realizations[traj]['denoised']['opt'][0][self.objVar] self.counter['oldOldFVal'][traj] = self.counter['oldFVal'][traj] + np.linalg.norm(self.counter['gfk'][traj]) / 2 self.counter['pk'][traj] = -(self.counter['gfk'][traj]) self.counter['gNorm'][traj] = np.amax(np.abs(self.counter['gfk'][traj])) # first step self.counter['deltaK'][traj] = np.dot(self.counter['gfk'][traj], self.counter['gfk'][traj]) self.counter['derPhi0'][traj] = np.dot(self.counter['gfk'][traj], self.counter['pk'][traj]) self.counter['alpha'][traj] = min(1.0, 1.01*2*(self.counter['oldFVal'][traj] - self.counter['oldOldFVal'][traj])/self.counter['derPhi0'][traj]) phi1 = self.counter['oldFVal'][traj] derPhi1 = self.counter['derPhi0'][traj] else: newGrad = dict((var,self.localEvaluateGradient(traj, gradHist = True)[var][0]) for var in self.getOptVars()) newGrad = np.asarray(list(newGrad.values())) # after step phi1 = self.realizations[traj]['denoised']['opt'][0][self.objVar] derPhi1 = np.dot(newGrad, self.counter['pk'][traj]) self.counter['lastStepSize'][traj], self.counter['newFVal'][traj], _, self.counter['task'][traj] = minpack2.dcsrch(self.counter['alpha'][traj], phi1, derPhi1, ftol=1e-4, gtol=0.4, xtol=1e-14, task = self.counter['task'][traj], stpmin=1e-100, stpmax=1e100, isave = self.counter['iSave'][traj] , dsave=self.counter['dSave'][traj]) # return of the line search can be those results # If task = 'FG' then evaluate the function and derivative at step and call dcsrch again # If task = 'CONV' then the search is successful. Store this point start a new point # If task = 'WARN' then the subroutine is not able to satisfy the convergence conditions. Counted as converged and resubmit the same point for the presistance # If task = 'ERROR' then there is an error in the input arguments if self.counter['task'][traj][:2] == b'FG': pass # No need to do anything because the value have already been updated elif self.counter['task'][traj][:11] == b'CONVERGENCE' : self.raiseADebug('Local minimal reached, start new line search') self.counter['task'][traj] = b'START' # start a new search elif self.counter['task'][traj][:7] == b'WARNING' : self.raiseAWarning(self.counter['task'][traj][9:].decode().lower()) self.counter['persistence'][traj] += 1 # counted as one converged point if self.counter['persistence'][traj] >= self.convergencePersistence: self.raiseAMessage(' ... Trajectory "{}" converged {} times consecutively!'.format(traj,self.counter['persistence'][traj])) self.convergeTraj[traj] = True self.removeConvergedTrajectory(traj) else: self.raiseAMessage(' ... converged Traj "{}" {} times, required persistence is {}.'.format(traj,self.counter['persistence'][traj],self.convergencePersistence)) else: self.raiseAWarning('Not able to calculate the forward step') self.counter['persistence'][traj] += 1 if self.counter['persistence'][traj] >= self.convergencePersistence: self.raiseAMessage(' ... Trajectory "{}" converged {} times consecutively!'.format(traj,self.counter['persistence'][traj])) self.convergeTraj[traj] = True self.removeConvergedTrajectory(traj) else: self.raiseAMessage(' ... converged Traj "{}" {} times, required persistence is {}.'.format(traj,self.counter['persistence'][traj],self.convergencePersistence)) self.counter['alpha'][traj] = self.counter['lastStepSize'][traj] grad = dict((var,self.counter['gfk'][traj][ind]/(self.optVarsInit['upperBound'][var]-self.optVarsInit['lowerBound'][var])) for ind,var in enumerate(self.getOptVars())) try: self.counter['gradNormHistory'][traj][1] = self.counter['gradNormHistory'][traj][0] except IndexError: pass # don't have a history on the first pass self.counter['gradNormHistory'][traj][0] = grad new = self._newOptPointAdd(grad, traj) if new is not None: # add new gradient points self._createPerturbationPoints(traj, new) # reset storage self._setupNewStorage(traj)