From 62f3b1024eb81172a022dc534c7705c989bb9277 Mon Sep 17 00:00:00 2001 From: slilonfe5 Date: Mon, 18 May 2026 12:45:20 -0400 Subject: [PATCH] Updated parmest.py to ensure PSD covariance matrix --- pyomo/contrib/parmest/parmest.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pyomo/contrib/parmest/parmest.py b/pyomo/contrib/parmest/parmest.py index 58c2b6d0a2f..fb221944ff2 100644 --- a/pyomo/contrib/parmest/parmest.py +++ b/pyomo/contrib/parmest/parmest.py @@ -525,6 +525,11 @@ def compute_covariance_matrix( cov = np.linalg.pinv(FIM) logger.warning("The FIM is singular. Using pseudo-inverse instead.") + # check if the covariance matrix is positive semi-definite + eigen_values = np.linalg.eigvalsh(cov) + if any(eig_val < -1e-10 for eig_val in eigen_values): + logger.warning("The covariance matrix is not positive semi-definite.") + cov = pd.DataFrame(cov, index=theta_vals.keys(), columns=theta_vals.keys()) return cov @@ -1479,6 +1484,17 @@ def _cov_at_theta(self, method, solver, step): solver=solver, tee=self.tee, ) + else: + raise ValueError( + 'One or more values are missing from "measurement_error". All values of ' + 'the measurement errors are required for the "SSE_weighted" objective.' + ) + else: + raise AttributeError( + 'Experiment model does not have suffix "measurement_error". ' + '"measurement_error" is a required suffix for the "SSE_weighted" ' + 'objective.' + ) else: raise ValueError( f"Invalid objective function for covariance calculation. "