Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion pyomo/gdp/plugins/hull.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ class Hull_Reformulation(GDP_to_MIP_Transformation):
'LeeGrossmann', or 'GrossmannLee'
EPS : float
The value to use for epsilon [default: 1e-4]
eigenvalue_tolerance : float
Numerical tolerance for eigenvalue-based positive/negative
semi-definite checks when using the exact hull reformulation for
quadratic constraints (``exact_hull_quadratic=True``). An
eigenvalue is considered non-negative (non-positive) if it is
greater than (less than) ``-eigenvalue_tolerance``
(``eigenvalue_tolerance``). Increasing this value makes the
convexity check more conservative; decreasing it makes it more
permissive. [default: 1e-10]
Comment thread
sergey-gusev94 marked this conversation as resolved.
Outdated
targets : block, disjunction, or list of those types
The targets to transform. This can be a block, disjunction, or a
list of blocks and Disjunctions [default: the instance]
Expand Down Expand Up @@ -184,6 +193,29 @@ class Hull_Reformulation(GDP_to_MIP_Transformation):
description="Epsilon value to use in perspective function",
),
)
CONFIG.declare(
'eigenvalue_tolerance',
cfg.ConfigValue(
default=1e-10,
domain=cfg.PositiveFloat,
Comment thread
sergey-gusev94 marked this conversation as resolved.
Outdated
description="Numerical tolerance for eigenvalue-based PSD/NSD checks "
"in exact hull quadratic reformulations",
doc="""
Numerical tolerance used when determining positive semi-definiteness
(PSD) or negative semi-definiteness (NSD) of the Hessian matrix Q in
the exact hull reformulation for quadratic constraints
(``exact_hull_quadratic=True``).

An eigenvalue ``lam`` is treated as non-negative if
``lam >= -eigenvalue_tolerance``, and non-positive if
``lam <= eigenvalue_tolerance``. Increasing this value makes the
convexity classification more conservative (i.e., Q must have
eigenvalues further from zero to be considered PSD/NSD); decreasing
it makes the check more permissive. For ill-conditioned Q matrices a
larger tolerance may be appropriate.
Comment thread
sergey-gusev94 marked this conversation as resolved.
Outdated
""",
),
)
CONFIG.declare(
'assume_fixed_vars_permanent',
cfg.ConfigValue(
Expand Down Expand Up @@ -976,7 +1008,7 @@ def _build_exact_quadratic_hull(
Q[idx_i, idx_j] += 0.5 * coef
Q[idx_j, idx_i] += 0.5 * coef

numerical_tolerance = 1e-10
numerical_tolerance = self._config.eigenvalue_tolerance
eigenvalues, _ = np.linalg.eigh(Q)
Q_is_psd = not np.any(eigenvalues < -numerical_tolerance)
Q_is_nsd = not np.any(eigenvalues > numerical_tolerance)
Comment on lines +1015 to 1018
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduces a new public config option (eigenvalue_tolerance) that affects whether the conic vs general exact-hull formulation is selected, but there do not appear to be any existing tests covering exact_hull_quadratic (and thus none validating that this tolerance is honored). Please add a focused unit test that sets exact_hull_quadratic=True and varies eigenvalue_tolerance to flip the PSD/NSD classification for a nearly-singular Q, asserting the chosen reformulation differs.

Copilot uses AI. Check for mistakes.
Expand Down