A variable is ineligible to be substituted out of a problem if (a) it is subject to any bounds or integrality conditions, or (b) it has already appeared on the right-hand side of a constraint that was used to make a substitution.
Case (a) includes bounds or integrality conditions specified in the variable’s declaration, and also bounds that are added by AMPL’s presolve phase. Thus turning presolve off (by setting option presolve 0
) may permit a greater number of substitutions.
For constraints indexed over a set, the incidence of case (b) may depend on the ordering of the set. Consider for example the constraints
var x {1..10};
subj to step {j in 1..9}: x[j] = x[j+1] + 1;
The first several constraints generated are
step[1]: x[1] = x[2] + 1
step[2]: x[2] = x[3] + 1
step[3]: x[3] = x[4] + 1
step[4]: x[4] = x[5] + 1
Constraint step[1]
may be used to substitute for x[1]
. Constraint step[2]
may not be used to substitute for x[2]
, however, because x[2]
has already appeared on the right-hand side of a constraint, namely step[1]
, that was used to make a substitution. Similarly, step[3]
may be used to substitute for x[3]
, but step[4]
may not be used to substitute for x[4]
, and so forth. Only the odd-numbered constraints step[j]
are eliminated by substitution in this case.
If instead you write the declaration with the ordered index set reversed,
subj to step {j in 9..1 by -1} x[j] = x[j+1] + 1;
then the constraints are generated as
step[9]: x[9] = x[10] + 1
step[8]: x[8] = x[9] + 1
step[7]: x[7] = x[8] + 1
step[6]: x[6] = x[7] + 1
and case (b) does not occur. All of the constraints step[j]
can be eliminated, and every variable except x[10]
is substituted out as a result.
Close attention to formulation may thus be necessary to get the substitutions that you want. Set option show_stats 1
to see how many substitutions are being made, and use AMPL’s constraint expansion commands to see the constraints (in order) before and after substitution.