I have some AMPL files in .mod format, which I want to convert to .nl format. In this way, I can then easily parse them for further processing.
However, I noticed that in the conversion the problem is changed.
An example of input where this problem arises is the following, taken from here.
var x {1..4} >= 0;
minimize obj:
2-x[1]*x[2]*x[3]
;
subject to constr1: x[1] + 2*x[2] + 2*x[3] - x[4] = 0;
subject to constr2: x[1] <= 1;
subject to constr3: x[2] <= 1;
subject to constr4: x[3] <= 1;
subject to constr5: x[4] <= 2;
let x[1] := 2;
let x[2] := 2;
let x[3] := 2;
let x[4] := 2;
#printf "optimal solution as starting point \n";
#let x[1] := 2/3;
#let x[2] := 1/3;
#let x[3] := 1/3;
#let x[4] := 2;
I tried to convert it by running
ampl -oghs041 hs041.mod
which produces the following hs041.nl
file
g3 2 1 0 # problem hs041
4 1 1 0 1 # vars, constraints, objectives, ranges, eqns
0 1 # nonlinear constraints, objectives
0 0 # network constraints: nonlinear, linear
0 3 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)
4 3 # nonzeros in Jacobian, gradients
0 0 # max name lengths: constraints, variables
0 0 0 0 0 # common exprs: b,c,o,c1,o1
b
0 0 1
0 0 1
0 0 1
0 0 2
x4
0 2
1 2
2 2
3 2
r
4 0
C0
n0
O0 0
o1
n2
o2
o2
v0
v1
v2
k3
1
2
3
J0 4
0 1
1 2
2 2
3 -1
G0 3
0 0
1 0
2 0
This is not the output I expected, since only one constraint in the form 0=0
is left.
My guess is that some simplifications are performed before converting the problem, and that the resulting problem is always equivalent to the original one.
Is this guess correct? Can I trust the fact that the problem in the .nl file is equivalent to the original one?
Is there a way to avoid such simplifications? I tried with the -P
and -L0
options
-Ln {0 = treat linear definitional constrs and var = decls as nonlin}
-P {skip presolve -- same as "option presolve 0;" }
but they do not help solving this issue.
Ampl performs a presolve algorithm before generating the nl file, so some variables and constraints may dissapear at that point. You can control Ampl's presolve with the presolve option (option presolve 0;
would disable presolve iterations). Other simplifications will be still perform, but they should be trivial ones. For example, x + 2 >= x + 1 - 2
could get simplified.
However, in your case most of the constraints are just bounds for variables (subject to constr2: x[1] <= 1
) so they are treated like that. In the 'b' sections of the nl file you can actually see these constraints:
b
0 0 1
0 0 1
0 0 1
0 0 2
So x1 has 2 bounds, 0 and 1, same for x2, x3, and for x4 there are 2 bounds, 0 and 2. I guess it would be redundant to send bounds for the variables and also constraints that are setting those bounds.
For any further example with slightly more difficult constraints, you could be just generating an nl file without simplifications, but constraints involving one variable and one constant are going to be converted into bounds for that variable.
For constraint 1, the linear part appears in a J segment and contains the linear coefficients for each involved variable. For example,
J0 4
0 1
1 2
2 2
3 -1
Means that constraint 0 (J0) has 4 variables (J0 4), and 4 lines come after especifying which variables and the coefficients (0 1 means variable x1 with coef 1, 1 2 means variable x2 with coef 2...).
In the r segment, bounds for the constraint are specified:
r
4 0
==> range of type 4 which is an equality, so body == 0
I don't know about any option that can do what you say, but here there are a bunch of options you could try just in case, see Presolve Options and Solve Options sections: https://dev.ampl.com/ampl/options.html#presolve-options
By the way, I usually generate an nl file through the "write command" rather than passing arguments. write gmymodel;
will generate mymodel.nl
.
Some other useful commands to review the model are expand;
and solexpand;
.
Yes, the nl file should be equivalent to the model, but simplified and reduced.
"In this way, I can then easily parse them for further processing.", I am curious about how do you parse better an nl file than the model itself! I am curious of what you are doing.