Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diagnostics toolbox: display_near_parallel_constraints() does not distinguish between equality and inequality constraints #1502

Open
OOAmusat opened this issue Oct 15, 2024 · 5 comments
Assignees
Labels
Priority:Normal Normal Priority Issue or PR

Comments

@OOAmusat
Copy link
Contributor

OOAmusat commented Oct 15, 2024

Running the diagnostics toolbox on a model with inequality constraints enforcing variable bounds is throwing up display_near_parallel_constraints() warnings:

MWE:

 @m.Constraint(m.periods)
    def eq_hw_tank_temperature_lb(m, key):
        return m.fs[key].hw_tank.T[0] >= (50 + 273.15) * pyunits.K

    @m.Constraint(m.periods)
    def eq_hw_tank_temperature_ub(m, key):
        return m.fs[key].hw_tank.T[0] <= (90 + 273.15) * pyunits.K

Diagnostics box output


====================================================================================
>>> dt.display_near_parallel_constraints()
WARNING: model contains export suffix 'scaling_factor' that contains 144
component keys that are not exported as part of the NL file.  Skipping.
====================================================================================
The following pairs of constraints are nearly parallel:

    eq_hw_tank_temperature_lb[0], eq_hw_tank_temperature_ub[0]
    eq_hw_tank_temperature_lb[1], eq_hw_tank_temperature_ub[1]
    eq_hw_tank_temperature_lb[2], eq_hw_tank_temperature_ub[2]
    eq_hw_tank_temperature_lb[3], eq_hw_tank_temperature_ub[3]
    eq_hw_tank_temperature_lb[4], eq_hw_tank_temperature_ub[4]
    eq_hw_tank_temperature_lb[5], eq_hw_tank_temperature_ub[5]
    eq_hw_tank_temperature_lb[6], eq_hw_tank_temperature_ub[6]
    eq_hw_tank_temperature_lb[7], eq_hw_tank_temperature_ub[7]
    eq_hw_tank_temperature_lb[8], eq_hw_tank_temperature_ub[8]
    eq_hw_tank_temperature_lb[9], eq_hw_tank_temperature_ub[9]
    eq_hw_tank_temperature_lb[10], eq_hw_tank_temperature_ub[10]
    eq_hw_tank_temperature_lb[11], eq_hw_tank_temperature_ub[11]
    eq_hw_tank_temperature_lb[12], eq_hw_tank_temperature_ub[12]
    eq_hw_tank_temperature_lb[13], eq_hw_tank_temperature_ub[13]
    eq_hw_tank_temperature_lb[14], eq_hw_tank_temperature_ub[14]
    eq_hw_tank_temperature_lb[15], eq_hw_tank_temperature_ub[15]
    eq_hw_tank_temperature_lb[16], eq_hw_tank_temperature_ub[16]
    eq_hw_tank_temperature_lb[17], eq_hw_tank_temperature_ub[17]
    eq_hw_tank_temperature_lb[18], eq_hw_tank_temperature_ub[18]
    eq_hw_tank_temperature_lb[19], eq_hw_tank_temperature_ub[19]
    eq_hw_tank_temperature_lb[20], eq_hw_tank_temperature_ub[20]
    eq_hw_tank_temperature_lb[21], eq_hw_tank_temperature_ub[21]
    eq_hw_tank_temperature_lb[22], eq_hw_tank_temperature_ub[22]
    eq_hw_tank_temperature_lb[23], eq_hw_tank_temperature_ub[23]

According to @andrewlee94, this issue is possibly because we do not distinguish between equality and inequality constraints in the check.

@dallan-keylogic
Copy link
Contributor

The quick, easy fix is to just set the equalities_only option in get_jacobian to True. However, that misses out on potential issues. Equalities shouldn't be near parallel to each other, and equalities shouldn't be near parallel to any inequalities. The nuance comes in when comparing inequalities to other inequalities. I think what we want to do is get normal vectors that point out of the feasible region and check whether the inner product of those normal vectors is greater than zero. We can find a unique normal vector in 2D, but, off the top of my head, I'm not sure what to do in higher dimensions.

@Robbybp , what do you think?

@dallan-keylogic
Copy link
Contributor

Also, incidentally, why are you using Constraints here? Setting variable bounds on m.fs[key].hw_tank.T[0] would generally be better form. The difference is that a solver like IPOPT allows transient violation of Constraints, but will truncate steps to keep variables within their bounds.

@dallan-keylogic
Copy link
Contributor

Actually, taking the gradient gives the normal vector already (for some reason I thought it gave a tangent vector), so we should be golden. We just need to partition the Jacobian between equality and inequality constraints, make sure the inequality constraints have appropriate signs based on whether they have lower bounds, upper bounds, or both, then apply the same test without taking the absolute value of the inner product.

@OOAmusat
Copy link
Contributor Author

Also, incidentally, why are you using Constraints here? Setting variable bounds on m.fs[key].hw_tank.T[0] would generally be better form. The difference is that a solver like IPOPT allows transient violation of Constraints, but will truncate steps to keep variables within their bounds.

I set the variable bounds. I came across when I started trying out different formulations for an infeasible model (I wanted to see if using constraints instead of bounds would help).

@ksbeattie ksbeattie added the Priority:Normal Normal Priority Issue or PR label Oct 24, 2024
@Robbybp
Copy link
Member

Robbybp commented Oct 25, 2024

Yeah, it shouldn't be too hard to exclude inequality-inequality pairs. Although I don't think parallel inequality-equality pairs are too big of a problem, so I'd be happy with just omitting inequalities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority:Normal Normal Priority Issue or PR
Projects
None yet
Development

No branches or pull requests

4 participants