Declarations of AMPL model components can be removed or redefined by use of the new purge, delete, and redeclare commands. Other new features let you change the value of a variable while fixing or unfixing it, and relax the integrality restrictions on variables.
ampl: model diet.mod; ampl: data; ampl data: set NUTR := A B1 B2 C ; ampl data: param: n_min n_max := ampl data? A 700 10000 ampl data? C 700 10000 ampl data? B1 700 10000 ampl data? B2 700 10000 ; ampl data: display n_min, n_max; : n_min n_max := A 700 10000 B1 700 10000 B2 700 10000 C 700 10000 ;AMPL exits data mode when it sees any statement (such as display above) that does not begin with a keyword (such as set or param) that begins a data statement.
Normally data values are read from files rather than being typed at the AMPL prompts. A command of the form
data filename;reads the contents of the named file as if it had been typed at the prompts, starting in data mode. The mode then reverts to whatever it was before the data statement was executed -- unless the last data statement in the file is incomplete, in which case data mode persists.
When you use data statements to assign values to model components, AMPL checks that no component is assigned a value more than once. Duplicate assignments are flagged as errors. In some situations, however, it is convenient to be able to change the data by issuing new data statements; for example, after solving for one scenario of a model, you may want to modify some of the data by reading a new data file that corresponds to a second scenario. The statements in the new file would normally be treated as erroneous duplicates, but you can tell AMPL to accept them by first giving one of the following commands:
reset data;The reset commands discard specified data, which must then be re-read before another problem can be generated and solved. The update commands retain the current data, but allow specified data values to be overwritten (once only) by subsequent data commands. The component-list, which has the same format as in the display command (Chapter 10.3), indicates the model components that are to be reset or updated. Without the component-list, these commands apply to all the components of the model.
reset data component-list;
update data;
update data component-list;
Previous restrictions on the location of an AMPL data
statement have now been lifted. In, particular, a data
statement may appear within an if statement to conditionally
read data. A data statement may also be used within a
for or repeat statement, in conjunction with
reset or update, to iteratively read a data file
that is being regenerated at each pass through a loop, typically by
some external program (an example is to be provided).
We describe first how read interprets its input, and
then where it looks for the input.
Interpretation of input. The read
command treats its input as an unformatted series of data values,
separated by white space (any combination of spaces, tabs and
newlines). The arglist specifies a series of components to
which these values are assigned. As in the case of print,
the arglist is a comma-separated list of args, which may
be any of:
Values are assigned to args in the order that they
are read. Thus it is legal to write, say,
Sources of input. If no redirection is
specified, values are read from the current input stream. Thus if you
have typed the read command at an AMPL prompt, you type the
values at subsequent prompts until all of the arglist entries have
been assigned values. For example:
Most often the input to read lies in a separate file. Then
you can use the optional redirection to specify this file; its
form is < filename, where filename is a string
that identifies a file on your computer. You can read more than once
from the same file,
What if you want an AMPL script to contain a read command
that reads values typed interactively? In this case you must redirect
the source of the values to the "standard input", which is
accomplished by writing a - as the filename. This can
be useful when you want a script to prompt the user. For example,
suppose that your script contains
Reading data: the read command
The new read command provides a way of reading
unformatted data into AMPL parameters and other components. It has
syntax similar to that of the print command:
read arglist redirectionopt ;
As in the case of display, print and
printf, the optional indexing-expr causes the
read command to be executed separately for each member of the
specified indexing set. Thus, for example, a statement beginning
read {i in ORIG}: ... has
the same effect as for {i in ORIG}
read ... .
read indexing-expr : arglist redirectionopt ;
component-ref
The component-ref must be a reference to a parameter, variable,
or constraint; it is meaningless to read a value into a set member or
any more general expression. As in the case of print, all
indexing must be explicit, so that for example you must say
read {j in DEST}
demand[j] ranther than read demand.
indexing-expr component-ref
( arglist )
param cost {ORIG,DEST} default 9999;
param ic symbolic in ORIG;
param jc symbolic in DEST;
param npairs integer;
read npairs, {1..npairs} (ic,jc,cost[ic,jc]);
The first input value, by being assigned to npairs,
determines how much more data will be read. The remainder of the
input comes in a series of threes; the first two values, read into
ic and jc, determine where in cost the
third value should be stored.
ampl: read npairs, {1..npairs} (ic,jc,cost[ic,jc]);
ampl? 3
ampl? GARY FRA 3000
ampl? GARY LAF 4500
ampl? CLEV WIN 4200
ampl: display cost;
cost :=
CLEV WIN 4200
GARY FRA 3000
GARY LAF 4500
;
The prompt changes from ampl? back to ampl: when all
the needed input has been read. If instead you put read
inside an AMPL script file that is read by use of include or
commands, then the input is read from the same file,
beginning directly after the ; of the read command.
ampl: read npairs < pairs.dat;
ampl: read {1..npairs} (ic,jc,cost[ic,jc]) < pairs.dat;
in which case each read starts reading the file where the
previous one left off. (To force reading to start at the beginning
again, use the command close filename.
param T integer > 0;
printf "\nHow many of the periods do you want to use?\n";
read T <- ;
and is stored in the file read.run. Then here's how it
would look in use:
ampl: include read.run;
How many of the periods do you want to use?
ampl? 5
In this case the value 5 would be assigned to T.
Removing or redefining model components
The delete command removes a previously declared
model component, provided that no other components use it in their
declarations. Thus normally you can delete a constraint, but you
cannot delete a variable -- because it appears in subsequent
constraint declarations. The form of the command is
delete component-list ;
where component-list is a space-separated or comma-separated
list of names of sets, parameters, variables, objectives, constraints
or problems. You can also include a
"name" of the form check n in the
component-list, to delete the nth check
statement in the current model.
The purge command has the same form,
purge component-list ;It removes not only the named components, but also all components that depend on them either directly (by referring to them) or indirectly (by referring to their dependents). Thus for example in diet.mod we have
param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; var Buy {j in FOOD} >= f_min[j], <= f_max[j]; minimize total_cost: sum {j in FOOD} cost[j] * Buy[j];The command purge f_min deletes parameter f_min and the components whose declarations refer to f_min, including parameter f_max and variable Buy. It also deletes objective total_cost, which depends indirectly on f_min through its reference to Buy.
Once a component has been removed by delete or purge, any previously hidden meaning of the component's name becomes visible again. After a constraint named prod is deleted, for instance, AMPL again recognizes prod as an iterated multiplication operator (Table 7-1 of the AMPL book).
The name of a component removed by delete or purge becomes again unused, and may subsequently be declared as the name of any new component of any type. If you only want to make some relatively small revision to a component's declaration, however, then you will probably find AMPL's new redeclare feature to be more convenient. You can say
redeclare declarationwhere declaration is the complete revised declaration that you would like to substitute. Looking again at diet.mod, for example,
redeclare param f_min {FOOD} > 0 integer;changes only 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. A redeclare can be applied to statements beginning with any of the following:
set param var minimize maximize subject to node arc problemYou can also redeclare the nth check statement by writing redeclare check n in front of your new check declaration.
To request a list of all components that a given component refers to, use the new xref command.
let Buy["beef"] := 0; fix Buy["beef"];you can fix and set the variable with one command:
fix Buy["beef"] := 0;The := phrase may also be used with the indexed form of the fix command:
fix {i in ORIG} Trans[i,"FRA"] := 100;The unfix command works in the same way, to simultaneously unfix and reset the value of a variable.
option relax_integrality 1;you tell AMPL to drop any restriction of variables to integer values. Variables declared integer get whatever bounds you specified for them, while variables declared binary are given a lower bound of zero and an upper bound of one. To restore the integrality restrictions, set the relax_integrality option back to 0.
Some of the solvers that work with AMPL provide their own directives for relaxing integrality, but these do not necessarily have the same effect as the AMPL's relax option. AMPL drops integrality restrictions before its presolve phase, so that the solver receives a true continuous relaxation of the original integer problem. If the relaxation is performed by the solver, however, then the integrality restrictions are still in effect during AMPL's presolve phase, and AMPL may perform some additional tightening and simplification as a result. As a simple example, when presolve sees the declarations
var X integer >= 0; subj to upXbd: 5 * X <= 12;it removes the constraint upXbd and places an upper limit of 2 on the variable X; this upper limit is sent to the solver, where it remains even if you specify a solver directive for integrality relaxation. If instead option relax_integrality is set to 1, AMPL converts the constraint to an upper limit of 2.4, which is sent to the solver.
The same situation can arise in much less obvious circumstances, and can lead to unexpected results. In general, the optimal value of an integer program under AMPL's relax_integrality option may be lower (for minimization) or higher (for maximization) than the optimal value reported by the solver's relaxation directive, unless AMPL's presolve phase is turned off by the command option presolve 0.
Return to the AMPL update page.