From 00975c5bd16a30d7ae48ce0a4cd2edd07ebfed3e Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 2 May 2024 14:58:32 +0000 Subject: [PATCH 01/15] revert sol_inform back to emtpy dict, update Solution class --- pyoptsparse/pyALPSO/pyALPSO.py | 2 +- pyoptsparse/pyCONMIN/pyCONMIN.py | 2 +- pyoptsparse/pyNSGA2/pyNSGA2.py | 2 +- pyoptsparse/pyOpt_solution.py | 18 ++++++++++-------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pyoptsparse/pyALPSO/pyALPSO.py b/pyoptsparse/pyALPSO/pyALPSO.py index 670deb309..3d0f6057c 100644 --- a/pyoptsparse/pyALPSO/pyALPSO.py +++ b/pyoptsparse/pyALPSO/pyALPSO.py @@ -191,7 +191,7 @@ def objconfunc(x): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {"value": "", "text": ""} + sol_inform = {} # Create the optimization solution sol = self._createSolution(optTime, sol_inform, opt_f, opt_x) diff --git a/pyoptsparse/pyCONMIN/pyCONMIN.py b/pyoptsparse/pyCONMIN/pyCONMIN.py index 7539b1b63..2ea9a90e3 100644 --- a/pyoptsparse/pyCONMIN/pyCONMIN.py +++ b/pyoptsparse/pyCONMIN/pyCONMIN.py @@ -240,7 +240,7 @@ def cnmngrad(n1, n2, x, f, g, ct, df, a, ic, nac): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {"value": "", "text": ""} + sol_inform = {} # Create the optimization solution sol = self._createSolution(optTime, sol_inform, ff, xs) diff --git a/pyoptsparse/pyNSGA2/pyNSGA2.py b/pyoptsparse/pyNSGA2/pyNSGA2.py index c83faa187..136f5ff30 100644 --- a/pyoptsparse/pyNSGA2/pyNSGA2.py +++ b/pyoptsparse/pyNSGA2/pyNSGA2.py @@ -183,7 +183,7 @@ def objconfunc(nreal, nobj, ncon, x, f, g): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {"value": "", "text": ""} + sol_inform = {} xstar = [0.0] * n for i in range(n): diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 9b26be66d..97fac4185 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -29,8 +29,8 @@ def __init__(self, optProb, xStar, fStar, lambdaStar, optInform, info): lambdaStar : dict The final Lagrange multipliers - optInform : int - The inform code returned by the optimizer + optInform : dict + The inform code and reason returned by the optimizer info : dict A dictionary containing timing and call counter info to be stored @@ -95,12 +95,14 @@ def __str__(self) -> str: for i in range(5, len(lines)): text1 += lines[i] + "\n" - inform_val = self.optInform["value"] - inform_text = self.optInform["text"] - text1 += "\n" - text1 += " Exit Status\n" - text1 += " Inform Description\n" - text1 += f" {inform_val:>6} {inform_text:<0}\n" + # Only print exit status, inform, and description if the optimizer provides informs + if self.optInform: + inform_val = self.optInform["value"] + inform_text = self.optInform["text"] + text1 += "\n" + text1 += " Exit Status\n" + text1 += " Inform Description\n" + text1 += f" {inform_val:>6} {inform_text:<0}\n" text1 += ("-" * 80) + "\n" From 21490b70a93c87c68750dabcf3bf0af607973cbc Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Thu, 2 May 2024 15:09:19 +0000 Subject: [PATCH 02/15] rename variable to camelCase --- pyoptsparse/pyALPSO/pyALPSO.py | 4 ++-- pyoptsparse/pyCONMIN/pyCONMIN.py | 4 ++-- pyoptsparse/pyIPOPT/pyIPOPT.py | 8 ++++---- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 8 ++++---- pyoptsparse/pyNSGA2/pyNSGA2.py | 4 ++-- pyoptsparse/pyOpt_optimizer.py | 4 ++-- pyoptsparse/pyPSQP/pyPSQP.py | 8 ++++---- pyoptsparse/pySLSQP/pySLSQP.py | 8 ++++---- pyoptsparse/pySNOPT/pySNOPT.py | 8 ++++---- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/pyoptsparse/pyALPSO/pyALPSO.py b/pyoptsparse/pyALPSO/pyALPSO.py index 3d0f6057c..1631fe2c9 100644 --- a/pyoptsparse/pyALPSO/pyALPSO.py +++ b/pyoptsparse/pyALPSO/pyALPSO.py @@ -191,10 +191,10 @@ def objconfunc(x): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {} + solInform = {} # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, opt_f, opt_x) + sol = self._createSolution(optTime, solInform, opt_f, opt_x) else: # We are not on the root process so go into waiting loop: self._waitLoop() sol = None diff --git a/pyoptsparse/pyCONMIN/pyCONMIN.py b/pyoptsparse/pyCONMIN/pyCONMIN.py index 2ea9a90e3..0046db8de 100644 --- a/pyoptsparse/pyCONMIN/pyCONMIN.py +++ b/pyoptsparse/pyCONMIN/pyCONMIN.py @@ -240,10 +240,10 @@ def cnmngrad(n1, n2, x, f, g, ct, df, a, ic, nac): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {} + solInform = {} # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, ff, xs) + sol = self._createSolution(optTime, solInform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 4f0de8bea..6f3880dfa 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -275,12 +275,12 @@ def intermediate(_, *args, **kwargs): self.hist.close() # Store Results - sol_inform = {} - sol_inform["value"] = info["status"] - sol_inform["text"] = self.informs[info["status"]] + solInform = {} + solInform["value"] = info["status"] + solInform["text"] = self.informs[info["status"]] # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, info["obj_val"], x, multipliers=info["mult_g"]) + sol = self._createSolution(optTime, solInform, info["obj_val"], x, multipliers=info["mult_g"]) # Indicate solution finished self.optProb.comm.bcast(-1, root=0) diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index 17436eed2..795714761 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -256,12 +256,12 @@ def nlgrad(m, me, mmax, n, f, g, df, dg, x, active, wa): # Store Results inform = ifail.item() - sol_inform = {} - sol_inform["value"] = inform - sol_inform["text"] = self.informs[inform] + solInform = {} + solInform["value"] = inform + solInform["text"] = self.informs[inform] # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, f, xs) + sol = self._createSolution(optTime, solInform, f, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyNSGA2/pyNSGA2.py b/pyoptsparse/pyNSGA2/pyNSGA2.py index 136f5ff30..d464cc0a1 100644 --- a/pyoptsparse/pyNSGA2/pyNSGA2.py +++ b/pyoptsparse/pyNSGA2/pyNSGA2.py @@ -183,7 +183,7 @@ def objconfunc(nreal, nobj, ncon, x, f, g): self.optProb.comm.bcast(-1, root=0) # Store Results - sol_inform = {} + solInform = {} xstar = [0.0] * n for i in range(n): @@ -197,7 +197,7 @@ def objconfunc(nreal, nobj, ncon, x, f, g): fStar = nsga2.doubleArray_getitem(f, 0) # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, fStar, xstar) + sol = self._createSolution(optTime, solInform, fStar, xstar) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyOpt_optimizer.py b/pyoptsparse/pyOpt_optimizer.py index f48224035..81ad0b15a 100644 --- a/pyoptsparse/pyOpt_optimizer.py +++ b/pyoptsparse/pyOpt_optimizer.py @@ -794,7 +794,7 @@ def _assembleObjective(self): return np.real(np.squeeze(ff)) - def _createSolution(self, optTime, sol_inform, obj, xopt, multipliers=None) -> Solution: + def _createSolution(self, optTime, solInform, obj, xopt, multipliers=None) -> Solution: """ Generic routine to create the solution after an optimizer finishes. @@ -824,7 +824,7 @@ def _createSolution(self, optTime, sol_inform, obj, xopt, multipliers=None) -> S "interfaceTime": self.interfaceTime - self.userSensTime - self.userObjTime, "optCodeTime": optTime - self.interfaceTime, } - sol = Solution(self.optProb, xStar, fStar, multipliers, sol_inform, info) + sol = Solution(self.optProb, xStar, fStar, multipliers, solInform, info) return sol diff --git a/pyoptsparse/pyPSQP/pyPSQP.py b/pyoptsparse/pyPSQP/pyPSQP.py index 5eba85686..1523018d1 100644 --- a/pyoptsparse/pyPSQP/pyPSQP.py +++ b/pyoptsparse/pyPSQP/pyPSQP.py @@ -259,9 +259,9 @@ def pdcon(n, k, x, dg): inform = iterm.item() if inform < 0 and inform not in self.informs: inform = -10 - sol_inform = {} - sol_inform["value"] = inform - sol_inform["text"] = self.informs[inform] + solInform = {} + solInform["value"] = inform + solInform["text"] = self.informs[inform] if self.storeHistory: self.metadata["endTime"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.metadata["optTime"] = optTime @@ -269,7 +269,7 @@ def pdcon(n, k, x, dg): self.hist.close() # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, ff, xs) + sol = self._createSolution(optTime, solInform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index 2207239b2..723b71f2a 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -260,12 +260,12 @@ def slgrad(m, me, la, n, f, g, df, dg, x): # Store Results inform = mode.item() - sol_inform = {} - sol_inform["value"] = inform - sol_inform["text"] = self.informs[inform] + solInform = {} + solInform["value"] = inform + solInform["text"] = self.informs[inform] # Create the optimization solution - sol = self._createSolution(optTime, sol_inform, ff, xs) + sol = self._createSolution(optTime, solInform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index c6def1323..9a1a116e5 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -500,9 +500,9 @@ def __call__( snopt.closeunit(self.getOption("iSumm")) # Store Results - sol_inform = {} - sol_inform["value"] = inform - sol_inform["text"] = self.informs[inform] + solInform = {} + solInform["value"] = inform + solInform["text"] = self.informs[inform] # Create the optimization solution if parse_version(self.version) > parse_version("7.7.0") and parse_version(self.version) < parse_version( @@ -511,7 +511,7 @@ def __call__( # SNOPT obj value is buggy and returned as 0, its thus overwritten with the solution objective value obj = np.array([obj.value * obj.scale for obj in self.optProb.objectives.values()]) - sol = self._createSolution(optTime, sol_inform, obj, xs[:nvar], multipliers=pi) + sol = self._createSolution(optTime, solInform, obj, xs[:nvar], multipliers=pi) restartDict = { "cw": cw, "iw": iw, From 8e8bd284d82f18f874fb2e29cf7783865b494454 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 14:49:17 +0000 Subject: [PATCH 03/15] solution inform as dataclass --- pyoptsparse/pyALPSO/pyALPSO.py | 4 ++-- pyoptsparse/pyCONMIN/pyCONMIN.py | 4 ++-- pyoptsparse/pyIPOPT/pyIPOPT.py | 21 ++++++++++++++++----- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 7 +++---- pyoptsparse/pyNSGA2/pyNSGA2.py | 4 ++-- pyoptsparse/pyOpt_history.py | 2 +- pyoptsparse/pyPSQP/pyPSQP.py | 5 ++--- pyoptsparse/pySLSQP/pySLSQP.py | 7 +++---- pyoptsparse/pySNOPT/pySNOPT.py | 7 +++---- 9 files changed, 34 insertions(+), 27 deletions(-) diff --git a/pyoptsparse/pyALPSO/pyALPSO.py b/pyoptsparse/pyALPSO/pyALPSO.py index 1631fe2c9..86735a890 100644 --- a/pyoptsparse/pyALPSO/pyALPSO.py +++ b/pyoptsparse/pyALPSO/pyALPSO.py @@ -190,8 +190,8 @@ def objconfunc(x): # Broadcast a -1 to indcate NSGA2 has finished self.optProb.comm.bcast(-1, root=0) - # Store Results - solInform = {} + # Optimizer has no exit conditions, so nothing to set + solInform = None # Create the optimization solution sol = self._createSolution(optTime, solInform, opt_f, opt_x) diff --git a/pyoptsparse/pyCONMIN/pyCONMIN.py b/pyoptsparse/pyCONMIN/pyCONMIN.py index 0046db8de..580a4bbc8 100644 --- a/pyoptsparse/pyCONMIN/pyCONMIN.py +++ b/pyoptsparse/pyCONMIN/pyCONMIN.py @@ -239,8 +239,8 @@ def cnmngrad(n1, n2, x, f, g, ct, df, a, ic, nac): # Broadcast a -1 to indcate SLSQP has finished self.optProb.comm.bcast(-1, root=0) - # Store Results - solInform = {} + # Optimizer has no exit conditions, so nothing to set + solInform = None # Create the optimization solution sol = self._createSolution(optTime, solInform, ff, xs) diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 6f3880dfa..b43e8c5fa 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -18,7 +18,20 @@ # Local modules from ..pyOpt_optimizer import Optimizer -from ..pyOpt_utils import ICOL, INFINITY, IROW, convertToCOO, extractRows, scaleRows +from ..pyOpt_solution import SolutionInform +from ..pyOpt_utils import ( + ICOL, + INFINITY, + IROW, + convertToCOO, + extractRows, + scaleRows, + try_import_compiled_module_from_path, +) + +# import the compiled module +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) +pyipoptcore = try_import_compiled_module_from_path("pyipoptcore", THIS_DIR) class IPOPT(Optimizer): @@ -274,10 +287,8 @@ def intermediate(_, *args, **kwargs): self.hist.writeData("metadata", self.metadata) self.hist.close() - # Store Results - solInform = {} - solInform["value"] = info["status"] - solInform["text"] = self.informs[info["status"]] + # Store optimizer exit condition and reason + solInform = SolutionInform(info["status"], self.informs[info["status"]]) # Create the optimization solution sol = self._createSolution(optTime, solInform, info["obj_val"], x, multipliers=info["mult_g"]) diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index 795714761..e060e387c 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -14,6 +14,7 @@ # Local modules from ..pyOpt_optimizer import Optimizer from ..pyOpt_utils import try_import_compiled_module_from_path +from ..pyOpt_solution import SolutionInform # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -254,11 +255,9 @@ def nlgrad(m, me, mmax, n, f, g, df, dg, x, active, wa): self.hist.writeData("metadata", self.metadata) self.hist.close() - # Store Results + # Store optimizer exit condition and reason inform = ifail.item() - solInform = {} - solInform["value"] = inform - solInform["text"] = self.informs[inform] + solInform = SolutionInform(inform, self.informs[inform]) # Create the optimization solution sol = self._createSolution(optTime, solInform, f, xs) diff --git a/pyoptsparse/pyNSGA2/pyNSGA2.py b/pyoptsparse/pyNSGA2/pyNSGA2.py index d464cc0a1..8cf7153f5 100644 --- a/pyoptsparse/pyNSGA2/pyNSGA2.py +++ b/pyoptsparse/pyNSGA2/pyNSGA2.py @@ -182,8 +182,8 @@ def objconfunc(nreal, nobj, ncon, x, f, g): # Broadcast a -1 to indcate NSGA2 has finished self.optProb.comm.bcast(-1, root=0) - # Store Results - solInform = {} + # Optimizer has no exit conditions, so nothing to set + solInform = None xstar = [0.0] * n for i in range(n): diff --git a/pyoptsparse/pyOpt_history.py b/pyoptsparse/pyOpt_history.py index 9767cbfa2..3475c93ce 100644 --- a/pyoptsparse/pyOpt_history.py +++ b/pyoptsparse/pyOpt_history.py @@ -221,7 +221,7 @@ def _processDB(self): if self.metadata["version"] != __version__: pyOptSparseWarning( - "The version of pyoptsparse used to generate the history file does not match the one being run right now. There may be compatibility issues." + f"The version of pyoptsparse used to generate the history file (v{self.metadata["version"]}) does not match the one being run right now (v{__version__}). There may be compatibility issues." ) def getIterKeys(self): diff --git a/pyoptsparse/pyPSQP/pyPSQP.py b/pyoptsparse/pyPSQP/pyPSQP.py index 1523018d1..1ce725044 100644 --- a/pyoptsparse/pyPSQP/pyPSQP.py +++ b/pyoptsparse/pyPSQP/pyPSQP.py @@ -13,6 +13,7 @@ # Local modules from ..pyOpt_optimizer import Optimizer from ..pyOpt_utils import try_import_compiled_module_from_path +from ..pyOpt_solution import SolutionInform # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -259,9 +260,7 @@ def pdcon(n, k, x, dg): inform = iterm.item() if inform < 0 and inform not in self.informs: inform = -10 - solInform = {} - solInform["value"] = inform - solInform["text"] = self.informs[inform] + solInform = SolutionInform(inform, self.informs[inform]) if self.storeHistory: self.metadata["endTime"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.metadata["optTime"] = optTime diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index 723b71f2a..adbbd8f13 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -15,6 +15,7 @@ from ..pyOpt_error import pyOptSparseWarning from ..pyOpt_optimizer import Optimizer from ..pyOpt_utils import try_import_compiled_module_from_path +from ..pyOpt_solution import SolutionInform # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -258,11 +259,9 @@ def slgrad(m, me, la, n, f, g, df, dg, x): # Broadcast a -1 to indcate SLSQP has finished self.optProb.comm.bcast(-1, root=0) - # Store Results + # Store optimizer exit condition and reason inform = mode.item() - solInform = {} - solInform["value"] = inform - solInform["text"] = self.informs[inform] + solInform = SolutionInform(inform, self.informs[inform]) # Create the optimization solution sol = self._createSolution(optTime, solInform, ff, xs) diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index 9a1a116e5..8fc0399ea 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -30,6 +30,7 @@ scaleRows, try_import_compiled_module_from_path, ) +from ..pyOpt_solution import SolutionInform # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -499,10 +500,8 @@ def __call__( if iSumm != 0 and iSumm != 6: snopt.closeunit(self.getOption("iSumm")) - # Store Results - solInform = {} - solInform["value"] = inform - solInform["text"] = self.informs[inform] + # Store optimizer exit condition and reason + solInform = SolutionInform(inform, self.informs[inform]) # Create the optimization solution if parse_version(self.version) > parse_version("7.7.0") and parse_version(self.version) < parse_version( From cf6d521e6cd691960f4e65df73b54dda62e1a511 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 15:09:07 +0000 Subject: [PATCH 04/15] whoops leftover from local branch --- pyoptsparse/pyOpt_solution.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 97fac4185..4a4739021 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -1,5 +1,6 @@ # Standard Python modules import copy +from dataclasses import dataclass # External modules import numpy as np @@ -8,8 +9,14 @@ from .pyOpt_optimization import Optimization +@dataclass(frozen=True) +class SolutionInform(): + """Data class that contains the optimizer solution value and reason""" + value: int + reason: str + class Solution(Optimization): - def __init__(self, optProb, xStar, fStar, lambdaStar, optInform, info): + def __init__(self, optProb, xStar, fStar, lambdaStar, optInform: SolutionInform | None, info): """ This class is used to describe the solution of an optimization problem. This class inherits from Optimization which enables a @@ -29,8 +36,9 @@ def __init__(self, optProb, xStar, fStar, lambdaStar, optInform, info): lambdaStar : dict The final Lagrange multipliers - optInform : dict - The inform code and reason returned by the optimizer + optInform : SolutionInform or None + Object containing the inform code and reason returned by the optimizer. + Optimizers that do not have inform exit codes do not set this variable. info : dict A dictionary containing timing and call counter info to be stored @@ -97,8 +105,8 @@ def __str__(self) -> str: # Only print exit status, inform, and description if the optimizer provides informs if self.optInform: - inform_val = self.optInform["value"] - inform_text = self.optInform["text"] + inform_val = self.optInform.value + inform_text = self.optInform.reason text1 += "\n" text1 += " Exit Status\n" text1 += " Inform Description\n" From 242c9b651009de595a6c7b8dd271803a3e84063b Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 15:37:37 +0000 Subject: [PATCH 05/15] fix for python < 3.12 --- pyoptsparse/pyOpt_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyoptsparse/pyOpt_history.py b/pyoptsparse/pyOpt_history.py index 3475c93ce..b90d10805 100644 --- a/pyoptsparse/pyOpt_history.py +++ b/pyoptsparse/pyOpt_history.py @@ -221,7 +221,7 @@ def _processDB(self): if self.metadata["version"] != __version__: pyOptSparseWarning( - f"The version of pyoptsparse used to generate the history file (v{self.metadata["version"]}) does not match the one being run right now (v{__version__}). There may be compatibility issues." + f"The version of pyoptsparse used to generate the history file (v{self.metadata['version']}) does not match the one being run right now (v{__version__}). There may be compatibility issues." ) def getIterKeys(self): From 8326a6404f389af11b83e337f9af9bb1cf375935 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 17:12:57 +0000 Subject: [PATCH 06/15] fix bad merge --- pyoptsparse/pyIPOPT/pyIPOPT.py | 1 + pyoptsparse/pyOpt_solution.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index b43e8c5fa..008321699 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -5,6 +5,7 @@ # Standard Python modules import copy import datetime +import os import time # External modules diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 4a4739021..78dfe068f 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -10,11 +10,13 @@ @dataclass(frozen=True) -class SolutionInform(): +class SolutionInform: """Data class that contains the optimizer solution value and reason""" + value: int reason: str + class Solution(Optimization): def __init__(self, optProb, xStar, fStar, lambdaStar, optInform: SolutionInform | None, info): """ From 4f68e10e757a6a595cef23f5caada9034ae56c97 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 17:22:51 +0000 Subject: [PATCH 07/15] isort --- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 2 +- pyoptsparse/pyPSQP/pyPSQP.py | 2 +- pyoptsparse/pySLSQP/pySLSQP.py | 2 +- pyoptsparse/pySNOPT/pySNOPT.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index e060e387c..fceaf5f63 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -13,8 +13,8 @@ # Local modules from ..pyOpt_optimizer import Optimizer -from ..pyOpt_utils import try_import_compiled_module_from_path from ..pyOpt_solution import SolutionInform +from ..pyOpt_utils import try_import_compiled_module_from_path # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/pyoptsparse/pyPSQP/pyPSQP.py b/pyoptsparse/pyPSQP/pyPSQP.py index 1ce725044..4a475df96 100644 --- a/pyoptsparse/pyPSQP/pyPSQP.py +++ b/pyoptsparse/pyPSQP/pyPSQP.py @@ -12,8 +12,8 @@ # Local modules from ..pyOpt_optimizer import Optimizer -from ..pyOpt_utils import try_import_compiled_module_from_path from ..pyOpt_solution import SolutionInform +from ..pyOpt_utils import try_import_compiled_module_from_path # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index adbbd8f13..c926e1789 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -14,8 +14,8 @@ # Local modules from ..pyOpt_error import pyOptSparseWarning from ..pyOpt_optimizer import Optimizer -from ..pyOpt_utils import try_import_compiled_module_from_path from ..pyOpt_solution import SolutionInform +from ..pyOpt_utils import try_import_compiled_module_from_path # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index 8fc0399ea..67ff9048c 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -20,6 +20,7 @@ # Local modules from ..pyOpt_optimization import Optimization from ..pyOpt_optimizer import Optimizer +from ..pyOpt_solution import SolutionInform from ..pyOpt_utils import ( ICOL, IDATA, @@ -30,7 +31,6 @@ scaleRows, try_import_compiled_module_from_path, ) -from ..pyOpt_solution import SolutionInform # import the compiled module THIS_DIR = os.path.dirname(os.path.abspath(__file__)) From b5b901d06d41328c9e870784dac292f68418e731 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 17:40:22 +0000 Subject: [PATCH 08/15] update testing utils --- pyoptsparse/testing/pyOpt_testing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyoptsparse/testing/pyOpt_testing.py b/pyoptsparse/testing/pyOpt_testing.py index c9535e397..22d317568 100644 --- a/pyoptsparse/testing/pyOpt_testing.py +++ b/pyoptsparse/testing/pyOpt_testing.py @@ -157,16 +157,16 @@ def assert_inform_equal(self, sol, optInform=None): ---------- sol : Solution object The solution object after optimization - optInform : int, optional + optInform : SolutionInform or None, optional The expected inform. If None, the default inform is used, which corresponds to a successful optimization termination. """ if optInform is not None: - self.assertEqual(sol.optInform["value"], optInform) + self.assertEqual(sol.optInform.value, optInform) else: # some optimizers do not have informs if self.optName in SUCCESS_INFORM: - self.assertEqual(sol.optInform["value"], SUCCESS_INFORM[self.optName]) + self.assertEqual(sol.optInform.value, SUCCESS_INFORM[self.optName]) def get_default_hst_name(self): # self.id() is provided by unittest.TestCase automatically From 7c59059ff963f40d53e9f49dc23840197ffd23ac Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 17:52:24 +0000 Subject: [PATCH 09/15] update tests --- tests/test_slsqp.py | 2 +- tests/test_user_termination.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_slsqp.py b/tests/test_slsqp.py index b7fa70e8e..2e459670a 100644 --- a/tests/test_slsqp.py +++ b/tests/test_slsqp.py @@ -41,6 +41,6 @@ def sens(xdict, funcs): optProb.addObj("obj") opt = OPT("SLSQP") sol = opt(optProb, sens=sens) - self.assertEqual(sol.optInform["value"], 0) + self.assertEqual(sol.optInform.value, 0) self.assertGreaterEqual(sol.xStar["xvars"][0], 0) self.assertAlmostEqual(sol.xStar["xvars"][0], 0, places=9) diff --git a/tests/test_user_termination.py b/tests/test_user_termination.py index 017255f34..b1fcde3a7 100644 --- a/tests/test_user_termination.py +++ b/tests/test_user_termination.py @@ -110,7 +110,7 @@ def test_obj(self, optName): self.assertEqual(termcomp.obj_count, 3) # Exit code for user requested termination. - self.assertEqual(sol.optInform["value"], self.optExitCode[optName]) + self.assertEqual(sol.optInform.value, self.optExitCode[optName]) @parameterized.expand(["IPOPT", "SNOPT"]) def test_sens(self, optName): @@ -131,7 +131,7 @@ def test_sens(self, optName): self.assertEqual(termcomp.sens_count, 4) # Exit code for user requested termination. - self.assertEqual(sol.optInform["value"], self.optExitCode[optName]) + self.assertEqual(sol.optInform.value, self.optExitCode[optName]) if __name__ == "__main__": From 59e8588c2b2fbf715a7deaa9bfc1514fb0a172b9 Mon Sep 17 00:00:00 2001 From: Eirikur Jonsson Date: Wed, 16 Apr 2025 19:08:48 +0000 Subject: [PATCH 10/15] update type hints to support python 3.9 --- pyoptsparse/pyOpt_solution.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 78dfe068f..3786f26c0 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -1,6 +1,7 @@ # Standard Python modules import copy from dataclasses import dataclass +from typing import Optional # External modules import numpy as np @@ -18,7 +19,7 @@ class SolutionInform: class Solution(Optimization): - def __init__(self, optProb, xStar, fStar, lambdaStar, optInform: SolutionInform | None, info): + def __init__(self, optProb, xStar, fStar, lambdaStar, optInform: Optional[SolutionInform], info): """ This class is used to describe the solution of an optimization problem. This class inherits from Optimization which enables a From 27d70a223c4f505eade041f11a9fc59451270250 Mon Sep 17 00:00:00 2001 From: Ella Wu <602725+ewu63@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:59:27 -0700 Subject: [PATCH 11/15] reason -> message --- pyoptsparse/pyIPOPT/pyIPOPT.py | 2 +- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 2 +- pyoptsparse/pyOpt_solution.py | 8 ++++---- pyoptsparse/pySLSQP/pySLSQP.py | 4 ++-- pyoptsparse/pySNOPT/pySNOPT.py | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 008321699..386d19039 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -288,7 +288,7 @@ def intermediate(_, *args, **kwargs): self.hist.writeData("metadata", self.metadata) self.hist.close() - # Store optimizer exit condition and reason + # Store optimizer exit condition and message solInform = SolutionInform(info["status"], self.informs[info["status"]]) # Create the optimization solution diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index fceaf5f63..ce3795dd7 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -255,7 +255,7 @@ def nlgrad(m, me, mmax, n, f, g, df, dg, x, active, wa): self.hist.writeData("metadata", self.metadata) self.hist.close() - # Store optimizer exit condition and reason + # Store optimizer exit condition and message inform = ifail.item() solInform = SolutionInform(inform, self.informs[inform]) diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 3786f26c0..8badab51a 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -12,10 +12,10 @@ @dataclass(frozen=True) class SolutionInform: - """Data class that contains the optimizer solution value and reason""" + """Data class that contains the optimizer solution value and message""" value: int - reason: str + message: str class Solution(Optimization): @@ -40,7 +40,7 @@ def __init__(self, optProb, xStar, fStar, lambdaStar, optInform: Optional[Soluti The final Lagrange multipliers optInform : SolutionInform or None - Object containing the inform code and reason returned by the optimizer. + Object containing the inform code and message returned by the optimizer. Optimizers that do not have inform exit codes do not set this variable. info : dict @@ -109,7 +109,7 @@ def __str__(self) -> str: # Only print exit status, inform, and description if the optimizer provides informs if self.optInform: inform_val = self.optInform.value - inform_text = self.optInform.reason + inform_text = self.optInform.message text1 += "\n" text1 += " Exit Status\n" text1 += " Inform Description\n" diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index c926e1789..8f0abf999 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -169,7 +169,7 @@ def __call__( # ================================================================= def slfunc(m, me, la, n, f, g, x): if (x < blx).any() or (x > bux).any(): - pyOptSparseWarning("Values in x were outside bounds during" " a minimize step, clipping to bounds") + pyOptSparseWarning("Values in x were outside bounds during a minimize step, clipping to bounds") fobj, fcon, fail = self._masterFunc(np.clip(x, blx, bux), ["fobj", "fcon"]) f = fobj g[0:m] = -fcon @@ -259,7 +259,7 @@ def slgrad(m, me, la, n, f, g, df, dg, x): # Broadcast a -1 to indcate SLSQP has finished self.optProb.comm.bcast(-1, root=0) - # Store optimizer exit condition and reason + # Store optimizer exit condition and message inform = mode.item() solInform = SolutionInform(inform, self.informs[inform]) diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index 67ff9048c..3f86761f6 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -500,7 +500,7 @@ def __call__( if iSumm != 0 and iSumm != 6: snopt.closeunit(self.getOption("iSumm")) - # Store optimizer exit condition and reason + # Store optimizer exit condition and message solInform = SolutionInform(inform, self.informs[inform]) # Create the optimization solution From 9a95ece58941bdf683255eaf44a5fd23e2d6448c Mon Sep 17 00:00:00 2001 From: Ella Wu <602725+ewu63@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:02:34 -0700 Subject: [PATCH 12/15] added alternate constructor --- pyoptsparse/pyIPOPT/pyIPOPT.py | 2 +- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 2 +- pyoptsparse/pyOpt_solution.py | 6 ++++++ pyoptsparse/pyPSQP/pyPSQP.py | 2 +- pyoptsparse/pySLSQP/pySLSQP.py | 2 +- pyoptsparse/pySNOPT/pySNOPT.py | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 386d19039..6249c9c69 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -289,7 +289,7 @@ def intermediate(_, *args, **kwargs): self.hist.close() # Store optimizer exit condition and message - solInform = SolutionInform(info["status"], self.informs[info["status"]]) + solInform = SolutionInform.from_informs(self.informs, info["status"]) # Create the optimization solution sol = self._createSolution(optTime, solInform, info["obj_val"], x, multipliers=info["mult_g"]) diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index ce3795dd7..c546d5223 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -257,7 +257,7 @@ def nlgrad(m, me, mmax, n, f, g, df, dg, x, active, wa): # Store optimizer exit condition and message inform = ifail.item() - solInform = SolutionInform(inform, self.informs[inform]) + solInform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution sol = self._createSolution(optTime, solInform, f, xs) diff --git a/pyoptsparse/pyOpt_solution.py b/pyoptsparse/pyOpt_solution.py index 8badab51a..5de0fe05e 100644 --- a/pyoptsparse/pyOpt_solution.py +++ b/pyoptsparse/pyOpt_solution.py @@ -15,7 +15,13 @@ class SolutionInform: """Data class that contains the optimizer solution value and message""" value: int + """The integer return code""" message: str + """The message string accompanying the return code""" + + @classmethod + def from_informs(cls, informs: dict[int, str], value: int): + return cls(value=value, message=informs[value]) class Solution(Optimization): diff --git a/pyoptsparse/pyPSQP/pyPSQP.py b/pyoptsparse/pyPSQP/pyPSQP.py index 4a475df96..a8b154578 100644 --- a/pyoptsparse/pyPSQP/pyPSQP.py +++ b/pyoptsparse/pyPSQP/pyPSQP.py @@ -260,7 +260,7 @@ def pdcon(n, k, x, dg): inform = iterm.item() if inform < 0 and inform not in self.informs: inform = -10 - solInform = SolutionInform(inform, self.informs[inform]) + solInform = SolutionInform.from_informs(self.informs, inform) if self.storeHistory: self.metadata["endTime"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.metadata["optTime"] = optTime diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index 8f0abf999..b518c58dd 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -261,7 +261,7 @@ def slgrad(m, me, la, n, f, g, df, dg, x): # Store optimizer exit condition and message inform = mode.item() - solInform = SolutionInform(inform, self.informs[inform]) + solInform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution sol = self._createSolution(optTime, solInform, ff, xs) diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index 3f86761f6..2a99d9152 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -501,7 +501,7 @@ def __call__( snopt.closeunit(self.getOption("iSumm")) # Store optimizer exit condition and message - solInform = SolutionInform(inform, self.informs[inform]) + solInform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution if parse_version(self.version) > parse_version("7.7.0") and parse_version(self.version) < parse_version( From a9ee6f792d4348ab46155b5d98787fd449e276c1 Mon Sep 17 00:00:00 2001 From: Ella Wu <602725+ewu63@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:24:46 -0700 Subject: [PATCH 13/15] rebase confusion --- pyoptsparse/pyIPOPT/pyIPOPT.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 6249c9c69..9af67c033 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -5,7 +5,6 @@ # Standard Python modules import copy import datetime -import os import time # External modules @@ -20,19 +19,7 @@ # Local modules from ..pyOpt_optimizer import Optimizer from ..pyOpt_solution import SolutionInform -from ..pyOpt_utils import ( - ICOL, - INFINITY, - IROW, - convertToCOO, - extractRows, - scaleRows, - try_import_compiled_module_from_path, -) - -# import the compiled module -THIS_DIR = os.path.dirname(os.path.abspath(__file__)) -pyipoptcore = try_import_compiled_module_from_path("pyipoptcore", THIS_DIR) +from ..pyOpt_utils import ICOL, INFINITY, IROW, convertToCOO, extractRows, scaleRows class IPOPT(Optimizer): From 1310d4b7bd2a521b4e7e2033d4f6f2d78303159f Mon Sep 17 00:00:00 2001 From: Ella Wu <602725+ewu63@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:41:14 -0700 Subject: [PATCH 14/15] version bump --- pyoptsparse/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyoptsparse/__init__.py b/pyoptsparse/__init__.py index 65feab940..c61c08fde 100644 --- a/pyoptsparse/__init__.py +++ b/pyoptsparse/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.14.0" +__version__ = "2.14.1" from .pyOpt_history import History from .pyOpt_variable import Variable From 76e77dd2227266101276bfa6547e6ee822fe9a12 Mon Sep 17 00:00:00 2001 From: Ella Wu <602725+ewu63@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:06:25 -0700 Subject: [PATCH 15/15] solInform -> sol_inform --- pyoptsparse/pyALPSO/pyALPSO.py | 4 ++-- pyoptsparse/pyCONMIN/pyCONMIN.py | 4 ++-- pyoptsparse/pyIPOPT/pyIPOPT.py | 4 ++-- pyoptsparse/pyNLPQLP/pyNLPQLP.py | 4 ++-- pyoptsparse/pyNSGA2/pyNSGA2.py | 4 ++-- pyoptsparse/pyPSQP/pyPSQP.py | 4 ++-- pyoptsparse/pySLSQP/pySLSQP.py | 4 ++-- pyoptsparse/pySNOPT/pySNOPT.py | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pyoptsparse/pyALPSO/pyALPSO.py b/pyoptsparse/pyALPSO/pyALPSO.py index 86735a890..25af17618 100644 --- a/pyoptsparse/pyALPSO/pyALPSO.py +++ b/pyoptsparse/pyALPSO/pyALPSO.py @@ -191,10 +191,10 @@ def objconfunc(x): self.optProb.comm.bcast(-1, root=0) # Optimizer has no exit conditions, so nothing to set - solInform = None + sol_inform = None # Create the optimization solution - sol = self._createSolution(optTime, solInform, opt_f, opt_x) + sol = self._createSolution(optTime, sol_inform, opt_f, opt_x) else: # We are not on the root process so go into waiting loop: self._waitLoop() sol = None diff --git a/pyoptsparse/pyCONMIN/pyCONMIN.py b/pyoptsparse/pyCONMIN/pyCONMIN.py index 580a4bbc8..f5c598001 100644 --- a/pyoptsparse/pyCONMIN/pyCONMIN.py +++ b/pyoptsparse/pyCONMIN/pyCONMIN.py @@ -240,10 +240,10 @@ def cnmngrad(n1, n2, x, f, g, ct, df, a, ic, nac): self.optProb.comm.bcast(-1, root=0) # Optimizer has no exit conditions, so nothing to set - solInform = None + sol_inform = None # Create the optimization solution - sol = self._createSolution(optTime, solInform, ff, xs) + sol = self._createSolution(optTime, sol_inform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyIPOPT/pyIPOPT.py b/pyoptsparse/pyIPOPT/pyIPOPT.py index 9af67c033..1ef57239c 100644 --- a/pyoptsparse/pyIPOPT/pyIPOPT.py +++ b/pyoptsparse/pyIPOPT/pyIPOPT.py @@ -276,10 +276,10 @@ def intermediate(_, *args, **kwargs): self.hist.close() # Store optimizer exit condition and message - solInform = SolutionInform.from_informs(self.informs, info["status"]) + sol_inform = SolutionInform.from_informs(self.informs, info["status"]) # Create the optimization solution - sol = self._createSolution(optTime, solInform, info["obj_val"], x, multipliers=info["mult_g"]) + sol = self._createSolution(optTime, sol_inform, info["obj_val"], x, multipliers=info["mult_g"]) # Indicate solution finished self.optProb.comm.bcast(-1, root=0) diff --git a/pyoptsparse/pyNLPQLP/pyNLPQLP.py b/pyoptsparse/pyNLPQLP/pyNLPQLP.py index c546d5223..16efbb137 100644 --- a/pyoptsparse/pyNLPQLP/pyNLPQLP.py +++ b/pyoptsparse/pyNLPQLP/pyNLPQLP.py @@ -257,10 +257,10 @@ def nlgrad(m, me, mmax, n, f, g, df, dg, x, active, wa): # Store optimizer exit condition and message inform = ifail.item() - solInform = SolutionInform.from_informs(self.informs, inform) + sol_inform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution - sol = self._createSolution(optTime, solInform, f, xs) + sol = self._createSolution(optTime, sol_inform, f, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyNSGA2/pyNSGA2.py b/pyoptsparse/pyNSGA2/pyNSGA2.py index 17c216690..d55994c82 100644 --- a/pyoptsparse/pyNSGA2/pyNSGA2.py +++ b/pyoptsparse/pyNSGA2/pyNSGA2.py @@ -190,7 +190,7 @@ def objconfunc(nreal, nobj, ncon, x, f, g): self.optProb.comm.bcast(-1, root=0) # Optimizer has no exit conditions, so nothing to set - solInform = None + sol_inform = None xstar = [0.0] * n for i in range(n): @@ -204,7 +204,7 @@ def objconfunc(nreal, nobj, ncon, x, f, g): fStar = nsga2.doubleArray_getitem(f, 0) # Create the optimization solution - sol = self._createSolution(optTime, solInform, fStar, xstar) + sol = self._createSolution(optTime, sol_inform, fStar, xstar) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pyPSQP/pyPSQP.py b/pyoptsparse/pyPSQP/pyPSQP.py index a8b154578..87bc156db 100644 --- a/pyoptsparse/pyPSQP/pyPSQP.py +++ b/pyoptsparse/pyPSQP/pyPSQP.py @@ -260,7 +260,7 @@ def pdcon(n, k, x, dg): inform = iterm.item() if inform < 0 and inform not in self.informs: inform = -10 - solInform = SolutionInform.from_informs(self.informs, inform) + sol_inform = SolutionInform.from_informs(self.informs, inform) if self.storeHistory: self.metadata["endTime"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.metadata["optTime"] = optTime @@ -268,7 +268,7 @@ def pdcon(n, k, x, dg): self.hist.close() # Create the optimization solution - sol = self._createSolution(optTime, solInform, ff, xs) + sol = self._createSolution(optTime, sol_inform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pySLSQP/pySLSQP.py b/pyoptsparse/pySLSQP/pySLSQP.py index b518c58dd..15908b4a0 100644 --- a/pyoptsparse/pySLSQP/pySLSQP.py +++ b/pyoptsparse/pySLSQP/pySLSQP.py @@ -261,10 +261,10 @@ def slgrad(m, me, la, n, f, g, df, dg, x): # Store optimizer exit condition and message inform = mode.item() - solInform = SolutionInform.from_informs(self.informs, inform) + sol_inform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution - sol = self._createSolution(optTime, solInform, ff, xs) + sol = self._createSolution(optTime, sol_inform, ff, xs) else: # We are not on the root process so go into waiting loop: self._waitLoop() diff --git a/pyoptsparse/pySNOPT/pySNOPT.py b/pyoptsparse/pySNOPT/pySNOPT.py index 2a99d9152..cfafd3ae5 100644 --- a/pyoptsparse/pySNOPT/pySNOPT.py +++ b/pyoptsparse/pySNOPT/pySNOPT.py @@ -501,7 +501,7 @@ def __call__( snopt.closeunit(self.getOption("iSumm")) # Store optimizer exit condition and message - solInform = SolutionInform.from_informs(self.informs, inform) + sol_inform = SolutionInform.from_informs(self.informs, inform) # Create the optimization solution if parse_version(self.version) > parse_version("7.7.0") and parse_version(self.version) < parse_version( @@ -510,7 +510,7 @@ def __call__( # SNOPT obj value is buggy and returned as 0, its thus overwritten with the solution objective value obj = np.array([obj.value * obj.scale for obj in self.optProb.objectives.values()]) - sol = self._createSolution(optTime, solInform, obj, xs[:nvar], multipliers=pi) + sol = self._createSolution(optTime, sol_inform, obj, xs[:nvar], multipliers=pi) restartDict = { "cw": cw, "iw": iw,