The Put Writing Facility

Introduction

While the GDX facility is widely used to exchange bulk GAMS data with other programs the put writing facility allows to generate sophisticated reports in GAMS. The result are external ASCII files that are structured using information that is stored by the GAMS system. The put writing facility offers users numerous ways to control three format layers: the format of the external file that is written to, the format of the pages of the external files and the format of output items. Hence the structure of the put writing facility is more complex and requires more programming than the display statement, but there is much more flexibility and control over the output. The put writing facility generates external files automatically when the GAMS program is executed. The files are written sequentially, a single page at a time. The current page is stored in a buffer, which is automatically written to an external file when the page is full. Thus, the put writing facility has only control over the current page and does not have the ability to go back to alter former pages. However, while a particular page is current, information placed on it may be overwritten or removed at will.

This chapter is organized as follows. We will first introduce the file statement and the put statement, which are at the core of the put writing facility. Then we will present a simple example that will serve as illustration. We will also introduce some widely used features as we comment on the example. The remainder on the chapter will cover in detail the external report files, also called put files, the structure of put file pages and ways to control their format, types of output items and their formatting controls, and the put_utility statement, a variant of the put statement that allows to special communication of formatted elements with the outside world. In addition, we will briefly discuss exception handling in the context of put statements and GAMS errors that are specific to put statements. We will conclude the chapter with an elaborate example. Note that put file attributes play a crucial role, since they are used for most formatting controls. A complete list of all file attributes is given in section Put File Attributes.

The Syntax

The basic structure of the put writing facility in its simplest form is as follows:

File file_name {,file_name};
put file_name;
put item {,item};

Note that the first line is a file statement. File statements define one or more external files that will be written to and specify internal names for them. These internal names wil be used in the GAMS model to reference the external files when they are written to. The second line is a put statement that assigns the file with the name file_name as the current file. The third line is a put statement that writes one or more items to the current file. Items are any type of output like explanatory text, set labels, parameters, and variable, equation values and model attributes.

Next, we will present more details on the file statement and the put statement in the following two subsections and then we will turn to a first example that will illustrate how the the put writing facility works.

The File Statement: Defining Put Files

External files that are written to with the put writing facility are called put files. They are defined with a file statement. The syntax for a file statement is as follows:

File[s] file_name ["text"] [external_file_name]
  {,file_name ["text"] [external_file_name] } ;

The keyword file or files indicates that this is a file statement. It is follwed by the internal name for the put file, file_name. The internal file name is a handle for the put file, it is used in the GAMS model to refer to the put file. The optional explanatory text may be used to describe the put file for future reference and to ease readability. The final part of the file statement is the actual name of the put file. Naming the external file is optional. In case it is omitted, by default, GAMS will create a name by appending the extension .put to the internal name. Consider the following example:

File results;

Note that in this statement no external file name is specified. Thus GAMS will create the external file results.put in the current working directory. Observe that by default, all put files are stored in the current working directory. There are several ways to specify alternative directories for put files. For details see section Choosing Where Put Files are Saved below.

Note
Multiple put files may defined with one file statement.

Consider the following example:

File  class1
      class2   "this defines a specific external file"  /report.txt/
      log      "this defines access to the GAMS log file" /''/;

Observe that the internal name of the first file is class1. As no external name is specified, GAMS will assign the absolute name class1.put to this file. The second file will be referenced in the model with the name class2 and it corresponds to the external file report.txt. The third file is special: the internal name '' is reserved for writing output to the GAMS log. Note that writing to the GAMS log can be useful to monitor how the solution process of the model is progressing.

For further details on put files, see section Put Files below.

The Put Statement

The put statement is at the core of the put writing facility. It has two different functions: it specifies which of the previously defined put files is the current file and it writes output to that file. The syntax for the first function is simple:

put file_name;

The keyword put indicates that this is a put statement, file_name is the internal name of a put file that was previously defined with a file statement. This put statement has the effect that the specified file is now ready to be written to. Note that this put statement is necessary even if only one put file has been previously defined. For an example of how it is used when output is written to several different files, see the next section.

The basic syntax for a put statement that is used to write output to a file is as follows:

put item {,item};

The statement begins with the keyword put followed by one or more items. Items may be a text (like a quoted text, an explanatory text, the name of a set element), a numerical value (like the value of a parameter, the value of an attribute, the solution status of the model) or a set value (YES or NO indicating whether a label is an element of a specific set). These items are discussed in detail in section Output Items below. In addition, GAMS facilitates writing a text block to a put file and including the content of an external file in a put file. For details see sections Text Items: Text Blocks and The Put_Utility Statement respectively.

Note that it is also allowed to use only one put statement to assign one file as the current file and write to it. The syntax follows:

put file_name item {,item};

In addition, it is permitted to use just one put statement to write to multiple files sequentially. Thus the most general form of a put statement is as follows:

put file_name item {,item} {,file_name item {,item}};

Note that only one file is current at a time. When a file is current, the output items following the name of this file will be written to the file. After this has been completed, the current file is reassigned to the next internal file name in the statement. The last internal file name used in a put statement continues to be the current file until a subsequent put statement uses an internal file name.

Observe that the keyword put has several variants: putclose, puttl, puthd, putpage and put_utility.

A First Example

We will use a small example to introduce the basic features of the put writing facility. The example is based on the well-known transportation model [TRNSPORT]. The following code segment could be placed at the end of the transportation model to create a report:

File factors /factors.dat/,
     results /results.dat/;
put factors;
put 'Transportation Model Factors' / /
    'Freight cost  ', f,
    @1#6, 'Plant capacity'/;
loop(i, put @3, i.tl, @15, a(i)/);
put /'Market demand'/;
loop(j, put @3, j.tl, @15, b(j)/);

put results;
put 'Transportation Model Results' / / ;
loop((i,j), put i.tl, @12, j.tl, @24, x.l(i,j):8:4 /);

In the first line, the file statement defines the internal file names factors and results and connects them to the external files factors.dat and results.dat respectively. These internal file names are used inside the model to reference files which are external to the model.

In the second line, the put statement assigns the file factors as the current file, that is the file which is currently available to be written to.

In the third line, the put statement starts the actual writing to the put file. The first item that is written is the quoted text string 'Transportation Model Factors'. The item is followed by two slashes. A slash instructs the cursor to move to the first column of the next line. Two slashes have the effect that the cursor is moved to the first column of the second line, thus introducing a blank line.

Attention
Two slashes // are a popular end of line comment character sequence. So an intended blank line can result in a comment in the GAMS code. A safe way to use slashes in put statement is to separate the slashes by a space.

The next item is the string 'Freight cost ' followed by the value of the scalar f. Note that these output items are separated by commas. Blanks and commas serve as delimiters for separating different output items. These delimiters leave the cursor at the next column position in the file following the last item written. In most cases, a blank and a comma may be used interchangeably. However, the comma is the stronger form and will eliminate any ambiguities.

In the fifth line, the code above starts with the instruction @1#6. In the context of put statements, the symbols @ and # serve to reposition the cursor to a specific column and row respectively. Thus in our case, the cursor is repositioned to column 1 of row 6 of the put file. Then another text string is written and a new line is started. The semicolon terminates the put statement. More details on cursor positioning are given in section Controlling the Cursor On a Page.

In line 6, the next put statement is embedded within a loop statement. Note that the set i is the looping set. The put statement writes at column position 3 the set label name and at column position 15 the value of the parameter a(i) for each element of the set i. Observe that set element labels are referenced with the name of the set and the suffix .te. For more information on identifier suffixes, see section Text Items below. Note that the put statement has to be placed within a looping structure, since only one element of the index set may be written with a put statement.

In line 7, the first symbol after the keyword put is a slash, that has the effect that a blank line is inserted before the text string 'Market demand' is written.

In line 8, we have again a put statement within a loop structure: the values of the parameter b are written in a similar way to those of parameter a in line 6.

After execution, the put file factors.dat will look as follows:

Transportation Model Factors

Freight cost         90.00

Plant capacity
  Seattle           350.00
  San-Diego         600.00

Market demand
  New-York          325.00
  Chicago           300.00
  Topeka            275.00

Note that this output has been formatted using the default file format values. GAMS offers several ways to customize the format, see sections Global Item Formatting Controls and Local Item Formatting Controls below for further information.

In the last three lines of the code above, the file results.dat is made current and the level values associated with the variable x along with their corresponding set element index labels are written line by line. Note that the format of the output results of the variable x is customized by specifying a field width of 8 spaces with 4 of these spaces reserved for decimal places. This is an example of local formatting. The put file results.dat will contain the following lines:

Transportation Model Results

Seattle    New-York     50.0000
Seattle    Chicago     300.0000
Seattle    Topeka        0.0000
San-Diego  New-York    275.0000
San-Diego  Chicago       0.0000
San-Diego  Topeka      275.0000

This small example has demonstrated the main features of the put writing facility. However, its surface has just barely been scratched. In the remainder of this chapter we will describe in detail the many features of the put writing facility. Observe that in section Creating a Report for the Model MEXSS at the end of this chapter we will present a more elaborate report.

Put Files

As mentuioned earlier, external files that are written to with the put writing facility are called put files. They are defined with a file statement and are made current with a put statement. Once they are current, they may be written to. By default, put files are saved in the current working directory. In this section we will cover more details on put files. We will discuss ways to specify other directories for put files, introduce the putclose statement, a variant of the put statement that closes the current file, and we will show how to append to an existing external file instead of replacing (overwriting) it. In addition, we will introduce the notion of put file attributes including a list of all attributes.

Choosing Where Put Files are Saved

Recall that by default, put files are saved in the current working directory. GAMS offers several ways to specify other directories for put files. The easiest way to specify another directory is by including the absolute or relative path in the file statement. Consider the following example:

File report / C:\Documents\GAMS\Output\report.dat /;

Note that the put file report.dat with the internal name report will be stored in the directory specified in the file statement instead of the current working directory.

An alternative directory for all put files in a model may be specified with the command line parameter PutDir. Assume we wish to write some ouput from running the well-known transportation model [TRNSPORT] to the file results defined above. Consider the following GAMS call:

   > gams trnsport PutDir=c:\output

Note that the file results.put will be stored in the directory specified in the GAMS call. Observe that storing put files in the directory specified with PutDir is applies to all file that are not specified via an absolute file name. For more information on command line parameters, see chapter The GAMS Call and Command Line Parameters. scratchdir as putdir option (.pdir) lets GAMS write put files into the scratch directory.

The content of a put file will be sent to the GAMS log file if the put file is specified in the following way:

File name / '' /;

For example, the following code snippet may be added to the transportation model [TRNSPORT]:

File name / '' /;
put name ;
put 'instructions that will go to the GAMS log' /;
put 'more instructions that will go to the GAMS log' /

As a result, the respective GAMS log will contain the following lines:

...
instructions that will go to the log file
more instructions that will go to the log file
*** Status: Normal completion
--- Job trnsport.gms Stop 01/25/17 15:46:09 elapsed 0:00:00.320

The Putclose Statement: Closing a Put File

Recall that the file statement and the put statement are at the core of the put writing facility. The putclose statement is a variant of the put statement, it is used to close a put file. The syntax is as follows:

putclose [file_name]  {item} {file_name item {item}};

If the file_name is missing, putclose will close the current file. Often the putclose statement is used in this simple form. Consider the following example:

File report;
put report;
put "This is a report."
putclose;

Note that the last line has the effect that the file report.put is closed. The file may be used again later. As usual, it has to be assigned as the current file and then it may be written to. By default, an existing file is overwritten (replaced). Alternatively, it may be appended to. For details see section Writing to an Existing Put File below. The briefest version of the above code is

File report; putclose report "This is a report."

Closing a put file is useful for example when writing a solver option file from within the GAMS model. Consider the following example, where we will create and close an option file for the solver MINOS.

File opt 'Minos option file'  / minos.opt /;
put opt 'Iteration limit          500'/
        'Feasibility tolerance    1.0E-7'/ ;
putclose opt;

Note that the file minos.opt is closed with a simple putclose statement. This will make the file available to be used by the solver. Observe that the code snippet above has to be placed before the respective solve statement.

Now, the last three lines in the example above may be reduced to two lines in the following way:

putclose opt 'Iteration limit          500'/
             'Feasibility tolerance    1.0E-7'/ ;

In this formulation, the putclose statement makes the file minos.opt current, writes to it and then closes the file after the last item has been written. Even though this is shorter, many users prefer the first formulation, since it is clearer.

Similarly to the put statement, the putclose statement may also be used to write to several files subsequently. The only difference to the put statement is, that the last current file will be closed after is has been written to.

Observe that GAMS automatically closes the put files of a model when it exits, even without a putclose statement.

Writing to an Existing Put File

When the put writing facility is used to write to a file that is not empty, by default, the existing content is overwritten (replaced). However, GAMS provides the option to append to the file instead via the file attribute append option (.ap). Consider the following example:

File append /append.dat/
put append;
put "This is the first line." /;
putclose;
append.ap = 1;
put append;
put "This is the second line.";

Note that the putclose statement in line 4 closes the file append.dat. The assignment in the next line instructs the put writing facility to append to the file if the file is opened again and written to. Thus the following output is generated:

This is the first line.
This is the second line

For information on file attributes in general, see section Put File Attributes below.

Put File Attributes

Put files have attributes that are mainly used to customize the format of put files, put file pages and output items. Put file attributes are accessed in the

following way:

file_name.attribute

Here file_name is the internal name of the put file and .attribute is the specific attribute that is to be accessed. We can also access the specific attribute of the current file by file.attribute. This useful in particular in batincludes that are used for multiple put files. Put file attributes may be used on the left-hand side and right-hand side of assignments. Consider the following example:

factors.nw = 10;
scalar x; x = factors.nw;

In the first line, the attribute numeric field width (.nw) of the put file with the internal name factors is assigned the value of 10. In the second line, the value of the attribute .nw is assigned to a scalar parameter x. In addition, put file attributes may be used as output items. For an example, see section Controlling the Cursor with File Attributes below. A complete list of put file attributes is given in Table 1.

Table 1: Put File Attributes

Put File Attribute Symbol Description Default Value Optional Values
Append option .ap Allows to append to an existing file, instead of replacing (overwriting) it. For more information, see section Writing to an Existing Put File. 0 0: Overwrite
1: Append
Bottom margin .bm Number of blank lines to be placed in the bottom margin of the page. The bottom margin lines are in adition to the lines specified with the file attribute page size (.ps). Note that this attribute is functional only if the value of the suffix print control (.pc) is zero. 0
Alphabetic case .case Specifies the case in which alphabetic characters are displayed in the put file, regardless of the input. Note that the meaning of 1 and 2 differs from the one for lcase. 0 0: Mixed case
1: Upper case
2: Lower case
Current column .cc This attribute may be used to return or set the current cursor column in the main window. For more information, see Current Cursor Column. 0 Value may be between 1 and the page width.
Current row .cr This attribute may be used to return or set the current cursor row in the main window. For more information, see Current Cursor Row. 1 Value may be between 1 and the page size minus any header rows, title rows and margins.
Number of put errors .errors See section Put Errors for details and an example. 0
Header current column .hdcc This attribute may be used to return or set the current cursor column in the header block. For more information, see Current Cursor Column. 0 Value may be between 1 and the page width.
Header current row .hdcr This attribute may be used to return or set the current cursor row in the header block. For more information, see Current Cursor Row. 1 Value may be between 1 and the size of the header.
Header last line .hdll This attribute may be used to return the number of the last line of the page header or reset the last row written in the page header. For more information, see Last Line Control. 0
Alphabetic label case .lcase Specifies the case in which alphabetic characters of a label are displayed in the put file, regardless of the original casing. 0 0: Mixed case
1: Lower case
2: Upper case
Label justification .lj Alignment of set labels. 2 1: Right, 2: Left, 3: Center
Last line .ll This attribute may be used to return the number of the last line of the main window or reset the last row written in the main window. For more information, see Last Line Control. 0
Left margin .lm Number of empty columns to be placed on the left of the page. 0
Last page .lp Returns the number of pages that are already in the put file. Note that setting this attribute to zero does not delete the pages that have been written to the file.
Label field width .lw Field width of set label output. For more information, see section Global Item Formatting Controls. 12 Values may be 0 or larger.
Number of decimals .nd Sets the number of decimals that are displayed for numeric items. A value of zero entails that fixed-format output will show the number rounded to the nearest integer. For an example, see section Global Item Formatting Controls. 2 Values may be between 0 and 20.
Numeric justification .nj Alignment of numeric output. 1 1: Right, 2: Left, 3: Center
Numeric round format .nr Selects the formatting used for numeric output. For example, one can choose to use scientific notation (i.e. E-format) for all numbers: this is especially useful for numbers so small that they display as only zeros in fixed format with the specified suffix number of decimals (.nd). For more information and an example, see section Global Item Formatting Controls. 1 0: Item is displayed in F or E format to fit given width and decimals.
1: Item is rounded to fit given width and decimals.
2: Item is displayed in E format to fit given width and decimals.
3: Item is rounded to fit given width.
4: Item is displayed in F or E format to fit given width.
Numeric field width .nw Field width of numeric output. For more information, see section Global Item Formatting Controls. 12 Values may be 0 or larger.
Numeric zero tolerance .nz Sets the tolerance level for which a number will be rounded to zero for display purposes. Note that in case this attribute is set to zero, rounding will be determined by the field width. 1.0e-10
PutDir becomes scratch directory .pdir Setting this to nonzero will result in resetting the PutDir to the scratch directory. Since the scratch directory is unknown while parameters are provided, this allows to use the scratch directory as PutDir. 0
Print control .pc Specifies the format of the put file. The options 4, 5, 6 and 8 create delimited files, which are especially useful when preparing output for the direct importation into other computer programs such as spreadsheets. For an example, see section Creating a Report for the Model MEXSS. 2 0: Standard paging based on the current page size. Partial pages are padded with blank lines. Note that the file suffix bottom margin (.bm) is only functional when used with this print control option.
1: FORTRAN page format. This option places the numeral one in the first column of the first row of each page in the standard FORTRAN convention.
2: Continuous page. This option is similar to .pc option zero, with the exception that partial pages in the file are not padded with blank lines to fill out the page.
3: ASCII page control characters inserted.
4: Formatted output; non-numeric output is quoted and each item is delimited with a blank space.
5: Formatted output; non-numeric output is quoted and each item is delimited with commas.
6: Formatted output; non-numeric output is quoted and each item is delimited with tabs.
7: Fixed width, fills up line with trailing blanks.
8: Formatted output; each item is delimited with a blank space.
Page size .ps Number of rows (lines) that may be placed on a page of the put file. It may be reset by the user at any place in the program.Observe that the specification of this attribute is only effective if the attribute print control (.pc) has a value other than its default value. Note that a put error will result if it is set to value that is smaller than the number of rows which have already been written to the current page. 60 Any value between 1 and 130.
Page width .pw Number of columns (characters) that may be placed on a single row of the page. It may be reset by the user at any place in the program. Note that a put error will result if it is set to value that is smaller than the number of columns which have already been written to the current page. Observe that if a value is specified that is above the upper limit, then the value will be reset to the upper limit. 32767 Any value between 1 and 32767.
Set value justification .sj Alignment of set values. 1 1: Right, 2: Left, 3: Center
Set value field width .sw Field width of set values. For more information, see section Global Item Formatting Controls. 12 Values may be between 0 and 20.
Text fill .tf Controls what content will be displayed, if there is no explanatory text for a set element, but a text item with suffix .te was specified. Note that options 4, 5 and 6 are useful if the output is intended to be included in a GAMS model at a later time. 2 0: Blanks are displayed.
1: Blanks will be displayed if the specified element does not exist, otherwise the name of the element will be displayed.
2: The name of the element is displayed.
3: The name of the element is displayed even if an explanatory text exists.
4: Like option 3, but displays output in quotes with comma separators.
5: Like option 4, but with periods as separators.
6: Like option 4, but with blanks as separators.
Text justification .tj Alignment of quoted text and explanatory text. 2 1: Right, 2: Left, 3: Center
Title current column .tlcc This attribute may be used to return or set the current cursor column in the title block. For more information, see Current Cursor Column. 0 Value may be between 1 and the page width.
Title current row .tlcr This attribute may be used to return or set the current cursor row in the title block. For more information, see Current Cursor Row. 1 Value may be between 1 and the size of the header.
Title last line .tlll This attribute may be used to return the number of the last line of the page title or reset the last row written in the page title. For more information, see Last Line Control. 0
Top margin .tm Number of blank lines to be placed at the top margin of the page. These lines are in addition to the number of lines specified with the file attribute page size (.ps). 0
Text field width .tw Field width for quoted text and explanatory text. Note that a value of zero forces the field width to match the exact size of the item being displayed. For more information, see section Global Item Formatting Controls. 0 Value may be 0 or larger.
Window size .ws Returns the number of rows that may be written to the main window given the number of rows in the title and header blocks and the page size. Note that this attribute is computed by GAMS and cannot be changed by the user.

Put File Pages

In this section we will discuss the structure of put file pages, in particular how to write titles and headers. In addition, we will give details on how users may control many aspects of the format of a put file page.

Adding Titles and Headers

Titles and headers are widely used when there are sections of a page that remain relatively constant throughout a document. There are three independent writing areas on each page of a put file: the title block, the header block and the main window. The layout of a page is shown in the following diagram.

   +-----------------+
   |   Title Block   | 
   +-----------------+
   |  Header Block   |
   +-----------------+
   |                 |
   |   Main Window   |
   |                 |
   +-----------------+

Note that the put statement writes to the main window. There are two variants of the put statement that write to the title block and header block respectively: the puttl statement and the puthd statement.

Observe that every page must have an entry in the main window. If a page has no output in its main window, the page will not written, regardless of whether there are output items in the title or header blocks. To force a page that has an empty window out to file, we recommend to simply write something innocuous to the window, like the following:

put ''; // space

This will initiate the main window of the page and thus the page will be written.

Further, note that the size of any area of a page is based on the number of lines written to it and the total number of lines has to be smaller than the specified page size. A new page is started automatically whenever a page is full. For details on manual pagination, see section The Putpage Statement: Controlling Paging. Each area of a page is maintained independently. For example, we may write to the title block first, then to the header block and then again to the title block. However once we have written to the main window, all subsequent entries to the title and header are written to the next page, not the current page.

The Puttl Statement: Writing to the Title Block

The puttl (or putTitle which can be used as a synonym) statement is a variant of the put statement that writes to the title block of a page. The syntax is as follows:

puttl [file_name] item {item};

The keyword puttl indicates that this is a puttl statement. The internal name of the file, file_name, may be omitted if the desired file is already current. Like in the put statement, the content that is written is one or more items, that may be a text string, a numerical value or a set value. For more information on items, see section Output Items below. Consider the following example:

puttl factors 'GAMS Put Example';

If this line is placed before the put statement that writes to the main window in the example above, then GAMS Put Example will be written to the title block.

Observe that title blocks often contain the name of the model and the number of the put page. Once content is placed in the title block, it will be repeated on every page unless it is modified or deleted. For details on how to write output like the page number to a put file, see section System Suffixes as Output Items below.

Note
If content has already been written to the main window of a page, the items in the puttl statement will appear in the title block starting from the next page. Thus the title has to be written before any entries in the main window if it is to appear on the current page.

Observe that if the title and header blocks contain too many lines given the page size, the page will overflow resulting in a put error.

The Puthd Statement: Writing to the Header Block

Like the puttl statement, the puthd (or putHeader which can be used as a synonym) statement is a variant of the put statement. Puthd statements write to the header block of a page. The syntax is as follows:

puthd [file_name] item {item};

The keyword puthd indicates that this is a puthd statement. The internal name of the file, file_name, may be omitted if the desired file is already current. Like in the put statement, the content that is written is one or more items. See section Output Items below for more information on items.

Observe that title blocks often contain a disclaimer or an instruction that is meant to be repeated on every page. Once content is placed in the header block, it will be repeated on every page unless it is modified or deleted.

Note
If content has already been written to the main window of a page, the items in the puthd statement will appear in the header block starting from the next page. Thus the header has to be written before any entries in the main window if it is to appear on the current page.

Observe that if the title and header blocks contain too many lines given the page size, the page will overflow resulting in a put error.

The Putclear Statement: Deleting Title and Header Blocks

The putclear (or putfmcl which can be used as a synonym) statement may be used to delete the title and header blocks. The syntax is simple:

putclear;

If the keyword putclear is inserted after a title and/or header block has been written, but before the main window has been written to, then the title and/or header blocks of the current page will be deleted. If the main window has already been written to, the the title and/or header block of the next and all subsequent pages will be deleted. Note that if the user wishes to delete either only the title or only the header block, the put file attributes .tlll and .hdll respectively may be set to zero. For more information, see Last Line Control.

The Putpage Statement: Controlling Paging

A new page is started automatically if the bottom of a page is reached. Alternatively, a new page may be started early using a variant of the put statement: the putpage statement. The syntax is as follows:

putpage [file_name] {item};

The keyword putpage indicates that this is a putpage statement. In its simplest form, the putpage statement consists of just the keyword. If only the keyword is used, the current page will be terminated. The optional file_name makes the put file with the internal name file_name current. If output items follow, they will be written to the current page and a new page will be made available for the next put statement.

Consider the following example:

File example / example.txt /;
putpage example "This text is placed in the main window and the page ends here.";
put "Here starts a new page in the same putfile."

Observe that three file attributes are helpful for manual paging: last page (.lp), window size (.ws) and last line (.ll).

Controlling the Format of a Put File Page

While GAMS established gracious defaults, there are numerous ways to customize the format of a put file page. In this section we will present the put file attributes that facilitate the control of various aspects of page formatting and ways to control the position of the cursor.

Controlling Page Size, Page Width and Margins

By default, 60 rows (lines) may be written on a put file page. At any point in the program the file attribute page size (.ps) may be used to reset this value. Note that the upper limit is 130. Note further, that a put error will result if the attribute is set to value that is smaller than the number of rows which have already been written to the current page. Observe that the specification of .ps is only effective if the attribute print control (.pc) has a value other than its default value.

By default, 255 characters (colums) may be written to each line of a put file page. Like the page size, the page width may be reset at any point. GAMS provides the file attribute page width (.pw) to do this. Note that the upper limit is 32767. Note further, that a put error will result if the attribute is set to value that is smaller than the number of columns which have already been written to the current page.

By default, put file pages do not have top, bottom and left margins. However, it is easy to specify blank lines for the margins with the file attributes top margin (.tm) and bottom margin (.bm). Note that the lines reserved for the margins are in addition to the value specified for the page size (.ps). Observe that the file attribute .bm is only functional if the value of the file attribute print control (.pc) is set to zero. In addition, the number of empty columns for left margins may be specified with the file attribute left margin (.lm)

Controlling the Print Format and the Use of Capital and Lower Case Letters

By default, GAMS prints continuous pages. However, the file attribute print control (.pc) offers several alternative options. For a full list, see the respective entry in Table Put File Attributes above. Note in particular that the options 4, 5, 6 and 8 create delimited files, which are useful for importing output to other applications like spreadsheets. For an example, see section Creating a Report for the Model MEXSS.

By default, alphabetic characters are displayed in the case they were inputted. Note that the value of 1 for the file attribute alphabetic case (.case) will display all output in capital letters, regardless of the input, and the value of 2 will result in only lower case letters being displayed.

Assume that we wish a put file report.txt to have pages with 72 characters to a row and 58 lines, ASCII page control characters to be inserted at the end of every page, an additional top margin of 6 lines and all output displayed in upper case. The following assignments will implement these specifications:

File report /report.txt/;
report.pw = 72; report.ps = 58; report.pc = 3;
report.tm = 6;  report.case = 1;

Controlling the Cursor On a Page

There are three ways to control the position of the cursor: with cursor control characters, with the system attribute system.tab and with file attributes. In this section we will give details on cursor control characters, while inserting tabs and file attributes that are relevant for cursor control will be discussed in the next two sections.

By default, the cursor is moved to the space immediately following the last character written. GAMS provides the control characters listed in Table 2 to specify another position for the cursor.

Symbol Description
#n Move cursor position to row n of current page.
@n Move cursor position to column n of current line.
/ Move cursor to first column of next line.

Table 2: Cursor Control Characters

Note that the numeric value n that follows the characters # and @ may be any expression or symbol with a numeric value. An example is given below. Note further, that the character @ is commonly used to align columns if the column headings have different widths. For an example, see section Creating a Report for the Model MEXSS. Observe that the character @ may be used to overwrite output items that were written earlier. Consider the following example:

File out /out.dat/;
put out;
put 'Good' @3 'morning everybody!';

This code snippet will generate the following output:

Gomorning everybody!

Observe that cursor control characters are also used and discussed in the example at the beginning of this chapter.

Controlling the Cursor with a System Attribute: Inserting Tabs

The system attribute system.tab may be used to insert tabs. Consider the following example:

File test / test.dat /;
put test;
put "1" system.tab "2" system.tab "3" ;

The put file will contain the following line, separating 1, 2, and 3 by tabs.

1   2   3

Controlling the Cursor with File Attributes

In addition to cursor control characters and tabs, the position of the cursor may be controlled using the file attributes that will be discussed in this section. These file attributes refer to the current column, the current row and the last line in the title block, the header block and the main window.

Current Cursor Column

As there are three independent writing areas on each put file page, there are three file attributes that refer to the current column. They are listed in Table 3.

Symbol Description
.cc Current cursor column in the main window.
.hdcc Current cursor column in the header block
.tlcc Current cursor column in the title block

Table 3: File Attributes for the Column Position of the Cursor

Note that the values for these attributes are numeric and they are updated only at the end of a put statement. Consequently, their values will remain constant during a put statement, even if multiple items or lines are displayed. Observe that the attributes may be used on the left-hand side and on the right-hand side of an assignment statement to set the current column position and return it respectively.

The following example illustrates the updating of the cursor control suffixes and the use of cursor control characters. The example is trivial but instructive:

Scalar  lmarg  'left margin'   /6/;
File out; put out;
put @(lmarg+2) 'out.cc = ', out.cc:0:0 '  ';
put @out.cc 'x'/ @out.cc 'y'/ @out.cc 'z  ';
put 'out.cc = ' out.cc:0:0;

The resulting file out.put will contain the following lines:

         out.cc = 1  x
                     y
                     z  out.cc = 23

Note that the scalar lmarg is set to a specific value that will be used as an alignment tab. Symbols which hold common alignment values such as margins or tabs are often useful for large structured documents. The first put statement uses the cursor control character @ to relocate the cursor to column 8 where the text item out.cc and the respective value for the file attribute .cc are displayed. Note that the numerical value of the file attribute is formatted locally with the effect that only integers are displayed. We observe that at the start of the first put statement the file attribute out.cc equals 1.

The second put statement illustrates the updating of the cursor control suffixes by writing the letters x, y and z on three different lines. Each is preceded by moving the cursor to the value of the file attribute .cc. Note that at the end of the first put statement the value of out.cc is updated to 20. Hence, out.cc is 20 at the start of the second put statement. As a single put statement is used to write all three letters, the value of out.cc remains constant and thus the letters are written in the same column. At the end of the second put statement the value of out.cc value is updated to 23 (observe that there are two blank spaces after the letter z).

The third put statement writes the current value of the file attribute out.cc, which is the value at the start of the put statement.

Current Cursor Row

As there are three independent writing areas on each put file page, there are three file attributes that refer to the current row. They are listed in Table 4.

Symbol Description
.cr Current cursor row in the main window
.hdcr Current cursor row in the header block
.tlcr Current cursor row in the title block

Table 4: File Attributes for the Row Position of the Cursor

Note that the values for these attributes are numeric and they updated only at the end of a put statement. Consequently, their values will remain constant during a put statement regardless of how many rows are displayed. Observe that the attributes may be used on the left-hand side and on the right-hand side of an assignment statement to set the current row and return it respectively. The files attributes for the row postion of the cursor behave similarly to those for the column position.

Last Line Control

Like the file attributes for the current column and row position, the file attributes for the last line have three variants, one for each writing area. They are given in Table 5.

Symbol Description
.ll Last line in the main window
.hdll Last line in the header block
.tlll Last line in the title block

Table 5: File Attributes for the Last Line

Note that unlike the row and column controls, the last line attributes are updated continuously. Last line attributes are especially useful for modifying the three writing areas of a page. They may be used on the left-hand side and on the right-hand side of an assignment statement to set the current last line and return it respectively. Rows will be deleted if the last line attribute is set to a value that is lower than the current row.

Attention
The file attributes .tlll and .hdll may not hold values applicable to the current page, because when the title or header blocks are modified, they will correspond to the title or header blocks of the next page if the main window has been written to on the current page.

As mentioned above, in addition to determining the last line in a writing area, these file attributes may be used to delete lines within a writing area. In the following example, the header block will be completely deleted by resetting the attribute .hdll to zero.

File out;
puthd out 'This header statement will be eliminated';
out.hdll = 0;

Note that a header is written initially. However, by changing the attribute .hdll to zero, the cursor is reset to the top of the header block. As a result, the header will not be written unless something new is added to the header block.

Output Items

Output items are the items in the put statement that are written to the put file. They may be a text, a numerical value or a set value. In this section we will provide more information on these three types of items. Observe that system suffixes and command line parameters are either text strings or have a numerical value. They may also be used as output items.

Text Items

Text items may be a quoted text, an explanatory text of identifiers and labels or names of set elements. In this section we will give details on each of these text items. In addition, text items may be system attributes or command line parameters. For these text items, see sections System Suffixes as Output Items and Command Line Parameters as Output Items respectively. Details on default field widths and alignments for text items and global and local customizing controls are given in section Customizing the Format of Output Items.

Text Items: Quoted Text

The simplest text output item is a quoted text. A quoted text is any combination of characters or numbers set apart by a pair of single (') or double (") quotes with each the items needing to use a matching pair. Thus the following three lines are all exactly equivalent.

put 'Run on ' system.date ' using source file ' system.ifile;
put "Run on " system.date " using source file " system.ifile;
put 'Run on ' system.date " using source file " system.ifile;

Note that there is a limit on the length of all output items: output items may not exceed the page width. In case this limit is exceeded, a put error will be reported in the listing file. Put errors are introduced and discussed in section Put Errors.

Text Items: Identifier Attributes

Text items like the explanatory text of an identifier, the name of a set element and the explanatory text of a set element are specified with identifier attributes. The identifier attributes are listed in Table 6.

Identifier Attribute Symbol Description
Explanatory text of an identifier .ts Displays the descriptive text associated with any identifier (like a set, a parameter, a variable, an equation, a model).
Name of a set element .tl Displays the names of the individual elements of a set. Observe that the put statement must be embedded in a loop statement, where the respective set is the looping set or the set is a singleton set.
Explanatory text of a set element .te(index_list) Displays the explanatory text associated with a set element. Note that this attribute requires the specification of a driving index. If the set is a simple set, the set name itself will have to be specified as index (see example below). If the set is defined over an index, then the index or a subset of the index may be specified. A special case arises in case users wish to gain access to the explanatory text that appears in the definition of another set (see example below). Observe that if there is no explanatory text for a set element in the set definition, then either the name of the set element (default) or a blank will be displayed, depending on the value of the file attribute text fill (.tf). Note that with .tf=3 even if an explanatory text exists, the name of the element will be displayed. Observe that the put statement must be embedded in a loop statement, where the respective set is the looping set or the set is a singleton set.
Indexed identifier with label combination .tn Displays the name of the identifier with all individual label combinations. Observe that the put statement must be embedded in a loop statement, where the respective index is the looping set or the set is a singleton set. See example below.

Table 6: Identifier Attributes

Consider the following example:

Set  i     master set of sites / i1  Seattle, i2  Portland
                                 i3  San Francisco, i4  Los Angeles, i5 /
     j     subset of sites     / i3 * i5 / ;

File out; put out i.ts /;
loop(i, put i.tl, i.te(i) /);

The resulting put file out.put will contain the following output:

master set of sites
i1          Seattle
i2          Portland
i3          San Francisco
i4          Los Angeles
i5          i5

Note that the explanatory text of the set i is written first, followed by the label names of the set i and their respective explanatory texts. Note further that even though the set i does not have an index (it is a simple set), an index is required for the attribute .te. In this case we specify as index the set itself. Observe that the set element i5 was defined without an explanatory text. By default, GAMS inserts the name of the element instead. This may be changed by alterning the code in the following way:

put out i.ts /;
out.tf = 0;
loop(i, put i.tl, i.te(i) /);

Note that we assign the value of zero to the file attribute text fill (.tf) before the put statement where one of the items refers to the explanatory text of a set element. As a result, a blank will be displayed where the explanatory text of the set element i5 is supposed to appear:

master set of sites
i1          Seattle
i2          Portland
i3          San Francisco
i4          Los Angeles
i5

Assume we also wish to display the elements of the set j and their explanatory texts. We could just adapt the code above for the set j and add the following two lines:

put / j.ts /;
loop(j, put j.tl, j.te(j) /);

These lines will result in the follwing output to be appended to the put file:

subset of sites
i3
i4
i5

Note that the explanatory text associated with the set elements is missing, since there is no explanatory text for the elements in the definition of the set j and the value of zero for text fill is still valid. However, we may gain access to the explanatory text of the set elements in the definition of the set i in the following way:

put / j.ts /;
loop(j, put j.tl, i.te(j) /);

Note that the the specification i.te(j) singles out the explanatory texts of the elements of the set i that are also elements of the set j. Hence we will obtain the desired output:

subset of sites
i3          San Francisco
i4          Los Angeles
i5

The following example illustrates the use of the identifier attribute .tn. The model [MEXSS] is a simplified representation of the Mexican steel sector, where five steel plants have to satisfy the demand for steel in three markets. Each steel plant i has several productive units m and the capacity of every unit in every plant is specified with the parameter k(m,i). Assume we wish to write to a put file a list of all nonzero capacities. We could add the following code to the model:

File out /out.dat/; 
put out 'Capacity (in metric tons)' / /;
loop((m,i)$k(m,i),
   put k.tn(m,i), @30 '=' k(m,i) /;
)

Note that we restrict the loop statement with a logical condition to exclude entries of zero. The put file out.dat will contain the following lines:

Capacity (in metric tons)

k('blast-furn','ahmsa')      =        3.25
k('blast-furn','fundidora')  =        1.40
k('blast-furn','sicartsa')   =        1.10
k('openhearth','ahmsa')      =        1.50
k('openhearth','fundidora')  =        0.85
k('bof','ahmsa')             =        2.07
k('bof','fundidora')         =        1.50
k('bof','sicartsa')          =        1.30
k('direct-red','hylsa')      =        0.98
k('direct-red','hylsap')     =        1.00
k('elec-arc','hylsa')        =        1.13
k('elec-arc','hylsap')       =        0.56

Observe that a more elaborate report for the model [MEXSS] is given in section Creating a Report for the Model MEXSS at the end of this chapter. The identifier attribute .tn is particularly useful when creating scalar EMP info files.

Text Items: Text Blocks

The easiest way to write blocks of text to a put file is with the dollar control options $onPut and $offPut. Consider the following example:

File fx; put fx;
$onPut
We will write four
lines of text to the put file,

including a blank line.
$offPut

The put file fx.put will contain the following lines.

We will write four
lines of text to the put file,

including a blank line.

Note that these dollar control options have a variant that allows the substitution of compile-time variables. For details see the description of $on/offPut.

Numeric Items

Numeric items may be values of parameters, variable and equation attributes or model attributes and expressions of such elemens. These numeric items will be discussed in this section. In addition, numeric items may be command line parameters. For these numeric items, see section Command Line Parameters as Output Items. Details on default field widths and alignments for numeric items and global and local customizing controls are given in section Customizing the Format of Output Items.

Numeric Items: Parameters and Functions

In our first example in this chapter, one of the output items was the parameter f. For convenience, we repeat the respective code below:

put 'Freight cost  ', f;

Note that the simple name of the parameter is sufficient. In the same example we also had two parameters that were defined over an index: a(i) and b(i). The respective lines of code follow:

loop(i, put @3, i.tl, @15, a(i)/);
* ...
loop(j, put @3, j.tl, @15, b(j)/);

Note that indexed parameters must be specified with their index and a put statement with an indexed parameter has to be embedded within a loop structure.

Numeric Items: Variable and Equation Attributes

Recall that data associated with variables and equations is stored in variable attributes and equation attributes respectively. A full list is given in sections Variable Attributes and Equation Attributes.

Suppose we wish to generate a report with the demand for each market in the transportation model [TRNSPORT], the satisfied demand after solution of the model and the marginal cost of meeting the demand. Recall that the demand data for each market is saved in the parameter b(j) and the relationship between shipment quantities and demand is encoded in equation demand(j). The following code will generate the desired report:

File report /report.dat/; put report;
loop(j,
   put 'Report for ' j.tl /
       'Demand'                          @35 b(j):10:0        /
       'Demand satisfied'                @35 demand.l(j):10:0 /
       'Marginal Cost of meeting demand' @35 demand.m(j):10:2 / /;
);

Note that we use three numeric output items: the parameter b(j), the level value of the equation demand.l(j) and the marginal value of the equation demand.m(j). Note further, that all three items are indexed over the set j and thus the put statement has to be placed within a loop statement. Observe that we customize the formatting of the items. For details see section Local Item Formatting Controls. The put file report.dat will contain the following output:

Report for New-York
Demand                                   325
Demand satisfied                         325
Marginal Cost of meeting demand         0.23

Report for Chicago
Demand                                   300
Demand satisfied                         300
Marginal Cost of meeting demand         0.15

Report for Topeka
Demand                                   275
Demand satisfied                         275
Marginal Cost of meeting demand         0.13

Numeric Items: Model Attributes

GAMS models have many model attributes. An introduction and a complete list is given in section Model Attributes. While in principle all model attributes may be used as output items, the attributes .modelStat and .solveStat with their string valued counter parts .TModStat and .TSolStat are used most frequently. They refer to the model status and solver termination condition after solution respectively. For a complete list of their values, see sections Model Status and Solver Status.

Suppose we wish to generate a report that contains the time it took to execute the solve statement of the transportation model [TRNSPORT], the objective value and the corresponding string valued model and solver status. Recall that the name of the model is transport. The following code will generate the desired report:

File report /report.dat/; put report;
put 'elapsed time in seconds of solve statement : ' transport.etSolve:0 /
    'objective value:                           : ' transport.objVal:0  /
    'model status:                              : ' transport.tmodstat  /
    'solver status:                             : ' transport.tsolstat  ;

Observe that we customize the formatting of the first two items. For details see section Local Item Formatting Controls. The put file report.dat will contain the following output:

elapsed time in seconds of solve statement : 0.11
objective value:                           : 153.68
model status:                              : 1 Optimal
solver status:                             : 1 Normal Completion

Set Value Items

There are only two set values: YES and NO. The set value will be YES if a label is an element of a specific set and NO otherwise. Consider the following example which is adapted from the example in section Text Items: Identifier Attributes above:

Set  i     master set of sites / i1  Seattle, i2  Portland
                                 i3  San Francisco, i4  Los Angeles, i5 /
     j     subset of sites     / i3 * i5 / ;

File out2 / out2.dat /;
put out2 j.ts /;
out2.tf = 0;
loop(i, put i.tl, j(i), '   ',  i.te(i) /);

Note that within the loop structure, the put statement writes each element of the set i, determines whether it is a member of the set j and displays the respective set value, and adds the explanatory text for the label. Hence the resulting put file out2.dat will look as follows:

subset of sites
i1      NO  Seattle
i2      NO  Portland
i3     YES  San Francisco
i4     YES  Los Angeles
i5     YES

Observe that the set values in the second column reflect set membership of the set j. Observe further, that the missing explanatory text for label i5 is displayed as a blank, since the value of the file suffix text fill (.tf) equals zero.

System Suffixes as Output Items

System suffixes contain information about a GAMS run, they are introduced and discussed in chapter System Attributes. System suffixes may be used as output items in the context of put statements. They are accessed in the following two ways:

system.attribute
%system.attribute%

Here system is a keyword and .suffix is a specific system suffixes. Note that system.suffix references the execution-time version (which can be of type string or numeric) of the system suffixes and %system.suffix% (which is interpreted by the compiler as part of the input string) references the compile-time version. For further details on the difference between execution-time and compile-time system suffixes, see chapter System Attributes. A complete list of all system suffixes is given in section List of all System Suffixes, in Table 7 we present a list of the most common system suffixes.

System Attribute Description
.date Program execution date
.ifile Input file name
.ofile Output file name
.rdate Restart file date
.rfile Restart file name
.sfile Save file name
.title Title of the model as specified by $title

Table 7: A Selection of System Suffixes

To illustrate how system suffixes are used, assume we wish to include the program execution date, the name of the input (GAMS) file, and the page number of the current put statement in the input file to the report results.dat in section A First Example above. We will modify the code in the following way:

File factors /factors.dat/, results /results.dat/;
* ...
put results;
puthd 'Program Execution Date:', @26, system.date /
    'Source File:', @26, system.ifile /;
    'Page Number:', @26, system.page / /;
put 'Transportation Model Results' / / ;
loop((i,j), put i.tl, @12, j.tl, @24, x.l(i,j):8:4 /);

The file results.dat will then contain the following lines:

Program Execution Date:  01/13/17
Source File:             C:\Documents\GAMS\Models\trnsport.gms
Page Number:             1

Transportation Model Results

Seattle    New-York     50.0000
Seattle    Chicago     300.0000
Seattle    Topeka        0.0000
San-Diego  New-York    275.0000
San-Diego  Chicago       0.0000
San-Diego  Topeka      275.0000

Note that the date is given in the American format: month/day/year and can be reset via the command line parameter DFormat. Also note that including the page number in the header block of a put file will have the effect that the pages of the put file will be numbered. Of course, this is especially useful for longer put files.

It is also possible to read environment variables at execution time in a put context using sysEnv.name as in the following example:

$setEnv hello world
put_utility 'log' / sysEnv.hello;

If the environment variable queried is not defined, the result depends on the value of the command line parameter stringChk.

Command Line Parameters as Output Items

Command line parameters may also be used as output items. They are introduced and discussed in chapter The GAMS Call and Command Line Parameters. For an overview of all GAMS command line parameters, see section List of Command Line Parameters. Like system suffixes , command line parameters are referenced in the context of a put statement either compile-time strings or in an execution time version as follows:

put "%gams.parameter%";
put gams.parameter;

Here parameter is a GAMS command line parameter. To illustrate how command line parameters are used, assume we wish to include the page size of the input file, the name of the input file and the name of the restart file in the report results.dat in section A First Example above. We will modify the code in the following way:

File factors /factors.dat/, results /results.dat/ ;
* ...
put results;
put 'Transportation Model Results'// ;
loop((i,j), put i.tl, @12, j.tl, @24, x.l(i,j):8:4 //);
put / "Page size         = %gams.ps%" 
    / "GAMS input file   = %gams.input%" 
    / "GAMS restart file = %gams.restart%";

The last three lines of the put file results.dat follow:

Page size         = 58
GAMS input file   = C:\Documents\GAMS\Models\trnsport.gms
GAMS restart file =

Note that there was no restart file in the GAMS run, thus the value for %gams.restart% is the empty string.

In this example it actually makes no difference if one uses the compile- or execution time version to query the value of a command line parameter. This might be different, when doing the compile and execution phase separately, e.g. when using remote execution. Here is a toy example showing the difference:

$onEchoV > logScrDir.gms
put_utility 'log' / '%gams.scrDir%';
put_utility 'log' / gams.scrDir;
$offEcho

$call gams logScrDir.gms a=c s=1 keep=1
$call gams logScrDir.gms a=e r=1 

In the log, one will see that %gams.scrDir% is evaluated in the first run at compile time already, while gams.scrDir is evaluated at execution time in the second run:

--- logScrDir.gms(1) 3 Mb
    C:\Data\t m p\225d\
--- logScrDir.gms(2) 3 Mb
    C:\Data\t m p\225e\

Customizing the Format of Output Items

GAMS provides global and local controls to modify the default format of output items. Global controls are set with file attributes and apply to all output items in a put file that follow the assignment of a file attribute. Local controls are used to change the format of only one specific output item.

Global Item Formatting Controls

The alignment (justification) of the field and the width of the field may be modified for all types of output items. The attributes that control field alignment are listed in Table 8. Note that possible values are 1 (right), 2 (left) and 3 (center).

Type of Output Item Symbol Default Value
Text items: set labels .lj 2: Left
Text items: quoted and explanatory text .tj 2: Left
Numeric values .nj 1: Right
Set values .sj 1: Right

Table 8: File Attributes for Field Alignment

The width of the field is specified with the number of spaces to be allocated. The attributes that control field width are liste in Table 9.

Type of Output Item Symbol Default Value
Text items: set labels .lw 12
Text items: quoted and explanatory text .tw 0
Numeric values .nw 12
Set values .sw 12 (maximum 20)

Table 9: File Attributes for Field Width

Note that the value of zero signifies a variable field width, matching the the exact size of the item being displayed. If a text output item does not fit within the specified field, truncation will occur to the right. For numeric output items, the decimal portion of a number is rounded or scientific notation is used to fit the number within the given field. If a number is still too large, asterisks will replace the value in the output file.

For example, the following assignment will set the field width for numeric items in the file out.put globally to 4:

out.nw = 4;

In addition to field alignment and field width, there are further global controls that apply to numeric output items only. They are given in Table 10.

File Attribute Symbol Description Default Value Optional Values
Number of decimals .nd Sets the number of decimals that are displayed for numeric items. A value of zero entails that fixed-format output will show the number rounded to the nearest integer. 2 Values may be between 0 and 20.
Numeric round format .nr Selects the formatting used for numeric output. For example, one can choose to use scientific notation (i.e. E-format) for all numbers: this is especially useful for numbers so small that they display as only zeros in fixed format with the value specified for number of decimals (.nd). The default rounding format will treat small values in this way, but in many situations, it is important to be aware that such small values exist. 1 0: Item is displayed in F or E format to fit given width and decimals.
1: Item is rounded to fit given width and decimals.
2: Item is displayed in E format to fit given width and decimals.
3: Item is rounded to fit given width.
4: Item is displayed in F or E format to fit given width.
Numeric zero tolerance .nz Sets the tolerance level for which a number will be rounded to zero for display purposes. Note that in case this attribute is set to zero, rounding is determined by the field width. 1.0e-10

Table 10: File Attributes for Global Format Control Specific to Numeric Items

Note that numeric items are always formatted to fit within the specified width limit, but their display may use fewer characters. Similarly, for some values of .nr, the number of digits shown is limited by the choice of the .nd parameter, but fewer digits may be shown. At most 17 significant digits are included - this is enough to represent any double-precision value unambiguously, i.e. as a base-10 string that converts back into this same double. With this in mind, any number can be represented fully in E-format using at most 24 digits, e.g. -1.25E+102.

With .nr=0, the formatting routines honor the decimals limit. Values closer to 1 are displayed in fixed format. Values so small they would display only zeros in fixed format are displayed in E-format, as are values too large for the width limit. Formatting with .nr=1 is similar, but small values are shown in fixed format even if they show all zeros. With .nr=2 E-format is used for all values, with the number of trailing digits respecting the decimals limit .nd. The decimals limit is ignored for .nr=3, and fixed format is used unless the value is so large that E-format output is shorter. Finally, .nr=4 is intended to be used with larger output widths, e.g. 18 or 24, in order to show values of all magnitudes in as full a precision as possible: it ignores the decimal limit and uses whatever format allows more significant digits in the specified width.

The following example illustrates the result of different combinations of numeric file attributes. Note that we will use five combinations of the file attributes .nd, .nz, .nr and .nw to display three numerical values.

Set  c  suffix combinations  / comb1 * comb9 /
     v  value indices        / value1 * value5 / ;

Table   suffix(c,*)   numeric suffix combinations
           nd      nz      nr      nw
comb1       3       0       0      12
comb2       3    1e-5       0      12
comb3       3    1e-5       1      12
comb4       8       0       0      10
comb5       6    1e-5       1      12
comb6       0    1e-5       1      12
comb7      10       0       2      18
comb8       0       0       3      14
comb9       0       0       4      18 ;

Parameter  value(v)   test values
      / value1     1.2345678901e14
        value2     [pi]
        value3      -0.1234567
        value4       0.0001234567
        value5       1.234567e-13 / ;

File out; put out;
out.nj=2; out.lw=10; out.cc=11;
loop (v, put v.tl:21);
loop (c,
  out.nd=suffix(c,"nd");
  out.nz=suffix(c,"nz");
  out.nr=suffix(c,"nr");
  out.nw=suffix(c,"nw");
  put / c.tl;
  loop (v,
    put @(ord(v)*21-10), value(v)
  )
);

Observe that we have chosen to align the values to the left. This will enhance readability as the model loops through the suffix combinations that entail different field widths. The resulting output file out.put follows:

          value1               value2               value3               value4               value5
comb1     1.234568E+14         3.142                -0.123               1.2345670E-4         1.234567E-13
comb2     1.234568E+14         3.142                -0.123               1.2345670E-4         0.000
comb3     1.234568E+14         3.142                -0.123               0.000                0.000
comb4     1.2346E+14           3.14159265           -0.1234567           0.00012346           1.2346E-13
comb5     1.234568E+14         3.141593             -0.123457            0.000123             0.000000
comb6     1.234568E+14         3                    -0                   0                    0
comb7      1.2345678901E+14     3.1415926536E+00    -1.2345670000E-01     1.2345670000E-04     1.2345670000E-13
comb8     1.23456789E+14       3.141592653590       -0.12345670000       0.000123456700       0.000000000000
comb9     123456789010000      3.141592653589793    -0.12345678          1.234567E-4          1.234567E-13

Note that in comb1 the display of values switches to the exponential notation when the value becomes smaller than the number of decimal places allowed. This is a result of .nr=0. Note further, that value4 is greater than the zero tolerance level (.nz), but smaller than the number of decimals allowed (.nd) in both, comb2 and comb3. However, .nr=0 results in the exponential notation in the display of comb2, while .nr=1 has the effect that this small value is rounded to zero. Observe that in comb6 fixed-format is used whenever allowed by the width limit, and in these cases the output is rounded to integer because .nd is set to zero. With comb7 E-format is used in all cases: a leading space is added for positive values and a minus sign to negative values, and the magnitude is indicated with an explicit plus/minus and two digits (three if necessary). With comb8 we see fixed-format used whenever possible and as many digits (significant or not) as allowed by the width. With comb9 we see only significant digits, with the format chosen to allow the display of as many digits as possible.

Local Item Formatting Controls

The local item formatting controls allow to format specific output items. Note that local formatting overrides global format settings. The syntax is as follows:

item:{<>}width:decimals;

Here item is the output item, followed by a colon, an alignment (justification) symbol, the field width, a colon and the number of decimals to be displayed. Note that the limit on the number of the decimal places is only valid for numeric output. Note further, that if a component of the local formatting feature is omitted, then the respective global formatting settings will be used. The local alignment symbols are listed in Table 11.

Symbol Alignment
> Right
< Left
<> Center

Table 11: Local Alignment Symbols

Observe that similar to global formatting, a field width of zero means that the field width will be variable, depending on the item to be displayed.

The following example serves as illustration. Observe that we use end-of-line comments to annotate the code.

File out; put out;

$eolCom //
Set       i    / i1*i3 /;
Parameter d(i) / i1 1426, i2 1347, i3 900 /;
Scalar    f    / 17.6745 /;

loop(i, put d(i):0:0 /);  // default justification and a field width
                          // of variable size with no decimals

put / 'Right Justified Comment':>50 
    / 'Center Justified Truncated Comment':<>20;

put / / f:<6:2;           // left aligned scalar with 6 spaces for field width
                          // and two decimals

The Put_Utility Statement

The put_utility statement is a variant of the put statement that may be used to execute external programs. The syntax is as follows:

put_utility [file_name] 'command' / 'arguments' {/ 'command' / 'arguments'};

The keyword put_utility and its synonym put_utilities indicate that this is a put_utility statement. The keyword is followed by the internal name of an external file, file_name. Note that file_name may be omitted. It is not required for the put_utility statement but might be used to activate a file to be used with following put statements. Command denotes one of the commands listed in Table 12 below. Commands are followed by a slash and their respective arguments. Observe that a put_utility statement may contain multiple command / argument pairs. An example is given below.

The following simple example illustrates the put_utility statement:

File test / test.txt /;
put test "This is the original file."

put_utility 'ren' / 'test.dat';
putclose "This is the renamed file.";
test.ap = 1;
put "Write to the renamed file.";

Note that first the put file test.txt with the internal name test is defined, made current and written to. Then the put_utility statement uses the command ren to rename the current put file. The new name is test.dat and the internal name test will from now on reference the new file test.dat. However, the original file test.txt is not deleted. Hence, the code above will create two external files: test.txt and test.dat. The file test.txt will contain the following line:

This is the original file.

The file test.dat will have the following content:

This is the renamed file.
Write to the renamed file.
Note
If Put File Attributes are specified, they are also considered for the put_utility commands and arguments. This could lead to surprising results in some cases, like in this example:
File test / test.txt /;
test.pc = 5;
put test "This is the original file."

put_utility 'ren' / 'test.dat';
putclose "This is the renamed file.";
This will trigger the following errors:
*** Error at line 5: Put_Utilities: Unknown request ""ren""
*** Error at line 5: Put_Utilities: Unknown request ""test.dat""
The problem is, that test.pc = 5; puts quotes around non-numeric output, and thus "ren" (including the quotes) is not recognized as command anymore. To overcome this issue test.pc should be set back to default for the ren command like this:
File test / test.txt /;
test.pc = 5;
put test "This is the original file.";

test.pc = 2;
put_utility 'ren' / 'test.dat';
test.pc = 5;
putclose "This is the renamed file.";

We will present a list of all commands and their arguments in Table 12 and give examples for most commands below.

Table 12: List of Commands and their Arguments

Command Description of Command Description of Arguments
assignText Allows to set the explanatory or label text of a singleton set element. See example below. Name of singleton set symbol and text.
click Adds a clickable file reference to the process window of the IDE. See example below. File name of the file to which the reference will point.
dropEnv Removes an environment variable at execution time. Name of the environment variable.
ECArguments Allows to set the arguments for execution time embedded code execution. See example in section Embedded Code at Execution Time. Text for the embedded code argument.
exec Passes a command to the operating system for execution. GAMS will wait until the command is executed. See example below. Note that the distinction between exec and shell is technical and may be operating system specific. Typically, the ability to use redirect of standard input output and the error console is involved. Command to be executed with arguments.
exec.aSync Passes a command to the operating system for execution. However, GAMS will not wait until the command is executed. Command to be executed with arguments. Job control is handled identical to jobs spawned via execute.async.
exec.aSyncNC Passes a command to the operating system for execution using a different console than the parent process (Windows only). GAMS will not wait until the command is executed, thus using multiple processors is possible. Job control is handled identical to jobs spawned via execute.async. Command to be executed with arguments.
exec.checkErrorLevel Passes a command to the operating system for execution. GAMS will wait until the command is executed, raises an execution error and aborts the execution, if the errorLevel returned is not 0. Command to be executed with arguments.
gdxIn Accesses the GDX file specified in the argument. A subsequent directive execute_load or execute_loadpoint without a specified file name will unload data from the GDX file thus accessed. See example below. Name of the GDX file that data will be loaded from.
gdxOut Creates a new GDX file or accesses an existing GDX file specified in the argument. A subsequent directive execute_unload without a specified file name will write to the GDX file thus created or accessed. Note that if an existing GDX file is accessed, it will be overwritten. See example below. Name of the GDX file to which data will be unloaded.
glb Used by GAMS to facilitate building the model library - not intended for users.
htm Used by GAMS to facilitate building the model library - not intended for users.
inc Includes the contents of an external file in the currently active put file. See example below. File name of external file.
incLog Includes the contents of an external file in the currently log file . See example below. File name of external file.
incMsg Includes the contents of an external file in the currently listing file . See example below. File name of external file.
incMsgLog Includes the contents of an external file in both, the log file and the listing file. See example below. File name of external file.
log Sends a message to the log file. See example below. Text of message.
msg Sends a message to the listing file. See example below. Text of message.
msgLog Sends a message to both, the log file and the listing file. See example below. Text of message.
ren Creates a new external name for the current put file. The internal name will reference the new external file. Any subsequent put statements will write to the new file. See the simple example above and a more complex example below. External file name.
save Writes a save file of the current state of execution. Name of save file.
setEnv Sets an environment variable at execution time. Name of the environment variable and its value.
shell Passes a command to the command shell processor, where it is processed. The processed form of the command is then passed to the operating system for execution. See example below. Note that the distinction between shell and exec is technical and may be operating system specific. Typically, the ability to use redirect of standard input output and the error console is involved. Command to be executed with arguments.
shell.checkErrorLevel Passes a command to the command shell processor, where it is processed. The processed form of the command is then passed to the operating system for execution. GAMS checks the errorLevel returned implicitly, raises an execution error and aborts the execution, if is not 0. Command to be executed with arguments.
solver Selects a solver for a given or all model types (use *) by name. See example below. Model type or * and solver name.
stdOut Sends a message to stdOut independent of the log file. Text of message.
stdErr Sends a message to stdErr independent of the log file. Text of message.
title Changes the title on the DOS window. New name for window.
winMsg Sends a message to a window on a Windows machine. For examples, see models [ASYNNTRP] and [MRW01] in the GAMS Test Library. Window name and message.
xsave Writes a compressed save file of the current state of execution. Name of compressed save file.

In the remainder of this section we will present examples.

Exec: Creating Empty Files by Executing External Program touch

Consider the following example:

Set i / 1*3 /;
loop(i, put_utility 'exec' / 'touch ' i.tl:0 '.txt');

Note that the command to be executed is touch. Thus this code snippet will create three empty files called 1.txt, 2.txt and 3.txt.

Exec and Ren: Creating Directories and Renaming Files

Consider the following example:

File test / test.txt /; put test;
Set i / i01*i07 /;

loop(i,
   put_utilities 'exec' / 'mkdir ' 'test-':0 i.tl:0;
   put_utilities 'ren' / 'test-':0 i.tl:0 '%system.dirSep%test-':0 i.tl:0 '.txt':0 ;
   put 'this should be ' i.tl );

Observe that as the loop is executed, the first put_utitily statement will create seven subdirectories called test-i01, ..., test-i07. The second put_utility statement will create a text file for each of the new subdirectories. The text file in subdirectory test-i01 is called test-i01.txt, the text file in subdirectory test-i02 is called test-i02.txt, etc. The put statement in the last line will write to each text file. For example, the following line will be generated for the text file test-i01.txt:

this should be i01

Note that at the end of the loop, the external file associated with the internal file name test is the put file test-i07.txt, since this file was the last current put file.

Inc: Including the Content of a File

In this example, we first create the external file recall.txt, write to it and close it. Then we create a new external file called report.dat. In a third step we include the content of the first file in the second file.

File recall /recall.txt/;
putclose recall "I am the external content."

File report /report.dat/;
put report "Here we include content from an external file.";
put_utility 'inc' / 'recall.txt' ;

Note that the file report.dat will contain the following lines:

Here we include content from an external file.
I am the external content.

IncMsg, IncLog and IncMsglog: Including the Content of a File to the Log File and Listing file

In this example, we first create the external file recall.txt, write to it and close it. Then we include the content of recall.txt into the log and listing file.

File recall /recall.txt/;
putclose recall "I am the external content." / "I go over more than one line.";

display 'before the include';
put_utility 'incMsg' / 'recall.txt' ;
display 'after the include';

The listing file of this model shows the content of recall.txt:

----      4 before the include
*** Start of include of file recall.txt
I am the external content.
I go over more than one line.
*** End of include of file recall.txt

----      6 after the include

Msg, Log and Msglog: Writing to the Log File and Listing file

Consider the following example:

put_utility 'msg'    / 'This message is for the lst file.' 
          / 'log'    / 'This message is for the log file.' 
          / 'msgLog' / 'And this message is for the lst and the log file.' ;

Note that the following two lines will be generated in the log file:

This message is for the log file.
And this message is for the lst and the log file.

In addition, the listing file will contain the following two lines just before the report file summary.

This message is for the lst file.
And this message is for the lst and the log file.

Gdxout: Creating GDX Files and Unloading Data to them

Consider the following example:

Set j / 2005*2007 /;
Scalar random;

loop(j,
   put_utility 'gdxOut' / 'data' j.tl:0;
   random = uniform(0,1);
   execute_unload random;
);

This code will create the GDX files data2005.gdx, data2006.gdx and data2007.gdx. Note that each GDX file will contain a value between zero and 1 for the scalar random. For example, the file data2005.gdx (exported to an ASCII via gdxdump) will have the following content:

Scalar random / 0.171747132 /;

Gdxin: Loading Data from GDX Files

Note that the following example is an extension of the previous example that demonstrated the use of the command gdxout.

loop(j,
   put_utility 'gdxIn' / 'data' j.tl:0 ;
   execute_load random; 
   display random;
);

This code loads the values of the scalar random from the GDX files data2005.gdx, data2006.gdx and data2007.gdx and displays them in the listing file of the GAMS input file:

----     19 PARAMETER random               =        0.172
----     19 PARAMETER random               =        0.843
----     19 PARAMETER random               =        0.550

Shell: Writing to Various Files

Consider the following example:

Set j / j1*j5 /;
Scalar random;

loop(j,
   random = uniformint(0,100);
   put_utility 'shell' / 'echo ' random:0:0 ' > ' j.tl:0;
);

Observe that the shell script command echo outputs an integer between zero and 100 to the files j1, ..., j5.

Click: Adding a Clickable Link

Assume that there is a file called sets.html in our working directory. Consider the following code snippet:

put_utility 'click' / 'sets.html' ;

If we run this code snippet with the GAMS IDE, the following clickable link will appear in the IDE process window:

>>> File sets.html

Solver: Select a solver by name at execution time

The solver keyword allows to select a solver at execution time by name. Normally, the option statement option solver=xpress, lp=cplex; is used to select the current solver, but in case where you want to programatically change the solver as in this example, this put_utility keyword can be useful. Consider the following code snippet which extends the [DICE] model:

...
set slv 'MIP solvers to run' / cplex, cbc, gurobi, mosek, scip, xpress /;
parameter rep 'report status, time, objective value, and more';
option bratio=1;
loop(slv,
   put_utility 'solver' / 'mip' / slv.tl:0;
   solve xdice using mip max wnx;
   rep(slv,'sstat')     = xdice.solveStat;
   rep(slv,'mstat')     = xdice.modelStat;
   rep(slv,'obj')       = xdice.objVal;
   rep(slv,'time')      = xdice.etSolve;
   rep(slv,'solver id') = xdice.sysIdent;
);
display rep;

If we run this code we get a report like this:

----     82 PARAMETER rep  report status, time, objective value, and more

             sstat       mstat         obj        time   solver id

cplex        1.000       1.000      21.000       0.455      19.000
cbc          1.000       8.000      21.000       2.804       6.000
gurobi       1.000       1.000      21.000       0.631      32.000
mosek        1.000       1.000      21.000       4.425      48.000
scip         1.000       1.000      21.000       3.907      65.000
xpress       1.000       1.000      21.000       2.571      71.000

If one want's to set a solver for all possible model types (similar to option solver=xpress;) specific model type has to be replaced by *: put_utility 'solver' / '*' / 'xpress';.

AssignText: Assigns label text to an element of a singleton set

GAMS has no string data type. The explanatory or label text of an element can serve in several situations as a poor man's string type and used in put and put_utility statements. The example below extends the [TRNSPORT] model and disables flow on a particular connection. The solution point file created by savePoint gets renamed to e.g. sol_seattle_new-york.gdx. The filename is assembled using the assigntext keyword. This has been packaged for better readability in some STRING macros:

...
$macro STRINGDEF(sym)         singleton set sym / sym /
$macro STRING(sym)            sym.te(sym)
$macro STRINGASSIGN(sym,text) put_utility 'assignText' / 'sym' / text
$macro STRINGAPPEND(sym,text) put_utility 'assignText' / 'sym' / sym.te(sym) text
alias (i,ii), (j,jj);
transport.savePoint = 1;
STRINGDEF(fname);
loop((ii,jj),
   x.up(ii,jj) = 0;
   solve transport min z using lp;
   x.up(ii,jj) = inf;
   STRINGASSIGN(fname,'sol');
   STRINGAPPEND(fname,'_' ii.tl:0);
   STRINGAPPEND(fname,'_' jj.tl:0 '.gdx');
   put_utility 'shell' / 'mv transport_p.gdx ' STRING(fname); 
);

Conditional Put Statements

In GAMS, shorthand notation for conditional statement are dollar conditions, as introduced in chapter Conditional Expressions, Assignments and Equations. Dollar conditions may also be used in the context of a put statement and its variants. The syntax in its most general form is as follows:

put $ logical_condition [file_name] item {item} {file_name item {item}};

Note that like all put statements, the conditional put statement begins with the keyword put. The keyword is followed by the dollar operator and a logical condition. If the logical condition is TRUE the put statement will be executed, otherwise the put statement will be ignored. For details on logical conditions in GAMS, see sections Logical Conditions and Filtering Sets. Observe that the remainder of the conditional put statement is identical to the regular put statement introduced in section The Put Statement.

The following example demonstrates how dollar conditions are used in the context of put statements.

put$(a > 10) 'Some output items';

Note that the quoted text will only be written to the put file if the scalar or variable a is greater than 10.

Errors Associated with Put Statements

There are two types of errors that may occur when the put writing facility is used: syntax errors and put errors. In this section we will discuss these errors.

Syntax Errors in Put Statements

Syntax errors are caused by the incorrect usage of the GAMS language, including unmatched parentheses, undefined identifiers, uncontrolled sets or the incorrect use of a keyword. These errors are detected during program compilation and are always fatal to program execution. For more information on compilation errors, see section Compilation Errors and the tutorials A GAMS Tutorial by Richard E. Rosenthal and Fixing Compilation Errors.

Put Errors

Put errors are unique to the put writing facility. They are detected during program execution and are caused when the specifications of file attributes are violated. Typical errors include assigning inappropriate values to file attributes and attempts to write outside a page, like moving the cursor with the cursor control character @ to a location beyond the page width. Consider the following example:

File out /out.dat/;
out.pw = 8;
put out "Let's try this.";

Note that we specify the page width (.pw) to be just 8 characters. However, the quoted text has clearly more than 8 characters. In such a case the GAMS code will be compiled and the log file will report "Normal completion". At the appropriate position in the listing file the following error will be reported:

**** PUT ERROR FOR FILE out AT LINE 5: PUT LINE OVERFLOW - LOOK FOR **** ON PUTFILE, YOU CAN RESET .PW UP TO 32767

The put file out.dat will contain the following line:

Let'****

As put errors are not fatal and are not emphasized in the log file, they may be easily overlooked. Especially in large put files, put errors may go undetected. GAMS provides the file attribute .errors that facilitates the display of the numer of put errors. Consider the following example:

File out /out.dat/;
out.pw = 8;
put out "Let's try this.";

abort$(out.errors) "Put errors in out:", out.errors;

Users may choose to output the number of put errors in a put file or display statement or even trigger an execution error as in the example above.

Creating a Report for the Model MEXSS

We started this chapter with a simple example and we will complete it with a more elaborate example. In this section we will show how the put writing facility may be used to create a report for the model [MEXSS]. The code for the report may be inserted at the end of the original model and is shown below in its entirety.

The model [MEXSS] analyzes the relative efficiency of five different plants for meeting the product requirements of ingot steel in three different markets. The model may be used to identify the major bottlenecks that constrain production in the system of plants. It will find the production levels in the steel mills and shipments from the mills to the markets that will meet the market requirements at least cost. We will create a report for this model that will present details on the available capacities of the productive units at the five plants, the unused capacities and the marginal values of the capacities. This report may be extended to include other data and results and the code may be reused to create new reports if the data in the model is changed. For models that are run periodically, say, weekly or monthly, reusable reports can be invaluable.

We will start the code for the report with defining the put file, setting the file attributes print control and page size and making the the put file current. Then we will specify some global formatting settings. We will continue with writing a title block and finally turn to the core of the report: a table with three subtables. Note that we will use in-line comments to annotate the code. The code follows:

$eolcom //
File out /out.dat/; 
out.pc=3; out.ps=54;       // print control, page size
put out;

* Global Format Settings:
Scalars   indent1    indent to first column of units display
          indent2    indent to first column of field labels
          indent3    indent to first column of first numeric field
          textwide   wide text       / 80 /
          textnarr   narrow text     / 30 / ;

out.nr  = 0;               // numeric round format
out.tw  = textwide;        // width of text field
out.lw  = 11;              // width of label field
out.nw  = 11;              // width of numeric field
out.nd  = 2;               // number of decimals displayed
indent1 = 3;
indent2 = 30;
indent3 = 27;

* Title Block
puttl   'MEXICO STEEL - SMALL STATIC MODEL':<> /
        system.date:<>/ / /;

* Main Window
out.tj = 3;                // alignment of text: center
put
  '      This report is based on selected data and results from the model'/
  'MEXSS in the GAMS Library. This model analyzes the relative efficiency'/
  'of five different plants in meeting the product requirements for ingot'/
  'steel in three different markets. The model aims to find the pattern  '/
  'of production levels in the mills and shipments from the mills to the '/
  'markets that will meet the market requirements at the least cost.     '/
  /
  'Reference:  Kendrick, D. A., Meeraus, A., Alatorre J., The Planning '/
  'of Investment Programs in the Steel Industry, John Hopkins Universi-'/
  'ty Press, 1984.                                                     '/
  / / /;

out.tj = 2;               // alignment of text: left
out.tw = textnarr;        // width of text field

putpage$(out.ll+card(m)+7 > out.ws);   // manual paging

put 'Table 1.  Plant Data and Results':0 /'-------'/;    // Table 1
out.cc = indent2;         // current column
loop(i, put i.tl:<>);     // column headings

put / / 'CAPACITY (metric tons)';                        // Capacity
loop(m,
   put / @indent1, m.te(m), @indent3;  // row headings
   loop(i, put k(m,i));                // numeric values
);

* Header Block with column headings for next page (will be used only if necessary)
puthd 'Table 1 (continued).  Plant Data and Results':0 /
      '-------------------'/;
out.hdcc = indent2;
loop(i, put i.tl:<>);     // column headings
puthd /''; 

* Main Window continued
if(out.ll+card(m)+sum((m,p)$b(m,p), 1)+3 > out.ws,
   putpage;               // manual paging
   else put / /;
); 

put 'UNUSED CAPACITY (metric tons)';                      // Unused Capacity
loop(m,
   put / @indent1, m.te(m), @indent3;   // row headings
   loop(i, put (k(m,i)-cc.l(m,i)));     // numeric values
);

if(out.ll+card(m)+4 > out.ws,
   putpage;               // manual paging
   else put / /;
);

put 'MARGINAL VALUE OF CAPACITY'/ @indent1 '(US$/ton)';   // Marginal Value of Capacity
loop(m,
   put / @indent1, m.te(m), @indent3;   // row headings
   loop(i, put abs(cc.m(m,i)));         // numeric values
);

Note that we set print control (.pc) to ASCII formfeed. Below we illustrate how to use one of the print control settings that generate a delimited file. Observe that we group all global format parameters and settings near the top of the code. This way of organizing the code will make it easy to modify the structure of the report in the future as needed. Observe further, that the output items in the title block are locally formatted to be center aligned.

In the remainder of the code the actual report is written in the main window. The block of text at the beginning serves as a brief introduction to the report. Note that the core of the report is a table consisting of three subtables, where the subtables share the column headings. Before writing the table, we insert a test - the conditional putpage statement - to determine whether there is a sufficient number of lines on the current page to accommodate the size of the first subtable. Thus the put writing facility would start a new page if there were not enough rows. We repeat similar tests before the code for the other two subtables. Observe that we insert a header block with the column headings. If a new page had to be started since there were not enough rows for the second or the third subtable, the header block would contain the column headings of the table. (Users might want to experiment by reducing the file attribute page size (.ps) to say, 30.) The report that will be generated follows:

                       MEXICO STEEL - SMALL STATIC MODEL
                                    01/31/17


           This report is based on selected data and results from the model
     MEXSS in the GAMS Library. This model analyzes the relative efficiency
     of five different plants in meeting the product requirements for ingot
     steel in three different markets. The model aims to find the pattern
     of production levels in the mills and shipments from the mills to the
     markets that will meet the market requirements at the least cost.

      Reference:  Kendrick, D. A., Meeraus, A., Alatorre J., The Planning
      of Investment Programs in the Steel Industry, John Hopkins Universi-
      ty Press, 1984.



Table 1.  Plant Data and Results
-------
                                ahmsa    fundidora  sicartsa     hylsa     hylsap

CAPACITY (metric tons)
  blast furnaces                 3.25       1.40       1.10       0.00       0.00
  open hearth furnaces           1.50       0.85       0.00       0.00       0.00
  basic oxygen converters        2.07       1.50       1.30       0.00       0.00
  direct reduction units         0.00       0.00       0.00       0.98       1.00
  electric arc furnaces          0.00       0.00       0.00       1.13       0.56

UNUSED CAPACITY (metric tons)
  blast furnaces                 0.13       0.00       0.00       0.00       0.00
  open hearth furnaces           0.00       0.00       0.00       0.00       0.00
  basic oxygen converters        0.00       0.72       0.14       0.00       0.00
  direct reduction units         0.00       0.00       0.00       0.00       0.39
  electric arc furnaces          0.00       0.00       0.00       0.23       0.00

MARGINAL VALUE OF CAPACITY
  (US$/ton)
  blast furnaces                 0.00      69.62      71.69       0.00       0.00
  open hearth furnaces          53.76       1.72       2.09     138.03     145.02
  basic oxygen converters       64.57       0.00       0.00     138.03     145.02
  direct reduction units         0.00       0.00       0.00      80.08       0.00
  electric arc furnaces        136.46     138.03     140.00       0.00      94.28

Assume we need the data reported in the first subtable above in a delimited file format in order to import it to other applications, like spreadsheets or databases. Consider the following code:

file out2 / 'out2.csv' /; 
out2.pc=5;
put out2 'capacity (metric tons)';
loop(i, put i.tl);
loop(m,
     put / m.te(m);
     loop(i, put k(m,i));
);

Note that we set the file attribute page control (.pc) to 5. This means that non-numeric output items will be quoted and each output item will be delimited with commas. Observe that field widths, alignments and horizontal cursor relocations were completely avoided. The put file out2.put will contain the following lines:

"capacity (metric tons)","ahmsa","fundidora","sicartsa","hylsa","hylsap"
"blast furnaces",3.25,1.40,1.10,0.00,0.00
"open hearth furnaces",1.50,0.85,0.00,0.00,0.00
"basic oxygen converters",2.07,1.50,1.30,0.00,0.00
"direct reduction units",0.00,0.00,0.00,0.98,1.00
"electric arc furnaces",0.00,0.00,0.00,1.13,0.56

While a comma is the most commonly used delimiting character, other delimiters like a blank space (.pc=4) and a tab (.pc=6) may also be used.

For other examples of code that uses the put writing facility, see the various models in the GAMS Model Library.