Using AMPL Studio

 

Contents
Overview
Example
Db connection
AMPL commands
Script & Tracing
AMPL and Studio
Viewlet

 

  Advanced Features of AMPL

 

AMPL provides a variety of commands like model, solve and display that tell the AMPL modeling system what to do with models and data. These commands are not part of AMPL modeling language itself but are intended to be used in an environment where you give a command, wait for the system to display a response, then decide what command to give next. In AMPL studio, these commands can be given from the command prompt window. Some of these commands are disabled; this is to avoid conflicting with Studio functionalities. However, the user can use a full set of AMPL commands in an independent command line windows using the ampl.exe which comes with AMPL Studio.

 

 

 Command prompt window in AMPL Studio.

Modelling Commands

Options

The behavior of AMPL commands depends on a variety of options. For example: Controlling the display of results, Choosing alternative solvers etc.

The option command displays and sets option values. Each option has a name and a value that may be a number or a character string. For example, the options prompt1 and prompt2 are strings that specify formats. The option display_width has a numeric value, which says how many characters wide the output produced by the display command maybe.

An option command can be issued at the command prompt.

 Example:

ampl: option prompt1 “A>” ;

A>

The issue of option command with prompt option changes the prompt from ampl to A>.

One can set solver options also by using this command.

ampl: option cplex_options;

To return all options to their default values use the command ‘reset options’.

 

Setting up and solving models and data

 

A model can be run from command prompt window. One can choose the solver for solving the problem by using option command.

To apply a solver to an instance of a model, we use model, data and solve command.

 

ampl: option solver cplexamp;

ampl: model steel4.mod;

ampl: data steel4.dat;

ampl: solve;

If the model declares more than one objective function, we can use objective command to select the objective function to pass to the solver. It consist of keyword objective followed by a name from minimize or maximize declaration. AMPL by default chooses first objective function.

ampl: objective Total_Number;

Modifying Data

To delete the current data for several model components, without changing the current model itself, use reset data command as in:

reset data MINREQ, MAXREQ, amt, n_min, n_max;

We can then use data command to read in new values for these sets and parameters. To delete all data type ‘reset data’.

The update data command works similarly, but does not actually delete any data until new values are assigned. Thus if we type:

 

update data MINREQ, MAXREQ, amt, n_min, n_max;

 

but read in new values for MINREQ,amt and n_min, the previous values for MAXREQ and n_max will remain. If instead we used reset data, MAXREQ and n_max would be without values.

 

The ‘reset data’ command also acts to resample the randomly computed parameters.

 

The ‘let’ command permits us to change particular data value while leaving the model the same, but it is more convenient for small or easy to describe changes than ‘reset data’ or ‘update data’.  For example: if a parameter ‘T’ in our data for some hypothetical model has a value 4 and we can change it to 3 by let command:

 

ampl: let T:=3;

ampl: solve ;

 

Modifying models

 

The ‘delete’ command removes a previously declared model component, provided that no other component use it in their declarations. The format of the command is simply ‘delete’ followed by a comma-separated list of names of model components:

 

ampl: model dietobj.mod;

ampl: data dietobj.dat;

ampl: delete Total_Number, Diet_Min ;

 

Normally we can-not delete a set, parameter or variable, because it is declared for use later in the model; but we can delete any objective or constraint.

The ‘purge’ command has the same form, but with keyword ‘purge’ in place of delete. It removes not only the listed components, but also all components that depend on them either directly or indirectly. If we are not sure which components depend on some given component, we can use ‘xref’ command to find out.

 

To change any component’s declaration we can use ‘redeclare’ command.

 

ampl: redeclare param f_min {FOOD} >0 integer;

 

changes the validity conditions on f_min. The declarations of all components that depend on f_min are left unchanged, as are any values previously read for f_min.

 

Changing the model: fix, unfix; drop, restore

 

The ‘drop’ command instructs AMPL to ignore certain constraints or objectives of the current model. As an example, the constraints are:

 

subject to Diet_Max { i in MAXREQ} :

                   sum { j in FOOD} amt[I,j] * Buy [j] <= n_max [i] ;

 

A ‘drop’ command can specify a particular one of these constraints to ignore:

 

drop Diet_Max[“CAL”] ;

 

The entire collection of constraints can be ignored by

 

drop {i in MAXREQ} Diet_Max[i] ;

 

The ‘restore’ command reverses the effect of drop. It has same syntax, except for the keyword ‘restore’.

 

The ‘fix’ command fixes specified variables at their current values, as if there were a constraint that the variables must equal these values; the unfix command reverses the effect. These commands have the same syntax as ‘drop’  and ‘restore’ except that they name variables rather than constraints.

Relaxing Integrality

Changing option ‘relax_integrality’ from its default of 0 to any nonzero value:

option  relax_integrality 1;

tells AMPL to ignore all restrictions of variables to integer values. Variables declared integer gets whatever bounds we specified for them, while variables declared binary are given a lower bound of zero and an upper bound of one. To restore integrality restrictions, set ‘relax_integrality’ option back to 0.

 

A variable’s name followed by the suffix ‘.relax’ indicates its current integrality relaxation status: 0 if integrality is enforced, nonzero otherwise. We can make use of this suffix to relax integrality on selected variables only. For example,

 

ampl: let Buy[‘CHK’].relax=1;

 

relaxes integrality only on the variable Buy[‘CHK’].

 

Some of the solvers that work with AMPL Studio provide their own directives for relaxing integrality but may have different effect as AMPL’s ‘relax_integrality’ option.

 

DISPLAY Commands

 

AMPL provides a rich variety of commands and options to help examine and report the results of optimization.

 

Browsing through results: display command

 

The easiest way to examine data and result values is to use ‘display’ command. It is also possible to capture the output of display command in a file, by adding >filename to the end of ‘display’ command; this redirection mechanism applies as well to other commands that produces the output.

The contents of the sets are shown by typing ‘display’ and a list of set names. For example a set of week days defined as the set WEEK would give the following result.

 

ampl: display WEEK;

set WEEK : = MON TUE WED THURS FRI SAT SUN;

 

The argument of ‘display’ need not be a declared set; it can be any of the expression that evaluate to sets. For example, we can see the union of all the sets AREA[p] (where PROD = {prod1, prod2, prod3, prod4}, AREA[prod1] = east, AREA[prod2] = north, AREA[prod3] = west, AREA[prod4] = south):

 

ampl: display union {p in PROD} AREA[p];

set union {p in PROD} AREA[p] := east north west south;

 

The ‘display’ command can also be used to see the value of a scalar model component.

 

ampl: display T;

T=4

Or the value of individual components from an indexed collection.

 

ampl: display avail[“reheat], avail[“roll”] ;

avail [‘reheat’] = 35

avail [‘roll’] = 40

 

or an arbitrary expression:

 

ampl: display sin(1)^2 + cos(1)^2;

sin(1)^2 + cos(1)^2 = 1

 

The major use of display, however, is to show whole indexed collection of data. For ‘one-dimensional’ data – parameters or variables indexed over a simple set – AMPL uses a column format. For example, if avail is indexed over some set, the use of display would work as:

 

ampl: display avail;

avail[*] :=

reheat 35

roll 40                                             

;

 

For ‘two-dimensional’ parameters or variables – indexed over a set of pairs or two simple sets – AMPL forms a list for small amounts of data or a table for larger amounts.

 

The ‘display’ command can show the value of any arithmetic expression that is valid in AMPL model. Single valued expression poses no difficulty, as in the case of these three profit components indexed over say set PROD and some set representing time period:

 

ampl: display sum{p in PROD, t in 1..T} revenue[p,t]*sell[p,t];

sum{p in PROD, t in 1..T} revenue[p,t]*sell[p,t] = 787810

 

Suppose however we want to see all the individual values of revenue[p,t] * sell[p,t]. Since, we can type ‘display revenue, sell’ to display the separate values of revenue [p,t] and sell [p, t], we might want to ask for the products of these values by typing:

 

ampl: display revenue * sell;

syntax error

context: display revenue >>> * <<< sell ;

 

AMPL does not recognize this kind of array arithmetic. To display an indexed collection of expressions, we must specify the indexing explicitly:

 

ampl: display {p in  PROD, t in 1..T} revenue[p,t]*sell[p,t];

revenue[p,t]*sell[p,t] [*,*] (tr)

:     bands coils

1     15000       9210

2     15600       87500

;

 

To apply the same indexing to two or more expressions, enclose a list of them in parentheses after the indexing expression.

 

Formatting options for display

 

The display command uses a few simple rules for choosing a good arrangement of data. By changing several options, we can control overall arrangement, handling of zero values and line width.  These options are summarized below with their default values.

 

Option

Details

display_1col

Maximum elements for a table to be displayed in list format(20)

display_transpose

Transpose tables if rows-colums < display_transpose (0)

display_width

Maximum line width (79)

gutter_width

Separation between table columns (3)

omit_zero_cols

If not 0, omit all-zero columns from displays (0)

omit_zero_rows

If not 0, omit all-zero rows from displays (0)

 

These options can be used with the keyword ‘option’ like

 

ampl: option display_1col 0;

 

to force the display to a compact form, or can be set to a very large number to force the list format.

 

List format & Compact format example:

 

ampl: display required;

required [*] :=

Fri1  100

Fri2  78

Fri3  52

Mon1  100

Mon2  78

Mon3  52

Sat1  100

Sat2  78

Thu1  100

Thu2  78

Thu3  52

Tue1  100

Tue2  78

Tue3  52

Wed1  100

Wed2  78

Wed3  52

;

 

In compact format:

 

Required [*] :=

Fri1  100   Mon1  100   Sat1  100   Thu2  78    Tue2  78    Wed2  78

Fri2  78    Mon2  78    Sat2  78    Thu3  52    Tue3  52    Wed3  52

Fri3  52    Mon3  52    Thu1  100   Tue1  100   Wed1  100

;

 

Numeric Options for display

 

The numbers in a table or list produced by display are the results of a transformation from the computer’s internal numeric representation to a string of digits and symbols. AMPL’s options for adjusting this transformation are shown in the table below along with their default values. The options falls under two categories: Options that affect only the appearance of numbers and options that affect the underlying solutions values as well.

 

Option

Details

display_eps

Smallest magnitude displayed different from zero (0)

display_precision

Digits of precision to which displayed numbers are rounded; full precision if 0 (6)

display_round

Digits left or (if negative) right of decimal place to which display numbers are rounded, overriding display_precision (“ ”)

solution_precision

Digits of precision to which solution values are rounded; full precision if 0 (0)

solution_round

Digits left or (if negative) right of decimal place to which solution values are rounded, overriding display_precision (“ ”)

 

Other output commands: print and printf

 

The print command

 

A print command produces a single line of output:

 

ampl: print {t in 1..T, p in PROD} Make [p,t] ;

5990 1407 6000 1400 1400 3500 2000 4200

 

Or, if followed by an indexing expression and a colon, a line of output for each member of the index set:

 

ampl: print {t in 1..T}: {p in PROD} Make[p,t];

5990 1407

6000 1400

1400 3500

2000 4200

 

Print entries are normally separated by a space, but option ‘print_separator’ can be used to change this.

 

The keyword ‘print’ (with optional indexing expression and colon) is followed by a print item or comma-separated list of print items. A print item can be a value, or an indexing expression followed by a value or parenthesized list of values. Thus a print item is much like a ‘display’ command, except that only individual values may appear.

 

‘print’ command has options ‘print_precision’ and ‘print_round’ options, which work exactly like the ‘display_precision’ and ‘display_round’ options for the display command.

 

The printf command

 

The syntax of printf is exactly the same as that of print, except that the first print item is a character string that provides formatting instructions for the remaining items:

 

ampl: printf “Total revenue is $%6.2f.\n”, sum {p in PROD, t in 1..T} revenue[p,t] * Sell[p,t];

          Total revenue is $787810.00

 

The format string contains two types of objects: ordinary characters, which are copied to the output, and conversion specifications, which govern the appearance of successive remaining print items. Each conversion specification begins with the character % and ends with a conversion character. The complete rules are much the same as for the ‘printf’ function in C programming language.

 

Related Solution values

 

AMPL provides ways of examining objectives, bounds, slacks, dual prices and reduced costs associated with the optimal solution. AMPL distinguishes the various values associated with a model component by use of “qualified” names that consist of a variable or constraint identifier, a dot(.), and a predefined “suffix” string.

 

Objective functions

 

The name of the objective function (from a minimize or maximize declaration) refers to the objective’s value computed from the current values of the variables. This name can be used to represent the optimal objective value in display, print, or printf.

 

ampl: print 100* Total_Profit;

7000

 

Here Total_Profit was an objective function.

 

Bounds and slacks

 

The suffixes .lb and .ub on a variable denote its lower and upper bounds, while slack denotes the difference of a variable’s value from its nearer bound.

 

ampl: display Buy.lb, Buy, Buy.ub, Buy.slack;

:     Buy.lb            Buy         Buy.ub            Buy.slack;

BEEF  2                 2           10                0

CHK   2                 10          10                0

FISH  2                 2           10                0

HAM   2                 2           10                0

MTL   2                 6.23596     10                3.76404

SPG   2                 5.25843     10                3.25843

TUR   2                 2           10                0

;

 

The reported bounds are those that were sent to the solver. Thus they include not only the bounds specified in >= and <= phrases of var declarations, but also certain bounds that were deduced from the constraints by AMPL’s presolve phase.

 

The suffixes .lb, .body, and .ub on constraints give the current values of these parts of the constraints, while the suffix .slack refers to the difference between the body and the nearer bound.

 

Dual values and reduced costs

 

Associated with each constraint in a linear program is a quantity variously known as the dual variable, marginal value or shadow price. In the AMPL command environment, these dual values are denoted by the names of the constraints, without any qualifying suffix. For example,  let there be a collection of constraints named ‘Demand’:

 

subject to Demand {j in DEST, p in PROD}: sum { i in ORIG} Trans[I,j,p]= demand[j,p];

 

and a table of dual values associated with these constraints can be viewed by

 

ampl: display Demand;

Demand [*,*]

:     bands       coils       plate :=

DET   201         190.714     199

FRA   209         204         211

FRE   266.2       273.714     285

LAF   201.2       198.714     205

STL   206.2       207.714     216

WIN   200         190.714     198

;                

 

A nearly identical concept applies to the bounds on a variable. The role of the dual value is played by the variable’s so called reduced costs, which can be viewed from the AMPL command environment by use of the suffix .rc

Details about dual values and reduced costs can be found in AMPL book and in standard linear programming textbooks.

 

Other display features for models and instances

 

Displaying model components: the show command

 

show command lists the names of all components of the current model:

 

ampl: model example.mod;

ampl: show;

parameters: demand limit

sets: DEST ORIG PROD

variables: use cost

constraints: Demand_supply

objective: Total_cost

checks: one, called check_1.

 

The display may be restricted to one or more types:

 

ampl: show vars;

variables: use cost

 

The show command can also display the declarations of individual components.

 

ampl: show Total_cost;

minimize Total_cost: sum{ i in ORIG, j in DEST, p in PROD} demand[p]*use[i,j] ;

 

Since the check statements in a model do not have names, AMPL numbers them in the order they appear.

 

Displaying model dependencies: the xref command

 

The xref command lists all model components that depend on a specified component, either directly( by refereeing to it) or indirectly (by referring to its dependents). If more than one component is given, the dependents are listed separately for each.

 

Example:

 

ampl: xref demand, Trans ;

# 2 entities depend on demand:

check 1

Demand

# 5 entities depend on Trans:

Total_Cost

Supply

Demand

Multi

Mini_Ship

 

In general the command is simply the keyword ‘xref’ followed by a comma-separated list of any combination of set, parameter, variable, objective and constraint names.

 

Displaying model instances: the expand command

 

In checking a model and its data for correctness, we may want to look at some of the specific constraints that AMPL is generating. The ‘expand’ command displays all constraints in a given indexed collection or specific constraints that one identifies.

 

ampl: model example.mod;

ampl: data example.dat;

ampl: expand Supply;

subject to Supply[‘GRAY’]:

            Trans[‘GRAY’,’FRA’] +   Trans[‘GRAY’,’DEN’]     + Trans [‘GRAY’, ‘LAN’] + Trans

[‘GARY’, ‘WIN’] = 1400;

subject to Supply[‘CLEV’]:

            Trans[‘CLEV’,’FRA’] +   Trans[‘CLEV’,’DEN’]     + Trans [‘CLEV’, ‘LAN’] + Trans

[‘CLEV’, ‘WIN’] = 2600;

 

Similarly objectives can also be expanded. When expand is applied to a variable, it lists all of the nonzero coefficients of that variable in the linear terms of objectives and constraints. When a variable also appears in nonlinear expressions within an objective or constraint, the term +nonlinear is appended to represent those expressions.

 

The command ‘expand’ alone produces an expansion of all variables, objectives and constraints in a model.

 

Generic synonyms for variables, constraints and objectives

 

Synonym

Details

_nvars

Number of variables in the current problem

_ncons

Number of constraints in the current problem

_nobjs

Number of objectives in the current problem

_varname{1.._nvars}

Names of variables in the current problem

_conname{1.._ncons}

Names of constraints in the current problem

_objname{1..n_objs}

Names of objectives in the current problem

_var{1.._nvars}

Synonyms for variables in the current problem

_con{1.._ncons}

Synonyms for constraints in the current problem

_obj{1.._nobjs}

Synonyms for objectives in the current problem

 

Resource listing

 

Changing option show_stats from its default of 0 to nonzero value requests summary statistics on the size of the optimization problem that AMPL generates:

 

ampl: model steelT.mod;

ampl: data steelT.dat;

ampl: option show_stats 1;

solve;

Presolve eliminates 2 constraints and 2 variables.

Adjusted problem:

24 variables, all linear

12 constraints, all linear ; 38 nonzeros

1 linear objective; 24 nonzeros.

MINOS 5.5 optimal solution found.

15 iterations, objective 515033

 

Changing option times from its default value of 0 to a nonzero value requests a summary of AMPL’s translator’s time and memory requirements. Similarly, by changing option gentimes to a nonzero value, we can get a detailed summary of the resources that AMPL’s genmod phase consumes in generating a model instance.

 

General facilities for manipulating output

 

Redirection of output

 

We can direct all output to a file instead of it appearing on display console, by adding a > and the name of the file:

 

ampl: display supply >multi.out;

 

The first command specificying >filename creates a new file by that name(or overwrites any existing file of the same name). Subsequent commands add to the end of the file, until the end of session or a matching close command:

 

ampl: close multi.out;

 

To open a file and append output to whatever is already there(rather than overwriting), use >> instead of >.

 

Output logs

 

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:

 

ampl: option log_file ‘multi.tmp’;

 

The log file collects all AMPL statements and the output that they produce.

Setting log_file to the empty string turns of writing to the file.

 

Limits on messages

 

By specifying option eexit n, where n is some integer, we determine how AMPL handles error messages. If n in not zero, any AMPL statement is terminated after it has produced abs(n) error messages; a negative value causes only the one statement to be terminated, while a positive value results in termination of the entire AMPL session.

The default value for –eexit is -10. Setting it to 0 causes all error messages to be displayed.

 

Command Scripts

 

A script is a sequence of commands, captured in a file, to be used and re-used.

 

Running scripts: include and commands

 

AMPL provides several commands that cause input to be taken from a file. The command:

 

include filename

 

is replaced by the contents of the named file. An include can even appear in the middle of some other statement, and does not require a terminating semicolon.

 

The ‘model’ and ‘data’ commands are special cases of ‘include’ that put the command interpreter into model or data mode before reading the specified file. By contrast, ‘include’ leaves the mode unchanged. For working with a small model, it might be convenient to put the model and data command and all the data statement in a file and then read in by use of ‘include’ command.

 

The statement:

 

commands filename;

 

is very similar to include, but is a true statement that needs a terminating semicolon and can only appear in a context where a statement is legal.

 

For example, ‘commands’ command may find its use while performing sensitivity analysis on a model by changing a parameter value. In this case we have to solve the model repeatedly by changing the data. So it would be better to put all these statements in a file and then call it by use of ‘commands’ command.

In many cases ‘commands’ command can be replaced by ‘include’ command. In general it is best to use commands within command scripts, however, to avoid unexpected interactions with repeat, for, if statements.

 

Iterating over a set: the ‘for’ statement

 

Many times we may have to repeat a few commands a few times. AMPL provides looping commands that can do this work automatically, with various options to determine how long the looping should continue.‘for’ statement, executes a statement or collection of statements once for each member of some set.

 

For example:

 

model steelT.mod;

data steelT.dat;

for {1..4} {

solve;

display Total_Profit > steelT.sens;

option display_1col 0;

option omit_zero_rows 0;

display Make > steelT.sens;

display Sell > steelT.sens;

option display_1col 20;

option omit_zero_rows 1;

display Inv > steelT.sens;

let avail[3] := avail[3] + 5;

}

The ‘for’ statement can be iterated over any set also.

 

Between the opening and closing brace of ‘for’ statement, we can place other statements like let, print, printf etc.

 

Iterating subject to a condition: the repeat statement 

 

A second kind of looping construct, the repeat statement, continues iterating as long as some logical condition is satisfied.

Generally the ‘repeat’ statement has the one of the following forms as illustrated:

 

repeat while condition {...};

repeat until condition {…};

repeat {…} while condition;

repeat {…} until condition;

 

The loop body, here indicated by {…}, must be enclosed in braces. Passes through the loop continue as long as the while condition is true, or as long as until condition is false. A condition that appears before the loop body is tested before every pass; if a while condition is false or an until condition is true before the first pass, then the loop body is never executed. A condition that appears after the loop body is tested after every pass, so that the loop is executed at least once in this case. If there is no while or until condition, the loop repeats indefinitely and must be terminated by other means, like the break statement.

 

Testing a condition: the ‘if-then-else’ statement

The if-then-else statement conditionally controls the execution of statements or groups of statements.

In the simplest case, the if statement evaluates a condition and takes a specified action if the condition is true:

 

If Make [“coin”,2] < 1500 then printf “under 1500\n” ;

 

The action may also be a series of commands grouped by braces as in the for and repeat commands.

 

An optional else specifies an alternative action that also may be a single command or group of commands:

 

If Make [“coin”,2] < 1500 then printf “under 1500\n” else printf  “Over 1500\n” ;

 

AMPL executes these commands by first evaluating the logical expression following if. If the expression is true, the command or commands following then are executed. If the expression is false, the command or commands following else, if any, are executed.

 

Terminating a loop: break and continue

 

Two other statements work with looping statements to make some scripts easier to write. The continue statement terminates the current pass through a for or repeat loop; all further statements in the current pass are skipped, and execution continues with the test that controls the start of the next pass(if any). The break statement completely terminates a for or repeat loop, sending control immediately to the statement following the end of the loop.

 

Stepping through a script: step, next, skip

 

If we suspect that a script might not be doing what we want it to do, we can tell AMPL to step through it one command at a time. This facility can be used to provide an elementary form of “symbolic debugger” for scripts.

 

To step through a script that does not execute any other scripts, reset the option ‘single_step’ to 1 from its default value of 0. For example:

 

ampl: option single_step 1;

ampl: commands steelT.sa7;

steelT.sa7:2(18) data…

<2>ampl:

 

The expression steelT.sa7:2(18) gives the filename, line number and character number where AMPL has stopped in its processing of the script. It is followed by the beginning of the next command (data) to be executed. On the next line we are returned to the ampl: prompt. The <2> in front indicates the level of input nesting; “2” means that execution is within the scope of a commands statement that was in turn issued in the original input stream.

At this point we may use step command to execute individual commands of the script. If step is followed by a number, that number of commands will be executed.

 

<2> ampl: step;

steelT.sa7:4(36) option …

 

To help through lengthy compound statement (for, repeat or if) AMPL provides alternatives to step. The next command steps past a compound command rather than into it. Typing ‘next n’ step past n commands in this way.

The commands skip and ‘skip n’ works like step and ‘step n’, except that they skip the next 1 or n commands in the script rather than executing them.

 

Manipulating character strings

 

String functions and operators: ‘&’, length, match, substr, sub, gsub

 

The concatenation operator ‘&’ takes two strings as operands, and returns a string consisting of the left operand followed by the right operand. For example:

 

ampl: model diet.mod;

ampl: data diet2.dat;

ampl: display NUTR, FOOD;

set NUTR :=  A          B1          B2;

set FOOD := BEEF  CHK   FISH;

ampl: set NUTR_FOOD := setoff {i  in NUTR, j in FOOD} i & “_” & j;

ampl: display NUTR_FOOD;

set NUTR_FOOD :=

A_BEEF      B1_BEEF     B2_BEEF

A_CHK       B1_CHK      B2_CHK

A_FISH      B1_FISH     B2_FISH;

 

Numbers as arguments to ‘&’ are automatically converted to strings. Numeric operands are always converted to full precision.

 

The ‘length’ string function takes a string as argument and returns the number of characters in it. The ‘match’ function takes two string arguments, and returns the first position where second appears as a substring in the first, or zero if the second never appears as a substring in the first. The ‘substr’ function takes a string and one or two integers as arguments. It returns a substring of the first argument that begins at the position given by the second argument; it has the length given by the third argument, or extends to the end of the string if no third argument is given. An empty string is returned if the second argument is greater than the length of the first argument, or if the third argument is less than 1.

AMPL provides two other functions, ‘sub’ and ‘gsub’, that look for the second argument in the first, like match, but that then substitute a third argument for either the first occurrence(sub) or all occurrences(gsub) found.

 

Interactions with Solvers

 

We briefly discuss the mechanisms used by AMPL to control and adjust the problems sent to solvers, and to extract and interpret information returned by them.

 

Presolve

 

AMPL’s presolve phase attempts to simplify a problem instance after it has been generated but before it is sent to a solver. It runs automatically when a ‘solve’ command is given or in response to other commands.  Any simplifications that presolve makes are reversed after a solution is returned, so that one can view the solution in terms of the original problem. Thus presolve normally proceeds silently behind the scenes. Its effects are only reported when we change option show_stats from its default value of 0 to 1.

We can determine which variable and constraints presolve eliminated by testing, to see which variables/ constraints have a status of “pre”.

 

ampl: print { j in 1.._nvars: _var[j].status = “pre” } : _varname [j];

Inv[‘bands’, 0]

Inv[‘coils’, 0]

ampl: print { i in 1.._ncons: _con[i].status = “pre”}:  _conname [i] ;

Init_Inv [‘bands’]

Init_Inv [‘coils’]

 

We can then use ‘show’ and ‘display’ to examine the eliminated components.

 

Activities of the presolve phase

 

·        AMPL first assigns each variable whatever bounds are specified in its ‘var’ declaration or the special bounds ‘-Infinity’ and ‘Infinity’ when no lower or upper bounds are given.

·        The presolve phase tries to use these bounds together with the linear constraints to deduce tighter bounds that are still satisfied by all of the problem’s feasible solutions. Concurrently, presolve tries to use the tighter bounds to detect variables that can be fixed and constraints that can be dropped.

·        Presolve works on a problem in two parts. In first part it applies some tests to deduct some bounds on variables and deduce linear constraints. In second part, there are a series of passes through the problem, each attempting to deduce still tighter variable bounds from the current bounds and the linear constraints.

Controlling the effects of presolve

 

To turn off presolve entirely, set option presolve to 0; to turn off the second part only, set it to one (1).  A higher value for this option indicates the maximum number of passes made in part two of presolve; the default is 10.

 

Following presolve, AMPL saves two sets of lower and upper bounds on the variables: ones that reflect the tightening of the bounds implied by constraints that presolve eliminated, and ones that reflect further tightening deduced from constraints that presolve could not eliminate. The problem has the same solution with either set of bounds, but the overall solution time may be lower with one or the other, depending on the optimization method in use and the specifics of the problem.

 

Some other variables to control presolve effects:

var_bounds : set it to 2 to pass the second set of bounds to the solver.

 

For integer variables, AMPL rounds any fractional lower bounds up to the next higher integer and any fractional upper bounds down to the next lower integer. To prevent the inaccuracies of finite precision computation, AMPL subtracts the value of option ‘presolve_inteps’ from each lower bound and adds it to each upper bound. If increasing this value to the value of option ‘presolve_intepsmax’ would make a difference to the rounded bounds of any of the variables, AMPL issues a warning.

 

To examine first and second set of presolve bounds we can use suffixes, .lb1 and .ub1 and .lb2 and .ub2 respectively. The suffixed .lb and .ub give the bound values currently passed to the solver, based on current values of options ‘presolve’ and ‘var_bounds’.

 

Detecting infeasibility in presolve

 

Presolve can determine many conditions that can make the problem infeasible.

 

a)     If any variable’s lower bound is greater than its upper bound then there can be no solution satisfying all the bounds and other constraints, and an error message is printed.

b)     Presolve’s more sophisticated tests can also find infeasibilities that are not due to any one variable. 

c)      When the implied lower and upper bounds for some variable or constraint body are equal then due to imprecision in the computations, the lower bound may come out slightly greater than the upper bound, causing AMPL’s presolve to report an infeasible problem. To circumvent this difficulty, we can reset the option ‘presolve_eps’ from its default value of 0 to some small positive value. Differences between lower and upper bounds are ignored when they are less than this value. If increasing the current ‘presolve_eps’ value to a value no greater than ‘presolve_epsmax’ would change presolve’s handling of the problem, then presolve displays a message to this effect.

d)     An imprecision in the computations can cause the implied lower bound on some variable or constraint body to come out slightly lower than the implied upper bound. Here no infeasibility is detected, but the presence of bounds that are nearly equal may make the solver’s work much harder than necessary. Thus whenever, the upper bound minus the lower bound on a variable or constraint body is positive but less than the value of option ‘presolve_fixeps’, the variable or constraint body is fixed at the average of two bounds. If increasing the value of ‘presolve_fixeps’ to at most the value of ‘presolve_fixepsmax’ would change the results of presolve, a message to this effect is displayed.

e)     The number of separate messages displayed by presolve is limited to a value of ‘presolve_warnings’, which is 5 by default. Increasing option ‘show_stats’ to 2 may elicit some additional information about the presolve run.

Retrieving results from solvers

 

AMPL sets two built in parameters after each run of ‘solve’ command to indicate the solver’s status after a run of the optimization problem. These two parameters are:

 

solve_result_num: Contains a number

solve_result : Contains a character string

 

This can be interpreted as the following:

 

Number

String

Interpretation

0-99

solved

Optimal solution found

100-199

solved?

Optimal solution indicated, but error likely

200-299

infeasible

Constraints cannot be satisfied

300-399

unbounded

Objective can be improved without limit

400-499

limit

Stopped by a limit that one sets (such as on iterations)

500-599

failure

Stopped by an error condition in the solver

 

This status information is used in scripts, where it can be tested to distinguish among cases that must be handled in different ways.

The built in parameter solve_exitcode records the success or failure of the most recent solver invocation. Initially -1, it is reset to 0 whenever there has been a successful invocation and to some system dependent nonzero value otherwise.

 

Solver status of objectives and problems

 

Sometimes it is convenient to be able to refer to the solve result obtained when a particular objective was most recently optimized. For this purpose, AMPL associates with each built in solve result parameter a ‘status’ suffix:

 

               Built in parameter

Suffix

solve_result

.result

solve_result_num

.result_num

solve_message

.message

solve_exitcode

.exitcode

 

Appended to an objective name, this suffix indicates the value of the corresponding built in parameter at the most recent solve in which the objective was current.

 

Solver statuses of variables

 

AMPL provides facilities to let solver return an individual status for each variable. The major use of solver status values from an optimal basic solution is to provide a good starting point for the next optimization run. The option ‘send_statuses’, when left at its default value of 1, instructs AMPL to include statuses with the information about variables sent to solver at each solve.

 

AMPL refers to a variable’s solver status by appending .sstatus to its name. Thus we can print the status of variables with display command.

 

A table of the recognized solver status values is stored in option sstatus_table:

 

ampl: option sstaus_table;

option sstatus_table ‘\

0     none  no status assigned\    

1     bas   basic\     

2     sup   superbasic\

3     low   nonbasic<= (normally = ) lower bound \

4     upp   nonbasic>= (normally=) upper_bound\

5     equ   nonbasic  at equal lower and upper bounds\

6     btw   nonbasic between bounds\

‘;

 

Solver statuses of constraints

 

Implementation of the simplex method typically adds one variable for each constraint that they receive from AMPL. Each added variable has a coefficient of 1 or -1 in its associated constraint, and coefficients of 0 in all other constraints. If the associated constraint is in inequality, the addition is used as a “slack” or “surplus” variable; its bounds are chosen so that it has effect of turning the inequality into an equivalent equation. If the associated constraint is an equality, the added variable is an “artificial” one whose lower and upper bounds are both zero.

 

To accommodate statuses of these logical variables, AMPL permits a solver to return status values corresponding to the constraints as well as the variables. The solver status of a constraint, written as the constraint name suffixed by .sstatus, is interpreted as the status of the logical variable associated with that constraint.

 

AMPL statuses

 

Only those variables, objectives and constraints that AMPL actually sends to a solver can receive solver statuses on return. So that we can distinguish these from components that are removed prior to a solve, a separate “AMPL status” is also maintained. We can work with AMPL statuses much like solver statuses, by using the suffix .astatus in place of .sstatus and referring to option astatus_table for a summary of the recognized values:

 

ampl: option astatus_table;

option astatus_table ‘\

0     in          normal state (in problem)\

1     drop        removed by drop command\

2     pre         eliminated by presolve

3     fix         fixed by fix command\

4     sub         defined variable, substituted out\

5     unused      not used  in current problem\

‘;

 

Exchanging information with solvers via suffixes

 

AMPL employs various qualifiers or suffixes appended to component names to represent values associated with a model component. AMPL can not anticipate all of the values that a solver might associate with model components, however. The values recognized as input or computed as output depend on the design of each solver and its algorithms. To provide for open ended representation of such values, new suffixes may be defined for the duration of AMPL session, either by the user for sending values to a solver, or by a solver for returning values. For this purpose we have user defined suffixes and solver defined suffixes.

User defined suffixes can be used to pass preferences for variable selection and branch direction to an integer programming solver. Similarly solver suffixes can be used for sensitivity analysis and infeasibility diagnosis. Users are referred to the AMPL book by R. Fourer, D. Gay and B.W. Kernighan (Chapter 14 – Interaction with solvers) for details.

 

Defining and using suffixes

 

A new AMPL suffix is defined by a statement consisting of the keyword ‘suffix’ followed by a suffix name and then one or more optional qualifiers that indicate what values may be associated with the suffix and how it may be used. The suffix statement causes AMPL to recognize suffixed expression of the form component-name.suffix name, where component-name refers to any currently declared variable, constraint or objective. The definition of a suffix remains in effect until the next ‘reset’ command or the end of the current AMPL session.  There are a few optional qualifiers of the suffix statement and they may appear in any order.

The optional ‘type’ qualifier in a suffix statement indicates what values may be associated with the suffixed expressions, with all numeric values being the default.

 

Suffix type

Values allowed

None specified

Any numeric value

Integer

Integer numeric values

Binary

0 or 1

Symbolic

Character strings listed in option suffix-name_table

 

All numeric-valued suffixed expressions have an initial value of 0. Their permissible values may be further limited by one or two bound qualifiers of the form

          >=     arith-expr

          <=     arith-expr

 

Where arith-expr is any arithmetic expression not involving variables.

 

For each symbolic suffix, AMPL automatically defines an associated numeric suffix, suffix-name_num. An AMPL option suffix-name_table must then be created to define a relation between the .suffix-name and .suffix-name_num values, as in the following example:

 

suffix iis symbolic OUT;

option iis_table ‘\

0     non   not in the iis\

1     low   at lower bound\

2     fix   fixed\

3     upp   at upper bound\  

‘;

 

Each line of the table consist of an integer value, a string value, and an optional comment.

 

The optional in-out qualifier determines how suffix values interact with the solver:

 

In-out

Handling of suffix values

IN

written by AMPL before invoking the solver,  then read in by solver

OUT

written out by solver, then read by AMPL after the solver is finished

INOUT

both read and written, as for IN and OUT above

LOCAL

neither read nor written

 

 

Alternating between Models

 

We have seen earlier how AMPL commands can be set up to run as programs that perform repetitive actions. In several examples, a script solves a series of related model instances, by including a solve statement inside a loop. The result is a simple kind of sensitivity analysis algorithm, programmed in AMPL’s command language.

 

Much more powerful algorithmic procedures can be constructed by using two models. An optimal solution for one model yields new data for the other, and the two are solved in alteration in such a way that some termination condition must eventually be reached. To use two models in this manner, a script must have some way of switching between them. Switching can be done with previously defined AMPL features, or more clearly and efficiently by defining separately-named problems and environments.

 

Named problems

 

At any point during an AMPL session, there is a current problem consisting of a list of variables, objectives and constraints. The current problem is named Initial by default and comprises all variables, objectives and constraints defined so far. We can define other “named” problems consisting of subsets of these components, however, and can make them current. When a named problem is made current, all of the model components in the problem’s subset are made active, while all other variables, objectives and constraints are made inactive. More precisely variables in the problem’s subset are unfixed and the remainder are fixed at their current values. Objectives and constraints in the problem’s subset are restored and the remainder are dropped.

 

We can define a problem most straightforwardly through a problem declaration that gives the problem’s name and its list of components. For example:

 

problem Cutting_Opt : Cut, Numer, Fill;

 

A new problem Cutting_opt is defined, and is specified to contain all of the Cut variables, the objective Number and all of the Fill constraints. At the same time, Cutting_opt becomes the current problem. Any fixed Cut variables are unfixed, while all other declared variables are fixed at their current values. The objective Number is restored if it had been previously dropped, while all other declared objectives are dropped; and similarly any dropped Fill constraints are restored, while all other declared constraints are dropped.

 

Any problem statement that refers to only one problem has the effect of making that problem current. 

 

We can display the current problem by using command ‘problem’:

 

ampl: model cut.mod;

ampl: data cut.dat;

ampl: problem;

problem Initial;

 

The current problem is always Initial until other named problems have been defined. The ‘show’ command can give a list of the named problems that have been defined.

 

ampl: show problems;

problems: Cutting_opt   Pattern_Gen

 

We can also use ‘show’ to see the variables, objectives and constraints that make up a particular problem or indexed collection of problems and use ‘expand’ to see the explicit objectives and constraints of the current problem, after all the data values have been substituted.

 

Named environments

 

In the same way that there is a current problem at any point in an AMPL session, there is also a current environment. Whereas a problem is a list of non fixed variables and non dropped objectives and constraints, an environment records the value of all AMPL options. By naming different environments, a script can easily switch between different collections of option settings.

 

At the start of an AMPL session the current environment is named Initial and each subsequent problem statement that defines a new named problem also defines a new environment having the same name as the problem. An environment initially inherits all the option settings that existed when it was created, but it retains new settings that are made while it is current. Any ‘problem’ or ‘solve’ statement that changes the current problem also switches to the correspondingly named environment, with options set accordingly.

 

In more complex situations, we can declare named environments independently of named problems, by use of statement that consists of the keyword ‘environ’ followed by a name:

 

environ Master;

 

For a more detailed description of the advance features of AMPL language, users are referred to the book on AMPL by R. Fourer, D. Gay and B.W. Kernighan and the AMPL website (www.ampl.com).

 

 

 

 

 

 

 

 

 

 

 

 

 

Contents Overview Example Db connection AMPL commands Script & Tracing AMPL and Studio Viewlet                                                                          

    

Copyright (c) 2012. Datumatic Ltd. Registration No. 04988675. UK.