The short answer is that “defined variables”,
var x {...} = ... ;
and “defining constraints”,
var x {...};
subject to X {...} : x[...] = ... ;
are handled differently in AMPL. The effects of this difference on both generation and solve time are highly problem-dependent, and you should experiment with both to determine what works best for your particular model.
The difference begins in generation, where AMPL converts a model and data into a problem instance that is written to a file in “.nl” format.
Defined variables are substituted out of the problem. At each place where a defined variable appears in an objective or constraint, it is replaced in the .nl file by a pointer to another part of the file where its definition is given. Variables in the definition are treated as nonlinear variables.
There is one exception. If the definition of the variable is a linear expression, and it appears in a linear objective or constraint, then the coefficients of the variable’s definition are substituted directly into the linear objective’s or constraint’s coefficient list. Variables in the definition can thus be treated as linear. (This exception can be turned off by setting AMPL option linelim to 0.)
Defining constraints are treated like other constraints. Thus the variable being defined remains as a variable in the problem, and the definition adds a constraint to the problem.
There is an alternative, however. When option substout is set to 1, AMPL tries to convert defining constraints into defined variables:
AMPL scans the constraints in the order of their appearance in the model, and defining constraints are converted to defined variables if the variable’s definition imposed no restrictions on it (such as integrality or bounds) and the variable has not appeared in any previous such constraint.
Additionally, the AMPL-solver interface converts the representation in the .nl file to a form that the solver can deal with. That may involve further changes in the representation of defined variables. And finally, solvers incorporate highly complex implementations of a variety of optimization ideas, which react to defined variables or defining constraints in ways that are different but hard to predict. Put all this together, and you can see why it’s better to experiment than to try to figure out in advance which approach will work best for a certain application.