def Run(self): """ Call the appropriate optimizer. This is the method we might want to call from an executable. """ xk = self.OptTab[self.jobtype]() ## Sometimes the optimizer doesn't return anything (i.e. in the case of a single point calculation) ## In these situations, don't do anything if xk == None: return ## Check derivatives by finite difference after the optimization is over (for good measure) check_after = False if check_after: self.mvals0 = xk.copy() self.FDCheckG() ## Print out final answer final_print = True if final_print: bar = printcool("Final optimization parameters:\n Paste to input file to restart",bold=True,color=4) print "read_mvals" self.FF.print_map(xk) print "/read_mvals" bar = printcool("Final physical parameters:",bold=True,color=4) self.FF.print_map(self.FF.create_pvals(xk)) print bar self.FF.make(xk,False,'result') print print "The final force field has been printed to the 'result' directory." #bar = printcool("\x1b[1;45;93mCongratulations, ForceBalance has finished\x1b[0m\n\x1b[1;45;93mGive yourself a pat on the back!\x1b[0m") bar = printcool("Congratulations, ForceBalance has finished\nGive yourself a pat on the back!",ansi="1;44;93") ## Write out stuff to checkpoint file self.writechk() return xk
def FDCheckH(self): """ Finite-difference checker for the objective function Hessian. For each element in the Hessian, use a five-point stencil in both parameter indices to compute a finite-difference derivative, and compare it to the analytic result. This is meant to be a foolproof checker, so it is pretty slow. We could write a faster checker if we assumed we had accurate first derivatives, but it's better to not make that assumption. The second derivative is computed by double-wrapping the objective function via the 'wrap2' function. """ Adata = self.Objective.Full(self.mvals0,Order=2)['H'] Fdata = np.zeros((self.FF.np,self.FF.np),dtype=float) printcool("Checking second derivatives by finite difference!\n%-8s%-20s%-20s%13s%13s%13s%13s" \ % ("Index", "Parameter1 ID", "Parameter2 ID", "Analytic","Numerical","Difference","Fractional"),bold=1,color=5) # Whee, our double-wrapped finite difference second derivative! def wrap2(mvals0,pidxi,pidxj): def func1(arg): mvals = list(mvals0) mvals[pidxj] += arg return f1d5p(fdwrap(self.Objective.Full,mvals,pidxi,'X',Order=0),self.h) return func1 for i in range(self.FF.np): for j in range(i,self.FF.np): Fdata[i,j] = f1d5p(wrap2(self.mvals0,i,j),self.h) Denom = max(abs(Adata[i,j]),abs(Fdata[i,j])) Denom = Denom > 1e-8 and Denom or 1e-8 D = Adata[i,j] - Fdata[i,j] Q = (Adata[i,j] - Fdata[i,j])/Denom cD = abs(D) > 0.5 and "\x1b[1;91m" or (abs(D) > 1e-2 and "\x1b[91m" or (abs(D) > 1e-5 and "\x1b[93m" or "\x1b[92m")) cQ = abs(Q) > 0.5 and "\x1b[1;91m" or (abs(Q) > 1e-2 and "\x1b[91m" or (abs(Q) > 1e-5 and "\x1b[93m" or "\x1b[92m")) print "\r %-8i%-20s%-20s% 13.4e% 13.4e%s% 13.4e%s% 13.4e\x1b[0m" \ % (i, self.FF.plist[i][:20], self.FF.plist[j][:20], Adata[i,j], Fdata[i,j], cD, D, cQ, Q)
def FDCheckG(self): """ Finite-difference checker for the objective function gradient. For each element in the gradient, use a five-point finite difference stencil to compute a finite-difference derivative, and compare it to the analytic result. """ Adata = self.Objective.Full(self.mvals0,Order=1)['G'] Fdata = np.zeros(self.FF.np,dtype=float) printcool("Checking first derivatives by finite difference!\n%-8s%-20s%13s%13s%13s%13s" \ % ("Index", "Parameter ID","Analytic","Numerical","Difference","Fractional"),bold=1,color=5) for i in range(self.FF.np): Fdata[i] = f1d7p(fdwrap(self.Objective.Full,self.mvals0,i,'X',Order=0),self.h) Denom = max(abs(Adata[i]),abs(Fdata[i])) Denom = Denom > 1e-8 and Denom or 1e-8 D = Adata[i] - Fdata[i] Q = (Adata[i] - Fdata[i])/Denom cD = abs(D) > 0.5 and "\x1b[1;91m" or (abs(D) > 1e-2 and "\x1b[91m" or (abs(D) > 1e-5 and "\x1b[93m" or "\x1b[92m")) cQ = abs(Q) > 0.5 and "\x1b[1;91m" or (abs(Q) > 1e-2 and "\x1b[91m" or (abs(Q) > 1e-5 and "\x1b[93m" or "\x1b[92m")) print "\r %-8i%-20s% 13.4e% 13.4e%s% 13.4e%s% 13.4e\x1b[0m" \ % (i, self.FF.plist[i][:20], Adata[i], Fdata[i], cD, D, cQ, Q)
def parse_inputs(input_file=None): """ Parse through the input file and read all user-supplied options. This is usually the first thing that happens when an executable script is called. Our parser first loads the default options, and then updates these options as it encounters keywords. Each keyword corresponds to a variable type; each variable type (e.g. string, integer, float, boolean) is treated differently. For more elaborate inputs, there is a 'section' variable type. There is only one set of general options, but multiple sets of target options. Each target has its own section delimited by the \em $target keyword, and we build a list of target options. @param[in] input_file The name of the input file. @return options General options. @return tgt_opts List of fitting target options. @todo Implement internal coordinates. @todo Implement sampling correction. @todo Implement charge groups. """ logger.info("Reading options from file: %s\n" % input_file) section = "NONE" # First load in all of the default options. options = deepcopy(gen_opts_defaults) # deepcopy to make sure options doesn't make changes to gen_opts_defaults options['root'] = os.getcwd() options['input_file'] = input_file tgt_opts = [] this_tgt_opt = deepcopy(tgt_opts_defaults) # Give back a bunch of default options if input file isn't specified. if input_file == None: return (options, [this_tgt_opt]) fobj = open(input_file) for line in fobj: try: # Anything after "#" is a comment line = line.split("#")[0].strip() s = line.split() # Skip over blank lines if len(s) == 0: continue key = s[0].lower() if key in bkwd: # Do option replacement for backward compatibility. key = bkwd[key] # If line starts with a $, this signifies that we're in a new section. if re.match('^\$',line): newsection = re.sub('^\$','',line).upper() if section in ["SIMULATION","TARGET"] and newsection in mainsections: tgt_opts.append(this_tgt_opt) this_tgt_opt = deepcopy(tgt_opts_defaults) if newsection == "END": newsection = "NONE" section = newsection elif section in ["OPTIONS","SIMULATION","TARGET"]: ## Depending on which section we are in, we choose the correct type dictionary ## and add stuff to 'options' and 'this_tgt_opt' (this_opt, opts_types) = (options, gen_opts_types) if section == "OPTIONS" else (this_tgt_opt, tgt_opts_types) ## Note that "None" is a special keyword! The variable will ACTUALLY be set to None. if len(s) > 1 and s[1].upper() == "NONE": this_opt[key] = None elif key in opts_types['strings']: this_opt[key] = s[1] elif key in opts_types['allcaps']: this_opt[key] = s[1].upper() elif key in opts_types['lists']: for word in s[1:]: this_opt.setdefault(key,[]).append(word) elif key in opts_types['ints']: if isfloat(s[1]): this_opt[key] = int(float(s[1])) else: this_opt[key] = int(s[1]) elif key in opts_types['bools']: if len(s) == 1: this_opt[key] = True elif s[1].upper() in ["0", "NO", "FALSE", "OFF"]: this_opt[key] = False elif isfloat(s[1]) and int(float(s[1])) == 0: this_opt[key] = False elif s[1].upper() in ["1", "YES", "TRUE", "ON"]: this_opt[key] = True elif isfloat(s[1]) and int(float(s[1])) == 1: this_opt[key] = True else: raise RuntimeError('%s is a true/false option but you provided %s; to enable, provide ["1", "yes", "true", "on" or <no value>]. To disable, provide ["0", "no", "false", or "off"].' % (key, s[1])) elif key in opts_types['floats']: this_opt[key] = float(s[1]) elif key in opts_types['sections']: this_opt[key] = ParsTab[key](fobj) else: logger.error("Unrecognized keyword: --- \x1b[1;91m%s\x1b[0m --- in %s section\n" \ % (key, section)) logger.error("Perhaps this option actually belongs in %s section?\n" \ % (section == "OPTIONS" and "a TARGET" or "the OPTIONS")) raise RuntimeError elif section == "NONE" and len(s) > 0: logger.error("Encountered a non-comment line outside of a section\n") raise RuntimeError elif section not in mainsections: logger.error("Unrecognized section: %s\n" % section) raise RuntimeError except: # traceback.print_exc() logger.exception("Failed to read in this line! Check your input file.\n") logger.exception('\x1b[91m' + line + '\x1b[0m\n') raise RuntimeError if section == "SIMULATION" or section == "TARGET": tgt_opts.append(this_tgt_opt) if not options['verbose_options']: printcool("Options at their default values are not printed\n Use 'verbose_options True' to Enable", color=5) return options, tgt_opts
def parse_inputs(input_file=None): """ Parse through the input file and read all user-supplied options. This is usually the first thing that happens when an executable script is called. Our parser first loads the default options, and then updates these options as it encounters keywords. Each keyword corresponds to a variable type; each variable type (e.g. string, integer, float, boolean) is treated differently. For more elaborate inputs, there is a 'section' variable type. There is only one set of general options, but multiple sets of target options. Each target has its own section delimited by the \em $target keyword, and we build a list of target options. @param[in] input_file The name of the input file. @return options General options. @return tgt_opts List of fitting target options. @todo Implement internal coordinates. @todo Implement sampling correction. @todo Implement charge groups. """ logger.info("Reading options from file: %s\n" % input_file) section = "NONE" # First load in all of the default options. options = deepcopy(gen_opts_defaults) # deepcopy to make sure options doesn't make changes to gen_opts_defaults options['root'] = os.getcwd() options['input_file'] = input_file tgt_opts = [] this_tgt_opt = deepcopy(tgt_opts_defaults) # Give back a bunch of default options if input file isn't specified. if input_file == None: return (options, [this_tgt_opt]) fobj = open(input_file) for line in fobj: try: # Anything after "#" is a comment line = line.split("#")[0].strip() s = line.split() # Skip over blank lines if len(s) == 0: continue key = s[0].lower() if key in bkwd: # Do option replacement for backward compatibility. key = bkwd[key] # If line starts with a $, this signifies that we're in a new section. if re.match('^\$',line): newsection = re.sub('^\$','',line).upper() if section in ["SIMULATION","TARGET"] and newsection in mainsections: tgt_opts.append(this_tgt_opt) this_tgt_opt = deepcopy(tgt_opts_defaults) if newsection == "END": newsection = "NONE" section = newsection elif section in ["OPTIONS","SIMULATION","TARGET"]: ## Depending on which section we are in, we choose the correct type dictionary ## and add stuff to 'options' and 'this_tgt_opt' (this_opt, opts_types) = (options, gen_opts_types) if section == "OPTIONS" else (this_tgt_opt, tgt_opts_types) ## Note that "None" is a special keyword! The variable will ACTUALLY be set to None. if len(s) > 1 and s[1].upper() == "NONE": this_opt[key] = None elif key in opts_types['strings']: this_opt[key] = s[1] elif key in opts_types['allcaps']: this_opt[key] = s[1].upper() elif key in opts_types['lists']: for word in s[1:]: this_opt.setdefault(key,[]).append(word) elif key in opts_types['ints']: if isfloat(s[1]): this_opt[key] = int(float(s[1])) else: this_opt[key] = int(s[1]) elif key in opts_types['bools']: if len(s) == 1: this_opt[key] = True elif s[1].upper() in ["0", "NO", "FALSE", "OFF"]: this_opt[key] = False elif isfloat(s[1]) and int(float(s[1])) == 0: this_opt[key] = False elif s[1].upper() in ["1", "YES", "TRUE", "ON"]: this_opt[key] = True elif isfloat(s[1]) and int(float(s[1])) == 1: this_opt[key] = True else: logger.error('%s is a true/false option but you provided %s; to enable, provide ["1", "yes", "true", "on" or <no value>]. To disable, provide ["0", "no", "false", or "off"].\n' % (key, s[1])) raise RuntimeError elif key in opts_types['floats']: this_opt[key] = float(s[1]) elif key in opts_types['sections']: this_opt[key] = ParsTab[key](fobj) else: logger.error("Unrecognized keyword: --- \x1b[1;91m%s\x1b[0m --- in %s section\n" \ % (key, section)) logger.error("Perhaps this option actually belongs in %s section?\n" \ % (section == "OPTIONS" and "a TARGET" or "the OPTIONS")) raise RuntimeError elif section == "NONE" and len(s) > 0: logger.error("Encountered a non-comment line outside of a section\n") raise RuntimeError elif section not in mainsections: logger.error("Unrecognized section: %s\n" % section) raise RuntimeError except: # traceback.print_exc() logger.exception("Failed to read in this line! Check your input file.\n") logger.exception('\x1b[91m' + line + '\x1b[0m\n') raise RuntimeError if section == "SIMULATION" or section == "TARGET": tgt_opts.append(this_tgt_opt) if not options['verbose_options']: printcool("Options at their default values are not printed\n Use 'verbose_options True' to Enable", color=5) # Expand target options (i.e. create multiple tgt_opts dictionaries if multiple target names are specified) tgt_opts_x = [] for topt in tgt_opts: for name in topt['name']: toptx = deepcopy(topt) toptx['name'] = name tgt_opts_x.append(toptx) return options, tgt_opts_x
def ScipyOptimizer(self,Algorithm="None"): """ Driver for SciPy optimizations. Using any of the SciPy optimizers requires that SciPy is installed. This method first defines several wrappers around the objective function that the SciPy optimizers can use. Then it calls the algorith mitself. @param[in] Algorithm The optimization algorithm to use, for example 'powell', 'simplex' or 'anneal' """ from scipy import optimize def xwrap(func,verbose=True): def my_func(mvals): if verbose: print Answer = func(mvals,Order=0,verbose=verbose)['X'] dx = (my_func.x_best - Answer) if my_func.x_best != None else 0.0 if Answer < my_func.x_best or my_func.x_best == None: color = "\x1b[92m" my_func.x_best = Answer else: color = "\x1b[91m" if verbose: if self.print_vals: print "k=", ' '.join(["% .4f" % i for i in mvals]) print "X2= %s%12.3e\x1b[0m d(X2)= %12.3e" % (color,Answer,dx) if Answer != Answer: return 1e10 else: return Answer my_func.x_best = None return my_func def gwrap(func,verbose=True): def my_gfunc(mvals): if verbose: print Output = func(mvals,Order=1,verbose=verbose) Answer = Output['G'] Objective = Output['X'] dx = (my_gfunc.x_best - Objective) if my_gfunc.x_best != None else 0.0 if Objective < my_gfunc.x_best or my_gfunc.x_best == None: color = "\x1b[92m" my_gfunc.x_best = Objective else: color = "\x1b[91m" if verbose: if self.print_vals: print "k=", ' '.join(["% .4f" % i for i in mvals]) print "|Grad|= %12.3e X2= %s%12.3e\x1b[0m d(X2)= %12.3e" % (norm(Answer),color,Objective,dx) print return Answer my_gfunc.x_best = None return my_gfunc if Algorithm == "powell": printcool("Minimizing Objective Function using Powell's Method" , ansi=1, bold=1) return optimize.fmin_powell(xwrap(self.Objective.Full),self.mvals0,ftol=self.conv_obj,xtol=self.conv_stp,maxiter=self.maxstep) elif Algorithm == "simplex": printcool("Minimizing Objective Function using Simplex Method" , ansi=1, bold=1) return optimize.fmin(xwrap(self.Objective.Full),self.mvals0,ftol=self.conv_obj,xtol=self.conv_stp,maxiter=self.maxstep,maxfun=self.maxstep*10) elif Algorithm == "anneal": printcool("Minimizing Objective Function using Simulated Annealing" , ansi=1, bold=1) return optimize.anneal(xwrap(self.Objective.Full),self.mvals0,lower=-1*self.trust0*np.ones(self.np),upper=self.trust0*np.ones(self.np),schedule='boltzmann') elif Algorithm == "cg": printcool("Minimizing Objective Function using Conjugate Gradient" , ansi=1, bold=1) return optimize.fmin_cg(xwrap(self.Objective.Full,verbose=False),self.mvals0,fprime=gwrap(self.Objective.Full),gtol=self.conv_grd)
def MainOptimizer(self,b_BFGS=0): """ The main ForceBalance adaptive trust-radius pseudo-Newton optimizer. Tried and true in many situations. :) Usually this function is called with the BFGS or NewtonRaphson method. The NewtonRaphson method is consistently the best method I have, because I always provide at least an approximate Hessian to the objective function. The BFGS method is vestigial and currently does not work. BFGS is a pseudo-Newton method in the sense that it builds an approximate Hessian matrix from the gradient information in previous steps; Newton-Raphson requires the actual Hessian matrix. However, the algorithms are similar in that they both compute the step by inverting the Hessian and multiplying by the gradient. The method adaptively changes the step size. If the step is sufficiently good (i.e. the objective function goes down by a large fraction of the predicted decrease), then the step size is increased; if the step is bad, then it rejects the step and tries again. The optimization is terminated after either a function value or step size tolerance is reached. @param[in] b_BFGS Switch to use BFGS (True) or Newton-Raphson (False) """ if any(['liquid' in tgt.name.lower() for tgt in self.Objective.Targets]) and self.conv_obj < 1e-3: warn_press_key("Condensed phase targets detected - may not converge with current choice of convergence_objective (%.e)\nRecommended range is 1e-2 - 1e-1 for this option." % self.conv_obj) # Parameters for the adaptive trust radius a = self.adapt_fac # Default value is 0.5, decrease to make more conservative. Zero to turn off all adaptive. b = self.adapt_damp # Default value is 0.5, increase to make more conservative printcool( "Main Optimizer\n%s Mode%s" % ("BFGS" if b_BFGS else "Newton-Raphson", " (Static Radius)" if a == 0.0 else " (Adaptive Radius)"), ansi=1, bold=1) # First, set a bunch of starting values Ord = 1 if b_BFGS else 2 #Ord = 2 global ITERATION_NUMBER ITERATION_NUMBER = 0 global GOODSTEP Best_Step = 1 if all(i in self.chk for i in ['xk','X','G','H','ehist','x_best','xk_prev','trust']): print "Reading initial objective, gradient, Hessian from checkpoint file" xk, X, G, H, ehist = self.chk['xk'], self.chk['X'], self.chk['G'], self.chk['H'], self.chk['ehist'] X_best, xk_prev, trust = self.chk['x_best'], self.chk['xk_prev'], self.chk['trust'] else: xk = self.mvals0.copy() print data = self.Objective.Full(xk,Ord,verbose=True) X, G, H = data['X'], data['G'], data['H'] ehist = np.array([X]) xk_prev = xk.copy() trust = abs(self.trust0) X_best = X X_prev = X G_prev = G.copy() H_stor = H.copy() ndx = 0.0 color = "\x1b[1m" nxk = norm(xk) ngr = norm(G) Quality = 0.0 restep = False GOODSTEP = 1 Ord = 1 if b_BFGS else 2 while 1: # Loop until convergence is reached. ## Put data into the checkpoint file self.chk = {'xk': xk, 'X' : X, 'G' : G, 'H': H, 'ehist': ehist, 'x_best': X_best,'xk_prev': xk_prev, 'trust': trust} if self.wchk_step: self.writechk() stdfront = len(ehist) > self.hist and np.std(np.sort(ehist)[:self.hist]) or (len(ehist) > 0 and np.std(ehist) or 0.0) stdfront *= 2 print "%6s%12s%12s%12s%14s%12s%12s" % ("Step", " |k| "," |dk| "," |grad| "," -=X2=- ","Delta(X2)", "StepQual") print "%6i%12.3e%12.3e%12.3e%s%14.5e\x1b[0m%12.3e% 11.3f\n" % (ITERATION_NUMBER, nxk, ndx, ngr, color, X, stdfront, Quality) # Check the convergence criteria if ngr < self.conv_grd: print "Convergence criterion reached for gradient norm (%.2e)" % self.conv_grd break if ITERATION_NUMBER == self.maxstep: print "Maximum number of optimization steps reached (%i)" % ITERATION_NUMBER break if ndx < self.conv_stp and ITERATION_NUMBER > 0 and not restep: print "Convergence criterion reached in step size (%.2e)" % self.conv_stp break if stdfront < self.conv_obj and len(ehist) > self.hist and not restep: # Factor of two is so [0,1] stdev is normalized to 1 print "Convergence criterion reached for objective function (%.2e)" % self.conv_obj break if self.print_grad: bar = printcool("Total Gradient",color=4) self.FF.print_map(vals=G,precision=8) print bar if self.print_hess: bar = printcool("Total Hessian",color=4) pmat2d(H,precision=8) print bar for key, val in self.Objective.ObjDict.items(): if Best_Step: self.Objective.ObjDict_Last[key] = val restep = False dx, dX_expect, bump = self.step(xk, data, trust) old_pk = self.FF.create_pvals(xk) old_xk = xk.copy() # Increment the iteration counter. ITERATION_NUMBER += 1 # Take a step in the parameter space. xk += dx if self.print_vals: pk = self.FF.create_pvals(xk) dp = pk - old_pk bar = printcool("Mathematical Parameters (Current + Step = Next)",color=5) self.FF.print_map(vals=["% .4e %s %.4e = % .4e" % (old_xk[i], '+' if dx[i] >= 0 else '-', abs(dx[i]), xk[i]) for i in range(len(xk))]) print bar bar = printcool("Physical Parameters (Current + Step = Next)",color=5) self.FF.print_map(vals=["% .4e %s %.4e = % .4e" % (old_pk[i], '+' if dp[i] >= 0 else '-', abs(dp[i]), pk[i]) for i in range(len(pk))]) print bar # Evaluate the objective function and its derivatives. data = self.Objective.Full(xk,Ord,verbose=True) X, G, H = data['X'], data['G'], data['H'] ndx = norm(dx) nxk = norm(xk) ngr = norm(G) drc = abs(flat(dx)).argmax() dX_actual = X - X_prev try: Quality = dX_actual / dX_expect except: print "Warning: Step size of zero detected (i.e. wrong direction). Try reducing the finite_difference_h parameter" Quality = 1.0 # This is a step length of zero. if Quality <= 0.25 and X < (X_prev + self.err_tol) and self.trust0 > 0: # If the step quality is bad, then we should decrease the trust radius. trust = max(ndx*(1./(1+a)), self.mintrust) print "Low quality step, reducing trust radius to % .4e" % trust if Quality >= 0.75 and bump and self.trust0 > 0: # If the step quality is good, then we should increase the trust radius. # The 'a' factor is how much we should grow or shrink the trust radius each step # and the 'b' factor determines how closely we are tied down to the original value. # Recommend values 0.5 and 0.5 trust += a*trust*np.exp(-b*(trust/self.trust0 - 1)) if X > (X_prev + self.err_tol): Best_Step = 0 # Toggle switch for rejection (experimenting with no rejection) Rejects = True GOODSTEP = 0 Reevaluate = True trust = max(ndx*(1./(1+a)), self.mintrust) print "Rejecting step and reducing trust radius to % .4e" % trust if Rejects: xk = xk_prev.copy() if Reevaluate: restep = True color = "\x1b[91m" print "%6s%12s%12s%12s%14s%12s%12s" % ("Step", " |k| "," |dk| "," |grad| "," -=X2=- ","Delta(X2)", "StepQual") print "%6i%12.3e%12.3e%12.3e%s%14.5e\x1b[0m%12.3e% 11.3f\n" % (ITERATION_NUMBER, nxk, ndx, ngr, color, X, stdfront, Quality) printcool("Objective function rises!\nRe-evaluating at the previous point..",color=1) ITERATION_NUMBER += 1 data = self.Objective.Full(xk,Ord,verbose=True) GOODSTEP = 1 X, G, H = data['X'], data['G'], data['H'] X_prev = X dx *= 0 ndx = norm(dx) nxk = norm(xk) ngr = norm(G) Quality = 0.0 color = "\x1b[0m" else: color = "\x1b[91m" G = G_prev.copy() H = H_stor.copy() data = deepcopy(datastor) continue else: GOODSTEP = 1 if X > X_best: Best_Step = 0 color = "\x1b[95m" else: Best_Step = 1 color = "\x1b[92m" X_best = X ehist = np.append(ehist, X) # Hessian update for BFGS. if b_BFGS: Hnew = H_stor.copy() Dx = col(xk - xk_prev) Dy = col(G - G_prev) Mat1 = (Dy*Dy.T)/(Dy.T*Dx)[0,0] Mat2 = ((Hnew*Dx)*(Hnew*Dx).T)/(Dx.T*Hnew*Dx)[0,0] Hnew += Mat1-Mat2 H = Hnew.copy() data['H'] = H.copy() datastor= deepcopy(data) G_prev = G.copy() H_stor = H.copy() xk_prev = xk.copy() X_prev = X if len(self.FF.parmdestroy_this) > 0: self.FF.parmdestroy_save.append(self.FF.parmdestroy_this) self.FF.linedestroy_save.append(self.FF.linedestroy_this) bar = printcool("Final objective function value\nFull: % .6e Un-penalized: % .6e" % (data['X'],data['X0']), '@', bold=True, color=2) return xk