def test_snopt(self): name = "tp109_snopt.hst" self.optimize("snopt", 1e-7, storeHistory=name) hist = History(name) self.assertNotIn("lin_con", hist.getConNames()) self.assertNotIn("lin_con", hist.getConInfo()) hist.getValues() hist.getValues(scale=True)
def check_hist_file(self, optimizer, tol): """ We check the history file here along with the API """ hist = History(self.histFileName, flag="r") # Metadata checks metadata = hist.getMetadata() self.assertEqual(metadata["optimizer"], optimizer) metadata_def_keys = ["optName", "optOptions", "nprocs", "startTime", "endTime", "optTime", "version"] for key in metadata_def_keys: self.assertIn(key, metadata) hist.getOptProb() # Info checks self.assertEqual(hist.getDVNames(), ["xvars"]) self.assertEqual(hist.getConNames(), ["con"]) self.assertEqual(hist.getObjNames(), ["obj"]) dvInfo = hist.getDVInfo() self.assertEqual(len(dvInfo), 1) self.assertEqual(dvInfo["xvars"], hist.getDVInfo(key="xvars")) conInfo = hist.getConInfo() self.assertEqual(len(conInfo), 1) self.assertEqual(conInfo["con"], hist.getConInfo(key="con")) objInfo = hist.getObjInfo() self.assertEqual(len(objInfo), 1) self.assertEqual(objInfo["obj"], hist.getObjInfo(key="obj")) for key in ["lower", "upper", "scale"]: self.assertIn(key, dvInfo["xvars"]) self.assertIn(key, conInfo["con"]) self.assertIn("scale", objInfo["obj"]) # callCounter checks callCounters = hist.getCallCounters() last = hist.read("last") # 'last' key should be present self.assertIn(last, callCounters) # iterKeys checks iterKeys = hist.getIterKeys() for key in ["xuser", "fail", "isMajor"]: self.assertIn(key, iterKeys) # extraFuncsNames checks extraFuncsNames = hist.getExtraFuncsNames() for key in ["extra1", "extra2"]: self.assertIn(key, extraFuncsNames) # getValues checks val = hist.getValues() # this check is only used for optimizers that guarantee '0' and 'last' contain funcs if optimizer in ["SNOPT", "SLSQP", "PSQP"]: val = hist.getValues(callCounters=["0", "last"], stack=True) self.assertEqual(val["isMajor"].size, 2) self.assertTrue(val["isMajor"][0]) # the first callCounter must be a major iteration self.assertTrue(val["isMajor"][-1]) # the last callCounter must be a major iteration # check optimum stored in history file against xstar assert_allclose(val["xuser"][-1], self.xStar1, atol=tol, rtol=tol)
def check_hist_file(self, optimizer): """ We check the history file here along with the API """ hist = History(self.histFileName, flag='r') # Metadata checks metadata = hist.getMetadata() self.assertEqual(metadata['optimizer'], optimizer) metadata_def_keys = [ 'optName', 'optOptions', 'nprocs', 'startTime', 'endTime', 'optTime', 'version' ] for key in metadata_def_keys: self.assertIn(key, metadata) # Info checks self.assertEqual(hist.getDVNames(), ['xvars']) self.assertEqual(hist.getConNames(), ['con']) self.assertEqual(hist.getObjNames(), ['obj']) dvInfo = hist.getDVInfo() self.assertEqual(len(dvInfo), 1) self.assertEqual(dvInfo['xvars'], hist.getDVInfo(key='xvars')) conInfo = hist.getConInfo() self.assertEqual(len(conInfo), 1) self.assertEqual(conInfo['con'], hist.getConInfo(key='con')) objInfo = hist.getObjInfo() self.assertEqual(len(objInfo), 1) self.assertEqual(objInfo['obj'], hist.getObjInfo(key='obj')) for key in ['lower', 'upper', 'scale']: self.assertIn(key, dvInfo['xvars']) self.assertIn(key, conInfo['con']) self.assertIn('scale', objInfo['obj']) # callCounter checks callCounters = hist.getCallCounters() last = hist.read('last') # 'last' key should be present self.assertIn(last, callCounters) # iterKey checks iterKeys = hist.getIterKeys() for key in ['xuser', 'fail', 'isMajor']: self.assertIn(key, iterKeys) # getValues check hist.getValues() hist.getValues(stack=True, major=False, scale=True) # this check is only used for optimizers that guarantee '0' and 'last' contain funcs if optimizer in ['SNOPT', 'SLSQP', 'PSQP']: val = hist.getValues(callCounters=['0', 'last']) self.assertEqual(val['isMajor'].size, 2) self.assertTrue( val['isMajor'] [0]) # the first callCounter must be a major iteration self.assertTrue( val['isMajor'] [-1]) # the last callCounter must be a major iteration
def test_slsqp_scaling_offset_optProb(self): """ Test that scaling and offset works as expected Also test optProb stored in the history file is correct """ test_name = "hs071_SLSQP_scaling_offset" histFileName = "{}.hst".format(test_name) optOptions = {"IFILE": "{}.out".format(test_name)} objScale = 4.2 xScale = [2, 3, 4, 5] conScale = [0.6, 1.7] offset = [1, -2, 40, 2.5] self.optimize( "slsqp", 1e-6, objScale=objScale, xScale=xScale, conScale=conScale, storeHistory=histFileName, offset=offset, optOptions=optOptions, ) # now we retrieve the history file, and check the scale=True option is indeed # scaling things correctly hist = History(histFileName, flag="r") orig_values = hist.getValues(callCounters="0", scale=False) optProb = hist.getOptProb() # check that the scales are stored properly for i, var in enumerate(optProb.variables["xvars"]): assert_allclose(xScale[i], var.scale, atol=1e-12, rtol=1e-12) assert_allclose(offset[i], var.offset, atol=1e-12, rtol=1e-12) for con in optProb.constraints: assert_allclose(conScale, optProb.constraints[con].scale, atol=1e-12, rtol=1e-12) for obj in optProb.objectives: assert_allclose(objScale, optProb.objectives[obj].scale, atol=1e-12, rtol=1e-12) # verify the scale option in getValues scaled_values = hist.getValues(callCounters="0", scale=True, stack=False) x = orig_values["xvars"][0] x_scaled = scaled_values["xvars"][0] assert_allclose(x_scaled, (x - offset) * xScale, atol=1e-12, rtol=1e-12) # now do the same but with stack=True stacked_values = hist.getValues(callCounters="0", scale=True, stack=True) x_scaled = stacked_values["xuser"][0] assert_allclose(x_scaled, (x - offset) * xScale, atol=1e-12, rtol=1e-12) # now we test objective and constraint scaling in getValues obj_orig = orig_values["obj"][0] obj_scaled = scaled_values["obj"][0] assert_allclose(obj_scaled, obj_orig * objScale, atol=1e-12, rtol=1e-12) con_orig = orig_values["con"][0] con_scaled = scaled_values["con"][0] assert_allclose(con_scaled, con_orig * conScale, atol=1e-12, rtol=1e-12)
def test_snopt(self): name = "tp109_snopt.hst" self.optimize("SNOPT", 1e-7, storeHistory=name) hist = History(name) self.assertNotIn("lin_con", hist.getConNames()) self.assertNotIn("lin_con", hist.getConInfo()) val = hist.getValues() hist.getValues(scale=True) # Check that the function values in the history are real self.assertTrue(np.isrealobj(val["obj"])) self.assertTrue(np.isrealobj(val["con"]))
def test_snopt(self): self.optName = "SNOPT" self.setup_optProb() sol = self.optimize(storeHistory=True, sens="CS") self.assert_solution_allclose(sol, 1e-7) hist = History(self.histFileName) self.assertNotIn("lin_con", hist.getConNames()) self.assertNotIn("lin_con", hist.getConInfo()) val = hist.getValues() hist.getValues(scale=True) # Check that the function values in the history are real self.assertTrue(np.isrealobj(val["obj"])) self.assertTrue(np.isrealobj(val["con"]))
def test_snopt(self): store_vars = [ 'step', 'merit', 'feasibility', 'optimality', 'penalty', 'Hessian', 'condZHZ', 'slack', 'lambda' ] optOptions = {'Save major iteration variables': store_vars} self.optimize('snopt', optOptions=optOptions, storeHistory=True) self.check_hist_file('SNOPT') hist = History(self.histFileName, flag='r') data = hist.getValues(callCounters=['last']) keys = hist.getIterKeys() self.assertIn('isMajor', keys) self.assertEqual(7, data['nMajor']) for var in store_vars: self.assertIn(var, data.keys()) # re-optimize with hotstart self.optimize('snopt', storeHistory=False, hotStart=self.histFileName) # now we should do the same optimization without calling them self.assertEqual(self.nf, 0) self.assertEqual(self.ng, 0) # another test with hotstart, this time with storeHistory = hotStart self.optimize('snopt', storeHistory=True, hotStart=self.histFileName) # now we should do the same optimization without calling them self.assertEqual(self.nf, 0) self.assertEqual(self.ng, 0) # final test with hotstart, this time with a different storeHistory self.optimize('snopt', storeHistory='snopt_new_hotstart.hst', hotStart=self.histFileName) # now we should do the same optimization without calling them self.assertEqual(self.nf, 0) self.assertEqual(self.ng, 0)
def test_snopt_setDVFromHist(self): """ Test that setDVFromHistory works as expected, even with scaling/offset """ test_name = "hs071_SNOPT_setDVFromHist" optOptions = { "Print file": "{}.out".format(test_name), "Summary file": "{}_summary.out".format(test_name), } histFileName = "{}.hst".format(test_name) self.optimize( "SNOPT", 1e-6, xScale=1.5, conScale=1.2, objScale=32, offset=1.5, storeHistory=histFileName, optOptions=optOptions, ) hist = History(histFileName, flag="r") first = hist.getValues(names="xvars", callCounters="last", scale=False) x_final = first["xvars"][0] self.optimize( "SNOPT", 1e-6, xScale=0.5, conScale=4.8, objScale=0.1, offset=1.5, setDV=histFileName, storeHistory=histFileName, optOptions=optOptions, ) # Verify the history file hist = History(histFileName, flag="r") second = hist.getValues(names="xvars", scale=False) x_init = second["xvars"][0] assert_allclose(x_init, x_final, atol=1e-5, rtol=1e-5) # assert that this only took one major iteration # since we restarted from the optimum self.assertEqual(second["xvars"].shape, (1, 4))
def test_snopt_setDVFromHist(self): """ Test that setDVFromHistory works as expected, even with scaling/offset """ self.optName = "SNOPT" histFileName = "hs071_SNOPT_setDVFromHist.hst" self.setup_optProb(xScale=1.5, conScale=1.2, objScale=32, offset=1.5) sol = self.optimize(storeHistory=histFileName) self.assert_solution_allclose(sol, self.tol["SNOPT"]) hist = History(histFileName, flag="r") first = hist.getValues(names="xvars", callCounters="last", scale=False) x_final = first["xvars"][0] self.setup_optProb(xScale=0.5, conScale=4.8, objScale=0.1, offset=1.5) sol = self.optimize(setDV=histFileName, storeHistory=histFileName) self.assert_solution_allclose(sol, self.tol["SNOPT"]) # Verify the history file hist = History(histFileName, flag="r") second = hist.getValues(names="xvars", scale=False) x_init = second["xvars"][0] assert_allclose(x_init, x_final, atol=1e-5, rtol=1e-5) # assert that this only took one major iteration # since we restarted from the optimum self.assertEqual(second["xvars"].shape, (1, 4))
def test_slsqp_setDV(self): """ Test that setDV works as expected, even with scaling/offset """ self.optName = "SLSQP" histFileName = "hs071_SLSQP_setDV.hst" newDV = {"xvars": np.array([1, 4, 4, 1])} self.setup_optProb(xScale=1.5, conScale=1.2, objScale=32, offset=1.5) sol = self.optimize(setDV=newDV, storeHistory=histFileName) self.assert_solution_allclose(sol, self.tol["SLSQP"]) # Verify the history file hist = History(histFileName, flag="r") init = hist.getValues(names="xvars", callCounters="0", scale=False) x_init = init["xvars"][0] assert_allclose(x_init, newDV["xvars"], atol=1e-5, rtol=1e-5)
def test_snopt(self): self.optName = "SNOPT" self.setup_optProb() store_vars = ["step", "merit", "feasibility", "optimality", "penalty", "Hessian", "condZHZ", "slack", "lambda"] optOptions = { "Save major iteration variables": store_vars, } self.optimize_with_hotstart(1e-8, optOptions=optOptions) hist = History(self.histFileName, flag="r") data = hist.getValues(callCounters=["last"]) keys = hist.getIterKeys() self.assertIn("isMajor", keys) self.assertEqual(36, data["nMajor"]) for var in store_vars: self.assertIn(var, data.keys()) self.assertEqual(data["Hessian"].shape, (1, 4, 4)) self.assertEqual(data["feasibility"].shape, (1, 1)) self.assertEqual(data["slack"].shape, (1, 1)) self.assertEqual(data["lambda"].shape, (1, 1))
def test_snopt(self): test_name = "hs015_SNOPT" store_vars = ["step", "merit", "feasibility", "optimality", "penalty", "Hessian", "condZHZ", "slack", "lambda"] optOptions = { "Save major iteration variables": store_vars, "Print file": "{}.out".format(test_name), "Summary file": "{}_summary.out".format(test_name), } self.optimize_with_hotstart("SNOPT", 1e-12, optOptions=optOptions) hist = History(self.histFileName, flag="r") data = hist.getValues(callCounters=["last"]) keys = hist.getIterKeys() self.assertIn("isMajor", keys) self.assertEqual(7, data["nMajor"]) for var in store_vars: self.assertIn(var, data.keys()) self.assertEqual(data["Hessian"].shape, (1, 2, 2)) self.assertEqual(data["feasibility"].shape, (1, 1)) self.assertEqual(data["slack"].shape, (1, 2)) self.assertEqual(data["lambda"].shape, (1, 2))
def test_slsqp_setDV(self): """ Test that setDV works as expected, even with scaling/offset """ test_name = "hs071_SLSQP_setDV" histFileName = "{}.hst".format(test_name) newDV = {"xvars": np.array([1, 4, 4, 1])} optOptions = {"IFILE": "{}.out".format(test_name)} self.optimize( "SLSQP", 1e-5, xScale=1.5, conScale=1.2, objScale=32, offset=1.5, setDV=newDV, storeHistory=histFileName, optOptions=optOptions, ) # Verify the history file hist = History(histFileName, flag="r") init = hist.getValues(names="xvars", callCounters="0", scale=False) x_init = init["xvars"][0] assert_allclose(x_init, newDV["xvars"], atol=1e-5, rtol=1e-5)
def test_ipopt(self): self.optName = "IPOPT" self.setup_optProb() optOptions = self.optOptions.pop(self.optName, None) sol = self.optimize(optOptions=optOptions, storeHistory=True) # Check Solution self.assert_solution_allclose(sol, self.tol[self.optName]) # Check informs self.assert_inform_equal(sol) # Check iteration counters hist = History(self.histFileName, flag="r") data_init = hist.read(0) self.assertEqual(0, data_init["iter"]) data_last = hist.read(hist.read("last")) self.assertEqual(11, data_last["iter"] ) # took 12 function evaluations (see test_ipopt.out) # Make sure there is no duplication in objective history data = hist.getValues(names=["obj"]) objhis_len = data["obj"].shape[0] self.assertEqual(12, objhis_len) for i in range(objhis_len - 1): self.assertNotEqual(data["obj"][i], data["obj"][i + 1])
from pyoptsparse import History plt.rcParams["text.usetex"] = True # Comment out if latex installation is not present plt.rcParams["font.family"] = "serif" plt.rcParams["font.size"] = 20 plt.rcParams["xtick.labelsize"] = 16 plt.rcParams["ytick.labelsize"] = 16 plt.rcParams["lines.linewidth"] = 3.0 parser = argparse.ArgumentParser() parser.add_argument("--histFile", type=str, default="opt.hst") parser.add_argument("--outputDir", type=str, default="./") args = parser.parse_args() optHist = History(args.histFile) histValues = optHist.getValues() fig, axes = plt.subplots(nrows=5, sharex=True, constrained_layout=True, figsize=(14, 10)) axes[0].plot("nMajor", "optimality", data=histValues, label="Optimality") axes[0].plot("nMajor", "feasibility", data=histValues, label="Feasibility") axes[0].set_yscale("log") axes[0].axhline(1e-4, linestyle="--", color="gray") axes[0].annotate("Convergence Criteria", xy=(3, 9e-5), ha="left", va="top", fontsize=24, color="gray") axes[0].legend(fontsize=20, labelcolor="linecolor", loc="upper right", frameon=False) axes[0].autoscale(enable=True, tight=True) axes[1].plot("nMajor", "obj", data=histValues, label="Objective") axes[1].set_ylabel("Objective \n($C_D$)", rotation="horizontal", ha="right", fontsize=24) axes[2].plot("nMajor", "alpha_fc", data=histValues, label="Alpha")
def check_hist_file(self, tol): """ We check the history file here along with the API """ hist = History(self.histFileName, flag="r") # Metadata checks metadata = hist.getMetadata() self.assertEqual(metadata["optimizer"], self.optName) metadata_def_keys = [ "optName", "optOptions", "nprocs", "startTime", "endTime", "optTime", "version", "optVersion", ] for key in metadata_def_keys: self.assertIn(key, metadata) # we test that SNOPT version is stored correctly if self.optName == "SNOPT" and key == "optVersion": self.assertNotEqual(metadata[key], None) hist.getOptProb() # Info checks self.assertEqual(set(hist.getDVNames()), self.DVs) self.assertEqual(set(hist.getConNames()), self.cons) self.assertEqual(set(hist.getObjNames()), self.objs) dvInfo = hist.getDVInfo() self.assertEqual(len(dvInfo), len(self.DVs)) for var in self.DVs: self.assertEqual(dvInfo[var], hist.getDVInfo(key=var)) conInfo = hist.getConInfo() self.assertEqual(len(conInfo), len(self.cons)) objInfo = hist.getObjInfo() self.assertEqual(len(objInfo), len(self.objs)) for obj in self.objs: self.assertEqual(objInfo[obj], hist.getObjInfo(key=obj)) for key in ["lower", "upper", "scale"]: for dvName in self.DVs: self.assertIn(key, dvInfo[dvName]) for con in self.cons: self.assertIn(key, conInfo[con]) for obj in self.objs: self.assertIn("scale", objInfo[obj]) # callCounter checks callCounters = hist.getCallCounters() last = hist.read("last") # 'last' key should be present self.assertIn(last, callCounters) # iterKey checks iterKeys = hist.getIterKeys() for key in ["xuser", "fail", "isMajor"]: self.assertIn(key, iterKeys) # extraFuncsNames checks extraFuncsNames = hist.getExtraFuncsNames() if hasattr(self, "extras"): for key in self.extras: self.assertIn(key, extraFuncsNames) # getValues checks val = hist.getValues() # timing checks times = hist.getValues(names="time", major=False)["time"] # the times should be monotonically increasing self.assertTrue(np.all(np.diff(times) > 0)) # the final time should be close to the metadata time # we only specify a relatively loose atol because of variations in overhead cost between machines assert_allclose(times[-1], metadata["optTime"], atol=1.0) # this check is only used for optimizers that guarantee '0' and 'last' contain funcs if self.optName in ["SNOPT", "PSQP"]: val = hist.getValues(callCounters=["0", "last"], stack=True) self.assertEqual(val["isMajor"].size, 2) self.assertTrue( val["isMajor"] [0]) # the first callCounter must be a major iteration self.assertTrue( val["isMajor"] [-1]) # the last callCounter must be a major iteration # check optimum stored in history file against xstar val = hist.getValues(callCounters="last", stack=False) for varName in self.DVs: assert_allclose(val[varName].flatten(), self.xStar[self.sol_index][varName], atol=tol, rtol=tol)