1.1
- What is AMPL?
1.2
- How does AMPL compare to other modeling languages and systems?
1.3
- How does AMPL compare to spreadsheet optimizers?
1.4
- How big a problem can AMPL solve?
1.5
- Can my program call AMPL as a subroutine?
1.6
- How can I learn more about AMPL?
2.1
- After I type the model as shown in Section 1.2 of the AMPL book, how do I save it to a file?
2.2
- How can I edit my model or data file without leaving the AMPL command environment?
2.3
- How do I solve a series of different random problems with data drawn from the same distribution?
2.4
- When does AMPL evaluate the conditions specified in my model's check statements?
2.5
- How do I write an "MPS file" for my problem?
2.6
- Why does AMPL write an MPS file that is different from what I expect?
2.7
- What are the transformations that AMPL applies to optimization problems?
2.8
- How can I prevent AMPL from transforming my problem?
3.1
- Why does AMPL reject my "let" statement with a "... has a := value in the model" message?
3.2
- What does AMPL mean by "syntax error"? I double-checked the offending statement in the AMPL book, and my syntax is fine.
3.3
- How can I tell whether messages on my screen are coming from AMPL or from the solver?
3.4
- Why does AMPL appear to "hang" for a long time without accepting any input or producing any output?
3.5
- Why does AMPL unexpectedly abort in the middle of doing something? I get a short error message, but I can't find it explained in the AMPL book or in the solver documentation.
3.6
- What should I do if I suspect that there is insufficient memory for my AMPL session?
4.1
- Why doesn't AMPL interpret the expression T..1 as I expect?
4.2
- Why does "set S := 50 .. 70" give me a set of only 3 members?
4.3
- I have declared "set S" and "param b {S}". How do I write an AMPL expression for the arg min of b[i] -- that is, the s in S such that b[s] equals the minimum of b[i] over all i in S?
4.4
- How can I get AMPL to index over the "power set" consisting of all subsets of a set?
4.5
- How can I apply AMPL's ordered-set functions to pairs and higher-dimensional objects?
4.6
- Why do I get an "invalid subscript discarded" message when I display an AMPL parameter?
5.1
- When I set option substout 1, why doesn't AMPL make the substitutions that I expect?
5.2
- Why does AMPL treat my linear program as nonlinear?
5.3
- When certain variables are fixed, the nonlinear expressions in my model all become linear. Why does AMPL still consider my model to be nonlinear in this case?
6.1
- How can I look at the explicit constraints that AMPL has generated from my model and data?
6.2
- How do I list all variables that have a certain property in the optimal solution?
6.3
- How do I get "ranges" and other sensitivity analyses?
6.4
- How do I get a "tableau column" from AMPL?
6.5
- Why can't I view an indexed collection of subsets by typing display {k in SS} POW[k]?
6.6
- How can I get the display command to list a set's members in the same order that they were given in my data file?
7.1
- How do I relax the integrality of only some of a model's integer variables?
7.2
- Why does my solver's relax directive sometimes give a higher objective value than AMPL's relax_integrality option?
7.3
- How can I "break" a run of an integer programming solver and get back the best integer solution found so far?
7.4
- How can I use the solver's "special ordered sets" feature?
8.1
- What is the student edition of AMPL?
8.2
- What is the professional edition of AMPL?
8.3
- What is AMPL Plus?
8.4
- Is there a graphical ("gui") version of AMPL?
8.5
- Can I get a version of AMPL that will run on my computer, under my computer's operating system?
8.6
- Where can I get more information about how AMPL works under specific operating systems?
8.7
- How can I determine the version number of the copy of AMPL that I'm currently running?
8.8
- How can I learn about updates to AMPL, and where can I get updated AMPL software?
9.1
- What solvers does AMPL support?
9.2
- Can I buy AMPL and the solvers separately?
9.3
- Where can I get more information about AMPL's interface to specific solvers?
9.4
- How can I interface my own solver to AMPL?
10.1
- Where can I get more information on AMPL?
10.2
- How can I get answers to more questions about AMPL?
AMPL is a computer language for describing production, distribution, blending, scheduling and many other kinds of problems known generally as large-scale optimization or mathematical programming.
AMPL's familiar algebraic notation and interactive command environment are designed to help formulate models, communicate with a wide variety of solvers, and examine solutions.
AMPL's flexibility and convenience make it ideal for rapid prototyping and development of models, while its speed and generality provide the resources required by repeated production runs.
AMPL is one of several optimization modeling systems that are designed around specialized algebraic modeling languages. These languages employ adaptations of familiar mathematical notation to describe optimization problems as
Some of the other commercially distributed algebraic modeling languages are:
AMPL provides strong support for validation, verification and reporting of optimal solutions, through numerous alternatives for presenting data and results. AMPL's extensive preprocessing routines can automatically carry out transformations that serve to reduce problem size, convert piecewise-linearities to linear terms, and substitute out selected variables.
AMPL is further distinguished by its continuing development to serve users' needs. Recent additions include looping and testing constructs for writing executable scripts in the AMPL command language, and facilities for defining and working with several interrelated subproblems. Numerous commands have also been added for producing diagnostic reports and custom-formatted tables.
There are also many optimization modeling systems based on representations other than algebraic modeling languages. Popular alternative forms include:
The Excel, 1-2-3 and Quattro spreadsheet packages come with solvers for linear, nonlinear, and integer programming; they accept enhanced add-in solvers as well. Their principal advantage lies in allowing all aspects of optimization -- including formulation, solution, and analysis of results -- to be performed within the spreadsheet environment. In particular, variables and constraints can be defined directly in terms of ranges of spreadsheet cells.
AMPL incorporates a far richer language than spreadsheet optimizers for describing optimization problems. As a result, AMPL is much more natural and reliable for developing and maintaining complex models. The difference is particularly pronounced when many model components have more than two dimensions (or more than two subscripts or indices, in AMPL terms).
By avoiding much of the spreadsheet overhead, AMPL also generates model instances faster than spreadsheet optimizers. AMPL's speed advantage is significant for a few thousand model components, and becomes relatively greater as problem size increases.
AMPL's interface design encourages developers to hook additional solvers to AMPL. Thus AMPL is available with a greater variety of solvers than spreadsheet optimizers.
AMPL models can use data stored in spreadsheet ranges, but only through the exchange of appropriately formatted text files. AMPL's new read command facilitates this exchange. AMPL Plus can also use the ODBC standard to read and write spreadsheet ranges that represent relational database tables.
Certain low-cost versions of AMPL have built-in limits on problem size. The student edition bundled with the AMPL book is limited to 300 variables and a total of 300 objectives and constraints, for example, and several packages having higher limits are offered by AMPL vendors. The professional edition of AMPL has no intrinsic limit on problem size, however; it is limited only by the resources available to the computer that is running AMPL.
In practice, memory is most often the limiting resource. The amount of memory used by AMPL necessarily depends on the numbers of variables and constraints, and on the number and complexity of the terms in the constraints -- or in the case of linear programs, on the number of nonzero coefficients in the constraints. Memory use also depends on the size and complexity of the model's sets and parameters. AMPL's presolve phase may require additional memory to execute (though it may accomplish problem reductions that allow savings of memory later).
AMPL's memory use for a linear program can be estimated crudely as 1000000 + 260 (m + n) + 50 nz bytes, where m is the number of constraints, n the number of variables, and nz the number of nonzeroes. Allowing for memory occupied by DOS, this suggests that the following sizes of problems might be accommodated on a PC:
m = 1200, n = 4800, nz = 14400 on a 4MB machine, m = 3600, n = 14400, nz = 43200 on an 8MB machine, m = 8000, n = 24000, nz = 96000 on a 16MB machine.
Memory required for a solver must be added, if the solver is to be run while AMPL remains active. See also our advice elsewhere in this FAQ for further comments on what to do (including running the solver separately) if you suspect a problem with insufficient memory.
Especially difficult problems may cause your solver to encounter its own resource limitations. Solvers that accept binary and integer variables, in particular, can consume impractical amounts of time and disk space as well as memory, even for problems of apparently modest size. Nonlinear problems can also be very time-consuming compared to linear programs in the same numbers of variables and constraints.
As a practical matter, there is no substitute for experimentation to determine the resource requirements of your particular problem. The best approach is usually to try out your model on progressively larger collections of data, so that you can record the trend in resource requirements as problem size increases.
Currently AMPL is not configured as a subroutine library (like CPLEX or OSL) whose individual pieces can be called as needed from a user's program. A "batch" session of AMPL can be executed from a C program, however. This feature can be used as a high-level "call" to AMPL that is sufficient for some applications.
Under Unix, MS-DOS or Microsoft Windows, you would execute AMPL by use of the system procedure, as in these examples:
system("ampl <cut.run");
system("ampl <cut.run >cut.out");
The argument to system can be anything one would type on a command line. Most commonly, an input file (cut.run above) contains a series of AMPL commands that read model and data input, invoke solvers, and write results to files. This arrangement does not provide for results to be passed back directly to your program; following the call to system, your program must get the results by reading a file that AMPL has written.
The AMPL book is the most comprehensive source of information on AMPL. It is written in the form of a textbook with an appendix for reference, in contrast to the more common format of a reference manual with some tutorial material at the front. Virtually all language features are illustrated by continuing, meaningful examples, and additional exercises are provided. A student edition of the AMPL software and the MINOS and CPLEX solvers is included.
See also the AMPL update pages for features added since the book was published.
You could use AMPL's new show command to display the declarations that you have typed in, but with the display output directed to a file rather than the screen. To save your work to file steel0.mod, for example, you could type
show XB,XC,profit,Time,B_limit,C_limit >steel0.mod;
This is a very inefficient and error-prone way to work with AMPL models, however. We recommend instead the approach introduced in Sections 1.3 and 1.4 (and used throughout the rest of the book). First use an editor to create files of model declarations and data, and then instruct AMPL to read from those files.
Use AMPL's shell command to invoke the editor you want to use. For example, if your editor is called edit and your file is diet2a.dat, give the command
shell "edit diet2a.dat";
The editor temporarily takes over the screen or current window. When you quit the editor, the AMPL prompt reappears, and all models, data and options are as before.
When you have returned from the editor, AMPL cannot tell which files you have changed! Thus to use a changed file, you must reset and read it again. The simplest approach is to reset and re-read everything, as in this example:
ampl: shell "edit diet.mod"; ampl: reset; ampl: model diet.mod; ampl: data diet2a.dat;
See our discussion of new reset features for ways to partially reset the model and data.
In a multiple-window environment (such as X on Unix workstations or Microsoft Windows on PCs) it's easier to edit files in their own windows, separate from the windows where you're running AMPL. You still need to reset and re-read after changing a file, though.
If you use a graphical interface to AMPL then you can create editing windows within the AMPL environment. The interface does know when you have changed a file, and it may carry out the reset and re-read operations automatically. To learn more, consult the instructions for the interface that you are using.
Use AMPL's reset data command to resample from all of the random-valued functions in the model. For example, in model steel4.mod from the AMPL book, suppose that parameter avail is changed so that its value is given by a random function:
param avail_mean {STAGE} >= 0;
param avail_variance {STAGE} >= 0;
param avail {s in STAGE} :=
Normal (avail_mean[s], avail_variance[s]);
with corresponding data
param: avail_mean avail_variance := reheat 35 5 roll 40 2 ;
Then AMPL will take new samples from the Normal distribution after each reset data:
ampl: model steel4.mod; ampl: data steel4.dat;
ampl: solve; MINOS 5.4: optimal solution found. 3 iterations, objective 187632.2489
ampl: display avail; reheat 32.3504 roll 43.038 ;
ampl: reset data avail;
ampl: solve; MINOS 5.4: optimal solution found. 4 iterations, objective 158882.901
ampl: display avail; reheat 32.0306 roll 32.6855 ;
Using this feature together with one of AMPL's new looping commands, you can automatically solve a series of random realizations from the model, and summarize the results:
model steel4.mod; data steel4.dat;
param nruns := 5;
param optvalue {1..nruns};
for {k in 1..nruns} {
reset data avail;
solve;
let optvalue[k] := total_profit;
}
display (sum {k in 1..nruns} optvalue[k]) / nruns;
If you use reset rather than reset data, then AMPL's random number generator is reset, and the values of avail repeat from the beginning. To get a different sequence of random numbers from the generator, you must change the random number seed; give the command option randseed n -- where n is a positive integer -- or option randseed 0 to have AMPL choose a seed based on the system clock.
Versions of AMPL prior to 19951020 work a little differently. For this and other fine points, see the supplementary reset data examples.
The check conditions are evaluated each time that AMPL generates (or re-generates) an instance of your model. Normally the generation of an instance is triggered by a solve command, but a few other commands such as write and solution can have the same effect.
You can force all check statements to be evaluated immediately by typing the command
check;
or by inserting this command into an AMPL script at the point where you want the checking to occur.
You can use AMPL's write command to create a file that contains a representation of your linear or integer program in a standard format known as MPS form. To write an MPS-form file for the diet LP from Chapter 2 of the AMPL book, for example, you could proceed as follows:
ampl: model diet.mod; ampl: data diet2a.dat;
ampl: option auxfiles rc;
ampl: write mdiet2;
AMPL interprets "write m..." as indicating that you want to write an MPS file, and creates the filename by appending ".mps" to the letters after the "m". Thus our example creates a file named diet2.mps. The format of this file is explained in the Linear Programming FAQ and in the manuals for many solvers.
Because MPS form limits the row (constraint or objective) and column (variable) names to 8 characters, AMPL substitutes artificial names such as R0001 and C0007. You can ask for supplementary files of the true AMPL component names, by also resetting option auxfiles rc; in the above example, you would get files diet2.row and diet2.col. The ordering of the names in these files corresponds to their numbering in the MPS file. (For a more detailed description of write and the auxfiles option, see Sections A.13.5 and A.13.6 of the AMPL book.)
An MPS file contains only the nonzero values that define one instance of your model. Thus an MPS file generated by AMPL is mainly useful as input to solvers that do not yet have a direct AMPL interface; because MPS form has been in use for a longer time than any comparable format, it is recognized by more solvers than any other file type. You may also find AMPL's MPS-file option useful for generating new instances of test problems, for submission to libraries such as netlib's lp/data or miplib. If you want to encourage people to use AMPL with your own solver, however, then you should consider hooking your solver to AMPL by use of AMPL's file format, which takes less space, can be processed faster, represents numbers more accurately, and applies to a broader variety of optimization problems (especially nonlinear ones).
Several kinds of transformations may be applied by AMPL before it writes out any representation of your problem. Normally you need not be aware of these changes, because AMPL reverses them after receiving the optimal solution from the solver. If you write an MPS file, however, it will correspond to the transformed problem; its coefficients and other values may have been changed, it may lack some of the variables and constraints that you defined, or it may contain auxiliary variables and constraints that AMPL added. To get a summary of AMPL's transformations, set option show_stats 1. To force AMPL to write the MPS file for your problem as stated, turn off the transformations.
Representations of numbers in MPS form are limited to 12 characters. As a consequence, the numbers in an MPS file may not have the full precision of the numbers that were generated from your AMPL model and data. Usually these precision discrepancies are inconsequential, but they do give rise to inaccuracies in the optimal solution computed from the MPS file.
Although MPS form is regarded as a standard, it has no definitive statement. As a result, there are a few special cases that are treated differently by different solvers; examples include variables that have an upper bound of zero and no lower bound, and integer variables declared without any bounds. AMPL's version of MPS form is designed to avoid using these unresolved default options, so that its MPS files can be compatible with as many solvers as possible. If using the MPS file gets you a significantly different optimal value from what you get by typing solve, however, then try looking at our list of MPS form inconsistencies.
AMPL's presolve phase attempts to transform your problem to an equivalent one that is smaller and easier to solve. Presolve first removes trivial model components, such as variables fixed at constant values and constraints that express simple lower or upper bounds. Then it applies an iterative procedure to tighten certain bounds on variables and constraints, with the result that additional variables may be fixed and constraints may be dropped. Many of these transformations are based on ideas first presented by A.L. Brearly, G. Mitra and H.P. Williams, in ``Analysis of Mathematical Programming Problems Prior to Applying the Simplex Algorithm,'' Mathematical Programming 8 (1975) 54-83. See also Experience with a Primal Presolve Algorithm for a detailed discussion of the implementation in AMPL.
If your model uses AMPL's notation for piecewise-linear terms in individual variables, then AMPL transforms your problem's piecewise-linear expressions to equivalent linear expressions, through the addition of auxiliary variables and constraints. Chapter 14 of the AMPL book describes the piecewise-linear notation in more detail. See also Expressing Special Structures in an Algebraic Modeling Language for Mathematical Programming for further discussion of how the transformation is carried out.
You can cause AMPL to eliminate certain variables from your problem, by substituting expressions specified in var declarations or in certain constraints. If the substitution comes from a constraint, then the constraint is also eliminated. See Sections 13.2 and A.15 of the AMPL book for more information.
To suppress the presolve phase, set option presolve 0.
To suppress transformation of piecewise-linear terms, set option pl_linearize 0.
To suppress elimination of variables by substitution from constraints, set option substout 0. (This is the default setting.) Substitutions specified within var declarations are always applied.
To see a summary of all transformations performed, set option show_stats 1.
Your let command is attempting to assign a value to some set or parameter. In the set's or parameter's declaration, however, you have used a := phrase to permanently define the value. A let command is not permitted to redefine the value of such a parameter; hence the error message that you received.
As an example, if the model declares
param dstot {p in prod} := sum {w in whse} ds[p,w];
then dstot[p] is permanently defined to take the value sum {w in whse} ds[p,w]. You can make any changes you like to the ds[p,w] values, and AMPL will automatically change the dstot[p] values accordingly. Any command beginning let {p in prod} dstot[p] := ... will be in error, however.
If you want to be able to use let to override the defined value of a parameter, use default in place of := in your param declaration.
AMPL is signaling an invalid statement of some sort, but the error may not be a matter of "syntax" in the usual sense. For example, you could be trying to define a set index at a place where it is already in use:
ampl: display {i in ORIG}:
ampl? supply[i] * sum {i in DEST} cost[i,j];
syntax error
context: supply[i] * sum {i >>> in <<< DEST} cost[i,j];
The index i cannot be defined following sum, because it is within the scope of the index i that was defined following display.
If you receive a syntax error that is particularly hard to interpret, please let us know.
When a solver starts up, it displays a brief identification string such as MINOS 5.4 or CPLEX 3.0. Output that occurs before this string can be assumed to come from AMPL, while output after is the solver's.
When a solver concludes its run, it returns a brief summary of the results, such as
optimal solution; objective 903202.0326 399 iterations (244 in phase I)
Output prior to this summary can be assumed to be caused by the solver, while output after is from AMPL again.
If AMPL appears to hang after a solve command but before any output from a solver, then it may be taking much more time to generate your problem than you expected. Try setting option times 1, gentimes 1 to get more output recording AMPL's progress, as explained in the FAQ question regarding insufficient memory.
The same advice applies if AMPL hangs after some other command, such as write or expand, that forces a lot of variables or constraints to be generated.
If AMPL appears to hang after a command that produces a listing, such as display, then the listing may be much longer than you expected. Usually it is possible to make a quick estimate of the size of the listing, in order to determine whether this could be the difficulty.
If AMPL appears to hang after a line or more from the solver, then your optimization problem may be taking much more time to solve than you expected. Try setting solver directives that provide more output recording progress toward an optimum. Some solvers may also respond to a "break" sequence by returning the best solution found so far. These features differ from one solver to the next and even from one algorithm to the next within the same solver; see the solver-specific documentation for details.
You have encountered a low-level error message generated by the operating system. AMPL and the solvers try to trap these messages so as to provide you with more useful information instead; but occasionally a mysterious message does get through.
Some messages, such as
no children unrecoverable error, STAT = 1001 not enough swap space
usually indicate that AMPL can't get enough computer resources to complete the current session. As an example, there might be insufficient disk space for AMPL to write the temporary file that the solver reads; to remedy the problem, you can reset option TMPDIR to change the directory to which temporary files are written. More often, however, the difficulty in this situation is insufficient memory, a more complicated matter that we discuss in the next question below.
Other messages, including
segmentation fault bus error
indicate a bug in AMPL or a solver. Often there is some way to work around this trouble temporarily, but you should also look for a more permanent fix. You can consult our bug fix log to see whether this bug has been found and fixed already; if not, you can tell us about the problem through our comment form. Either way, you will want to request a newer version of the AMPL software that incorporates the fix.
If AMPL fails before passing control to the solver, your computer may not have enough memory to hold all of the variables, constraints and objectives generated by the AMPL translator. If a failure occurs after the solver takes over, memory might be short because AMPL has taken most of it for generating the problem, leaving not enough memory for the solver to be active at the same time.
As a start in diagnosing these situations, display listings of AMPL's memory use by repeating your run with one or more of
option times 1; option gentimes 1; option show_stats 1;
The times listing includes the amount of memory used by each phase of the AMPL translator:
parse initial processing of model data read initial processing of data compile translation of model and data genmod generation of an explicit optimization problem merge postprocessing of optimization problem collect postprocessing of optimization problem presolve reduction of problem size output writing of problem file to be read by solver
The gentimes listing includes memory allocated for processing each declaration in the model. If AMPL fails before invoking a solver, this information will tell you how far it got. For failures in the presolve phase, you can save some memory by setting option presolve 0, though a larger problem will be sent to the solver as a result. (Each line in a times or gentimes listing appears when processing of the phase or component is finished. Thus the cause of a memory failure must be in the phase or component after the last one that appeared in the listing. It may help to first run a smaller version of your problem, so that you can see what ought to appear in a complete, correct listing.)
If failure doesn't occur until after the solver is invoked, then the show_stats listing also appears, giving the numbers of variables and constraints generated and the numbers removed by presolve. If there are more variables or constraints than you expected, then check the gentimes listing for a declaration that has required a very large amount of memory (relative to what the whole model requires). The offending declaration may be incorrect; or, even if it is technically correct, the declaration may specify a very large number of variables or constraints that are unnecessary to the formulation. (Even if a variable is never referenced in the model, it takes up some minimum amount of space in the data structure that AMPL maintains in memory.)
If the difficulty is indeed insufficient memory to run the solver under AMPL, then there is a good chance that you can work around the problem by running AMPL and your solver separately. Here's an example of how this is done:
ampl: model models\multmip3.mod; ampl: data models\multmip3.dat;
ampl: write bmultmip3; # "b" indicates a binary problem file
ampl: quit
C:\AMPL> cplex multmip3 No MIP presolve or aggregator reductions.
C:\AMPL> ampl
ampl: model models\multmip3.mod; ampl: data models\multmip3.dat;
ampl: solution multmip3.sol;
CPLEX 3.0: optimal integer solution; objective 235625 684 simplex iterations 126 branch-and-bound nodes
ampl: display Trans;
Trans [CLEV,*,*] : bands coils plate := DET 0 525 100 FRA 275 50 50 ...
This is inconvenient, but it can substantially reduce the overall memory requirement.
To diagnose insufficient memory, you may need some idea of the amount of memory available for allocation by AMPL and the solver. Your computer may have a utility to help with this, or you may be able to run a short C program like this that tries to allocate as much as possible:
#include <stdio.h> #include <stdlib.h>
main()
{
long int avail, incr;
avail = 0;
for (incr = 1024 * 1024; incr >= 1; incr >>= 1) while (malloc(incr)) avail += incr;
printf ("Total allocated: %i\n", avail);
}
Keep in mind that the available memory is often influenced not only by the amount of memory physically installed in the computer, but by the amount of disk space allocated to memory swapping and by the requirements of all other processes currently running on the computer.
In general, AMPL interprets a..b as {a, a+1, a+2, ..., b-1, b}. Thus when T is greater than one, T..1 is an empty set. To specify the ordered set that goes from T down to 1, write "T..1 by -1".
You have declared "set S" in your model and "set S := 50 .. 70" in your data. Set expressions are not recognized in AMPL's data mode, however. Instead AMPL tries to recognize 50 .. 70 as a space-delimited list of members of S, with the result that it has found three members: the numbers 50 and 70, and the string "..".
To define S to equal 50 .. 70 by use of your data file, first declare S in your model by
param begin; param end > begin; set S := begin .. end;
Then state in the data file:
param begin := 50; param end := 70;
Alternatively, it's legal to give "set S := 50 .. 70" as your declaration of S. This is a less desirable approach, however, because it moves some of the specific data values into the model.
There's no specific arg min operator in AMPL. However, proceeding directly from the definition, you can define the arg min explicitly by a set expression like
{s in S: b[s] = min {i in S} b[i]}
This expression gives a subset of S, however, containing all of the members of S that achieve the minimum. To get just one member representing the arg min, you can define this to be an ordered set,
set b_argmin ordered := {s in S: b[s] = min {i in S} b[i]};
Then first(b_argmin) is guaranteed to be one member of S that minimizes b[i].
As an alternative, you can use AMPL's new for and if commands to write a script that loops over S to compute the arg min explicitly:
param bmin; param imin symbolic in S;
let bmin := Infinity;
for {i in S} {
if b[i] < bmin then {
let bmin := b[i];
let imin := i;
}
}
In general this is a slower alternative than defining b_argmin as above. It admits a greater variety of generalizations in complex cases, however.
AMPL can index model components by objects (numbers and character strings) but not by sets of objects. Hence you can't model a power set directly. You may be able to get the same effect, however, by constructing a numbered list of subsets.
As an example, suppose that you want to index over all subsets of the set of the first n nonnegative integers. You can declare:
param n integer > 0; set S := 0 .. n - 1;
set SS := 0 .. 2**n - 1;
set POW {k in SS} := {i in S: (k div 2**i) mod 2 = 1};
Since there are n members of S, there are 2**n subsets of S. Hence there exists a one-to-one correspondence between the members of the set SS := 0 .. 2**n - 1 and the subsets of S. By use of a simple encoding, you can make this correspondence explicit; the indexed collection of sets POW above is declared such that POW[k] is the kth distinct subset of S. (To see the whole power set, type display POW.)
Much the same can be done for an arbitrary ordered set S:
set S ordered;
param n := card {S};
set SS := 0 .. (2**n - 1);
set POW {k in SS}
:= {i in S: (k div 2**(ord(i)-1)) mod 2 = 1};
Either way, you can use indexing over POW to get the effect of indexing over the power set. In the following example, each member s of S has a weight Wt[s], and the average "weight" of all members of any subset of S is constrained not to exceed n/2:
var Wt {S} >= 0;
subj to MaxWt {k in SS}:
sum {i in POW[k]} Wt[i] <= (n / 2) * card(POW[k]);
A more involved example, which represents a traveling salesman problem as an integer program, is provided in tsp.mod. Constraints like this can be useful for studying and testing certain formulations of combinatorial problems, provided that the underlying set (S in our example) is kept to a reasonably small size.
AMPL does not define any ordering on pairs, triples, or objects of higher dimension. Thus next, prev, and other functions that apply to objects in ordered sets cannot be applied to pairs, triples, or tuples of higher dimension. For the same reason, first, last and other functions of ordered sets may not be applied to multi-dimensional sets.
You may apply these functions to individual indices of a multi-dimensional parameter or variable, however. The following examples are from steelT2.mod (Figure 5-3) of the AMPL book:
subject to balance0 {j in PROD}:
Make[j,first(WEEKS)] + inv0[j]
= Sell[j,first(WEEKS)] + Inv[j,first(WEEKS)];
subject to balance {j in PROD, t in WEEKS: ord(t) > 1}:
Make[j,t] + Inv[j,prev(t)] = Sell[j,t] + Inv[j,t];
Most models that involve both ordered and multidimensional sets can be handled by some variation of this approach.
Either a data table gave values for the parameter with incorrect subscripts, or the parameter's indexing set changed, causing some previously valid subscripts to become invalid. For example, in the diet.mod + diet.dat example (Figures 2-1 and 2-2) of the AMPL book, values of parameter cost are supplied for all eight members of set FOOD:
ampl: display cost;
cost [*] := BEEF 3.19 FISH 2.29 MCH 1.89 SPG 1.99 CHK 2.59 HAM 2.89 MTL 1.99 TUR 2.49 ;
If you remove the member "CHK" from FOOD, using for example a let command, then you get a message that cost["CHK"] has also been dropped from the data:
ampl: let FOOD := FOOD diff {"CHK"};
ampl: display cost; Error executing "display" command: error processing param cost: invalid subscript cost['CHK'] discarded.
cost [*] := BEEF 3.19 HAM 2.89 MTL 1.99 TUR 2.49 FISH 2.29 MCH 1.89 SPG 1.99 ;
Since cost["CHK"] has now been dropped, no further error message will appear if you type "display cost" again.
To avoid error messages of this sort, you can define a more flexible set structure for your model as shown in dietflex.mod and dietflex.dat. The auxiliary set DIET_DROP defaults to empty, so that the problem is solved for all foods; but you can change DIET_DROP to {"CHK"} to solve without member "CHK":
ampl: model dietflex.mod; ampl: data dietflex.dat; ampl: option show_stats 1;
ampl: solve;
8 variables, all linear 6 constraints, all linear; 47 nonzeros 1 linear objective; 8 nonzeros.
MINOS 5.4: optimal solution found. 13 iterations, objective 118.0594032
ampl: let FOOD_DROP := {"CHK"};
ampl: solve;
7 variables, all linear 6 constraints, all linear; 42 nonzeros 1 linear objective; 7 nonzeros.
MINOS 5.4: optimal solution found. 3 iterations, objective 117.3218891
Changing FOOD_DROP does not affect the set FOOD_ALL, and consequently all of the subscripts in the data remain valid.
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 new constraint expansion commands to see the constraints (in order) before and after substitution.
Symptoms of this problem are an option show_stats 1 listing that refers to nonlinear variables and constraints, and rejection by the solver with a "contains nonlinear constraints" message. The cure may be (a) to reformulate the model so that certain unintended nonlinearities are made linear, or (b) set option linelim 1 so that substituted linear variables do not become nonlinear.
Case (a) can occur because you have overlooked a simple nonlinearity, such as a variable multiplying or dividing another variable. AMPL's built-in arithmetic functions, including simple ones such as abs and max, are treated as nonlinear when applied to variables; if ... then ... else ... expressions are also nonlinear if variables appear in the expression following the if. You may be able to convert these kinds of "nonlinearities" to equivalent linear expressions, but AMPL cannot do the conversion automatically. (The only such conversions currently built into AMPL are for the piecewise-linear functions described in Chapter 14 of the AMPL book.)
Case (b) occurs when AMPL's defined variable feature is invoked to substitute an expression for a variable -- either by using the = operator in declarations of variables, or by setting option substout 1 to infer substitutions from the constraints. Under option linelim 0, AMPL does not substitute explicitly in the constraints, but instead records the substitution as an additional piece of information in the file sent to the solver. This affords very efficient handling of sub-expressions that appear at many places in a problem, but it has the side-effect of causing all variables in a substituted expression to be treated as nonlinear. To request explicit substitution, so that linearity is preserved, set option linelim 1. This is the default for AMPL versions 20000327 and later, but if you're using an earlier version you'll need to set option linelim 1 explicitly.
Versions of AMPL prior to 20000128 are unable to recognize linearity in this case. If you are using one of these earlier versions and cannot obtain an update, you may be able to handle this situation in a more indirect way, such as by writing a script to alternate between related linear models in which the fixed variables are replaced by parameters.
As a simple example, suppose you want to minimize a quadratic function of variables X[i] and Y[j]:
param q {1..n,1..n};
var X {1..n} >= 0;
var Y {1..n} >= 0;
minimize Quadratic:
sum {i in 1..n, j in 1..n} X[i] * q[i,j] * Y[j];
The objective becomes linear when you fix either all the X[i] or all the Y[j]. This suggests creating two new linear objectives in which parameters are substituted for the variables to be fixed:
param xfix {1..n};
param yfix {1..n};
minimize QuadX:
sum {i in 1..n, j in 1..n} X[i] * q[i,j] * yfix[j];
minimize QuadY:
sum {i in 1..n, j in 1..n} xfix[i] * q[i,j] * Y[j];
Given some initial yfix[j] values, you can use a linear programming solver to minimize QuadX. Then you can assign the optimal values of X[i] to xfix[i], after which you can use a linear programming solver to minimize QuadY. Finally you can assign the optimal values of Y[j] to yfix[j], and repeat. This iteration is readily written using AMPL's new repeat loop construct as:
repeat {
objective QuadX;
solve;
let {i in 1..n} xfix[i] := X[i];
objective QuadY;
solve;
let {j in 1..n} yfix[j] := Y[j];
} until abs(QuadX - QuadY) < 0.001;
For brevity we have not shown constraints, which can alternated like the objectives by use of drop and restore (Section 10.8 of the AMPL book) or AMPL's new named problem feature. We also caution that an iterative scheme like this may never stop; a guarantee of termination can be supplied only for certain special cases.
AMPL's new expand command can display any explicit linear constraint, or indexed collection of constraints. For example:
ampl: model transp.mod; ampl: data transp.dat;
ampl: expand Demand['STL'];
s.t. Demand['STL']: Trans['GARY','STL'] + Trans['CLEV','STL'] + Trans['PITT','STL'] = 1700;
ampl: expand Supply;
s.t. Supply['GARY']: Trans['GARY','FRA'] + Trans['GARY','DET'] + Trans['GARY','LAN'] + Trans['GARY','WIN'] + Trans['GARY','STL'] + Trans['GARY','FRE'] + Trans['GARY','LAF'] = 1400;
s.t. Supply['CLEV']: Trans['CLEV','FRA'] + Trans['CLEV','DET'] + Trans['CLEV','LAN'] + Trans['CLEV','WIN'] + Trans['CLEV','STL'] + Trans['CLEV','FRE'] + Trans['CLEV','LAF'] = 2600;
s.t. Supply['PITT']: Trans['PITT','FRA'] + Trans['PITT','DET'] + Trans['PITT','LAN'] + Trans['PITT','WIN'] + Trans['PITT','STL'] + Trans['PITT','FRE'] + Trans['PITT','LAF'] = 2900;
The expand command also works with variables and objectives, and has indexing options similar to those of display or print for determining which components are expanded.
The built-in parameter _nvars contains the number of variables; a symbolic parameter _varname[j] contains the AMPL name of the jth variable; and _var[j] is a "synonym" that refers to the jth variable. Thus to show the names of all variables that are below their upper bounds at the optimum, for example, you can write:
ampl: display {j in 1.._nvars:
ampl? _var[j] < _var[j].ub - 0.00001} _varname[j];
_varname[j] [*] := 2 "PD_Ship['SE']" 5 "DW_Ship['NE','BWI']" 6 "DW_Ship['SE','EWR']" 7 "DW_Ship['SE','BWI']" ;
This is only one of the uses for AMPL's generic synonyms for variables, constraints and objectives. See the discussion of AMPL's new generic synonym feature for more details.
AMPL's new suffix feature can be used by solvers to return ranging information. See in particular the discussion of solver-defined suffixes for an example of range output from CPLEX. If you are using a solver that offers ranging, you may need to update the AMPL driver for that solver in order to get access to the ranging suffixes; see our solver listing for information on solver vendors and download sites.
AMPL does not currently support "parametric" algorithms for postoptimal analysis of objective functions or constraint right-hand sides.
In practice, ranging often provides sensitivity information of limited usefulness, and parametric algorithms are limited to certain kinds of linear changes to the data. You may do better to write a simple AMPL script that solves the same model for a series of different parameter values. For an example, see our writeup on AMPL's new looping commands and related features for programming in the command language.
AMPL cannot determine by itself the values from the linear programming tableau, because the sparse linear algebra routines capable of computing these values are found only in the solvers. Efficient solver implementations avoid computing or storing more than a few tableau columns at a time, however. Hence AMPL also has no solver directives that can cause tableau values to be returned.
For a specific AMPL model, it is possible to set up an auxiliary model that finds the tableau values, at least in the nondegenerate case; see our diet tableau example based on the diet model from Chapter 2 of the AMPL book. This approach is highly inefficient, but should be adequate for small linear programs -- up to a few dozen variables, say.
The display command does not currently recognize {k in SS} POW[k] where POW is an indexed (subscripted) set. For this elementary case, you can exhibit the whole indexed collection of subsets by giving just the name of the collection:
display POW;
You can also exhibit each of the indexed sets separately, by using the iterated form of the display command; it resembles the ordinary form, but with a colon after the index set:
display {k in SS}: POW[k];
This gives the same output as if you had typed a separate statement display POW[k] for each member k of SS. Any set expression (or list of expressions) may follow the colon.
Add the keyword "ordered" to the set's declaration, after the set name. It can be useful to declare a set ordered for purposes of ordering the output, even when the ordering plays no role in the model.
There is no easy way to do this at present.
For each integer variable X that you potentially want to relax, you might declare a companion continuous variable Xc that has the same bounds, and then substitute (X + Xc) for each appearance of X in the objective and constraints. Once the model is set up in this way, you can use AMPL's fix and unfix commands to switch between the two possibilities. To leave X integer, fix Xc at zero while leaving X to vary; to relax X, fix X at zero while leaving Xc to vary.
These two ways of relaxing integrality can give different results because they interact differently with AMPL's presolve phase.
Under option relax_integrality 1, all integer variables are changed to continuous before AMPL's presolve. Thus presolve works on the "true" relaxation, and the reduced LP that comes out of presolve has the same objective value as the true relaxation.
Under option relax_integrality 0, all integer variables remain integer through AMPL's presolve phase. Presolve may take advantage of this integrality to further tighten bounds and reduce the problem size. If the solver's relax directive is subsequently set, then it will solve the relaxation of the presolved integer program, which may not have the same objective value as the true relaxation. (Specifically, its value may be higher for a minimization, or lower for a maximization.)
As a simple example, imagine a minimization model in which there are integer variables X[t] constrained by sum {t in 1..T} X[t] <= 7.5. If relax_integrality is set to 1, then the variables are made continuous, but otherwise the constraint remains the same. If relax_integrality is instead left at 0, then presolve will tighten 7.5 to 7 before sending the integer program to the solver. This has no effect on the integer optimum, but by tightening the constraint it may cause the solver's relaxation to have a higher value than AMPL's relaxation.
For purposes of solving the problem, the solver's higher relaxation value is normally to be preferred. In some iterative schemes that solve a series of relaxations, however, only the lower true relaxation value makes sense. To ensure that you get the optimum of the true relaxation, either set option relax_integrality 1 or set option presolve 0 and turn on the solver's relax directive.
The "break" signal (Ctrl-C for many computers) stops the solver and returns control to AMPL, but does not necessarily return any solution from the solver. Some solvers may make provision to "catch" the break signal and return the best solution found so far; consult the solver directive instructions to see if this is the case for the solver that you are using.
Various solver directives can stop a run and return the current incumbent optimal solution, but they must be given before the run begins. Available stopping criteria may include number of branch-and-bound nodes, number of integer solutions, and total time. Directives are different for each solver, so consult AMPL's solver directive instructions for details.
Special ordered sets of type 2 (SOS2s) are used automatically by some solvers (including CPLEX and OSL) to handle piecewise-linear functions as described in Chapter 14 of the AMPL book.
Special ordered sets of type 1 and 3 are most useful for handling variables that are restricted to a finite but not regularly-spaced series of values. For example, a variable Cap[j] standing for capacity of warehouse j might be required to take one of the values 0, 15, 25 or 30. AMPL doesn't currently have any convenient way to express such restrictions. (CPLEX's sosscan directive invokes a preprocessor that can automatically identify constraints that have a SOS3 interpretation. However, AMPL does not usually supply enough information about these constraints to afford any significant efficiency in the branch-and-bound process.)
The AMPL Student Edition consists of the AMPL software together with the MINOS and CPLEX solvers. It is limited to 300 variables and 300 constraints and objectives, and does not support user-defined functions, but is otherwise identical to the full professional edition.
The latest version of the student edition for PCs is the AMPL Plus 1.6 Student Edition, which incorporates a Microsoft Windows graphical user interface. Users of the AMPL Plus Student Edition software will need to download a new version for 2002 -- see our book software update instructions for details. Student editions of the AMPL translator and some corresponding solvers can also be downloaded for most popular Unix workstations and for Linux on PCs.
Educational discounts for other versions of AMPL are also available from several AMPL vendors.
The professional edition is the full-featured, unrestricted version. Numbers of variables and constraints are limited only by available computer resources.
Professional edition users may choose among numerous solvers. Several vendors offer packages of the AMPL software with selected solvers. Other solvers may be added at any time, at only the cost of the solver software; you do not need to buy additional AMPL software in order to add a solver.
AMPL Plus is a graphical model development environment based on the AMPL software. AMPL Plus version 1.6 is available for Windows 95, 98 and NT as a 32-bit application.
See our AMPL Plus page for more information on features and availability of AMPL Plus.
A full-featured Microsoft Windows gui is provided by the above-mentioned AMPL Plus.
Several experimental AMPL graphical interfaces for Windows are also available for downloading at no charge.
If you are using a Unix workstation, AMPL's command-line environment should run nicely within a command or text window. The workstation's windowing software lets you scroll back through an AMPL session and copy previous AMPL commands. You can set up other windows to simultaneously view the model and data.
On 80386, 80486, and Pentium-based personal computers (or "PCs" or "IBM clones"), AMPL runs under MS-DOS and its derivatives (such as IBM DOS) and under Microsoft Windows 3.1, 95 and NT. A math coprocessor is used if available, but is not required. (AMPL does not run on earlier 8088 or 80286-based computers.)
AMPL runs on RISC workstations from DEC, Hewlett-Packard, IBM, Silicon Graphics, and Sun, under their versions of Unix. Both Solaris 1.1 (alias SunOS 4.1) and Solaris 2.x are supported on Sun machines. Unix versions are also available for PCs running Linux and FreeBSD.
There are not currently any versions of AMPL that support Apple Macintosh computers.
If you are using the student edition of AMPL that comes with the AMPL book, then you will find this information in a booklet ("Using the AMPL Student Edition Under MS-DOS") that is also packaged with the book.
Operating system information for other AMPL versions is available in two booklets, "Using AMPL Under MS-DOS" and "Using AMPL Under Unix". You can download them in gzip-compressed postscript form (see our instructions), or write to info@ampl.com to request a printed copy.
You can look at the current version message by invoking AMPL with the -v command-line switch:
% ampl -v AMPL Version 20000516
Or, at any point in an AMPL session, you can see the version message by looking at the contents of AMPL's version option, by typing
ampl: option version; option version 'AMPL Version 20000516\ '; ampl:
or
ampl: print $version;
AMPL Version 20000516
ampl:
The 8-digit number represents a date in the form yyyymmdd -- 16 May 2000 in this example. You can compare this date against the dates of the entries in the AMPL change logs and in the writeups of new AMPL features.
AMPL's modeling language and environment have continued to evolve in response to users' needs. Thus many significant features have been added since the publication of the AMPL book. See the AMPL Extensions page for links to online summaries, descriptions and examples of new features.
To obtain the latest updates to the AMPL student edition software, see our downloads page. If you send the one-line E-mail message "subscribe ampl" to netlib@research.bell-labs.com, then you will receive an e-mail message whenever we update this software. (Updates are made frequently. Send netlib the message "unsubscribe ampl" to turn these notifications back off.)
For updates to other AMPL software, contact if possible the vendor that originally sold you AMPL. If you're having trouble locating your vendor, our vendor list may help. If vendor information is not available or your original vendor cannot be located, write to info@ampl.com for assistance.
AMPL works with a variety of solvers for linear, nonlinear and integer programming. See our solver listings for details.
Yes. Once you have AMPL running, you add a solver by simply
The procedure is equally simple if you already have a solver running, and want to later add AMPL to your system.
There is a separate AMPL driver for each solver package. The driver may be already included in the package (as in the case of CPLEX), or may be available on-line (as for MINOS and OSL), or may be available directly from the solver's distributor. Details are provided in our solver listing.
In most cases, there is no extra charge for the AMPL driver.
Many solver options can be specified directly from AMPL. You don't need to prepare separate "spec files" or run solvers outside the AMPL environment in order to get the benefits of these options.
If you are using the student edition software that comes with the AMPL book, then you will find a guide to using the packaged solvers (MINOS and CPLEX) in a booklet ("Using the AMPL Plus Student Edition Under Microsoft Windows") that is packaged with the book.
For the professional edition of AMPL, separate guides to solver directives are available online, from the solver developers, or both. See the AMPL solver listing for more information.
AMPL has a publicly documented interface that you can use to make your own link to any solver you are developing. The interface works through files; AMPL writes a problem file to be read by your solver, and your solver writes a solution file to be read back by AMPL. The file format has equivalent binary and ASCII versions. It offers the flexibility needed to support a wide variety of solvers, yet is designed to afford very efficient reading and writing.
The AMPL interface is described and illustrated in "Hooking Your Solver to AMPL". You can also download standard interface routines (in C) for reading and writing the AMPL file formats, along with a variety of examples of complete AMPL/solver links; see our hooking page for details.
The AMPL book is the definitive introduction, tutorial and reference for AMPL. Its contents, introduction and first chapter are available on-line, along with ordering instructions. All copies of the book include a disk containing the student edition of AMPL for DOS/Windows PCs.
To learn about new AMPL features have been implemented since the appearance of the book, see the AMPL Extensions pages.
The following articles describe and analyze many aspects of the design of AMPL:
Mail to info@ampl.com is forwarded to the AMPL developers for reply. See our vendor listing for direct numbers and addresses of particular vendors of AMPL and solvers.