hdavid16 / DisjunctiveProgramming.jl

A JuMP extension for Generalized Disjunctive Programming
MIT License
27 stars 3 forks source link

Have `@disjunction` automatically add exactly one constraints with a keyword argument #72

Closed pulsipher closed 11 months ago

pulsipher commented 11 months ago

Since 99% of the time this is the case, automating it would be nice. I think we should make it opt-in (i.e., the default would be false).

One other thing to consider is whether the reformulations are still valid if this constraint is not given.

hdavid16 commented 11 months ago

I think we should force this on the @disjunction call. It wasn't there before because we couldn't distinguish Nested from non nested disjunctions. Now that we can, we can add the appropriate Exactly constraint.

pulsipher commented 11 months ago

Ok, so you would prefer something like @disjunction(model, name_expr, lvars, exactly1 = true) (i.e., the default is true)?

hdavid16 commented 11 months ago

I think we should add it and not give the user the option of not adding it.

pulsipher commented 11 months ago

One thing to consider is that under the new formal definition of GDP it seems like we are decoupling the exactly one constraint from the disjunction, so there might be cases where an exactly one constraint is not given. So, would it not be better to give the user an option to not add it and then have reformulations error that rely on this assumption?

pulsipher commented 11 months ago

@bernalde, do you have any thoughts on this?

hdavid16 commented 11 months ago

This recent paper always includes the exactly constraint as part of the extended GDP notation: https://arxiv.org/pdf/2303.04375.pdf.

pulsipher commented 11 months ago

Right and this paper also explicitly uses an exactly one constraint: https://www.sciencedirect.com/science/article/pii/S009813542300217X. The question is whether GDP requires there to always be an exactly one constraint. For instance, would it be possible to enforce exactly 2 out of 3 disjuncts?

hdavid16 commented 11 months ago

Not unless there were some valid reformulation, which is currently not the case.

Conceptually, you need to select exactly one disjunct region (even if they are not proper (have some overlap)).

bernalde commented 11 months ago

The "exactly one" is an explicit way of writing an exclusive or for more than 2 elements. In GDP, it was usually written this exclusive or which is not quite well defined. In disjunctive programming, you do not enforce the "only one" condition; it is a disjunction in its true case (at least one), i.e., sum_i y_i <= 1. A way of setting things straight is by using normal disjunctions and then enforcing the "exactly one" as part of the logical constraints. Practically, this would require the flexibility that Josh wants to put in the code of a flag deciding whether you want \sum_i y_i =1 or <=1. This is the way that it is implemented in Pyomo.GDP.

pulsipher commented 11 months ago

Thanks for the input @bernalde.

After talking with @hdavid16 offline, the game plan is as follows:

This will enable users to specify things like Exactly(2) or AtLeast(1) that are valid for reformulations like big-M, but not Hull.