Add Complementarity support for NL Writer v2 #3458
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes # .
Summary/Motivation:
At work, I tried to use pyomo to solve a complementarity problem but it raised a ValueError as pyomo\repn\plugins\nl_writer.py does not know how to process Complementarity constraints.
Changes proposed in this PR:
-Add a block to handle complementarity constraints and the auxiliary variable/additional constraints after conversion to its standard form. When comparing my .nl file to AMPL's nl file, it seems that the additional equality constraint we add in to_standard_form() from complementarity.py is
c: (v - expression == 0)
while AMPL defines it as c:( v + expression == 0)
Essentially, Pyomo's auxiliary variable v is minus the auxiliary variable from AMPL, which makes it tricky to reconcile a .nl file written by Pyomo and one written by AMPL. I have not changed complementarity.py as Pyomo's choice is valid, it's simply a matter of convention.
Minimal example reproducing the issue being fixed:
from pyomo.environ import *
from pyomo.mpec import *
from pyomo.opt import WriterFactory
m = ConcreteModel()
m.x = Var(bounds=(0, 1))
m.y = Var(bounds=(0, 1))
m.c = Complementarity(expr=complements(m.x >= 0, m.y >= 0))
m.obj = Objective(expr=m.x+m.y, sense=maximize)
writer = WriterFactory('nl_v2')
filename_v2 = "model_v2.nl"
writer(m, filename_v2, solver_capability=(lambda x: False), io_options={})
Any ideas on how to test the validity of this implementation? I can see the .nl written by the code above has the correct number of variables (x, y and v the auxiliary), 2 constraints, one complementarity linear (5 1 3) and one equality (4 0)
g3 1 1 0 # problem unknown
3 2 1 0 1 # vars, constraints, objectives, ranges, eqns
0 0 1 0 0 0 # nonlinear constrs, objs; ccons: lin, nonlin, nd, nzlb
0 0 # network constraints: nonlinear, linear
0 0 0 # nonlinear vars in constraints, objectives, both
0 0 0 1 # linear network variables; functions; arith, flags
0 0 0 0 0 # discrete variables: binary, integer, nonlinear (b,c,o)
3 2 # nonzeros in Jacobian, obj. gradient
0 0 # max name lengths: constraints, variables
0 0 0 0 0 # common exprs: b,c,o,c1,o1
C0
n0
C1
n0
O0 1
n0
x0
r
5 1 3
4 0
b
0 0 1
0 0 1
2 0
k2
1
2
J0 1
1 1
J1 2
0 -1
2 1
G0 2
0 1
1 1
Legal Acknowledgement
By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution: