Frequently Asked Questions about AMPL (and the AMPL home FAQ)

Q1: How do I do double summation in AMPL?


A1: If you're summing over x[i,j] over i in products and j in companies, it looks like:

sum{i in products, j in companies} x[i,j]

Q2: How do I index just one element of a variable in AMPL? e.g. How do I write Xproduct1,company2 = 0?


A2: To reference a single index in AMPL, you use double quotes, i.e.,

s.t. X["product1", "company2"]=0;
However, if your set indices are numbers, you do not use the quotes, i.e., if instead of product1, product2, etc, your set indices for products are 1, 2, etc, then it would be
s,t, X[1, "company2"]=0;

Q3: When we saved the original file prod0.mod (straight from the website), ampl could read it from the directory. But, when we copied the content of the file into a wordpad file, and then saved it as prod0.mod, and then called it in AMPL, it gave the following error:

prod0.mod, line 1 (offset 0):

syntax error

context: >>>{\ <<< rtfl\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}{\f1\fswiss\fprq2\fcharset0 Arial;}}

ampl?

A3: This happens when you save the mod file as a rich-text-format (RTF) in the Wordpad. Save the file as a Text document instead.

Q4: How do I model multi-period inventory in AMPL, e.g., the constraints Inv[t] = Inv[t-1] + Make[t] - Demand[t]?

A4: The AMPL files inventory.mod and inventory.dat in AMPL folder models a simple multiperiod (4 periods) inventory problem with the above constraint. The key is to define the inventory variable from 0 to T, but the production variable is defined from 1 to T.

Q5: What are the commands used for sensitivity analysis in AMPL?


A5: See here for these and some other useful commands. Before using these commands, you need to instruct AMPL to use the CPLEX solver (if you are using the Windows version; the UNIX version uses the CPLEX version by default), and instruct CPLEX to store sensitivity analysis information. This is done by the following commands:

ampl: option solver cplex; # if using Windows version
ampl: option cplex_options 'sensitivity';
AMPL often does some preprocessing of the LP, which sometimes causes CPLEX to report incorrect/meaningless sensitivity-analysis information. So it's also a good idea to turn this preprocessing-feature off by typing "option presolve 0;" at the AMPL prompt.

Q6: How do I obtain a transcript of my AMPL session?


A6: There are three ways to do this.

  1. The log_file option instructs AMPL to save subsequent commands and responses to a file. The option's value is a string that is interpreted as a filename; thus you might say
    	ampl: option log_file 'log.tmp';
    
    to instruct AMPL to create a file log.tmp with commands and outputs from your AMPL session. The log file receives all AMPL statements and the output that they produce, with a few exceptions described below. Setting log_file to the empty string,
    	ampl: option log_file '';
    
    turns off writing to the file; the empty string is the default value for this option.

    When AMPL reads from an input file by means of a model, data or include command, the statements from that file are not copied to the log file -- although any output resulting from those statements does get logged. In typical situations, this arrangement prevents your model and data files from being echoed to your log file. To request that AMPL echo the contents of input files, change the option log_model (for input in model mode) or log_data (for input in data mode) from its default value of 0 to some nonzero value.

  2. Batch execution: type your AMPL commands in a "run"-file named 'filename' as you would at the AMPL prompt and type "include 'filename';" in AMPL. This executes the commands that you typed in sequence just as if they were executed at the AMPL prompt. This way 'filename' contains a transcript of your AMPL session.

  3. Window-capture: This is WINDOWS specific. You can copy the contents of the command-prompt window in which you execute AMPL to a file. Click the icon on the upper-left corner of the command-prompt window, and in the menu select Edit->Mark to mark the desired portion, or Edit->Select All to select the entire contents of the window. Then use Edit->Copy to copy this to the clipboard, open a new file, and paste this information.

Q7: How do I do declare and initialize a 3D-array in AMPL?


A7: Here is an example. Suppose you have the following three sets.

set index1 := a b c; 
set index2 := x y z; 
set index3 := d e f;
The command "param threeDarray {index1, index2, index3};" placed in the model file declares a 3D-array, threeDarray, whose elements are indexed by index1, index2, and index3. To initialize this 3D-array, use the following command in the data file:
# data file 
param threeDarray := ['a',*,*]: d e f := x 10 5 4 y 2 3 8 z 6 4 5 ['b',*,*]: d e f := x 6 5 2 y 4 23 9 z 12 3 15 ['c',*,*]: d e f := x 10 7 78 y 6 7 8 z 4 5 6 ;
See also the AMPL files threed-ex.mod and threed-ex.dat in the AMPL folder.

Q8: How do I declare a conditional expression in AMPL?


A8: Use the if-then-else construct. Suppose we want an expression that is 1 if some parameter a is equal to 5 and 0 otherwise. One can do this by the following expression: "if (a==5) then 1 else 0;" This statement can be used in place of any expression that requires a number. For example, one can have a statement like "param b:=(if (a==5) then 1 else 0);" which sets b to 1 or 0 depending on the value of a, or one can use a conditional expression in a constraint: "subject to constr: x=(if a==5) then 1 else 0);". One can even use nested "if-then-else" statements to do a multiple-case analysis. Some examples are:

subject to c1 {i in setname}: 2*x+z[i]+(if (a==5) then 1 else 0) <= y[(if (b==4) then 1 else 2)];
subject to c2 {i in setname}: z[i]<=(if (a==4) then 3*y[i] 
					       else if (a<=3) then (if a<=1 then -2*y[i] else y[i]+a) 
					       else if (a==5) then 4*y[i] 
					       else y[i]-4);

Q9: Given two sets s1, s2, how I define a set that is their union/intersection in AMPL?


A9: If the model file contains the declarations

set s1; 
set s2;
then the following commands in the model file define s3 and s4 to be respectively the union and intersection of the two sets.
set s3 := s1 union s2; 
set s4 := s1 intersect s2;

Q10: How do I declare integer variables and parameters in AMPL?


A10: To declare an integer variable, say x, use the following statement in the model file: "var x integer;" or "var x binary;" to declare x to be a {0,1}-variable. Here are some more examples:

# model file
var x integer >=0, <=1;		# declares an integer variable x s.t. 0 <= x <= 1, i.e., a 0-1 integer variable x
var z binary;				# declares a 0,1-variable z - "binary" is a convenient shorthand for "integer >=0, <=1"
var y {product} integer >=0; 	# declares integer variables y[j]>=0 for every element j of the set product
There is no new syntax for declaring integer parameters in the data file. To ensure that the data is indeed integer, one can add the keyword "integer" after the "param" declaration, as in the syntax for declaring integer variables. For example, to ensure that puzzle is initialized as a 2D-integer array with non-negative entries, one can use the statement "param puzzle {1..N,1..N} integer >=0;" in the model file.

Q11: How do I solve integer programs in AMPL?


A11: The AMPL version on the machines in the MC 3006 and MC 3009 Nexus Labs comes with a solver called Gurobi (actually the solver is called "gurobi_ampl"), which can handle integer programs. First, you need to instruct AMPL to use this solver by typing the command "option solver gurobi_ampl;". Then, once the model and data files have been set up to use integer variables, and loaded into AMPL (by using the "model ...; data ...;" commands), all one needs to do is type "solve;" to solve the IP.

The student version of AMPL, which is what you have if you downloaded AMPL from the course website, uses MINOS as the default solver which ignores integrality constraints and solves the LP-relaxation of the problem. The CPLEX and Gurobi solvers that come with the student version of AMPL can only only solve IPs of a limited size.

For Mac machines, there does not seem to be a Gurobi solver, but the solver lp_solve can solve IPs and there is supposedly no predefined limit on the size of IPs it can be solve. So it might be possible to use this solver to solve IPs (lp_solve is also available for WINDOWS machines; see the AMPL website for more documentation).

We strongly recommend using Gurobi in conjunction with AMPL on the machines in the MC 3006 and MC 3009 labs to solve IPs.

Q12: How do I find out how many CPU cycles it takes to solve my IP using CPLEX+AMPL? How do obtain information about the branch-and-bound tree?


A12: To obtain timing information, type "option gurobi_options 'timing=1';". To obtain information about the branch-and-bound tree (how many nodes still need to be explored, the current lower and upper bounds etc.), use "option gurobi_options 'outlev=1';". You can instruct Gurobi+AMPL to output both pieces of information by saying "option gurobi_options 'outlev=1 timing=1';". Here is a sample output produced by setting both outlev=1 and timing=1 in gurobi_options.

 
ampl: option gurobi_options 'outlev=1 timing=1';
ampl: solve;
netlicchk: ampl_lic: gurobi not licensed for this machine.
Gurobi 2.0.1: outlev=1
timing=1
Optimize a model with 13949 Rows, 11874 Columns and 87802 NonZeros
Presolve removed 0 rows and 2991 columns
Presolve time: 0.23s
Presolved: 13949 Rows, 8883 Columns, 101082 Nonzeros

Root relaxation: objective 1.137500e+03, 410 iterations, 0.05 seconds

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

     0     0  1137.5000    0   24          -  1137.5000     -      -    0s
     0     0  1695.0000    0   28          -  1695.0000     -      -    0s
     0     0  1768.5000    0   25          -  1768.5000     -      -    0s
     0     0  1786.0833    0   42          -  1786.0833     -      -    1s
     0     0  1809.8000    0   65          -  1809.8000     -      -    1s
     0     0  1905.5000    0   41          -  1905.5000     -      -    1s
     0     0  1914.5635    0   51          -  1914.5635     -      -    1s
H    0     0                       2217.0000  1914.5635  13.6%     -    1s
     0     0  1914.5679    0   48  2217.0000  1914.5679  13.6%     -    1s
     0     0  1914.5679    0   28  2217.0000  1914.5679  13.6%     -    2s
     0     0  1914.5679    0   27  2217.0000  1914.5679  13.6%     -    2s
     0     0  1914.5679    0   45  2217.0000  1914.5679  13.6%     -    2s
     0     0  1914.5679    0   71  2217.0000  1914.5679  13.6%     -    2s
     0     0  1914.5679    0   53  2217.0000  1914.5679  13.6%     -    3s
H    0     0                       2204.0000  1914.5679  13.1%     -    3s
     0     0  1914.5679    0   50  2204.0000  1914.5679  13.1%     -    3s
     0     0  1914.5679    0   50  2204.0000  1914.5679  13.1%     -    3s
H    0     0                       2105.0000  1914.5679  9.05%     -    3s
H    0     2                       2007.0000  1914.5679  4.61%     -    4s
     0     2  1914.5679    0   48  2007.0000  1914.5679  4.61%     -    4s
     6     5  1938.0000    4   14  2007.0000  1928.6596  3.90%  30.8    5s
H    8     7                       2001.0000  1929.9044  3.55%  26.5    5s
*   66     9               7       1995.0000  1940.8131  2.72%  27.1    6s

Cutting planes:
  Cover: 1
  Implied bound: 49
  Clique: 2
  Flow cover: 28
  Zero half: 10

Explored 158 nodes (5675 simplex iterations) in 7.31 seconds
Thread count was 2 (of 2 available processors)

Optimal solution found (tolerance 1.00e-04)
Best objective 1.9950000000e+03, best bound 1.9950000000e+03, gap 0.0%
Optimize a model with 13949 Rows, 11874 Columns and 87802 NonZeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    1.9130000e+03   8.000000e+00   0.000000e+00      0s
     136    1.9950000e+03   0.000000e+00   0.000000e+00      0s

Solved in 136 iterations and 0.03 seconds
Optimal objective  1.995000000e+03

Times (seconds):
Input =  0.235
Solve =  7.312 (summed over threads)
Output = 0.125
Elapsed = 8
Gurobi 2.0.1: optimal solution; objective 1995
5675 simplex iterations; 158 branch-and-cut nodes
plus 136 simplex iterations for intbasis
ampl: 
Here is a brief description of what some of the columns represent. The "Nodes" columns give the current number of exlored and unexplored nodes in the branch-and-bound tree. Gurobi does not always completely explore a branch, but backtracks sometimes and moves to other parts of the branch-and-bound tree. Thus, there may be some unexlpored nodes in the tree. The "Current Node" columns list information about the current node: "Obj" lists the optimal value of the LP relaxation at the current node. An "H" in the left-most column indicates that an integer solution is found at this node. The "BestBd" column gives the value of the best integer solution found so far. The "Gap" column gives the relative gap between the best integer solution found and the current upper bound, if an integer solution has been found.
Gurobi sometimes automatically generates cuts, especially at the root node, to tighten the LP relaxation. At the end, Gurobi also reports the number and type of the cuts used, in this column.

The timing information, by default, gives a measurement of the CPU-time used (not the elapsed time, which is load-dependent).

Q13: Where can I find more information about Gurobi-AMPL?


A13: Consult the following (sparse) user manual for Gurobi+AMPL, [protect/AMPL_Guide_2.0.pdf].

Q14: How do I print to the screen or to a file in AMPL?


A14: The print and printf commands allow you to print arbitrary text to the screen or to a file. The display command can be used to print the values of variables and parameters on the screen, not arbitrary text.
For example to print "Hello world" on the screen, you can use the command print "Hello world";. The print command automatically adds a newline to the end of the text; the printf command does not. So to display the same text using printf, you can say printf "Hello world\n";. The "\n" add a newline at the end. You can also use print and printf to display the values of one-dimensional variables or parameters (i.e., not arrays). So, for example, you can say print n; or print "The value of n=",n,"and the value of N is",N;. To do the same thing with printf you need to use the "%d" conversion character (like in C) to indicate that the expression whose value to be printed is an integer. So you would type printf "%d",n; or printf "The value of n=%d and the value of N is %d\n",n,N;. With any of these command print, printf or display adding "> filename" at the end (before the ";") sends the output to the file named filename. Multiple such commands can be used to add to the same file. Here is a transcript showing the use of these commands.

print "the value of n is ",n," and the value of N is",N;
the value of n is  3  and the value of N is 9
ampl: printf "The value of n is %d and the value of N is %d\n",n,N;      
The value of n is 3 and the value of N is 9
ampl: print n;
3
ampl: print "n=",n,"and N=",N,"and n+N=",n+N;
n= 3 and N= 9 and n+N= 12
ampl: printf "This is just a test";
This is just a testampl: printf "This is a test with a newline at the end\n";
This is a test with a newline at the end
ampl:
ampl: printf "Remember n=%d, and N=%d, so n^2=%d, which lo and behold is equal to %d (i.e., N)\n",n,N,n*n,N;
Remember n=3, and N=9, so n^2=9, which lo and behold is equal to 9 (i.e., N)
ampl: 
ampl: # You can print to a file by including ">filename" at the end of the print or printf command
ampl: # For example, the following command prints the above statement to the file output.txt 
ampl:
ampl: printf "Remember n=%d, and N=%d, so n^2=%d, which lo and behold is equal to %d (i.e., N)\n",n,N,n*n,N > output.txt;
ampl:
ampl: # You can also use ">filename" at the end of a display command to direct its output to a file
ampl: display n > output.txt; 
ampl: