157
Linking your Solver to GAMS THE COMPLETE NOTES Don't Panic !! GAMS GAMS Development Corporation 1217 Potomac Street, N.W. Washington, DC 20007 Tel: (202) 342-0180 Internet: [email protected]

Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

  • Upload
    ngokhue

  • View
    219

  • Download
    5

Embed Size (px)

Citation preview

Page 1: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

Linking your Solver to GAMSTHE COMPLETE NOTES

Don't Panic !!

GAMSGAMS Development Corporation1217 Potomac Street, N.W.Washington, DC 20007

Tel: (202) 342-0180Internet: [email protected]

Page 2: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

2

TABLE OF CONTENTS1 Connecting your solver to GAMS2 An Introduction to the GAMS I/O library2.1 Introduction2.2 GAMS - The Operating Procedure2.3 Restarts with GAMS2.4 The Objective Function2.5 Data Types2.6 Dynamic Memory vs Fixed Arrays2.7 Passing Algorithm Options to the solver2,8 Overview of GAMS Input - Output Subroutines2,9 Error Handling2.10 The Status file2.11 The Dictionary file3 GAMS I/O Subroutines4 Implementation Notes5 Examples for linear systems6 Nonlinear section of GAMS I/O library7 GAMS Nonlinear I/O Subroutines8 Examples for Nonlinear systems

Page 3: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support
Page 4: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

4

1 CONNECTING YOUR SOLVERWITH GAMS

To make GAMS aware of your solver, you have to add your solver to the list in the filegamscomp.txt. This is the 'solver capability' file - it contains information about eachsolver: it's name, the model types that it can solve (LPs, MIPs etc.), how to run the solverand the list of default solvers for all model types. An entry in a typical gamscomp.txtfile for the PC is listed below:

bdmlp 2 0 1 LP RMIPgamsbdm3gams3bdm.exe

The first digit contains the file type or file format in which the matrix and solutionfiles are read and written. The file type is described below:

File type Description0 Coded files (ASCII or EBCDIC)1 Binary Stream I/O2 Fortran Unformatted I/O3 Salford Fortran Unformatted I/O4 VMS G_FLOATING

This file format is written by GAMS and expected on the way back if you specify a 1 asfile type. Pick a file type which is supported by your compiler.

Coded (text) files are the slowest, and the most disk space consuming. It should only beused when running GAMS in a distributed environment, where the solver and GAMS arerunning on two different machines of a different architecture. Coded files are normalASCII (EBCDIC) files.

The other file types are all for binary files, which are written in blocks, currently of 800bytes. The floating point numbers are written in full precision (i.e. 8 bytes), so the matricespassed on via coded files and binary files are slightly different. Some tricks areimplemented to reduce the size of the files (removal of redundant information andcompression).

File type 1 reads and writes the files as a stream of bytes. Some Fortran compilers canhandle this, and all C and Pascal compilers use this method. File type 2 is for most Fortrancompilers. Writing unformatted files normally results in a 4 bytes header containing the

Page 5: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

length of the record n , then n data bytes, and then a footer which is a copy of the header.File type 3 is a special format for the Salford 386 Fortran compiler. There the header andthe footer are 5 bytes long, with the first byte a -1, following by a 4 byte integer containingthe length n.

The second number gives information about the dictionary file that is used to pass on theGAMS symbol table where the names of the equations and variables are stored. Thisdictionary file is written optionally depending on the value of this number. The Dictionaryfile types are as follows:

File type Description0 No dictionary file1 Standard dictionary file2 Dictionary file with quoted strings

The third number is used to make the system read the name of the executable that ispresent on the third line. This is usually needed only inside embedded systems likeDICOPT that use other solvers to solve various sub-problems.

The second line lists the batch file that is called when your solver is used. The accessstring contains the name (and optionally the path) of the shell script (batch file or exec)that call the solver. A typical batch file is GAMSBDM3.BAT which is listed below:

@echo offgams3bdm %4gamscmex %3gamsnext %3

The first line calls the solver, with the control file specified on the command line. Thesecond line calls GAMS, so that it can read the solution, and proceed executing. Theparameter on this call is the parameter files GAMS uses for internal control. GAMSproduces a GAMSNEXT batch file, which contains instructions what to do next, and the callto it is specified on the third line. For your specific machine, it is probably a good adviceto have a look at the scripts we provide for MINOS, BDMLP and ZOOM, and alter one ofthem to suit your needs.

In order to add your solver to GAMS, use a text editor to add your solver to theGAMSCOMP.TXT file. If desired, you can also change the defaults, so that your solver isused by default. Then create the batch file that is similar to the one described above byreplacing the gams3bdm on the second line by the name of your executable.

Page 6: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

6

2 THE GAMS INPUT-OUTPUTLIBRARY

2.1. INTRODUCTION

This document describes the GAMS I/O library, available for developers, who want tointegrate their own solvers with GAMS. Currently we have C and Fortran versions of thislibrary available on a variety of platforms. The entire list of platforms and compilers isgiven in Appendix A.

There are a number of advantages when a solver is using this library, instead of its owninput/output routines. First, these routines have been heavily tested and as a result arevirtually bug-free (lets hope so!). Second the library is ported to a large number ofplatforms. A solver using this library will contain only a few machine dependent parts, soporting a solver is now almost reduced to linking with the appropriate version of thelibrary. For instance, using this library we are now capable of doing a complete port ofour solvers within a few hours, a task that earlier often required a few days. Third, thelibrary is optimized for different machine architectures. We have put lots of effort ininvestigating how we can exploit the features of a given machine architecture. As a resultwe can achieve performance gains compared to reading and writing MPS files up to afactor of 100.

2.2. GAMS - THE OPERATING PROCEDURE

GAMS first compiles the input file which is specified in the GAMS source language. Thenthe GAMS execution system takes control. As soon as a SOLVE statement is encountered,the corresponding model will be generated, and stored in two files called the control fileand the data (or matrix) file. For nonlinear models, an additional file called the instructionfile is also generated by GAMS. Before terminating, GAMS will also write its completestate to the disk in the form of temporary work files. Then GAMS terminates, and a shellscript (or batch file) will give control to the solver. After the solver has completed its joband terminated, it has to pass on the solution information to GAMS through two files - thesolution file and the status file. The shell script now gives control back to GAMS, whichfirst reads the work files and restores its state a it was before terminating. Then thesolution and status file as written by the solver are read. GAMS generates its listing filefor the problems and then continues with executing the statements after the SOLVEstatement. GAMS, therefore, communicates with its solvers through the set of filessummarized in Table 1.

From among the files generated by GAMS, the solver should first read the control file.This file contains all kind of statistics on the problem, like the number of variables, the

Page 7: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

number of constraints, the type of the model etc. Then the data/matrix file, containing thecoefficients of the matrix and the bounds on the variables, should be read. For NLP's thenon-linear instruction file should also be read. This contains information how to evaluatethe non-linear functions specified in the model, and their derivatives, in a compiled format.These instructions are interpreted by an interpreter, whose use is explained in the non-linear section of this document.

GAMS ÄÄÄÄÄ> solvercontrol filedata fileinstruction file

statistics of the problemproblem matrixnonlinear instructions for NLP's

(gamscntr.scr)(gamsmatr.scr)(gamsinst.scr)

solver ÄÄÄÄÄ> GAMSstatus filesolution file

messages from solversolution returned by the solver

(gamsstat.scr)(gamssolu.scr)

Table 1. Files used for communication(The names in parentheses are typical file names)

The subroutines in the I/O library hide the actual format of the various files from the user.In fact on some platforms the data and solution file may be using a complicatedcompressed binary format. Data files, non-linear instruction files and solution files arereduced in size by a factor of two when using binary files, and the I/O speed improvementfactor is approximately 10. The handling of the files is completely done inside the library,and the actual file format is transparent to the user of the library.

In this document, we will start with concepts applicable to linear or mixed-integerprogramming. (The individual routines are described in roughly the order in which theyare used.) The details needed for nonlinear work are mostly collected in the section onnonlinear programming, near the end. Many of the general purpose routines haveparameters that are only used for nonlinear problems. These are discussed with thegeneral description of those routines. Other routines are only used in nonlinearprogramming. Their description can be found in the nonlinear section.

RESTARTS WITH GAMS

If your solver support hot restarts, it is very desirable to give GAMS the opportunity to usethis feature. In many practical situations several solve statements appear in a row, withrelatively minor changes in the data. Allowing restarts will speed up solution times for thesolves following the first one, by a considerable amount.

GAMS itself does not have the notion of a basis. The only thing it knows about are levelsand marginals. However this is enough information for the solver to reconstruct anoptimal basis. You should try to run a small LP with BDMLP, with 2 solves in a row. Thesecond solve will need 0 (or 1, depending how one is counting) iterations to reach an

Page 8: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

8

optimal solution. This paragraph will give you some advice on how such a basis can beconstructed.

We will use the marginal to determine whether a variable (either a structural or a logicalvariable) goes into the basis or not. If the marginal is zero, it can go into the basis. Youmay want to count the number of variables that are declared basic until now, so that youare sure there are no more basic variables than there are rows. If the marginal is non-zero,the variable is non-basic. You can use the levels and the bounds to determine whether weshould set the status to lower, to upper, or that it is a free variable. Note that a non-basicfree variable is possible in GAMS: consider the example where a variable is returned non-basic at one of its bounds (i.e. with a non-zero marginal), and that the user resets thebounds before the subsequent solve. If you want to declare free variables basic make surethere are no more than m basics (that is if your solver can not handle this).

On the way back, the routine that writes a solution record will ask you for the basis status(nonbasic lower, nonbasic upper, basic, or super-basic). GAMS itself is not using thisinformation, it will only save the level values and the marginals. But when using binaryfiles we may not want to write the level if the status is nonbasic upper or nonbasic lower.So be sure if you say that a variable is nonbasic, it is really at one of its bounds, becauseGAMS will set it to the corresponding bound. In case of doubt, declare the variable assuperbasic: this will force the routine to write the level and marginal. Especially whenlinking GAMS to (mixed) integer solvers you should pay attention to this point: often thestatus of integer variables is reported wrong by the solvers (that is they correspond to themost recent subproblem instead of the original problem). Again, if a variable is non-basicbut you are not sure at which bound it is sitting (or even if it is at a bound at all), report itto GAMS as a superbasic.

THE OBJECTIVE FUNCTION

The files written for the solver contain an objective variable index, which corresponds tothe variable the user has specified in the GAMS solve statement. Your solver probablyneeds to optimize the value of a row (or nonlinear function). There are two ways toarrange for this.

The most straight forward approach is to add an extra row to the problem. This shouldhave one coefficient, value 1.0, in the column corresponding to the GAMS objectivevariable, iobvar, and be non-binding. The row activity of this added row will then equalthat of the variable the user has specified. This extra row is probably most convenientlyadded after the other rows have been read. Notice that now the problem has numrow + 1rows, and one more non-zero. When writing solution records remember to ignore the lastrow.

For nonlinear or network problems, it may be preferable to reformulate the row in whichthe objective variable occurs. This is especially desirable if the only nonlinearities in theproblem are in the definition of the objective variable. In the nonlinear programming

Page 9: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

section we describe how this reformulation is be done. For linear problems see thediscussion above before KGV(14).

DATA TYPES

We have only used logical (boolean), integer, real and character data types. Our genericreal type in this text is DOUBLE PRECISION, although the implementation notes forparticular machine (e.g Crays) may indicate that the binaries are actually single precision.The integer is the generic integer on the particular machine/compiler combination. Onsome machines we may use INTEGER*2 and INTEGER*4.

DYNAMIC MEMORY vs. FIXED ARRAYS

This paragraph is mainly important for solvers written in Fortran. Most fortran basedsolvers are have fixed array sizes. Always spaces is allocated for say n columns, m rowsand nz non-zeroes. If the model is much smaller than these numbers, lots of memory iswasted. If the model exceeds these limits, the solver will not be able to handle it. Somecommercial solvers (LAMPS, SCICONIC) allow the user to reconfigure the maximum sizeby recompiling parts of the system, and then link it together. SCICONIC provides eventwo versions of their executables: a small one and a bigger one. The problem with fixedsize arrays is that they are always too small or too big.

In BDMLP, GAMS/MINOS, GAMS/OSL, GAMS/CONOPT and GAMS/ZOOM weadopted another approach. The solver does an estimation of the workspace needed basedon the statistics of the model (number or rows, columns, nonzeroes etc.), and then requestsa contiguous chunk of memory of that size. When the request is granted arrays are mappedinto this workspace and the algorithm can start reading the matrix. If the availableworkspace is smaller than the estimate then one can decide to give up, or still to try tosolve it, because the fill-in may be less than estimated. Notice that this set up is relativelyeasy in GAMS because the counts (number of rows etc.) are known in advance. Whenreading an MPS file this is not the case.

The GAMS user has the possibility to override the estimate done by the solver. If there is astatement OPTION WORK=8000 or MODEL.WORKSPACE = 2 in the GAMS model,the user wants to allocate 8000 double words (8 byte quantities) or 2 megabyte for hismodel. This value is passed on to the solver, and if non-zero it should override theestimate.

PASSING ALGORITHM OPTIONS TO SOLVER

GAMS uses a separate option file in order to pass algorithm specific options on to thesolver. Each line in the option file specifies a single option, using one or both items asfollows:

• A keyword - Required for all options.

Page 10: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

10

• A number or character string that represents the value for the option specified by thekeyword.

Any line starting with a '*' in column 1 is a comment. The following two examples ofoption files for OSL and CPLEX illustrate its use.

* OSL Option file * CPLEX option filemethod dsimplex dualpresolve -1 presolve 0

Both option files cause the problem to be solved by the dual simplex method without usingthe presolve features of the algorithms.

The user can specify the list of keywords that are the names of the various options that canbe passed on through GAMS. The GAMS I/O library provides subroutines that can beused to read the option file and pass the values of the various options to be passed on tothe solver.

OVERVIEW OF GAMS INPUT-OUTPUT SUBROUTINES

The linear part of the library consists of the subroutines listed in tables 2,3, and 4. All theuser-callable routines are presented (some internal routines are not listed). The routines aresplit up in three parts: input, output and resident. For machines with no virtual memoryand tight memory (the PC is an example), the input and output part may be overlaid, whilethe resident part should remain in core if possible.

subroutine short description

GFINITGFMACHGFRCNTGFSTATGFOPSTGFPGSZGFOPTIGFRDOPGFTIMEGFWDIRGFSDIRGFCDIRGFRROWXGFRCOLXGFRCOF

InitializationReturn machine constantsRead GAMS control fileReturn status file nameOpen the status fileReturn page size of status fileReturn option file nameRead option fileReturn GAMS timeReturn GAMS working directoryReturn GAMS system directoryReturn GAMS scratch directoryRead a row recordRead a col recordRead a matrix coefficient

Table 2. Overview of the input library routines

Page 11: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

subroutine short description

GFERR

GFWSTAGFWROWGFWCOLGFWBNDGFWRTIGFWCTIGFWWTIGFWNODGFCLOS

Write error message and terminate(should not be called by the user)Write model and solution statusWrite now (solution)Write column (solution)Write best integer boundWrite reading timeWrite calculation timeWrite writing timeWrite nodes usedClose down the I/O library

Table 3. Overview of the output library routines

There is a certain order in which the routines should be called. For instance the GFINITroutine should be called first, and you should read the row records before the columnrecords. The next diagram gives a rough idea in what order the routines should be called.You may also want to take a look at the examples presented a few pages further.

subroutine short description

GFCLCKGFSTCTGFRWERGFCLERGFRCERGFMSGGFGETMGFFREMMEMINFGETPARGFUOPNGFUOPUGFFRSTGFINDXGFFRMTGFXARGGFSGET

ClockStatus file controlReport row errorReport column errorReport element errorWrite a messageRequest a memory blockRelease a memory blockPrints memory statisticsInterrogate GAMS Parameter fileOpen a fileOpen an unformatted filePosition first non-blank in stringLength string excluding trailing blanksReturns "good" formatting string for printing a realFind i'th parameter from command lineFind i'th token in a string

Table 4. Overview of the resident library routines

Page 12: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

12

1. CALL GFINIT ! initialize the system2. CALL GFRCNT ! read control file

extract nrows,ncols,etc.3. CALL GFOPST ! open status file

orCALL GFSTAT ! get status file name and open it by yourself

4. CALL GFGETM ! allocate enough memoryneeded for fortran codes only

5. for i:=1 to nrows doCALL GFRROWXAdd additional row for the objective (optional)

6.if needed add one non-zero in objective row

7. solve the problem8. CALL GFWSTA ! write status9. for i:=1 to nrows do

CALL GFWROW10.for i:=1 to ncols do

CALL GFWCOL

Table 6. Outline of subroutine calling order

ERROR HANDLING

Most of the errors that can occur while executing the library routines are the result ofprogramming mistakes or incompatibilities. If any such errors are detected, an errormessage is written, and execution terminated. Two files are being used to report errors.First the status file. This file is used to write information that GAMS can copy to thelisting (.LST) file once it takes over control again. The log file is the file where the solverwrites information about the progress of the algorithm etc. The log file will normally bethe screen. If neither files are opened, error messages are written to standard output (i.e. infortran WRITE (*,*) is used).

THE STATUS FILE

The status file is a text file written by the solver. Parts of the status file will be copied byGAMS to the listing file. The status file contains certain control characters that areprocessed by GAMS. Inserting these control characters is normally done by calls toGFSTCT. These control sequences look like "=n" where n is a digit. For instance a "=1"means start copying and "=2" means stop copying. All these control sequences start incolumn 1. So a solver may produce the next file:

Page 13: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

=1 ************************************* * H Y P E R L P, By Solvers Inc. * ************************************* Version 0.001 Release A

=2

Problem is read in. Scaling: min row scale = 0.01 max row scale = 100.0 min col scale = 0.001 max col scale = 1e3 Start of SIMPLEX algorithm. Problems in iteration 2764748: basis nearly singular. Switching to COMPLEX algorithm. Too difficult... going back to SIMPLEX Solved, accuracy check : 1.0e-5

The part between the "=1" and the "=2" is echoed to the GAMS listing file. The otherpart becomes only visible for the user if he or she has a statement option sysout=onin the GAMS model, or if the solver had added a "=4" to the status file (normally by usingCALL GFSTCT('SYSOUT'). It is good practice to include the sysout control sequence tothe status file if something is going wrong in the solver, so that extra debugginginformation is copied to the listing file.

In case you want to use a different control character than the "=", because one of yourstring start with an equal sign in column 1, you can reset the control character by callingCALL GFSTCT('CHRSW&'), where the '&' may be any (printable) character.

THE DICTIONARY FILE

The Dictionary file is used to pass on the GAMS symbol table where the names of theequations and variables are stored. This dictionary file is written optionally depending onan entry in the GAMSCOMP.TXT file as explained in Chapter 1. The user can generatethe GAMS names of the various set elements, sets, variables and equations by using thefollowing subroutines that access the dictionary file:

subroutine short description

Page 14: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

14

GFDICTFDICTMEMREADDICTGETROWINFOGETCOLINFOGETROWNAMEGETCOLNAMEGETDECLARGETSETSIZEGETSETDECL

Returns name of dictionary fileAllocates memory for dictionary file informationRead dictionary fileReturns name of equation and indices for given rowReturns name of variable and indices for given columnReturn name of equation for given rowReturn name of variable for given columnReturn domains of equation or variableReturn number of elements in a given setReturn all the elements in a given set

Table 4. Overview of the dictionary file library routines

Page 15: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

CHAPTER 3

GAMS INPUT/OUTPUTSUBROUTINES

List of Subroutines:

DICTMEMGETCOLINFOGETCOLNAMEGETDECLARGETPARGETROWINFOGETROWNAMEGETSETDECLGETSETSIZEGFCDIRGFCLCKGFCLERGFCLOSGFDATEGFDICTFGFERRGFFREMGFFRMT

GFFRSTGFGETMGFINDXGFINITGFMACHGFMSGGFOPOKGFOPSTGFOPTIGFPGSZGFRCERGFRCNTGFRCOFGFRCOLXGFRDOPGFRROWXGFRWERGFSDIR

GFSGETGFSTATGFSTCTGFTIMEGFUOPNGFUOPUGFWBNDGFWCOLGFWCTIGFWDIRGFWNODGFWROWGFWRTIGFWSTAGFWWTIGFXARGMEMINFREADDICT

Page 16: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

16

SUBROUTINE DICTMEM

Allocates memory for information in dictionary file.

Fortran SUBROUTINE DICTMEM(IUNIT,DWNEEDED)INTEGER IUNIT, DWNEEDED

Pascal n.a.

C dictmem(void)

Description of the parameters

IUNIT (input)

Unit number that can be used to read header info in dictionary file.

DWNEEDED (output)

Number of double words needed to store data structure. This has to be called beforeGFGETM.

Page 17: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GETCOLINFO

This subroutine gets the name of the variable block and individual indices of acolumn.

Fortran SUBROUTINE GETCOLINFO(I,NAME,INDEX,NIND,ARRAY)INTEGER I, NINDDOUBLE PRECISION ARRAY(*)CHARACTER*10 NAME, INDEX(10)

Pascal n.a.

C getcolinfo(i,name,index,nind)int ichar* namechar** indexint* nind

Description of the parameters

I (input)

Column number

NAME (output)

Stem name of variable

INDEX (output)

List of indices of variable. Empty if the variable has no indices.

NIND (output)

Number of indices

ARRAY (input/output)

A double precision vector, used for accessing the allocated memory.

Page 18: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

18

SUBROUTINE GETCOLNAME

Gets GAMS equation name of a column

Fortran SUBROUTINE GETCOLNAME(I,NAME,ARRAY)INTEGER IDOUBLE PRECISION ARRAY(*)CHARACTER*10 NAME

Pascal n.a.

C getcolname(i,name,namelen)int ichar* nameint namelen

Description of the parameters

I (input)

Column number

NAME (output)

Name of corresponding variable

ARRAY (input/output)

A double precision vector, used for accessing the allocated memory.

Page 19: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GETDECLAR

Gets domains of variable or equation

Fortran SUBROUTINE GETDECLAR(NAME,NIND,DOM,ARRAY)CHARACTER*10 NAMEINTEGER NINDCHARACTER*10 DOM(10)DOUBLE PRECISION ARRAY(*)

Pascal n.a.

C getdeclar(name,nind, dom)char* nameint nindchar **dom

Description of the parameters

NAME (Input)

Name of variable or equation

NIND (Output)

Number of indices for variable or equation

DOM (Output)

Domains of variable or equation

ARRAY (Input/Output)

A double precision vector, used for accessing the allocated memory.

Page 20: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

20

FUNCTION GETPAR

Interrogate the GAMS parameter file.

Fortran SUBROUTINE GETPAR(N,KEY,PAR,UNIT)INTEGER NCHARACTER*10 KEY(N)CHARACTER*80 PAR(N)INTEGER UNIT

Pascal n.a.

C n.a.

Description of the parameters

N (input)

The number of parameters you are requesting.

KEY (input)

The parameter names. For an overview of the available parameters see thedocument "The GAMS parameter file".

PAR (output)

Strings containing the values of the parameters specified in KEY. Empty strings ' ')will be returned for non-existing ones.

UNIT (input)

Unit number to be used by this routine. Afterwards you can re-use the unit for otherpurposes.

Page 21: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GETROWINFO

This subroutine gets the name of the row block and individual indices of a row.

Fortran SUBROUTINE GETROWINFO(I,NAME,INDEX,NIND,ARRAY)INTEGER I, NINDDOUBLE PRECISION ARRAY(*)CHARACTER*10 NAME, INDEX(10)

Pascal n.a.

C getrowinfo(i,name,index,nind)int ichar* namechar** indexint* nind

Description of the parameters

I (input)

Row number

NAME (output)

Stem name of equation

INDEX (output)

List of indices of equation row. Empty if the equation has no indices.

NIND (output)

Number of indices

ARRAY (input/output)

A double precision vector, used for accessing the allocated memory.

Page 22: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

22

SUBROUTINE GETROWNAME

Gets GAMS equation name of a row

Fortran SUBROUTINE GETROWNAME(I,NAME,ARRAY)INTEGER IDOUBLE PRECISION ARRAY(*)CHARACTER*10 NAME

Pascal n.a.

C getrowname(i,name,namelen)int ichar* nameint namelen

Description of the parameters

I (input)

Row number

NAME (output)

Name of corresponding equation

ARRAY (input/output)

A double precision vector, used for accessing the allocated memory.

Page 23: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GETSETDECL

This subroutines returns all the elements (labels) that belong to a set

Fortran SUBROUTINE GETSETDECL(NAME,RC, SIZE,ALIAS,N,. CLIST, ARRAY) CHARACTER*10 NAME, ALIAS INTEGER NIND DOUBLE PRECISION ARRAY(*)

Pascal n.a.

C n.a.

Description of the parameters

NAME (Input)

Name of the set

N (Input)

Declared number of elements in set

SIZE (Output)

Actual number of elements in the set. Should be less than N

CLIST (Output)

List of elements (labels) corresponding to set

RC (output)

Return Code. It's value can be interpreted as follows:

RC Explanation0 Success1 NAME is not a set2 NAME is an alias3 Not enough space in CLIST

ALIAS (Output)

Page 24: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

24

Set aliased with NAME. Returned only if RC = 2

ARRAY (Input/Output)

A double precision vector, used for accessing the allocated memory.

Page 25: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GETSETSIZE

Returns number of elements in a set

Fortran SUBROUTINE GETSETSIZE(NAME,SIZE,ALIAS,ARRAY)CHARACTER*10 NAME, ALIASINTEGER NINDDOUBLE PRECISION ARRAY(*)

Pascal n.a.

C n.a.

Description of the parameters

NAME (Input)

Name of set

SIZE (Output)

The interpretations for the values of SIZE are as follows

SIZE Explanation>0 NAME is a proper set with SIZE entries0 NAME is not a set-1 NAME is an alias

ALIAS (Output)

Set aliased with NAME. Returned only if SIZE = -1

ARRAY (Input/Output)

A double precision vector, used for accessing the allocated memory.

Page 26: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

26

SUBROUTINE GFCDIR

Subroutine GFCDIR returns the scratch directory, i.e. the directory where the matrixfile etc. are sitting. This is the right place to to put (large) scratch files that are usedby the solver.

Fortran SUBROUTINE GFCDIR(SCRDIR)CHARACTER*80 SCRDIR

Pascal procedure gfcdir(var scrdir : pathname);

C gfcdir(scrdir)char **scrdir;

Description of the parameters

SCRDIR (output)

SCRDIR is a character string that contains on exit the scratch directory.

Page 27: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFCLCK

Clock, returns used CPU time since start of the solver, or since the call to GFINIT.

Fortran DOUBLE PRECISION FUNCTION GFCLCK()

Pascal n.a.

C double gfclck()

On some systems there are problems with the clock. CMS for instance resets thetime at 12.00 midnight. Other clocks have a short range, and start counting at zeroagain after the job is running for some time. We have protected us as much aspossible against these problems. The best thing is to call GFCLCK at regular,sufficiently small, intervals. In order to obey the GAMS RESLIM option, you need tokeep track of the used up CPU time anyway. Calling GFCLCK each iteration tocheck against the RESLIM value, is a good approach, and provides our clock routinewith enough information to recover from most problems pictured above.

Page 28: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

28

SUBROUTINE GFCLER

Subroutine GFCLER passes on an error message concerning column ICOL to GAMS.GAMS will translate this column number into the correct GAMS name.

Fortran SUBROUTINE GFCLER(ICOL,MSGNO,MESS)INTEGER ICOL, MSGNOCHARACTER*(*) MESS

Pascal procedure gfcler(icol, msgno: integer, mess : messt);

C gfcler(icol,msgno,mess)int icol, msgno;char *mess;

Description of the parameters

ICOL (input)

ICOL is the column number of the variable corresponding to this error.

MSGNO (input)

MSGNO is the number of the error message. This number is used for look up. Onlyone instance of the message string is stored inside GAMS, where message stringsare considered to be the same if the message number is the same. Note that nocheck on the string itself is done, so it is your responsibility to make sure that themessage numbers are different for different messages. The allowed range forMSGNO is from 1 to 100.

MESS (input)

MESS is the string containing the message. GAMS will store and report only thefirst 50 characters of this string (ignoring the leading blanks).

Page 29: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFCLOS

This is used to close down the library routines. Checks are done that all calls havebeen made the correct number of times.

Fortran SUBROUTINE GFCLOS

Pascal procedure gfclos;

C gfclos()

This is used to close down execution of the I/O library. Systems that use binary fileswill not work unless this call is made. No parameters are passed. No further callscan be made to any library routines that do file input or output.

Page 30: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

30

SUBROUTINE GFDATE

Subroutine GFDATE returns the date when the current GAMS job started.

Fortran SUBROUTINE GFDATE(GMSDAT)CHARACTER*10 GMSDAT

Pascal procedure gfdate(var gmsdat: char10);

C gfdate(gmsdat)char **gmsdat;

Description of the parameters

GMSDAT (output)

GMSDAT is a character string that contains on exit the date.

Page 31: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFDICTF

Subroutine GFDICTF returns the name of the dictionary file. This is neededbecause the user has to open it.

Fortran SUBROUTINE GFDICTF(FLN)CHARACTER*80 FLN

Pascal procedure gfstct(cmd : cmdstring);

C gfdictf(fln)char *fln;

Description of the parameters

FLN (output)

Name of dictionary file

Page 32: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

32

SUBROUTINE GFERR

Error handling. The errors are reported in both the log file and the status file. Foruse in embedded systems, you may want to use your own error recovery routine.You can replace the default GFERR routine by your own one. The header of thisroutine should look as below. NUM is the error number, SUBROU is the name of theroutine where the error was detected.

All the error codes that are used by the library and the corresponding errormessages are listed in Table 5. In the chapter Error Messages you will find a moredetailed description of the errors, when they can occur, and what to do about it. Allerrors we have listed are the result of programming errorrs and serious hardwarefailures (disk full etc.), and should not occur during normal operation by the enduser.

Fortran SUBROUTINE GFERR(NUM,SUBROU)INTEGER NUMCHARACTER*(*) SUBROU

Pascal n.a.

C n.a.

Error Number Description

1 Illegal status code in opnfil (internal error)2 Illegal format code in opnfil (internal error)3 Could not open file4 MIP solver need to solve the problem5 NLP solver needed to solve the problem6 Control file version is incompatible7 Calling order of routines is wrong8 Too many calls to GFRROWX

9 Too many calls to GFRCOLX

10 Binary file error while reading row11 Binary file error while reading column12 Binary file error while reading buffer13 Binary file error while writing buffer14 Too many calls to GFRCOF

15 Not read all the coefficients yet16 Too many calls to GFWROW or GFWCOL

17 Error while reading instruction file18 Not enough storage for nl instructions19 Binary file type for other machine

Page 33: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

20 Illegal command string for status control21 Binary file buffer already occupied22-24 Not used25 Illegal address field in nonlinear instruction26 Illegal opcode for nonlinear instruction27 Illegal nonlinear instruction start index28 Consecutive calls to GFGETM

Table 5. Error number and Messages

Errors marked by internal error are probably problems in the library itself. ContactGAMS Development to discuss how to solve them. Other errors are likely to beprogramming errors in your code. Please inspect your code carefully before callingGAMS Development.

Page 34: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

34

SUBROUTINE GFFREM

Free the memory space allocated by the call to GFGETM.

Fortran SUBROUTINE GFFREM(ARRAY)DOUBLE PRECISION ARRAY(*)

Pascal n.a.

C n.a.

Description of the parameters

ARRAY (input)

The double precision vector, used for accessing the allocated memory.

Hints for using GFGETM and GFRETM

To be able to run a fortran program using the dynamic memory routines on allplatforms, for which we provide this facility, you have to set up your program in acertain way. The dynamic array Z should be in a labelled common block in the mainprogram. This array should then be passed as an assumed dimension array to asubroutine. This is necessary for DOS-Microsoft to ensure that (a) the array originis on a paragraph boundary, and (b) huge mode addressing is enforced for allreferences to Z. This arrangement is illustrated in the example in appendix LP-4.After the problem size is determined, GFGETM is called to allocate memory, andthen this memory is partitioned before the problem is read in. The example in theappendices show how to use GFGETM to allocate dynamic memory. Notice how,inside the routine SUB2, components of Z are treated as separate arrays.

Page 35: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFFRMT

Calculates a good format string for printing a double precision number with valueVALUE. The string returned is of the form Fw.d or Ew.d. The G format in Fortrandoes not work very well: it switches to E format too quickly.

Fortran SUBROUTINE GFFRMT(VALUE,WIDTH,DECS,FRMTST)DOUBLE PRECISION VALUEINTEGER WIDTH,DECSCHARACTER*(*) FRMTST

Pascal n.a.

C n.a.

Description of the parameters

VALUE (input)

Value of the number to be printed.

WIDTH (input)

Width of the field.

DECS (input)

Number of decimals required.

FRMTST (output)

Format string. Normaly a string of length 10 should be sufficient to handle allcases.

Example of use

Page 36: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

36

C 1 2C 12345678901234567890 FRM14 = '(1X,A,1X, )' CALL GFFRMT(Z,14,4,FRM14(10:19)) WRITE(IOLOG,FRM14) 'GAMS provided cutoff of ',Z

Page 37: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFFRST

Returns position of first non-blank character in string. Returns 0 if not found: i.e. ifall characters in string are blanks.

Fortran INTEGER FUNCTION GFFRST(ST)CHARACTER*(*) ST

Pascal n.a.

C n.a.

Page 38: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

38

SUBROUTINE GFGETM

Memory management. On many machines it has proven possible to request memoryat execution time in a Fortran program. The normal way to use this routine is toestimate how much is needed after the problem characteristics have been obtainedfrom GFRCNT but before any data is read. It is a fatal error to call GFGETM twicewithout an intervening call to GFFREM.

This subroutine is not available for Pascal and C. Pascal prohibits the use of asimilar mechanism, because of the strong type checking. Some Pascal systemsallow allocation of dynamic arrays, consult the compiler documentation. Whenusing Turbo Pascal one can use getmem and freemem to simulate dynamic arrays. Itis important that array bound checking is turned off when using this trick. For anexample see the implementation notes on Turbo Pascal. C allows dynamicallocation of arrays by malloc. See the C example in the appendix how this can beimplemented.

Fortran SUBROUTINE GFGETM(ARRAY,FIRST,MEMREQ,& MEMGOT,MAXMEM)DOUBLE PRECISION ARRAY(*)INTEGER FIRST,MEMREQ,MEMGOT,MAXMEM

Pascal n.a.

C n.a.

Description of the parameters

GFGETM tries to allocate space for MEMREQ double precision reals. It returns theamount of memory it could grab MEMGOT, where it is located: FIRST is the firstuseable position in the array, and on some machines, how much there is available:MAXMEM. The result is that when MEMGOT>0 the following memory locations areavailable for the user: ARRAY(FIRST)..ARRAY(FIRST+MEMGOT-1). Note that ingeneral MEMGOT can be smaller or larger than MEMREQ. The caller should decide,based on the value of MEMGOT whether it is worthwile to start solving the problemor not. In any case GFGETM should be followed by a GFFREM. In case you want touse the memory, you can partition the array and pass on the partition boundaries toa subroutine. In this way the subroutine can operate on ``normal'' arrays, while stillhaving the advantage of dynamic memory. For an example see appendix LP-4.

ARRAY (input)

Page 39: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

A double precision vector, used for accessing the allocated memory.

FIRST (output)

The first useable position in the array.

Page 40: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

40

MEMREQ (input)

The amount of memory to be requested, in units of double precision reals (normally8 bytes).

MEMGOT (output)

The amount of memory allocated. Your program should check that this is ≥MEMREQ and terminate if not.

MAXMEM (output)

The maximum amount of memory that can be allocated (again in units of doubleprecision reals), or 0. Some operating systems allow us to give back the maximumsize we can allocate. For those systems we return it. Others cannot do it, there wereturn 0.

Example of use

See appendix LP-4.

Machine specific behavior

DOS (real mode)

On DOS (Microsoft Fortran) GFGETM always allocate all memory that is available,regardless the value of REQMEM. DOS is a single tasking operating system, and thememory that is not used, can not be used for anything. This is the rationale toallocate everything.

UNIX,386

On all UNIX systems and on the 386 (NDP Fortran) we allocate exactly what isasked for. If this is not available nothing is allocated (in which case we do a binarysearch to find out the maximum that could be allocated).

Page 41: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFINDX

Returns the length of the string ST minus the number of trailing blanks.

Fortran INTEGER FUNCTION GFINDX(ST)CHARACTER*(*) ST

Pascal n.a.

C n.a.

Example of use

c read option file

CALL GFOPTI(OPTFLN) ! get option file name OPTLEN = GFINDX(OPTFLN) ! calc length of filename IF (USEOPT) THEN IF (GFOPOK(IOOPT)) THEN ! if true, that start reading WRITE(IOLOG,13) OPTFLN(1:OPTLEN) ! write message to log CALL RDSPEC(IOOPT,IOSTA,IOLOG) ! read option file CLOSE(IOOPT) ELSE ! write message to log and status file WRITE(IOLOG,11) OPTFLN(1:OPTLEN) CALL GFSTCT('START') WRITE(IOSTA,11) CALL GFSTCT('STOPC') ENDIF ENDIF

11 FORMAT(' Cannot find option file ',A,/ & ' Using defaults instead.') 13 FORMAT(' Reading option file ',A)

Page 42: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

42

SUBROUTINE GFINIT

Subroutine GFINIT is used to initialize the library routines. It must be called beforeany of the other routines. It initializes the clock and various internal variables.

Fortran SUBROUTINE GFINIT(IOUNIT, IOSTA, SCREEN)INTEGER IOUNIT, IOSTA, SCREEN

Pascal procedure gfinit;

C gfinit()

Description of the parameters

Note that the Pascal and the C versions do not have the i/o units as parameters. Thisis because in Fortran one has to reserve i/o units for files, and those i/o units areglobal. I.e. the library cannot pick any i/o unit number, because this may already bein use by the user.

In the case of Pascal, the files iolog, iosta and ioscrn are declared as global data. Aninclude file containing the declarations should be included immediately after theprogram or module header. All these files are of type text.

IOUNIT (input)

This is the Fortran file unit that will be used to read and write the potentially largedata files. These are the data (matrix) file, the nonlinear instruction file (if there arenonlinearities), the solution file, and the matrix output file (normally only withspecial iterative solvers such as DICOPT). Note (a) you should not use this unit foryour own files, and (b) only one of the above named files can be opensimultaneously. Termination will occur if you intermingle operations on these files.The library routines will open each one on the first call that uses it, and close it afterthe last.

IOSTA (input)

This is the unit for the status file. The user should open the status file, after callingGFINIT, GFRCNT, and GFSTAT but before any other library routine. This file shouldbe opened for writing, and it should be an ordinary text file. Note that the libraryalso provides a routine for this purpose: GFOPST. You can write your ownmessages to the status file so that they will appear in the GAMS listing (.LST) file.For the exact format of the status file see the paragraph about the status file.

Page 43: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SCREEN (input/output)

This unit is connected to the screen. If necesary it will be opened by GFINIT.Depending on the user's program, this unit may be used to write summaryinformation to an interactive user. This argument should be a variable and not aconstant!

There are two units which can be used to pass information to the user: the screen(unit SCREEN) and the log file (unit IOLOG, available after calling GFRCNT). All theinformation written to the screen is directly written to the console, withoutinterference of the library. The information written to the log file however, canappear either on the screen, or on a disk file or may vanish. This depends on howGAMS is called. A GAMS call with the options1 LOGOPTION=2 andLOGFILE=SCREEN.DMP, will redirect all the output you will normally see on thescreen to the file SCREEN.DMP. A GAMS invocation with LOGOPTION=0 will causeGAMS to run in silent mode. The default is LOGOPTION=1: output to the console.If you want the output of your solver to behave accordingly, you should write to theIOLOG unit instead of the SCREEN unit or *. This option is useful in differentsituations: users run both gams and the solver in silent mode, which is nice whenyou have slow communication lines, or more important, when GAMS is embeddedin a larger system. The complete screen output of a session can be written to a diskfile, which may be helpful in case something is going wrong.

If you want to prevent the user from redirecting a message (say you want to haveyour copyright message always to appear on the screen) then use the SCREEN unit.Note: on UNIX systems the GFINIT may reset the SCREEN unit to 0 (stderr) or 6(stdout), because writing directly to /dev/tty can cause problems when the programis executed on a network under control of a remote shell. Therefore SCREEN shouldbe variable and not a constant!

1 For an exact description of the GAMS options see the GAMS documentation.

Page 44: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

44

SUBROUTINE GFMACH

Subroutine GFMACH returns a set of machine constants, like EPS, HUGE, etc. Wehave listed here the values that are returned when the machine is using doubleprecision (8 byte) IEEE floating point.

Fortran SUBROUTINE GFMACH(RMACH, IMACH)DOUBLE PRECISION RMACH(6)INTEGER IMACH(4)

Pascal procedure gfmach(var mach: machrec);

C gfmach(mach)machrec *mach;

Description of the parameters

RMACH (output)

RMACH(1) Epsilon, the smallest value ∈ > 0, such that 1.0 + ∈ ≠ 1.0. Sometimes an approximation of thisvalue is returned with RMACH(1) > ∈. Fordouble precision IEEE floating point arithmeticthis value is 2.220446049250313E-16.

RMACH(2) Huge, largest positive real number that can berepresented by the machine. Any expressionreturning a value larger than Huge may triggeran overflow exception. IEEE double precisionvalue: 1.797693134862316E+308.

RMACH(3) MinExponent, largest negative decimal exponentthat can be respresented by the machine. Doubleprecision IEEE value: -307.

RMACH(4) MaxExponent, largest positive decimal exponentthat can be respresented by the machine. Doubleprecision IEEE value: 308.

RMACH(5) Precision, the number of significant decimaldigits. Double precision IEEE value: 15.

Page 45: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

RMACH(6) Tiny, smallest positive number that can berepresented by the machine. Double precisionIEEE value: 2.225073858507201E-308.

Notice that on VAX/VMS there are two REAL*8 floating point formats:D_floating (the default) and G_floating. If your solvers require G_floating, the IOlibrary has to be translated from generic fortran into VMS by fortrans with gfloatdefined. The DEC AXP running OpenVMS has G_floating as default (which iscurrently the only one we support). G_floating is represented by a file type of 4 inthe gamscomp.txt file.

IMACH (output)

This integer array returns the sizes of different data types in terms of the allocationunits ("words") that are being used by the dynamic memory allocation routinesGFGETM.

IMACH(1) intw, the number of (long) integers that fit in aword.

IMACH(2) shortw, the number of short integers that fit in aword. If no short integers exist on a certainmachine, intw is returned.

IMACH(3) llogw, the number of long logicals (LOGICAL*4)that fit in a word.

IMACH(4) slogw, the number of short logicals (LOGICAL*1

or LOGICAL*2 depending on the machine) that fitin a word.

C version

The C version only returns the RMACH parameters. For interrogating sizes usesizeof(). The machrec type is defined as:

typedef struct { double rmach[6+1]; } machrec; .

Notice that we start at [1]. rmach[0] is undefined.

Page 46: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

46

SUBROUTINE GFMSG

Writes a message to the log file and the status file. It checks is both files are alreadyopened. In case log file is not available yet it writes the message to standard outputusing WRITE(*,*).

Fortran SUBROUTINE GFMSG(MSG)CHARACTER*(*) MSG

Pascal n.a.

C n.a.

Description of the parameters

MSG (input)

Message to be printed.

Page 47: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFOPOK

Function GFOPOK returns true if opening of the option file was successful, and itreturns false otherwise. It uses GFOPTI for this purpose. For the C version a NULL

pointer is returned if opening the file was unsuccessful.

Fortran LOGICAL FUNCTION GFOPOK(IUNUT)INTEGER IUNIT

Pascal function gfopok(var f : text) : boolean;

C FILE* gfopok();

Example of use

c read option file

CALL GFOPTI(OPTFLN) ! get option file name OPTLEN = GFINDX(OPTFLN) ! calc length of filename IF (USEOPT) THEN IF (GFOPOK(IOOPT)) THEN ! if true, that start reading WRITE(IOLOG,13) OPTFLN(1:OPTLEN) ! write message to log CALL RDSPEC(IOOPT,IOSTA,IOLOG) ! read option file CLOSE(IOOPT) ELSE ! write message to log and status file WRITE(IOLOG,11) OPTFLN(1:OPTLEN) CALL GFSTCT('START') WRITE(IOSTA,11) CALL GFSTCT('STOPC') ENDIF ENDIF

11 FORMAT(' Cannot find option file ',A,/ & ' Using defaults instead.') 13 FORMAT(' Reading option file ',A)

NB. The function GFINDX returns the length of a string minus the number of trailingblanks.

Page 48: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

48

SUBROUTINE GFOPST

Subroutine GFOPST opens the status file. It calls GFSTAT to find out the name of thefile.

Fortran SUBROUTINE GFOPST()

Pascal procedure gfopst;

C gfopst()

Page 49: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFOPTI

Subroutine GFOPTI returns the option file name so that you can open the option fileand parse it. This is only done if useopt, returned by GFRCNT, is true. Beware thatthe option file may not exist (GAMS is not checking on that): you should checkwith an INQUIRE statement before you attempt to read it. If it does not exist, just usedefault values for all settings. This routine should not be called before callingGFRCNT, because otherwise the filename is not known yet.

It is advised to use the routine GFOPOK for this purpose. Opening the option fileturns out to be a machine specific piece of code: some systems, notably CMS, toinclude code that is different from other platforms. GFOPOK will hide this for you.

Fortran SUBROUTINE GFOPTI(FLN)CHARACTER*80 FLN

Pascal procedure gfopti(var fln : filename)

C gfopti(fln)char **fln;

Example of use

CHARACTER*80 FLNOPT LOGICAL EXISTS. USEOPT : CALL DEFAULT ! set default values IF (USEOPT) THEN ! this comes from CALL GFOPTI(FLNOPT) ! get option file name INQUIRE(FILE=FLNOPT,EXIST=EXISTS) ! test for existance IF (EXISTS) CALL RDOPTS(FLNOPT) ! if ok read option file ENDIF :

Page 50: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

50

SUBROUTINE GFPGSZ

Subroutine GFPGSZ returns the page width and the page size of the listing file thatGAMS will produce. This information can be used for writing a status file thatmatches these sizes. This routine should not be called before GFRCNT.

Fortran SUBROUTINE GFPGSZ(PAGWID,PAGSIZ)INTEGER PAGWID, PAGSIZ

Pascal procedure gfpgsz(var pagwid, pagsiz : integer)

C gfpgsz(pagwid, pagsiz)int *pagwid, *pagsiz;

Page 51: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFRCER

Subroutine GFRCER passes on an error message concerning row IROW and columnICOL to GAMS. GAMS will translate these numbers into the correct GAMS name.Typical use for this routine is to report a jacobian element that looks suspicious in anon-linear programming algorithm.

Fortran SUBROUTINE GFRWER(IROW,ICOL, MSGNO,MESS)INTEGER IROW. MSGNOCHARACTER*(*) MESS

Pascal procedure gfrwer(irow, icol, msgno: integer, mess : messt);

C gfrwer(irow,icol,msgno,mess)int irow, icol, msgno;char *mess;

Description of the parameters

IROW (input)

IROW is the row number of the equation corresponding to this error.

ICOL (input)

ICOL is the column number of the variable corresponding to this error.

MSGNO (input)

MSGNO is the number of the error message. This number is used for look up. Onlyone instance of the message string is stored inside GAMS, where message stringsare considered to be the same if the message number is the same. Note that nocheck on the string itself is done, so it is your responsibility to make sure that themessage numbers are different for different messages. The allowed range forMSGNO is from 1 to 100.

MESS (input)

MESS is the string containing the message. GAMS will store and report only thefirst 50 characters of this string (ignoring the leading blanks).

Page 52: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

52

SUBROUTINE GFRCNT

Subroutine GFRCNT is used to read and return control information. Values arereturned in vectors to avoid an overwhelmingly long parameter list. However,many of the returned values are given acronyms in the explanation so they can beeasily referred to later.

Fortran SUBROUTINE GFRCNT(IOCNTR, IOLOG,& MIPOK, NLPOK,& XGV, KGV, LGV, KNV, KMV) INTEGER IOCNTR, IOLOG LOGICAL MIPOK, NLPOK INTEGER KGV(30), KNV(30), KMV(30) LOGICAL LGV(30) DOUBLE PRECISION XGV(30)

Pascal procedure gfrcnt(mipok, nlpok : boolean; var cntinfo : cntrec);

C gfrcnt(mipok, nlpok, cntinfo, argi)BOOLE mipok, nlpok;cntrec* cntinfo;char *arg1;

Description of the parameters

IOCNTR (input)

IOCNTR is the unit number to be used for reading the control file. Normally thecontrol file name is passed through the command line (see the section Connectingyour solver with GAMS), or through redirection. On some machines you shouldprovide a correct environment for opening this file (see the implementation notes).The file will be opened and closed by GFRCNT.

IOLOG (input, output)

This is the unit for the log file. Normally the log file is connected to the screen, butit can also be a disk file or a scratch file. The user can write information about theprogress of the algorithm to this unit. The log file is opened by GFRCNT. Theoutput value of IOLOG is either the input value (i.e. it is not changed), or it is thevalue you specified for SCREEN in the GFINIT call. See the discussion on GFINIT.

MIPOK (input)

Set this variable to .TRUE. if discrete variables can be handled, to .FALSE. value ifnot. If not, but they appear in this problem, the program will be terminated.

Page 53: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

NLPOK (input)

Set this variable to .TRUE. if nonlinearities can be handled, to .FALSE. value if not.If not, but they appear in this problem, the program will be terminated.

XGV (output)

The vector XGV is a general real (double precision) vector. The meaning of theelements is shown in the table below.

XGV(1) Resource limit in seconds, reslim. Thesolver should terminate if more than reslimCPU seconds have been elapsed. See theparagraph about GFCLCK for moreinformation about timings.

XGV(2)-XGV(6) A set of 5 real user cells that can be set by the user'sGAMS program. This should only be used in thedevelopment phase of the solver.

XGV(7) The value of the MIP absolute optimality criterion. Thisis the OPTCA option in the GAMS model. Only appliesto integer problems, i.e. if ismip (see further) is true.The MIP solver should stop, as soon as the best solutionpossible is within OPTCA of the best integer solutionfound so far.

XGV(8) The value of the MIP relative optimalitycriterion. This is the OPTCR option in the GAMSmodel. Only applies to mixed integer problems,i.e. if ismip is true. The MIP solver should stop,as soon as the best solution possible is within100 X OPTCR percent of the best integer solutionfound so far.

XGV(9) The value of the WORK option in GAMS. Thisvalue can be used to override core estimations.This value is normally used in Fortran basedsolvers who want to use dynamic memory.

Page 54: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

54

XGV(10) The value GAMS uses for + ∞: plinfy.

XGV(11) The value GAMS uses for - ∞: minfy.

XGV(12) The value GAMS uses for ``undefined'': undef.

XGV(13) The value GAMS uses for ``not available'': na.

XGV(14) The value GAMS uses for ``epsilon'': eps.

XGV(15) Cutoff value, cutoff. If icutof=1 (see the KMV

array) this value can be used to ignore parts ofthe branch and bound tree that have a bestpossible value worse than this one. Also knownas incumbent. In case of maximization any partof the tree with an upperbound lower than thisvalue can be ignored. This cell is only set if themodel is a MIP model.

XGV(16) Cheating parameter, cheat. If icheat=1 (see theKMV array), this value can be used to explore thebranch-and-bound tree is a quicker fashion.Every new node should be at least |cheat| betterthan the current node. In other words, once aninteger solution is found, the cutoff valuemaintained by the algorithm may be updated byadding (or subtracting in case of minimization)the absolute value of this parameter to (from) thecurrent cutoff. If icheat=0 don't use cheating.This cell is only set if the model is a MIP model.

XGV(17)..XGV(30) Reserved for future use.

KGV (output)

The vector KGV is a general integer vector.

KGV(1) The number of row records in the matrix, numrow.There is no objective row in this matrix -- one may needto be added (see below).

Page 55: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

KGV(2) The number of column records in the matrix, numcol.

KGV(3) The number of nonzeroes in the matrix, numnnz. It maybe necessary to add one for the objective row. Thenumber of nonzeroes in the rhs-vector are not includedin this figure.

KGV(4) The number of the numrow right-hand-side values thatare nonzero, numrhs.

KGV(5) The number of the numcol columns that are fixed,numfxv.

KGV(6) The largest number of nonzeroes in a column, maxcol.

KGV(7) The sequence number in the matrix of the objectivevariable, iobvar.

KGV(8) Iteration limit, itnlim. After the solver has performeditnlim iterations it should terminate, and write a solutionfile with an indication that the maximum number ofiterations is exceeded.

KGV(9)-KGV(13) A set of 5 integer user cells that can be set by the user'sGAMS program. These can be used a rudimentary formof an option file. Of course, if the solver is in generaluse it should have a well-designed option file.

The next few cells are useful to find out if the model can be "reformulated"by substituting out the GAMS objective variable. In many cases users havea free objective variable that really defines an objective function, eg:

OBJ.. Z =E= ....;

In some cases it is needed or advantageous for the solver to consider the rhsof OBJ as the objective function. Of course in general the expression is:

a*z + f(x) = b;

We can reformulate and use

Page 56: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

56

( b - f(x) ) / a

as objective if the following conditions hold:

(1) The objective variable is a free variable (user may have specifiedbounds on it).

(2) The objective variable should appear only in this row.

(3) This row is an equality.

(4) and z is a linear variable.

Notice that we have the constant b/a in the objective. In many cases one hasto take this constant out of the objective, remember it and compensate theobjective before reporting the solution. When reporting the solution z has tobe reconstructed as well as the equation OBJ (i.e. level and marginal). As zis a free variable the marginal (reduced cost) can be made 0 (basis status:BASIC). The OBJ row is binding and the dual should be made -1 or +1depending on whether we are minimizing or maximizing.

In case reformulation is not possible one should add a dummy row to themodel with only one nonzero element: a +1 or -1 in the GAMS ObjectiveVariable position. This increases the number of rows by 1 and the numberof nonzeroes also by 1.

KGV(14) Number of nonzeroes in the objective. If > 1 theobjective variable appears in more than one row andreformulation is not possible.

KGV(15) Last row index in the objective column. If KGV(9)=1 thenthis points to the objective row.

KGV(16) 0 if there are no bounds on the objective variable, 1 ifthe objective variable has bounds.

KGV(17) Number of =E= constraints in the model.

KGV(18) Number of =G= constraints in the model.

Page 57: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

KGV(19) Number of =L= constraints in the model.

KGV(20) Number of =N= constraints in the model.

KGV(21)..KGV(30) Reserved for future use.

LGV (output)

The vector LGV is a general logical vector.

LGV(1) If .TRUE. use basis information implicit in the matrix, if.FALSE., do not, usebas.

LGV(2) If .TRUE., attempt to read user's option file at theappropriate time. If .FALSE, do not, useopt. The formatand syntax of the option file are the responsibility of thealgorithm builder. Also reading and parsing the optionfile is left to the solver. For an example how toimplement an option file parser, see the section on theoption file.

LGV(3) If .TRUE., the sense of optimization is to minimize,otherwise maximize, ismin.

LGV(4) If .TRUE., the problem contains discrete (binary orinteger) variables. Otherwise not, ismip.

LGV(5) If .TRUE., the problem contains nonlinearities.Otherwise not, isnlp.

LGV(6) The SYSOUT option in GAMS. If .TRUE., GAMS willcopy the complete status file to the listing file. (You canalso force this from within the solver by the subroutine call:

CALL GFSTCT('SYSOUT').

LGV(7)..LGV(30) Reserved for future use.

KNV (output)

Page 58: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

58

KNV is a general integer vector. It is used in accomodating nonlinearities.Assignments are made to this vector only if you said you could handlenonlinearities, i.e. if nlpok is true.

KNV(1) Count of rows that contain nonlinear terms, numnnr.

KNV(2) Count of the variables that appear nonlinearly in theproblem, numnnv. This will never be set to zero if theproblem is nonlinear, i.e. it is a good indicator to testwhether a model is non-linear.

KNV(3) Count of nonzero elements in the incidence matrix thatcorrespond to nonlinear terms. Again this will never bezero if the problem is nonlinear.

KNV(4) The length of the array needed to store the nonlinearinstructions, lenins. This will be a general integer array.

KNV(5) Workspace needed by the non-linear instructioninterpreter nlwork.

KNV(6) Number of domain errors allowed while evaluatingnonlinearities, maxerr.

KNV(7) The maximum address that can be stored in the addressfield of a non-linear instruction. When movinginstruction you should not exceed this limit.

KNV(8)..KNV(30) Reserved for future use.

KMV (output)

KMV is a general integer vector. The values are used in accomodating mixedinteger programs. Assignments are made to this vector only if you specified thatyou can handle discrete variables, i.e. if mipok is true.

KMV(1) Count of binary variables in the problem, binvar.

KMV(2) Count of integer variables in the problem, intvar. Thetotal number of discrete variables is binvar + intvar +SOS1var + SOS2var.

Page 59: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

KMV(3) Number of binary variables needed to represent all theinteger variables int the in the problem, bin2var. If thesolver can only handle binary variables, a generalinteger variable Xk ∈ {1,...,M} can be converted to asum of binary variables bi using the expansion:

χk=ΣL

i=12i-1bi

where L = Llog2MO. KMV(3) reports the sum of allvalues of L for each integer variable. The total numberof zero-one variables required is then binvar + bin2var+ SOS1var + SOS2var. If your solver can handlegeneral integer variables you should not use thisexpansion.

KMV(4) Count of variables of SOS type I in the problem,SOS1var.

KMV(5) Count of variables of SOS type II in the problem,SOS2var.

KMV(6) User specified node limit. If this value is zero, thenignore it, otherwise stop as soon as number of nodesstored in the node table exceeds this number. nodlim.

KMV(7) icutof, indicator whether or not the user has specified acutoff value or incumbent. icutof =0 means no value isspecified, icutof=1 means: user specified a cutoff valueof cutoff. This value can be found in the XGV array.This value can then be used to ignore parts of the branchand bound tree (i.e. parts that exceed this cutoff).

KMV(8) icheat, indicator whether or not the user has specified acheat parameter. The value of the cheat parameter canbe found in the XGV array. If user wants to cheat, he iswilling to risk missing integer solutions in order toexplore the tree faster. icheat=0 indicates that the userdoes not want to cheat, icheat=1 indicates that cheatingis requested.

Page 60: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

60

KMV(9) priots, indicator whether priorities are specified by theuser. priots=0 means no priorities and priots=1 meanspriorities are present. If this value is 1 then for eachdiscrete variable a priority is passed on by GAMS.

KMV(10)..KMV(30) Reserved for future use.

Page 61: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFRCOF

Subroutine GFRCOF is used to read a nonzero record from the data file. There mustbe nnzcol calls to GFRCOF between each call to GFRCOLX (above). The data file willbe closed after the very last call to GFRCOF.

Fortran SUBROUTINE GFRCOF(COEFF, IROSEQ, NLTYP)DOUBLE PRECISION COEFFINTEGER IROSEQ, NLTYP

Pascal procedure gfrcof(var coeff : float; var iroseq, nltyp :integer);

C gfrcof(coeff, iroseq, nltyp)double *coeff;int iroseq, nltyp;

Description of the parameters

COEFF (output)

The value of the coefficient.

IROSEQ (output)

The sequence number of the row in which this coefficient occurs.

NLTYP (output)

Only useful if there are nonlinearities (isnlp). Value 0 is returned if this is aconstant (linear) coefficient, 1 otherwise.

In appendix 1 Fortan code is presented that shows how to read a problem into afixed size array system. The same program but using dynamic arrays is shown later.Also a Turbo Pascal and a C version is shown.

Page 62: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

62

SUBROUTINE GFRCOLX

Subroutine GFRCOLX is used to read a column record from the data file. The firstcall to this routine must be preceded by exactly numrow calls to GFRROWX. Theremust be nnzcol calls to GFRCOF between successive calls to GFRCOLX, to return thenonzero elements of each column in sequence.

Fortran SUBROUTINE GFRCOLX(CDATA,IDATA)DOUBLE PRECISION CDATA(5)INTEGER IDATA(4)

Pascal procedure gfrcolx(var coldata : colrec);

C gfrcolx(coldata)colrec *coldata;

Description of the parameters

CDATA (output)

This double precision vector contains the level and the bounds of the variables.

CDATA(1) The lower bound on the column. Note that you shouldcheck whether this is the special value corresponding to-INF. (See GFSPVL)

CDATA(2) The level value for the column. It will not be one of thespecial values.

CDATA(3) The upper bound on the column. Note that you shouldcheck whether this is the special value corresponding toINF. (See GFSPVL).

CDATA(4) If this is a discrete row (IDATA(3) <> 0) and (priots = 1)(see KMV(9) in GFRCNT), then this value is the priority ofthe current variable. Priorities are real numbers andlower numbers mean higher priorities. You have to scalethe numbers that are provided here to your own prioritynumbers (often integers between 1 and 255). This can bedone once all the numbers have been read. For instanceif your range is 1..255, and you have stored the realpriorities provided by gams in xprior[i] and you wantyour integer priorities in iprior[i] iprior[i] := int(

Page 63: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

(xprior[i]-lo+d)/d + 0.001) where lo := min(xprior[i])and hi := max(xprior(i)) and d = (hi-lo)/255.

CDATA(5) dual value (reduced cost) for column. Can be used forwarm restarts.

Page 64: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

64

IDATA (output)

The vector IDATA is a general integer vector.

IDATA(1) The number of nonzero coefficient in this column, (alsothe number of coefficient records following), nnzcol.

IDATA(2) The marginal value for the column. This will be either$+1$ (not basic) or 0 (basic). This information is used ifa basis has to be constructed, as indicated by usebas.

IDATA(3) The variable type. A nonzero value means that thevariable is discrete. The following map shows therelationships.

IDATA(3) Variable type0 Continuous variable1 Binary variable2 Integer variable3 SOS type 1 variable4 SOS type 2 variable

IDATA(4) The new SOS set indicator. This variable is only usefulif the problem contains discrete variables, and thevariable type is SOS I or SOS II. If the current column isthe first member of an SOS set, IDATA(4) will be setnonzero, else to zero.

Page 65: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFRDOP

This is the option file reader for Fortran. It is a little bit complex due to "sparse"storage of strings. If you only have integer and real options things are easy. Forstring options a little bit more work is required,

Fortran SUBROUTINE GFRDOP(U,IOSTA,IOLOG,& N, MAXS, IVAL, RVAL,& MAXSTR, NSTR, FLAG,& KW, TYPE, SVAL)INTEGER U, IOSTA, IOLOGINTEGER N, MAXSCHARACTER*10 KW(N)CHARACTER*1 TYPE(N)CHARACTER*80 SVAL(MAXS)INTEGER IVAL(N)DOUBLE PRECISION RVAL(N)INTEGER MAXSTR(MAXS), NSTR(MAXS)LOGICAL FLAG(N)

Pascal n.a.

C n.a.

Description of the parameters

U (input)

Unit to be used by the option file reader

IOSTA (input)

Unit of status file (content of the option file will be echoed to the status file).

IOLOG (input)

Unit of the log file (content of the option file will be echoed to the log file).

N (input)

Number of different options

KW (input)

Page 66: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

66

Keyword of each option. Must be unique (this is not checked). Keywords should bespecified in uppercase.

TYPE (input)

Array of types:

type description'I' Integer'R' Real (i.e. double precision)'S' String (i.e. CHARACTER*80)'T' String or empty'N' No argument

IVAL (input/output)

For integer options K, IVAL(K) may be set by the user. For a string option K, thecaller has to specify in IVAL(K) the position L in the array SVAL where the stringhas to be stored.

RVAL (output)

For real options K, RVAL(K) may be set by the user.

SVAL (output)

For a string option K, SVAL(IVAL(K)).... will contain user specified strings.

FLAG (output)

If FLAG(K) = .TRUE. then the user has set option K.

MAXSTR (input)

String option K can have up to MAXSTR(IVAL(K)) string arguments

NSTR (output)

String option K has NSTR(IVAL(K)) string arguments (NSTR(IVAL(K)). LE.

MAXSTR(IVAL(K))).

Page 67: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFRROWX

Subroutine GFRROWX is used to read a row record from the data (matrix) file. Thisfile will be opened on the first call to this routine, so you don't have to worry aboutthat. If you call this routine more times than there are rows in the problem, an errormessage will be issued and the program will be terminated.

Fortran SUBROUTINE GFRROWX(RDATA, IDATA)DOUBLE PRECISION RDATA(3)INTEGER IDATA(2)

Pascal procedure gfrrowx(var rowdata : rowrec);

C gfrrowx(rowdata)rowrec *rowdata;

Description of the parameters

RDATA (output)

The vector RDATA is a general real (double precision) vector.

RDATA(1) An indication that a variable is superbasic. If nonzero, itis the row activity level: SUM(J,A(I,J)*X(J)). If themarginal is zero, RDATA(1) will also be zero. It is only tobe used by some NLP solvers, like MINOS.

RDATA(2) The right-hand-side value, bj.

RDATA(3) Dual value (marginal) for row. This can be used towarm restarts.

IDATA (output)

The vector IDATA is a general integer vector.

IDATA(1) The type of the equation. The values are in the rangeIDATA(1) in {0,1,2,3}, with the following meaning:

constraint type GAMS syntax IDATA(1)equality =E= 0greater-than constraint =G= 1

Page 68: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

68

less-than constraint =L= 2free row =N= 3

IDATA(2) The marginal value indicator for the row or slack. Thiswill be either +1 (not basic) or 0 (basic). Thisinformation is used if a basis has to be constructed, asindicated by usebas. Some hints on how to set up a basisbased on these marginal indicators is given in theparagraph

Page 69: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFRWER

Subroutine GFRWER passes on an error message concerning row IROW to GAMS.GAMS will translate this row number into the correct GAMS name.

Fortran SUBROUTINE GFRWER(IROW,MSGNO,MESS)INTEGER IROW. MSGNOCHARACTER*(*) MESS

Pascal procedure gfrwer(irow, msgno: integer, mess : messt);

C gfrwer(irow,msgno,mess)int irow, msgno;char *mess;

Description of the parameters

IROW (input)

IROW is the row number of the equation corresponding to this error.

MSGNO (input)

MSGNO is the number of the error message. This number is used for look up. Onlyone instance of the message string is stored inside GAMS, where message stringsare considered to be the same if the message number is the same. Note that nocheck on the string itself is done, so it is your responsibility to make sure that themessage numbers are different for different messages. The allowed range forMSGNO is from 1 to 100.

MESS (input)

MESS is the string containing the message. GAMS will store and report only thefirst 50 characters of this string (ignoring the leading blanks).

Page 70: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

70

SUBROUTINE GFSDIR

Subroutine GFSDIR returns the system directory, i.e. the directory where the gamssystem files are residing. Note that you can only assume that the user has readpermission to this directory.

Fortran SUBROUTINE GFSDIR(SYSDIR)CHARACTER*80 SYSDIR

Pascal procedure gfsdir(var sysdir : pathname);

C gfsdir(sysdir)char **sysdir;

Description of the parameters

SYSDIR (output)

SYSDIR is a character string that contains on exit the system directory.

Page 71: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

FUNCTION GFSGET

Extracts the i-th token from a string. Tokens are series of non-blank characters, andare separated by (one or more) blanks.

Fortran SUBROUTINE GFSGET(I,LINE,TOKEN)INTEGER ICHARACTER*(*) LINE,TOKEN

Pascal n.a.

C n.a.

Description of the parameters

I (input)

The sequence number of the token you are interested in.

LINE (input)

Input string. Is not altered by this routine.

TOKEN (output)

String containing the result. Will be ``empty'' for non-existing parameters, i.e. if i<1or i>maxtok TOKEN will get assigned the string ' '.

Page 72: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

72

SUBROUTINE GFSTAT

Subroutine GFSTAT returns the status file name so that you can open the status file.This routine should be called after GFRCNT. Normally you would use GFOPST forthis: GFOPST calls GFSTAT and opens the file for you.

Fortran SUBROUTINE GFSTAT(FLN)CHARACTER*80 FLN

Pascal procedure gfstat(var fln : filename);

C gfstat(fln)char** fln;

In Fortran you should open the status file with the same unit number you passed onto GFINIT. The file format should be a flat text file. The next code fragmentillustrates this

PROGRAM EXAMPLE1

INTEGER IOSTA ! unit number of the status file INTEGER GFUNIT ! unit number for internal lib routines INTEGER IOLOG ! unit number log file INTEGER SCREEN ! unit number screen INTEGER IOCNTR ! unit number control file DOUBLE PRECISION XGV(30) ! storage control info INTEGER KGV(30) LOGICAL LGV(30) INTEGER DUMMY

C define the unit numbers

IOSTA = 10 IOLOG = 11 GFUNIT = 12 SCREEN = 3 IOCNTR = 2

C initialize and read control file

CALL GFINIT(GFUNIT, IOSTA, SCREEN) CALL GFRCNT(IOCNTR, IOLOG, .FALSE., .FALSE., & XGV,KGV,LGV,DUMMY,DUMMY)

C open status file, next two statements can be replaced by

CALL GFOPST()

Page 73: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

C write a message to the satus file

CALL GFSTCT('STARTC') WRITE(IOSTA,*) ' ********************************' WRITE(IOSTA,*) ' * SUPERLP, BY SOLVERS INC. *' WRITE(IOSTA,*) ' ********************************' CALL GFSTCT('STOPC')

END

Some of the routines in this example are explained in the next few pages.

Page 74: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

74

SUBROUTINE GFSTCT

Subroutine GFSTCT controls the status file. Using this routine you can give thefollowing commands to GAMS while it is reading the status file: start copying, stopcopying, page eject, character switch and sysout.

A page eject will tell GAMS to insert a page eject at this place when it is insertingthe status file into the GAMS listing file. The page size for the listing file can beinterrogated by a call to GFPGSZ.

A character switch tells GAMS not longer to consider a "=" in column 1 as acontrol character, but to use another character for that purpose. For example CALL

GFSTCT('CHRSW#') will switch the control character to "#". Normally one shouldnot use an alphanumeric character for this purpose, but if you do, you should kownthat the character you pass on, will be uppercased.

A sysout results in copying the complete status file into the GAMS listing file. Thismay be useful in case of an error. Note that this can also be forced in other ways:first through a GAMS option OPTION SYSOUT), and second by certain values of thesolver status and the model status (see GFWSTA).

Fortran SUBROUTINE GFSTCT(CMD)CHARACTER*(*) CMD

Pascal procedure gfstct(cmd : cmdstring);

C gfopst(cmd)char *cmd;

Description of the parameters

CMD (input)

CMD is a character string containing one of the following commands: 'STARTC','STOPC', 'EJECT', 'CHRSW.' or 'SYSOUT'.

Example of use

CALL GFSTCT('SYSOUT')

Page 75: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFTIME

Subroutine GFTIME returns the time when the current GAMS job started.

Fortran SUBROUTINE GFTIME(GMSTIM)CHARACTER*10 GMSTIM

Pascal procedure gftime(var gmstim : char10);

C gftime(gmstim)char **gmstim;

Description of the parameters

GMSTIM (output)

GMSTIM is a character string that contains on exit the time.

Page 76: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

76

SUBROUTINE GFUOPN

Opens a file, for which the user provides a filename. The file to be opened is a flatsequential text file.

Fortran SUBROUTINE GFUOPN(FLN, IUNIT, CMODE)CHARACTER*(*) FLNINTEGER IUNITCHARACTER CMODE

Pascal n.a.

C n.a.

Description of the parameters

FLN (input)

Filename of the file to be opened.

IUNIT (input)

Unit number to be used.

CMODE (input)

Character code that determines how the file should be opened. 'R' means forreading, 'W' for writing and 'A' for appending.

Page 77: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFUOPU

As GFUOPN but now for unformatted files. Notice that unformatted files areincompatible over different machines and over different compilers. You may useunformatted files for scratch files. Notice we do not provide any support for directaccess files, i.e. the organization is sequential.

Fortran SUBROUTINE GFUOPU(FLN, IUNIT, CMODE)CHARACTER*(*) FLNINTEGER IUNITCHARACTER CMODE

Pascal n.a.

C n.a.

Description of the parameters

FLN (input)

Filename of the file to be opened.

IUNIT (input)

Unit number to be used.

CMODE (input)

Characater code that determines how the file should be opened. 'R' means forreading, 'W' for writing.

BUGS:

This routine cannot be used while the matrix is being read or while the solution fileis being written.

Page 78: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

78

SUBROUTINE GFWBND

For MIP problems report the best possible integer solution, bstbnd. The user wantsto stop when either |objval-bstbnd| ≤ optca or |objval-bstbnd| ≤ optcr * |bstbnd|.The values for optca and optcr can be found in the arrays returned by GFRCNT.

Fortran SUBROUTINE GFWBND(BSTBND)DOUBLE PRECISION BSTBND

Pascal procedure gfwbnd(bstbnd : float);

C gfwbnd(bstbnd)double bstbnd;

Description of the parameters

BSTBND (input)

Use BSTBND to pass the best possible value for an integer solution.

Page 79: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFWCOL

Subroutine GFWCOL is used to write column records to the solution file. Exactlynumcol calls are required.

Fortran SUBROUTINE GFWCOL(LEVEL,MARGIN,& BASIND,VARSTA)DOUBLE PRECISION LEVEL,MARGININTEGER BASIND,VARSTA

Pascal procedure gfwcol(level, margin : float; basind, varsta :integer);

C gfwrow(level, margin, basind, varsta)double level, margin;int basind, varsta;

The same range considerations apply as to GFWROW. The parameters passed havethe same purpose as in GFWROW.

Description of the parameters

LEVEL (input)

The activity level for the column.

MARGIN (input)

The marginal value for the column. The following sign convention should be usedfor nonbasic columns in an optimal solution to be consistent with other solvers:

Minimization Maximizationat lowerbound positive negativeat upperbound negative positive

BASIND (input)

The basis indicator. Mapping is as below.

BASIND Basis status0 nonbasic at lower bound1 nonbasic at upper bound2 basic3 superbasic or non-basic but not at one of its

bounds

Page 80: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

80

The third option can be used for variables in an NLP which are superbasic,or in the case of a MIP, where a variable is non-basic and fixed by thealgorithm between its bounds. NOTE: The internal I/O routines may packthe solution by not passing back the level if it is at one of its bounds. So onlyuse option 0 or 1 if the levels are really at their original bounds.

In general this means that you have to be very careful with integer variables:in many cases they will have a status of lets say upper, but this is the state inthe last subproblem, which does not have the same bounds as the originalproblem ! In SCICONIC there is another problem: when using dynamicpresolve during the branch and bound even the bounds of the linearvariables may be changed. In case you want to be sure that the level value ispassed back without packing, declare it superbasic!

GAMS uses only the marginals to give a subsequent solve a hint how to setup the basis.

VARSTA (input)

The variable status indicator. Mapping is as below.

VARSTA Status0 normal (OK)1 non-optimal2 infeasible3 unbounded

To prevent conversion problems and system failure, this subroutine filters thevalues of LEVEL and MARGIN. All numbers closer to zero than dwarf = 1.0E-20 willbe set to zero. All numbers with magnitude equal to or larger than huge = 1.0E31$will be set to undefined when returned to GAMS. You can use the values epsilon,undefined, plinfy, and minfy (see GFRCNT) to return special values.

Page 81: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFWCTI

Optional routine for giving GAMS more fine-grained timing info.

Fortran SUBROUTINE GFWCTI(CALTIM)DOUBLE PRECISION CALTIM

Pascal procedure gfwcti(caltim : float);

C gfwrti(caltim)double caltim;

Description of the parameters

CALTIM (input)

Use CALTIM to pass the time the solver needed to solve the problem. This valueshould correspond to the pure calculation time, i.e. no input or output.

Page 82: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

82

SUBROUTINE GFWDIR

Subroutine GFWDIR returns the working directory, i.e. the directory where thelisting file is written to. Normally this is the users current directory. It can beassumed that the user has read and write permission to this directory.

Fortran SUBROUTINE GFWDIR(WRKDIR)CHARACTER*80 WRKDIR

Pascal procedure gfwdir(var wrkdir : pathname);

C gfwdir(wrkdir)char **wrkdir;

Description of the parameters

WRKDIR (output)

WRKDIR is a character string that contains on exit the working directory.

Page 83: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFWNOD

Optional routine to inform GAMS how many nodes were traversed in the branch-and-bound search.

Fortran SUBROUTINE GFWNOD(NODUSD)INTEGER NODUSD

Pascal procedure gfwnod(nodusd : integer);

C gfwnod(nodusd)integer nodusd;

Description of the parameters

NODUSD (input)

Use NODUSD to pass the number of nodes visited during the branch-and-boundsearch.

Page 84: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

84

SUBROUTINE GFWROW

Subroutine GFWROW is used to write row records to the solution file. Exactlynumrow calls are required.

Fortran SUBROUTINE GFWROW(LEVEL,MARGIN,& BASIND,EQSTAT)DOUBLE PRECISION LEVEL,MARGININTEGER BASIND,EQSTAT

Pascal procedure gfwrow(level, margin : float; basind, eqstat :integer);

C gfwrow(level, margin, basind, eqstat)double level, margin;int basind, eqstat;

Description of the parameters

LEVEL (input)

LEVEL is the activity level of the row: SUM(J, A(I,J)*X(J)).

MARGIN (input)

The marginal value for the row. The following sign conventions should be used forthe nonbasic rows in an optimal solution if you want to be consistent with othersolvers:

Minimization Maximization=L= constraint negative positive=G= constraint positive negative

BASIND (input)

The basis indicator. Mapping is as below. Note that this indicator is about theequation level, and not the slack (if the slack is non-basic at lowerbound, then thelevel is non-basic at upperbound).

BASIND Basis status0 nonbasic at lower bound

Page 85: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

1 nonbasic at upper bound2 basic3 superbasic or non-basic but not at one of its

bounds

EQSTAT (input)

The equation status indicator. Mapping is as below.

EQSTAT Status0 normal (OK)1 non-optimal2 infeasible3 unbounded

To prevent conversion problems and system failure, this subroutine filters thevalues of LEVEL and MARGIN. All numbers closer to zero than dwarf = 1.0E-20will be set to zero. All numbers with magnitude equal to or larger than huge =1.0E31 will be set to undefined when returned to GAMS. You can use the valuesepsilon, undefined, plinfy, and minfy (see GFRCNT) to return special values.

Page 86: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

86

SUBROUTINE GFWRTI

Optional routine for giving GAMS more fine-grained timing info.

Fortran SUBROUTINE GFWRTI(RDTIME)DOUBLE PRECISION RDTIME

Pascal procedure gfwrti(rdtime : float);

C gfwrti(rdtime)double rdtime;

Description of the parameters

RDTIME (input)

Use RDTIME to pass the time the solver needed to read the problem.

Page 87: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFWSTA

Subroutine GFWSTA opens the solution file, and writes the model and solver statusto it.

Fortran SUBROUTINE GFWSTA(MODSTA,SOLSTA,& ITSUSD,RESUSD,OBJVAL,DOMERR)INTEGER MODSTA,SOLSTA,ITSUSD,DOMERRDOUBLE PRECISION RESUSD,OBJVAL

Pascal procedure gfwsta(modsta, solsta, itsusd : integer;resusd, objval : float; domerr : integer);

C gfwsta(modsta, solsta, itsusd, resusd, objval, domerr)int modsta, solsta, itsusd, domerr;double resusd, objval;

Description of the parameters

MODSTA (input)

This is the model status, an integer value drawn from the following list which mostaccurately describes the solution to be returned, if any.

modsta Message produced by GAMS1 OPTIMAL2 LOCALLY OPTIMAL3 UNBOUNDED4 INFEASIBLE5 LOCALLY INFEASIBLE6 INTERMEDIATE INFEASIBLE7 INTERMEDIATE NONOPTIMAL8 INTEGER SOLUTION9 INTERMEDIATE NON-INTEGER

10 INTEGER INFEASIBLE11 NO SOLUTION12 * ERROR UNKNOWN13 * ERROR NO SOLUTION

An asterix in the table indicates that GAMS will trigger a SYSOUT.

SOLSTA (input)

This is the solver status. The mapping is below.

Page 88: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

88

solsta Message produced by GAMS1 NORMAL COMPLETION2 ITERATION INTERRUPT

3 RESOURCE INTERRUPT4 * TERMINATED BY SOLVER5 EVALUATION ERROR LIMIT6 UNKNOWN7 (free for future use)8 ERROR PREPROCESSOR ERROR(S)9 ERROR SETUP FAILURE10 * ERROR SOLVER FAILURE11 * ERROR INTERNAL ERROR12 ERROR POST-PROCESSOR ERROR13 * ERROR SYSTEM FAILURE

If the solver does not write a solution (for instance because is terminated due to afatal error), GAMS will notice this and will use a default solution that says:modsta=13 and solsta=13. For an explanation of the exact meaning of the messagessee page 117 of the GAMS User's Guide.

ITSUSD (input)

Use ITSUSD to pass the number of iterations used.

RESUSD (input)

Use RESUSD to pass the value of the used up CPU seconds.

OBJVAL (input)

OBJVAL must be set to the value of the user's objective variable. If the problem isreformulated, pass the value the variable would assume in the orginal problem.

DOMERR (input)

This is only used for NLP's, return 0 for LP's or MIP's. The number of evaluationerrors occured. If the NLP algorithm tries to evaluate SQRT(X), X<0 the system doesnot terminate immediately. Instead a ``reasonable'' number is returned, and thenumber of errors nlerrs is incremented by one. As soon as nlerrs >= maxerr, oneshould terminate the algorithm. Use this routine to report nlerrs to GAMS.

Page 89: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFWWTI

Optional routine for giving GAMS more fine-grained timing info.

Fortran SUBROUTINE GFWWTI(WRITIM)DOUBLE PRECISION WRITIM

Pascal procedure gfwwti(writim : float);

C gfwrti(writim)double writim;

Description of the parameters

WRITIM (input)

Use WRITIM to pass the time the solver needed to write the solution.

Page 90: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

90

FUNCTION GFXARG

Extracts the i-th parameter from the command line.

Fortran SUBROUTINE GFXARG(I,ARG)INTEGER ICHARACTER*(*) ARG

Pascal n.a.

C n.a.

Description of the parameters

I (input)

The sequence number of the command line parameter you are interested in.

ARG (output)

String containing the result. Will be ``empty'' for non-existing parameters, i.e. if i<1or i>maxarg ARG will get assigned the string ' '.

Page 91: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE MEMINF

Writes memory statistics in the same way as BDMLP, MINOS, ZOOM and OSL.On all machines except the PC the units in which info is printed is Megabytes. Onthe PC we use KB.

Fortran SUBROUTINE MEMINF(IOSTA, CON,& ESTIM, LUCORE, MAXZ, MAXBLK)INTEGER IOSTA,CONINTEGER ESTIM, LUCORE, MAXZ, MAXBLK

Pascal n.a.

C n.a.

Description of the parameters

IOSTA (input)

Unit number of the status file.

CON (input)

Unit number of the log file.

ESTIM (input)

Estimated memory requirements in 8-byte words.

LUCORE (input)

User provided memory request. 0 if not applicable. See GFRCNT.

MAXZ (input)

Size of obtained memory by GFGETM. Again in 8-byte words.

MAXBLK (input)

Maximum memory size that can be requested. 0 if not applicable. Returned byGFGETM.

Page 92: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

92

SUBROUTINE READDICT

Read the dictionary file

Fortran SUBROUTINE READDICT(IUNIT,ARRAY,CRMAX,CRUSED)INTEGER IUNITDOUBLE PRECISION ARRAY(*)INTEGER CRMAX, CRUSED

Pascal n.a.

C readdict()

Description of the parameters

IUNIT (input)

Unit number to read dictionary file

ARRAY (input)

A double precision vector, used for accessing the allocated memory.

CRMAX (input)

Maximum memory available in double words for dictionary file

CRUSED (output)

Memory used in double word reals

Page 93: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

CHAPTER 4

IMPLEMENTATION NOTES

Microsoft Fortran for 286 DOSNDP 4.4 Fortran for Extended DOS (386 and above)Unix: Sun OS 4.1.xIBM VM CMS

Page 94: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

94

MICROSOFT FORTRAN

For the 286 DOS environment, we use the Microsoft Fortran compiler, version 5.We compile the I/O library programs using the following makefile example:

#----------------------------------------#--- Microsoft fortran version 5.0 ------#----------------------------------------## because has to go into overlays# no library possible#F77 = flF77OPTS = /c /FPi /AH /Ox

OBJS = allmem.obj iolib1.obj iolib2.obj iolib3.objiolib4.obj \

iolib5.obj iolib6.obj

.for.obj: $(F77) $(F77OPTS) $<

iolib.lib: $(OBJS) echo all done

iolib1.$(OBJEXT) : iolib1.$(FOREXT) defines.inc gmscom.incnlcon1.inc

iolib2.$(OBJEXT) : iolib2.$(FOREXT) defines.inc gmscom.incnlcon1.inc

iolib3.$(OBJEXT) : iolib3.$(FOREXT) defines.inc gmscom.incnlcon1.inc

iolib4.$(OBJEXT) : iolib4.$(FOREXT) defines.inc gmscom.incnlcon1.inc

iolib5.$(OBJEXT) : iolib5.$(FOREXT) defines.inc gmscom.incnlcon1.inc

iolib6.$(OBJEXT) : iolib6.$(FOREXT) defines.inc gmscom.inc

allmem.obj : allmem.ob copy allmem.ob allmem.obj

The /c flag tells the compiler only to compile (no linking). The /AH flag says wewant to use the HUGE memory model. This is needed when you want to use arrays >64K. Also our dynamic memory routines require that the huge memory model isused. /FPi instructs the compiler to generate inline floating point code, and the /Oxoption tells the compiler to do its best on optimization. When using this libraryalways use the huge memory model.

Page 95: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

allmem.obj is a little assembly routine for the memory allocation.

Page 96: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

96

To link this into your program you could use something like:

#----------------------------------------#--- Microsoft fortran version 5.0 ------#----------------------------------------F77 = flF77OPTS = /c /FPi /AHF77NOPTS = /c /FPi /AH /OdLD = linkLDOPTS = @dolnkFOREXT = forOBJEXT = objEXENAME = gams2bdm.exeSPECOBJS = allmem.objIOLIBDIR = \gams225\iolib\# comment needed for \COPY = copy

.$(FOREXT).$(OBJEXT):$(F77) $(F77OPTS) $<

OBJS = block1.$(OBJEXT) block2.$(OBJEXT)block3.$(OBJEXT) \

block4.$(OBJEXT) block5.$(OBJEXT)iolib1.$(OBJEXT) \

iolib2.$(OBJEXT) iolib3.$(OBJEXT)iolib4.$(OBJEXT) \

$(SPECOBJS)

$(EXENAME): $(OBJS) $(LD) $(LDOPTS)

del *.obj

block1.$(OBJEXT): block1.$(FOREXT) bdmlpcb.inc defines.incblock2.$(OBJEXT): block2.$(FOREXT) bdmlpcb.inc defines.incblock3.$(OBJEXT): block3.$(FOREXT) bdmlpcb.inc defines.incblock4.$(OBJEXT): block4.$(FOREXT) bdmlpcb.inc defines.incblock5.$(OBJEXT): block5.$(FOREXT) bdmlpcb.inc defines.inc

iolib1.$(OBJEXT): $(IOLIBDIR)iolib1.$(OBJEXT)$(COPY) $(IOLIBDIR)iolib1.$(OBJEXT) .

iolib2.$(OBJEXT): $(IOLIBDIR)iolib2.$(OBJEXT)$(COPY) $(IOLIBDIR)iolib2.$(OBJEXT) .

iolib3.$(OBJEXT): $(IOLIBDIR)iolib3.$(OBJEXT)$(COPY) $(IOLIBDIR)iolib3.$(OBJEXT) .

iolib4.$(OBJEXT): $(IOLIBDIR)iolib4.$(OBJEXT)$(COPY) $(IOLIBDIR)iolib4.$(OBJEXT) .

defines.inc: $(IOLIBDIR)defines.inc$(COPY) $(IOLIBDIR)defines.inc .

Page 97: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

allmem.$(OBJEXT): allmem.obcopy allmem.ob allmem.$(OBJEXT)

Page 98: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

98

The linker response file looks like:

block1+iolib3+(block2+block3+block4+block5)+(iolib1+iolib4)+(iolib2)

+allmemgams2BDM.exe/E/INF/F/PACKC

c:\lib\,

The input routines (GFRCNT, GFRROWX etc) are located in IOLIB1, the outputroutines (GFWSTA, GFWROW etc) in IOLIB2 and the "resident" parts (GFCLCK etc) inIOLIB3. IOLIB4 contains the license checker.

Page 99: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

NDP 386 FORTRAN

The NDP 386 compiler allows you to use the protected mode of the 386 CPU. Thisgives you (a) more speed and (b) more memory than having it running in the (8086compatible) real mode. The switching software to and from protected mode isprovided by Phar Lap. We use NDP version 4.4.1 and Phar Lap tools version 7.0.

The makefile we used to generate I/O library is as follows:

#### Make File for iolib# generates IOLIB.LIB###

OBJS = iolib1.obj iolib2.obj iolib3.obj iolib4.obj iolib5.objiolib6.obj

fpu287 = -n1fpu387 = -n3fpuW = -n4

f77opt = -c $(fpu387) -OML -on -phar1

iolib.lib : $(OBJS) 386lib iolib -replace $(OBJS)

.f.obj: mf386 $(f77opt) $<

A makefile for a user application can look like:

OBJS = main.obj miles.obj lusol.obj cplib.obj \ cpmain.obj gfdict.obj mpsge.obj nlio.obj \ ..\iolib\iolib.lib

fpu287 = -n1fpu387 = -n3fpuW = -n4

f77opt = $(fpu387) -OLM -on -phar1

.f.obj: mf386 -c $(f77opt) $<

gams3mls.exe: $(OBJS) 386link @miles.lnk bind386 \phar386\bin\run386b gams3mls cfig386 gams3mls -vdisk -maxi 64

Page 100: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

100

del gams3mls.exp

main.obj: main.fslcp.obj: slcp.flusol.obj: lusol.fcpmain.obj: cpmain.fcplib.obj: cplib.fnlio.obj: nlio.fmpsge.obj: mpsge.f

where the linker response file is:

c:\ndp386\lib\dos386.objc:\ndp386\lib\__co387.objc:\ndp386\lib\profdumy.objmain.objmiles.objlusol.objcplib.objcpmain.objgfdict.objmpsge.objnlio.obj-twocase-exegams3mls-nomap-lib ..\iolib\iolib-lib c:\ndp386\lib\libf3h-lib c:\ndp386\lib\libc3h-lib c:\ndp386\lib\libm3h-lib c:\ndp386\lib\libg3h-pack

Page 101: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

UNIX FORTRAN

Sun Fortran for the SUN OS 4.1.x Operating System is used to illustrate themakefiles for the various flavours of Unix.

The makefile we used to generate the library iolib.a is as follows:

#### Make File for iolib# generates iolib.a###

F77 = f77F77OPTS = -c -OFOREXT = fOBJEXT = o

.$(FOREXT).$(OBJEXT):$(F77) $(F77OPTS) $<

iolib.a: iolib1.$(OBJEXT) \iolib2.$(OBJEXT) \iolib3.$(OBJEXT) \iolib4.$(OBJEXT) \iolib5.$(OBJEXT) \iolib6.$(OBJEXT) \falloc.oar r iolib.a *.oranlib iolib.a

iolib1.$(OBJEXT): iolib1.$(FOREXT) defines.inc gmscom.inciolib2.$(OBJEXT): iolib2.$(FOREXT) defines.inc gmscom.inciolib3.$(OBJEXT): iolib3.$(FOREXT) defines.inc gmscom.inciolib4.$(OBJEXT): iolib4.$(FOREXT) defines.inc gmscom.inciolib5.$(OBJEXT): iolib5.$(FOREXT) defines.inc gmscom.inciolib6.$(OBJEXT): iolib6.$(FOREXT) defines.inc gmscom.inc

falloc.o: falloc.ccc -c -DPOSTUC falloc.c

A makefile for a user application can look like:

F77 = f77F77OPTS = -c -OLD = f77LDOPTS = -o gamsmiles.out -BstaticFOREXT = fOBJEXT = oLIBEXT = a

Page 102: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

102

EXENAME = gamsmiles.out

SRCS = main.$(FOREXT) miles.$(FOREXT) lusol.$(FOREXT) \ cplib.$(FOREXT) cpmain.$(FOREXT)

gfdict.$(FOREXT) \mpsge.$(FOREXT) nlio.$(FOREXT)

OBJS = main.$(OBJEXT) miles.$(OBJEXT) lusol.$(OBJEXT) \cplib.$(OBJEXT) cpmain.$(OBJEXT) gfdict.$(OBJEXT)

\mpsge.$(OBJEXT) nlio.$(OBJEXT) ../iolib/iolib.a

.SUFFIXES: .$(FOREXT) .$(OBJEXT)

.$(FOREXT).$(OBJEXT):$(F77) $(F77OPTS) $<

$(EXENAME): $(OBJS)$(LD) $(LDOPTS) $(OBJS)

main.$(OBJEXT): main.$(FOREXT)miles.$(OBJEXT): miles.$(FOREXT)lusol.$(OBJEXT): lusol.$(FOREXT)cplib.$OBJEXT): cplib.$(FOREXT)cpmain.$(OBJEXT): cpmain.$(FOREXT)gfdict.$(OBJEXT): gfdict.$(FOREXT)mpsge.$(OBJEXT) : mpsge.$(FOREXT)nlio.$(OBJEXT): nlio.$(FOREXT)

Page 103: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

IBM VM CMS

The standard implementation is for the VS FORTRAN compiler, Release 2.(Timing is done with the library function CPUTIME.) For VM systems wenormally supply a TXTLIB which is compatible with VM/CMS or VM/XA, butdoes not exploit the 31-bit addressing of VM/XA. An "XA exploitive" library isalso available, but it will not run under VM/CMS. Similarly with MVS systems.

The GAMS control file and the screen output file must be equivalenced with thecorresponding Fortran file units outside your program. The following Rexxskeleton shows an example of this. (On MVS an exactly similar scheme is neededusing TSO ALLOCATE statements. The name of the control file in this case is ....)

/* Rexx solver EXEC */ /* We assign 90 to SCREEN in the solver (subroutineGFINIT) */

'FILEDEF 90 TERM' /* We assign 91 to IOSNTR in the solver (subroutineGFRCNT) */ /* The name of the control file is GAMSCNTR DATA */

'FILEDEF 91 DISK GAMSCNTR DATA' /* The solver program name is MYSOLVER (module) */

address COMMAND 'MYSOLVER''FILEDEF 90 CLEAR''FILEDEF 91 CLEAR'

/* Control is returned to GAMS automatically */

Page 104: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

104

CHAPTER 5

EXAMPLES FOR LINEARSYSTEMS

LP-1 Fixed Array type of LP problem in FortranLP-2 Fixed Array type of LP problem in PascalLP-3 Dynamic Array type of LP problem in CLP-4 Dynamic Array type of LP problem in FortranLP-5 Example of MPS file generation of GAMS model

Page 105: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

EXAMPLE LP-1

This example shows how to read an LP problem into a fixed size array type of LPsystem. The matrix is stored column wise, and an extra dummy objrective row isadded at the bottom.

C-------------------------------------------------------------------- PROGRAM EXAMPLEC--------------------------------------------------------------------CC Example how to read an LP into a fixed array LP systemC Data is stored in common block LPMODC

C-- common data

INTEGER MAXN, MAXN1, MAXM, MAXNZ PARAMETER (MAXN=100,MAXN1=101,MAXM=100,MAXNZ=1000) COMMON /LPMOD/ AA, IROW, JCOL, & LB, X, UB, RHS, & ISIGN, & N,M,NZ,OBJVAR, & GINF, GMINF ! gams values for + and - inf DOUBLE PRECISION GINF, GMINF DOUBLE PRECISIONAA(MAXNZ),LB(MAXN),UB(MAXN),RHS(MAXN),X(MAXN) INTEGER IROW(MAXNZ),JCOL(MAXN1),ISIGN(MAXM) INTEGER N,M,NZ,OBJVAR

C-- local vars

INTEGER IOSTA ! unit number of the status file INTEGER GFUNIT ! unit number for internal lib routines INTEGER IOLOG ! unit number log file INTEGER SCREEN ! unit number screen INTEGER IOCNTR ! unit number control file DOUBLE PRECISION XGV(30) ! storage control info INTEGER KGV(30) LOGICAL LGV(30) INTEGER DUMMY

C define the unit numbers

IOSTA = 10 IOLOG = 11 GFUNIT = 12 SCREEN = 13 IOCNTR = 14

Page 106: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

106

C initialize and read control file

CALL GFINIT(GFUNIT, IOSTA, SCREEN) CALL GFRCNT(IOCNTR,IOLOG,.FALSE.,.FALSE., & XGV,KGV,LGV,DUMMY,DUMMY)

C open status file

CALL GFOPST()

C write a message to the status file

CALL GFSTCT('STARTC') WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) ' * SUPERLP, BY SOLVERS INC. *' WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) CALL GFSTCT('STOPC')

C store info in common block

M = KGV(1)+1 ! one extra contraint: objective row N = KGV(2) NZ = KGV(3)+1 ! and in that row 1 extra non-zero OBJVAR= KGV(7) GINF = XGV(10) GMINF = XGV(11)

IF (N.GT.MAXN) CALL LPERR(IOLOG,IOSTA,'TOO MANY VARIABLES') IF (M.GT.MAXM) CALL LPERR(IOLOG,IOSTA,'TOO MANY CONTRAINTS') IF (NZ.GT.MAXNZ) CALL LPERR(IOLOG,IOSTA,'TOO MANYNON-ZEROES')

CALL READAT(IOLOG,IOSTA)

END

C-------------------------------------------------------------------- SUBROUTINE READAT(IOLOG,IOSTA)C--------------------------------------------------------------------C READ DATA FILE

INTEGER IOLOG, IOSTA

C-- common data

INTEGER MAXN, MAXN1, MAXM, MAXNZ PARAMETER (MAXN=100,MAXN1=101,MAXM=100,MAXNZ=1000) COMMON /LPMOD/ AA, IROW, JCOL, & LB, X, UB, RHS, & ISIGN, & N,M,NZ,OBJVAR,

Page 107: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

& GINF, GMINF ! gams values for + and - inf DOUBLE PRECISION GINF, GMINF DOUBLE PRECISIONAA(MAXNZ),LB(MAXN),UB(MAXN),RHS(MAXN),X(MAXN) INTEGER IROW(MAXNZ),JCOL(MAXN1),ISIGN(MAXM) INTEGER N,M,NZ,OBJVAR

C-- local vars

PARAMETER(DWARF=1.0D-10,HUGE=1.0D10) DOUBLE PRECISION X5VEC(5) INTEGER I4VEC(4) INTEGER I, J, NZCOL, IDUMMY, NNZ

WRITE(IOLOG,901)

DO 10, I=1,M-1 CALL GFRROWX(X5VEC,I4VEC) RHS(I) = X5VEC(2) ISIGN(I) = I4VEC(1) 10 CONTINUE

C add objective row

RHS(M) = 0.0D0 ISIGN(M) = 3 ! a free row

WRITE(IOLOG,902)

NNZ = 1

DO 20, J=1,N CALL GFRCOLX(X5VEC,I4VEC) LB(J) = X5VEC(1) IF (LB(J).EQ.GMINF) LB(J) = -HUGE X(J) = X5VEC(2) UB(J) = X5VEC(3) IF (UB(J).EQ.GINF) UB(J) = HUGE NZCOL = I4VEC(1) JCOL(J) = NNZ DO 30, I=1,NZCOL CALL GFRCOF(AA(NNZ),IROW(NNZ),IDUMMY) NNZ = NNZ + 1 30 CONTINUE IF (J.EQ.OBJVAR) THEN AA(NNZ) = 1.0D0 IROW(NNZ) = M

NNZ = NNZ+1 ENDIF 20 CONTINUE JCOL(NNZ) = N+1

WRITE(IOLOG,903)

Page 108: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

108

901 FORMAT(' READING ROWS...') 902 FORMAT(' READING COLUMNS...') 903 FORMAT(' PROBLEM IS LOADED')

END

C-------------------------------------------------------------------- SUBROUTINE LPERR(IOSTA, IOLOG, MESS)C--------------------------------------------------------------------C write message to status file and log file and terminate

IMPLICIT NONE INTEGER IOSTA, IOLOG CHARACTER*(*) MESS

CALL GFSTCT('SYSOUT')

WRITE(IOSTA,100) MESS WRITE(IOLOG,100) MESS

100 FORMAT(' *** ERROR: ',A80)

STOP

END

Page 109: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

EXAMPLE LP-2

The Turbo-pascal version of example LP-1 is:

program test;{$N+,E+}

uses iolib, typedef;

const maxn = 100; maxn1 = 101; maxm = 100; maxnz = 1000;

type mess = packed array[1..20] of char;

var aa : array[1..maxnz] of double; lb, ub, x : array[1..maxn] of double; rhs : array[1..maxm] of double; irow : array[1..maxnz] of integer; jcol : array[1..maxn1] of integer; isign : array[1..maxm] of integer;

m : integer; n : integer; nz : integer; objvar : integer; ginf : double; gminf : double;

cntinfo : cntrec;

procedure lperr(var statusfile : text; var logfile : text; message : mess); begin gfstct('sysou'); writeln(statusfile,' *** Error: ',message); writeln(logfile ,' *** Error: ',message); halt; end;

procedure readat(var logfile : text;

Page 110: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

110

var statusfile : text); const dwarf = 1.0e-10; huge = 1.0e10; var row : rowrec; col : colrec; nzcol : inte ger; idummy : integer; nnz : integer; i, j : integer;

begin writeln(logfile,'Reading rows ...'); for i := 1 to m-1 do begin gfrrowx(row); rhs[i] := row.rdata[2]; isign[i] := row.idata[1]; end;

rhs[m] := 0.0; isign[m] := 3;

writeln(logfile,'Reading columns ...'); nnz := 1; for j := 1 to n do begin gfrcolx(col); lb[j] := col.cdata[1]; if (lb[j]=gminf) then lb[j] := -huge; x[j] := col.cdata[2]; ub[j] := col.cdata[3]; if (ub[j]=ginf) then ub[j] := huge; nzcol := col.idata[1]; jcol[j] := nnz; for i := 1 to nzcol do begin gfrcof(aa[nnz], irow[nnz], idummy); nnz := succ(nnz); end; if (j=objvar) then begin aa[nnz] := 1.0; irow[nnz] := m;

nnz := nnz + 1; end; end;

jcol[nnz] := n+1; writeln(logfile,'Problem is loaded');

Page 111: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

end;

begin gfinit; gfrcnt(false, false,cntinfo); gfopst;

gfstct('start'); writeln(iosta,' ****************************** '); writeln(iosta,' * SUPERLP, BY SOLVERS INC. * '); writeln(iosta,' ****************************** '); writeln(iosta); gfstct('stopc');

m := cntinfo.kgv[1]+1; n := cntinfo.kgv[2]; nz := cntinfo.kgv[3]+1; objvar := cntinfo.kgv[7]; ginf := cntinfo.xgv[10]; gminf := cntinfo.xgv[11];

if (n>maxn) then lperr(iolog, iosta, 'Too many variables '); if (m>maxm) then lperr(iolog, iosta, 'Too many constraints'); if (nz> maxnz) then lperr(iolog, iosta, 'Too many non-zeroes ');

readat(iolog, iosta);

end.

Page 112: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

112

EXAMPLE LP-3

C provides good facilities for dynamic memory allocation and variable lengtharrays. The next example shows how to exploit these features.

/* * example.c * * run as "example gamscntr.scr" * */#include <stdio.h>#include <stdlib.h>#include "iolib.h"

#define HUGE 1.0E31#define DWARF 1.0E-20

int m,n,nz,objvar;double ginf, gminf;double *aa;double *lb,*x,*ub;double *rhs;int *irow;int *jcol;int *isign;

void readat(logfile, statusfile)FILE *logfile, *statusfile;{ rowrec row; colrec col; int nzcol; int idummy; int nnz; int i,j;

fprintf(logfile,"Reading rows ...\n"); for (i=0;i<m-1;++i) { gfrrowx(&row); rhs[i] = row.rdata[2]; isign[i] = row.idata[1]; }

/* objective row at the end */ rhs[m-1] = 0.0; isign[m-1] = 3;

fprintf(logfile,"Reading columns ...\n"); nnz = 0; for (j=0;j<n;++j) { gfrcolx(&col);

Page 113: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

lb[j] = col.cdata[1]; if (lb[j] == gminf) lb[j] = -HUGE; x[j] = col.cdata[2]; ub[j] = col.cdata[3]; if (ub[j] == ginf) ub[j] = HUGE; nzcol = col.idata[1]; jcol[j] = nnz; for (i=0;i<nzcol;++i) { gfrcof(&aa[nnz],&irow[nnz],&idummy); --irow[nnz]; ++nnz; } if (j==objvar) { aa[nnz] = 1.0; irow[nnz] = m-1; /* objective row */ ++nnz; } }

jcol[n] = nnz;

fprintf(logfile,"Problem is loaded\n"); gfstct("START"); fprintf(statusfile,"Problem is loaded\n"); gfstct("STOPC");}

char *mymalloc(size)int size;{ char *p;

p = (char *) malloc(size); if (p==NULL) { fprintf(gfiolog,"ERROR: not enough memory"); exit(1); } return ( p );}

main(argc, argv)int argc;char *argv[];{

cntrec cntinfo; char *statfile;

gfinit(); gfrcnt(FALSE,FALSE,&cntinfo,argv[1]); gfopst();

Page 114: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

114

gfstct("start"); fprintf(gfiosta," ********************************\n"); fprintf(gfiosta," * super_lp, by solvers inc. *\n"); fprintf(gfiosta," ********************************\n\n"); gfstct("stopc");

m = cntinfo.kgv[1]+1; /* one extra for dummy objective row */ n = cntinfo.kgv[2]; nz = cntinfo.kgv[3]+1; /* one extra element in objective */ objvar = cntinfo.kgv[7]; /* no need to subtract one: already done by gfrcnt */ ginf = cntinfo.xgv[10]; gminf = cntinfo.xgv[11];

aa = (double *) mymalloc(nz*sizeof(double)); lb = (double *) mymalloc(n*sizeof(double)); ub = (double *) mymalloc(n*sizeof(double)); x = (double *) mymalloc(n*sizeof(double)); rhs = (double *) mymalloc(m*sizeof(double)); irow = (int *) mymalloc(nz*sizeof(int)); jcol = (int *) mymalloc((n+1)*sizeof(int)); isign = (int *) mymalloc(m*sizeof(int));

readat(gfiolog, gfiosta);

}

Page 115: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

EXAMPLE LP-4

This example shows how to setup a dynamic memory Fortran system. Notice thatafter a nesting two subroutine calls we can code as if it is a fixed size array type ofsystem. So all the dirty code concering the dynamic memory can be isolated in onefile, that contains the few outermost subroutines and the program.

C-------------------------------------------------------------------- PROGRAM EXAMPLEC--------------------------------------------------------------------CC Example how to read an LP into a dynamic array LP systemCC

IMPLICIT NONE

COMMON /DYNARR/ Z DOUBLE PRECISION Z(1) INTEGER CORESZ

CORESZ = 2

CALL SUB1(Z,CORESZ)

END

C-------------------------------------------------------------------- SUBROUTINE SUB1(Z, CORESZ)C--------------------------------------------------------------------

IMPLICIT NONE

INTEGER CORESZ DOUBLE PRECISION Z(CORESZ)

INTEGER INTSIZ PARAMETER(INTSIZ=2) ! 2 integers fit in a real*8 (on manymachines)

COMMON /LPMOD/ N,M,NZ, ! #cols, #rows, #non-zeroes & MA,MIROW,MJCOL,MLB,MUB,MRHS,MISIGN,MX, ! sizes & PA,PIROW,PJCOL,PLB,PUB,PRHS,PISIGN,PX !position INTEGER N,M,NZ,MA,MIROW,MJCOL,MLB,MUB,MRHS,MISIGN,MX

Page 116: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

116

INTEGER PA,PIROW,PJCOL,PLB,PUB,PRHS,PISIGN,PX

C-- local vars

INTEGER IOSTA ! unit number of the status file INTEGER GFUNIT ! unit number for internal lib routines INTEGER IOLOG ! unit number log file INTEGER SCREEN ! unit number screen INTEGER IOCNTR ! unit number control file DOUBLE PRECISION XGV(30) ! storage control info INTEGER KGV(30) LOGICAL LGV(30) INTEGER DUMMY INTEGER NEEDED ! memory needed INTEGER MEMGOT, MAXMEM ! allocated, available INTEGER ISTART ! first useable position in z INTEGER OBJVAR DOUBLE PRECISION GMINF, GINF

C define the unit numbers

IOSTA = 10 IOLOG = 11 GFUNIT = 12 SCREEN = 13 IOCNTR = 14

C initialize and read control file

CALL GFINIT(GFUNIT, IOSTA, SCREEN) CALL GFRCNT(IOCNTR, IOLOG, .FALSE., & .FALSE., XGV, KGV, LGV, DUMMY, DUMMY)

C open status file

CALL GFOPST()

C write a message to the status file

CALL GFSTCT('STARTC') WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) ' * SUPERLP, BY SOLVERS INC. *' WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) CALL GFSTCT('STOPC')

C extract info

M = KGV(1)+1 ! one extra contraint: objective row N = KGV(2) NZ = KGV(3)+1 ! and in that row 1 extra non-zero OBJVAR= KGV(7) GINF = XGV(10)

Page 117: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

GMINF = XGV(11)

C Do a memory estimationC In "real life" add space for basis, lu-factors, eta-vectors,C workspace, etc. All arrays of which the size depends on theC size of the problem should be accomodated within this array.

MA = NZ ! NZ reals are needed to store A MIROW = 1 + (NZ/INTSIZ) ! space needed to store IROW MJCOL = 1 + ((N+1)/INTSIZ) ! etc. MLB = N MUB = N MX = N MRHS = M MISIGN = 1 + (M/INTSIZ)

CALL MPART(1,NEEDED) ! calculate size of memory needed

WRITE(IOLOG,900) NEEDED*8

CALL GFGETM(Z, ISTART, NEEDED, MEMGOT, MAXMEM)

WRITE(IOLOG,901) MEMGOT*8 WRITE(IOLOG,902) MAXMEM*8 IF (MEMGET.LT.NEEDED) & CALL LPERR(IOLOG,IOSTA,' NOT ENOUGH MEMORY')

CALL MPART(ISTART,DUMMY) ! calculate partitioning

CALL SUB2(IOLOG, IOSTA, M, N, N+1, NZ, OBJVAR, GMINF, GINF, & Z(PA),Z(PIROW),Z(PJCOL),Z(PLB), & Z(PUB),Z(PRHS),Z(PISIGN),Z(PX))

900 FORMAT(' MEMORY NEEDED :',I8,' BYTES') 901 FORMAT(' MEMORY USED :',I8,' BYTES') 902 FORMAT(' MAX. AVAILABLE :',I8,' BYTES')

END

C-------------------------------------------------------------------- SUBROUTINE SUB2(IOLOG, IOSTA, M, N, N1, NZ, OBJVAR, GMINF,GINF, & AA, IROW, JCOL, LB, UB, RHS, ISIGN, X)C--------------------------------------------------------------------

IMPLICIT NONE

C now we can work with "normal" arrays

Page 118: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

118

INTEGER IOLOG, IOSTA, M, N, N1, NZ DOUBLE PRECISION AA(NZ), LB(N), UB(N), X(N), RHS(M) DOUBLE PRECISION GMINF, GINF INTEGER IROW(NZ), JCOL(N1), ISIGN(M), OBJVAR

C now read the data file

CALL READAT(IOLOG, IOSTA, ! in case we want to writesomething & M, N, N1, NZ, OBJVAR, GMINF, GINF, & AA, IROW, JCOL, LB, UB, RHS, ISIGN, X)

C place here the call to the solver

C Here come calls to write the solution

CALL GFCLOS() ! close down the I/O library END

C-------------------------------------------------------------------- SUBROUTINE READAT(IOLOG, IOSTA, M, N, N1, NZ, OBJVAR, GMINF, & GINF, AA, IROW, JCOL, LB, UB, RHS, ISIGN,X)C--------------------------------------------------------------------C READ DATA FILE

IMPLICIT NONE

C-- PARAMETERS

INTEGER IOLOG, IOSTA, M, N, N1, NZ DOUBLE PRECISION AA(NZ), LB(N), UB(N), X(N), RHS(M) DOUBLE PRECISION AA(NZ), GMINF, GINF INTEGER IROW(NZ), JCOL(N1), ISIGN(M), OBJVAR

C-- LOCALS DOUBLE PRECISION X5VEC(5) INTEGER I4VEC(4) INTEGER I, J, NZCOL, IDUMMY, NNZ

WRITE(IOLOG,901)

DO 10, I=1,M-1 CALL GFRROWX(X5VEC,I4VEC) RHS(I) = X5VEC(2) ISIGN(I) = I4VEC(1) 10 CONTINUE

C add objective row

RHS(M) = 0.0D0 ISIGN(M) = 3 ! a free row

Page 119: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

WRITE(IOLOG,902)

NNZ = 1

DO 20, J=1,N CALL GFRCOLX(X5VEC,I4VEC) LB(J) = X5VEC(1) IF (LB(J).EQ.GMINF) LB(J) = -HUGE X(J) = X5VEC(2) UB(J) = X5VEC(3) IF (UB(J).EQ.GINF) UB(J) = HUGE NZCOL = I4VEC(1) JCOL(J) = NNZ DO 30, I=1,NZCOL CALL GFRCOF(AA(NNZ),IROW(NNZ),IDUMMY) NNZ = NNZ + 1 30 CONTINUE IF (J.EQ.OBJVAR) THEN AA(NNZ) = 1.0D0 IROW(NNZ) = M NNZ = NNZ + 1 ENDIF 20 CONTINUE

JCOL(N+1) = NNZ

WRITE(IOLOG,903)

901 FORMAT(' READING ROWS...') 902 FORMAT(' READING COLUMNS...') 903 FORMAT(' PROBLEM IS LOADED')

END

C-------------------------------------------------------------------- SUBROUTINE LPERR(IOSTA, IOLOG, MESS)C--------------------------------------------------------------------C write message to status file and log file and terminate

IMPLICIT NONE INTEGER IOSTA, IOLOG CHARACTER*(*) MESS

CALL GFSTCT('SYSOUT')

WRITE(IOSTA,100) MESS WRITE(IOLOG,100) MESS

100 FORMAT(' *** ERROR: ',A80)

Page 120: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

120

STOP

END

C-------------------------------------------------------------------- SUBROUTINE MPART(ISTART,IEND)C--------------------------------------------------------------------C this subroutine partitions the memory whereC ISTART is the first available REAL*8 slot.C It returns IEND, the last occupied slot.C Use also to esimate memory requirements by callingC it with ISTART=1;

IMPLICIT NONE INTEGER ISTART,IEND

COMMON /LPMOD/ N,M,NZ, ! #cols, #rows, #non-zeroes & MA,MIROW,MJCOL,MLB,MUB,MRHS,MISIGN,MX, ! sizes & PA,PIROW,PJCOL,PLB,PUB,PRHS,PISIGN,PX !position INTEGER N,M,NZ,MA,MIROW,MJCOL,MLB,MUB,MRHS,MISIGN,MX INTEGER PA,PIROW,PJCOL,PLB,PUB,PRHS,PISIGN,PX

INTEGER INTSIZ

INTSIZ = 2 ! two 4 byte integers fit in one real*8

PA = ISTART PIROW = PA + MA PJCOL = PIROW + MIROW PLB = PJCOL + MJCOL PUB = PLB + MLB PX = PUB + MUB PRHS = PX + MX PISIGN = PRHS + MRHS IEND = PISIGN + MISIGN - 1

END

Page 121: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

EXAMPLE LP-5

The next example shows how an MPS file can be generated for a linear model.

C-------------------------------------------------------------------- PROGRAM GAMSMPSC--------------------------------------------------------------------CC Example how to read an LP, and to produce an MPS fileCC

IMPLICIT NONE

COMMON /DYNARR/ Z DOUBLE PRECISION Z(1) INTEGER CORESZ

CORESZ = 2

CALL SUB1(Z,CORESZ)

END

C-------------------------------------------------------------------- SUBROUTINE SUB1(Z, CORESZ)C--------------------------------------------------------------------

IMPLICIT NONE

INTEGER CORESZ DOUBLE PRECISION Z(CORESZ)

INTEGER INTSIZ PARAMETER(INTSIZ=2) ! 2 integers fit in a real*8

COMMON /LPMOD/ N,M,NZ, ! #cols, #rows, #non-zeroes & MLB, MUB, MRHS, ! #lb, #ub, #rhs slots & PLB, PUB, PRHS ! positions INTEGER N,M,NZ,MLB,MUB, MRHS INTEGER PLB, PUB, PRHS

C-- local vars

INTEGER IOSTA ! unit number of the status file INTEGER GFUNIT ! unit number for internal lib routines INTEGER IOLOG ! unit number log file

Page 122: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

122

INTEGER IOMPS ! unit number mps file INTEGER SCREEN ! unit number screen INTEGER IOCNTR ! unit number control file DOUBLE PRECISION XGV(30) ! storage control info INTEGER KGV(30) LOGICAL LGV(30) INTEGER DUMMY INTEGER NEEDED ! memory needed INTEGER MEMGOT, MAXMEM ! allocated, available INTEGER ISTART ! first useable position in z INTEGER OBJVAR DOUBLE PRECISION GMINF, GINF

C define the unit numbers

IOSTA = 10 IOLOG = 11 GFUNIT = 12 SCREEN = 13 IOCNTR = 14 IOMPS = 15

C initialize and read control file

CALL GFINIT(GFUNIT, IOSTA, SCREEN) CALL GFRCNT(IOCNTR, IOLOG, .FALSE., & .FALSE., XGV, KGV, LGV, DUMMY, DUMMY)

C open status file

CALL GFOPST()

C write a message to the status file

CALL GFSTCT('STARTC') WRITE(IOSTA,*) ' **********************************' WRITE(IOSTA,*) ' * GAMSMPS, BY GAMS DEVELOPMENT *' WRITE(IOSTA,*) ' **********************************' WRITE(IOSTA,*) WRITE(IOSTA,*) ' This solver will generate an MPS file ofyour' WRITE(IOSTA,*) ' current model. The file is called GAMS.MPS' WRITE(IOSTA,*) ' and should be in your current directory.' WRITE(IOSTA,*) CALL GFSTCT('STOPC')

C extract info

M = KGV(1)+1 ! one extra contraint: objective row N = KGV(2) NZ = KGV(3)+1 ! and in that row 1 extra non-zero OBJVAR= KGV(7)

Page 123: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

GINF = XGV(10) GMINF = XGV(11)

C Do a memory estimationC we need to store the bounds, and the right hand sidec so that is 2*n+m slots.

MLB = N MUB = N MRHS = M

CALL MPART(1,NEEDED) ! calculate size of memory needed

WRITE(IOLOG,900) NEEDED*8

CALL GFGETM(Z, ISTART, NEEDED, MEMGOT, MAXMEM)

WRITE(IOLOG,901) MEMGOT*8 WRITE(IOLOG,902) MAXMEM*8 IF (MEMGOT.LT.NEEDED) & CALL LPERR(IOLOG,IOSTA,' NOT ENOUGH MEMORY')

CALL MPART(ISTART,DUMMY) ! calculate partitioning

CALL SUB2(IOLOG, IOSTA, IOMPS, & M, N, N+1, NZ, OBJVAR, GMINF, GINF, & Z(PLB), Z(PUB), Z(PRHS))

900 FORMAT(' MEMORY NEEDED :',I8,' BYTES') 901 FORMAT(' MEMORY USED :',I8,' BYTES') 902 FORMAT(' MAX. AVAILABLE :',I8,' BYTES')

END

C-------------------------------------------------------------------- SUBROUTINE WRTMPS(IOMPS, FIELD1, FIELD2, FIELD3, FIELD4)C--------------------------------------------------------------------CC Write a single line to the mps fileCC Fields start at columns 2, 5, 15 and 25

c --- arguments INTEGER IOMPS ! io unit mps file CHARACTER*(*) FIELD1, FIELD2, FIELD3, FIELD4

c --- locals CHARACTER*36 LINE INTEGER LAST, I

Page 124: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

124

LINE = ' ' LAST = 0

IF (LEN(FIELD1).GT.0) THEN LAST = 1 + LEN(FIELD1) LINE(2:LAST) = FIELD1 ENDIF

IF (LEN(FIELD2).GT.0) THEN LAST = 4 + LEN(FIELD2) LINE(5:LAST) = FIELD2 ENDIF

IF (LEN(FIELD3).GT.0) THEN LAST = 14 + LEN(FIELD3) LINE(15:LAST) = FIELD3 ENDIF

IF (LEN(FIELD4).GT.0) THEN LAST = 24 + LEN(FIELD4) LINE(25:LAST) = FIELD4 ENDIF

WRITE(IOMPS,100) LINE(1:LAST)

100 FORMAT (A)

RETURN END

C-------------------------------------------------------------------- CHARACTER*8 FUNCTION ROWNAM(K)C--------------------------------------------------------------------

C --- arguments INTEGER K

c --- locals CHARACTER*8 NAME

NAME = ' ' WRITE(NAME,100) K ROWNAM = NAME

100 FORMAT('R',I7.7)

RETURN END

C--------------------------------------------------------------------

Page 125: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

CHARACTER*8 FUNCTION COLNAM(K)C--------------------------------------------------------------------

C --- arguments INTEGER K

c --- locals CHARACTER*8 NAME

NAME = ' ' WRITE(NAME,100) K COLNAM = NAME

100 FORMAT('C',I7.7)

RETURN END

C-------------------------------------------------------------------- CHARACTER*12 FUNCTION VALUE(X)C--------------------------------------------------------------------

C --- arguments DOUBLE PRECISION X

c --- locals CHARACTER*12 NAME CHARACTER*7 FRMT DOUBLE PRECISION ABSX INTEGER SIZE, DECS

NAME = ' ' FRMT = '(F12.9)' ABSX = ABS(X)

IF (ABSX.GE.1.0D0) THEN SIZE = NINT(LOG10(ABSX)+0.5D0) IF (SIZE.GT.10) & WRITE(*,*) 'Overflow in MPS file, ****** written' DECS = MAX(0,10-SIZE) WRITE(FRMT(6:6),'(I1)') DECS ENDIF

WRITE(NAME,FRMT) X VALUE = NAME

RETURN END

Page 126: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

126

C-------------------------------------------------------------------- SUBROUTINE SUB2(IOLOG, IOSTA, IOMPS, & M, N, N1, NZ, OBJVAR, GMINF, GINF, & LB, UB, RHS)C--------------------------------------------------------------------

IMPLICIT NONE

C now we can work with "normal" arrays

INTEGER IOLOG, IOSTA, IOMPS, M, N, N1, NZ DOUBLE PRECISION LB(N), UB(N), RHS(M) DOUBLE PRECISION GMINF, GINF INTEGER OBJVAR

DOUBLE PRECISION X5VEC(5) INTEGER I4VEC(4) DOUBLE PRECISION AA, ABSX INTEGER I, J, NZCOL, IDUMMY, IROW

CHARACTER*8 ROWNAM, COLNAM CHARACTER*12 VALUE

DOUBLE PRECISION DWARF PARAMETER(DWARF=1.0D-8)

CHARACTER RTYP(4) DATA RTYP/'E','G','L','N'/

OPEN(UNIT=IOMPS, FILE='GAMS.MPS') ! ????????????????????? WRITE(IOMPS,950) 'GAMSMOD' WRITE(IOMPS,951)

WRITE(IOLOG,901)

DO 10, I=1,M-1 CALL GFRROWX(X5VEC,I4VEC) RHS(I) = X5VEC(2) ! store rhs for rhs-section CALL WRTMPS(IOMPS, RTYP(I4VEC(1)+1),ROWNAM(I),' ',' ') 10 CONTINUE

C add objective row

RHS(M) = 0.0D0 CALL WRTMPS(IOMPS, 'N',ROWNAM(M),' ',' ')

WRITE(IOLOG,902) WRITE(IOMPS,953)

Page 127: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

DO 20, J=1,N CALL GFRCOLX(X5VEC,I4VEC) LB(J) = X5VEC(1) UB(J) = X5VEC(3) NZCOL = I4VEC(1) DO 30, I=1,NZCOL CALL GFRCOF(AA,IROW,IDUMMY) CALL WRTMPS(IOMPS,'',COLNAM(J),ROWNAM(IROW),VALUE(AA)) 30 CONTINUE IF (J.EQ.OBJVAR) THEN CALL WRTMPS(IOMPS,'',COLNAM(J),ROWNAM(M),VALUE(1.0D0)) ENDIF 20 CONTINUE

WRITE(IOLOG,903) WRITE(IOMPS,957)

DO 40,I=1,M ABSX = ABS(RHS(I)) IF (ABSX.GT.DWARF) THEN CALL WRTMPS(IOMPS,' ','RHS',ROWNAM(I),VALUE(RHS(I))) ENDIF 40 CONTINUE

WRITE(IOLOG,904) WRITE(IOMPS,961)

DO 50,I=1,N IF (LB(I).EQ.UB(I)) THEN CALL WRTMPS(IOMPS,'FX','BOUND',COLNAM(I),VALUE(LB(I))) ELSE IF (LB(I).EQ.GMINF) THEN IF (UB(I).EQ.GINF) THEN CALL WRTMPS(IOMPS,'FR','BOUND',COLNAM(I),' ') ELSE CALL WRTMPS(IOMPS,'MI','BOUND',COLNAM(I),' ') IF (UB(I).NE.0.0D0) THEN CALLWRTMPS(IOMPS,'UP','BOUND',COLNAM(I),VALUE(UB(I))) ENDIF ENDIF ELSE IF (UB(I).NE.GINF) THEN CALLWRTMPS(IOMPS,'UP','BOUND',COLNAM(I),VALUE(UB(I))) ENDIF IF (LB(I).NE.0.0D0) THEN CALLWRTMPS(IOMPS,'LO','BOUND',COLNAM(I),VALUE(LB(I))) ENDIF ENDIF 50 CONTINUE

Page 128: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

128

WRITE(IOMPS,966) WRITE(IOLOG,905)

CALL GFCLOS() ! close down the I/O library CLOSE(IOMPS)

901 FORMAT(' READING ROWS AND WRITING ROW SECTION') 902 FORMAT(' READING COLUMNS AND WRITING COLUMN SECTION') 903 FORMAT(' WRITING RHS SECTION') 904 FORMAT(' WRITING BOUND SECTION') 905 FORMAT(' DONE')

950 FORMAT('NAME',10X,A) 951 FORMAT('ROWS') 953 FORMAT('COLUMNS') 957 FORMAT('RHS') 961 FORMAT('BOUNDS') 966 FORMAT('ENDATA')

END

C-------------------------------------------------------------------- SUBROUTINE LPERR(IOSTA, IOLOG, MESS)C--------------------------------------------------------------------C write message to status file and log file and terminate

IMPLICIT NONE INTEGER IOSTA, IOLOG CHARACTER*(*) MESS

CALL GFSTCT('SYSOUT')

WRITE(IOSTA,100) MESS WRITE(IOLOG,100) MESS

100 FORMAT(' *** ERROR: ',A)

STOP

END

C-------------------------------------------------------------------- SUBROUTINE MPART(ISTART,IEND)C--------------------------------------------------------------------C this subroutine partitions the memory whereC ISTART is the first available REAL*8 slot.C It returns IEND, the last occupied slot.

Page 129: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

C Use also to esimate memory requirements by callingC it with ISTART=1;

IMPLICIT NONE INTEGER ISTART,IEND

COMMON /LPMOD/ N,M,NZ, ! #cols, #rows, #non-zeroes & MLB, MUB, MRHS, ! #lb, #ub, #rhs slots & PLB, PUB, PRHS ! positions INTEGER N,M,NZ,MLB,MUB, MRHS INTEGER PLB, PUB, PRHS

PLB = ISTART PUB = PLB + MLB PRHS = PUB + MUB IEND = PRHS+ MRHS

END

Page 130: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

130

CHAPTER 6

NON-LINEAR SECTION OF GAMSINPUT-OUTPUT LIBRARY

ll Introductionll Storagell How the Interpreter worksll Storing gradients

Page 131: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

INTRODUCTION

This document describes how algorithms for solving non-linear programmingproblems can be hooked up to GAMS. A prerequisite is a thorough understandingof the linear I/O library. We advise first to set up your code so that it can solvesimple LP's.

The core of this library is the non-linear interpreter. This interpreter executes codethat is produced by GAMS. It calculates based on the current level values X newvalues for thefunctions, and for the gradients. The gradients are plugged back into the matrix (i.e.it updates the non-linear non-zeroes in the matrix). The function values are returnedin an array.

The interpreter works only on the non-linear part of the problem, i.e. the linear partof the function values are not calculated. These parts can be added later on.

The interpreter works on an equation by equation basis. It calculates both thegradients and the function values. If only function values are needed, it is possibleto strip out the instructionsthat involve the gradients. Notice however, that the gain in execution speed is notvery high, because GAMS produces quite efficient code, in which lots ofintermediate results are shared between the function and derivative calculations.

For most users the library consists of only two high-level components: a routine toread in the non-linear instructions and set up the datastructures, and a routine theevaluates the non-linear functions and gradients (this one executes the interpreter).An example of such a generic is included in the appendix. That code executes thefollowing steps:

1. Initialize IO library and read control file.2. Allocate memory and partition it.3. Read the matrix file.4. Read non-linear instructions and set-up data structures.5. Evaluate function values and gradients at current point.

Page 132: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

132

Note that evaluating the gradients at the original point is not very useful: GAMSalready did this for you, and the matrix already contains the correct gradients for thenon-linear non-zeroes.

In addition we provide a large amount of source code that shows how to load theinstructions, how to patch them and how to run the interpreter. More advancedapplications may require access to other low-level routines.

Currently the non-linear IO library is only available in Fortran and C.

Page 133: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

STORAGE

There are two objects to store for non-linear models: the non-linear instructionsthemselves, and some non-linear workspace, which is used for storing constantsand the stack.

The instructions can be stored in an INTEGER*4 array of length lenins which isreturned in KNV(4) by GFRCNT. It is possible to scatter individual equationsaround, butno statistics are available on the length of the non-linear code for each equation, sothis can only be done after reading (part of) the non-linear code.

The constants and reserved space for the stack should be stored in an doubleprecision array of length nlwork, which is returned in the parameter KNV(5) byGFRCNT.

HOW THE INTERPRETER WORKS

The interpreter executes the non-linear instructions. These instructions are stored in{INTEGER*4} array's, in an equation by equation fashion. The interpretercalculates the level of the nonlinear part of a single equation and the gradients, andplugs those gradients back into the matrix. There is no easy way to ask theinterpreter to update the gradientsfor a certain column. Each instruction has the following format:

opcode address

The precise format (2 byte opcode, 2 byte address field versus 1 byte opcode, 3 byteaddress field) is machine dependent: we optimize here for machine architecture.Examples of instructions are "add variable X(address) to value on top of the stack",and "store row level in user parameter G, by assigning it the value on top of thestack" (in this case the address field is irrelevant). For a large extend the interpretercan be considered as a black box. A few instructions need more attention however.

STORING GRADIENTS

The most important one is the "store derivative" instruction. This instruction putsthe gradient of equation i and variable j, i.e. δfi(x)/δxj back into the matrix. The

Page 134: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

134

location within the matrix is contained in the address field of the instruction. Thislocation has to be stored there before running the interpreter, by some initializationroutine, typically in step 4 of the algorithm outlined above.

The example routine that performs step 4 is shown in in Appendix 2. First we readthe non-linear code, then we compute an array with pointers to the store derivativeinstructions, and then we update the address field of these instructions. The pointersare stored in an integer array of size nz (the same size as the matrix), which shouldcontain before calling the non-linear set up routine the non-linearity pattern of thematrix:

jtyp[k] = 0 if corresponding nonzero element A[k] is linear 1 otherwise.

This array can be set up this way while reading the matrix: parameterNLTYP of subroutine GFRCOF (read non-zero coefficient) is 0 for a linearnon-zero, and 1 for a non-linear non-zero.

The subroutine GFRINS reads the instructions and the constants. Then we callGFJTYP to set up an array with pointers to the store derivative instructions, andfinally we use thisarray to update them.

Page 135: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

CHAPTER 7

GAMS NONLINEARINPUT/OUTPUT SUBROUTINES

GFDMPAGFDMPEGFINSFGFJTYPGFNSTOGFNTRPGFRINS

Dump instructions pertaining to one equation in ASCII formatDump all instructions in ASCII formatReturn Instruction file nameFinds the Store Derivative instructionsStores Nonlinear instructionsCalculates nonlinear function value and gradientsRead Nonlinear instructions

Page 136: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

136

SUBROUTINE GFDMPA

Subroutine GFDMPA dumps all the instructions. It assumes that they are sitting in acontiguous array. The routine GFRINS delivers them this way, and if you did notscatter them around you can use this routine to dump all the non-linear instructionsto the status file.

Fortran SUBROUTINE GFDMPA(MESS,INSTR,LINS)CHARACTER*(*) MESSINTEGER LINSINTEGER INSTR(LINS)

Pascal n.a.

C n.a.

Description of the parameters

MESS (input)

Character string containing a message that is printed to the status file.

INSTR (input)

Instruction array containing the non-linear instructions.

LINS (input)

Length of the instruction array. Is returned by GFCNTR in KNV(4).

Page 137: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFDMPE

Subroutine GFDMPE dumps the instructions belonging to one equation in humanreadible format to the status file. This routine is for debugging. You may need it ifyou try to patch the instructions for a particular purpose.

Fortran SUBROUTINE GFDMPE(MESS,INSTR,LINS)CHARACTER*(*) MESSINTEGER LINSINTEGER INSTR(LINS)

Pascal n.a.

C n.a.

Description of the parameters

MESS (input)

Character string containing a message that is printed to the status file.

INSTR (input)

Instruction array containing non-linear instructions for a particular equation.

LINS (input)

Number of instructions for this equation.

Page 138: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

138

SUBROUTINE GFINSF

Subroutine GFINSF returns the instruction file name so that you can open theinstruction file. This routine should be called after GFRCNT. It is called by thehigh-level subroutine GFRINS.

Fortran SUBROUTINE GFINSF(FLN)CHARACTER*80 FLN

Pascal n.a.

C n.a.

Page 139: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFJTYP

Subroutine GFJTYP finds the Store Derivative instructions.All instructions aresupposed to be contiguous. It returns the pointers to the store derivative instructionsin the integer array JTYP(LJAC) which should contain a 0 for a linear non-zero and a1 for a non-linear non-zero on input. On output JTYP(K) is still 0 if AA[k] is a linearnon-zero element, but if it is a non-linear element, it contains the relative positionof the store derivative instruction with respect to the start of the row to wich AA[k]

belongs. That means on output linear elements have a JTYP[k] of 0, and non-linearelements have a positive JTYP[k].

Fortran SUBROUTINE GFJTYP(INSTR, LINS, IROW, JCOL, JLEN,& JTYP, LJAC, ISCR, LSCR)INTEGER LINS, LJAC, LCOL, LSCRINTEGER IROW(LJAC), JTYP(LJAC), JCOL(LCOL)INTEGER JLEN(LCOL), ISCR(LSCR)INTEGER INSTR(LINS)

Pascal n.a.

C n.a.

Description of the parameters

INSTR (input)

The array that holds the non-linear instructions.

LINS (input)

Length of the instruction array. Is returned by GFCNTR in KNV(4).

IROW (input)

Integer array holding the row indices of the non-zero elements.

JROW (input)

Integer array holding the column pointers.

JLEN (input)

Page 140: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

140

Integer array holding the length of each column.

JLEN (input)

Integer array holding the length of each column.

JTYP (input/output)

Integer array holding on input the non-linearity pattern of thenon-zeroes:

jtyp[k] = 0 if corresponding nonzero element A[k] is linear1 otherwise.

On output JTYP[k] for non-linear non-zero elements, points to the store derivativeinstructions (relative to the beginning of each equation). The value of JTYP[k] forthe linear non-zero elements remains 0.

LJAC (input)

Length of the array holding the matrix (jacobian). If there are no holes in the matix(i.e. if jcol[j]+jlen[j]=jcol[j+1]) then this is equal to the number of non-zeroelements.

LCOL (input)

Length of the array JCOL. Should be equal to the number of variables n.

ISCR (scratch)

Integer scratch array. Length should be at least equal to the number of variables n.

LSCR (input)

Length of integer scratch array. Should be at least equal to the number of variablesn.

Page 141: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

SUBROUTINE GFNSTO

Subroutine GFNSTO stores a non linear instruction with opcode IOPCOD andaddress field IADDR in INSTR(ISEQ). This is a low-level routine, only to be used ifyou do advanced things like patching instructions.

Fortran SUBROUTINE GFNSTO(INSTR, ISEQ, IOPCOD, AIIDR& ESTIM, LUCORE, MAXZ, MAXBLK)INTEGER IOSTA,CONINTEGER ESTIM, LUCORE, MAXZ, MAXBLK

Pascal n.a.

C n.a.

Description of the parameters

INSTR (input)

Instruction array.

ISEQ (input)

Position within the instruction array, i.e. the instruction (iopcod,iaddr) will bestored at location INSTR(ISEQ).

IOPCOD (input)

Opcode. This is a positive integer between 1 and 74.

IADDR (input)

Address field. This is an integer that should be between -32768 and 32767 for thePC and between -8388607 and +8388607 for larger machines. This implies thatmodels with more than 32767 (8388607) non-zero elements can not be solved usingthe current setup.

Page 142: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

142

SUBROUTINE GFNTRP

Subroutine GFNTRP calculates the non-linear function value and the gradients,based on the current levels X for one equation.

Fortran SUBROUTINE GFNTRP(X, F, A, INSTR, NLWORK,& NUMERR, Z, REFRM, N, NZ, NCON,& LINS)INTEGER NUMERR, REFRMINTEGER N,NZ,NCON,LINSINTEGER INSTR(LINS)DOUBLE PRECISION X(N), F, A(NZ), NLWORK(NCON), Z(*)

Pascal n.a.

C n.a.

Description of the parameters

X (input)

The double precision array with the current level values.

F (output)

The function value of the current row. This is a scalar.

A (output)

The double precision array of the Jacobian (the A matrix).

INSTR (input)

The array that holds the non-linear instructions.

NLWORK (input)

The non-linear work array as was set up by GFRINS.

NUMERR (input/output)

Page 143: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

This variable should accumulate the number of "domain violations" encountered inthe interpreter. It should be set to 0 before calling the interpreter for the first time.After each call the the interpreter the user should compare this value with KNV(6) asprovided by GFRCNT. If numerr > knv(6) then terminate with a solution status of 5.See the documentation on GFWSTA.

Z (input)

Start of the Z array. See example 1 and the description of GFENLE for moreinformation.

REFRM (input)

Reformulation level. Currently only used for MINOS. Other users should pass on a0.

N (input)

Number of structural variables n. Dimension of X.

NZ (input)

Number of nonzero elements nz. Dimension of the array A holding the matrix.

NCON (input)

Size of non-linear workspace array. Is returned by GFCNTR in KNV(5).

LINS (input)

Length of the instruction array. Is returned by GFCNTR in KNV(4).

Page 144: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

144

SUBROUTINE GFRINS

Subroutine GFRINS is used to read the non-linear instructions. In case the model islinear it returns control to the caller immediately.

Fortran SUBROUTINE GFRINS(INSTR, LENINS, NLWORK,& LENWRK)INTEGER LENINS,LENWRKINTEGER INSTR(LENINS)DOUBLE PRECISION NLWORK(LENWRK)

Pascal n.a.

C n.a.

Description of the parameters

INSTR (output)

The array that will hold on output the non-linear instructions. It's length is LENINS.It should be an INTEGER*4 array.

LENINS (input)

The length of the integer array that will hold the instructions. This length is reportedby GFRCNT as KNV(4). It may be longer than KN(4) but not smaller.

NLWORK (output)

This is a non-linear work array. After this array is initialized by GFRINS it shouldnot be touched by the user. The interpreter will need this array to find someinformation and for scratch space.

LENWRK (input)

Length of the non-linear work array. Should be at least KNV(5), as reported byGFRCNT.

Remarks

Page 145: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

After reading the instructions in to memory, one should patch them up so that theStore Derivative instructions point to the right place in the the A matrix. In order toevaluate all instructions you have to loop on the non-linear equations.

Page 146: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

146

CHAPTER 8

EXAMPLES FOR NONLINEARSYSTEMS

NLP-1 NLP problem in Fortran where instructions are loaded andevaluated

Page 147: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

EXAMPLE NLP1 - LOAD NONLINEAR INSTRUCTIONS ANDEVALUATE

The next listings show you how to set up data structures for a non-linear model.The file NLEX1.FOR is a slightly modified version of the one that is presented in thelinear documentation in Example LP-4. It allocates more memory to make sure wecan load the non-linear instructions.Two subroutines NLINIT and NLEVAL are shown that act as wrappers around thelower level routines in the I/O library. NLINIT should be called after reading thematrix, and NLEVAL to evaluate the function and the gradients.

C-------------------------------------------------------------------- PROGRAM NLEXAM1C--------------------------------------------------------------------CC Example how to read an NLP into a dynamic array LP systemCC

IMPLICIT NONE

COMMON /DYNARR/ Z DOUBLE PRECISION Z(1) INTEGER CORESZ

CORESZ = 2

CALL SUB1(Z,CORESZ)

END

C-------------------------------------------------------------------- SUBROUTINE SUB1(Z, CORESZ)C--------------------------------------------------------------------

IMPLICIT NONE

INTEGER CORESZ DOUBLE PRECISION Z(CORESZ)

INTEGER INTSIZ PARAMETER(INTSIZ=2) ! 2 integers fit in a real*8

COMMON/NLPMOD/ N,M,NZ,

Page 148: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

148

& MA,MIROW,MJCOL,MJLEN,MLB,MUB,MRHS,MISIGN,MX, & MINS,MNLW,MSCR,MJTYP,MF, & PA,PIROW,PJCOL,PJLEN,PLB,PUB,PRHS,PISIGN,PX, & PINS,PNLW,PSCR,PJTYP,PF INTEGER N,M,NZ,MA,MIROW,MJCOL,MJLEN,MLB,MUB,MRHS,MISIGN,MX INTEGER MINS,MNLW,MSCR,MJTYP,MF INTEGER PA,PIROW,PJCOL,PJLEN,PLB,PUB,PRHS,PISIGN,PX INTEGER PINS,PNLW,PSCR,PJTYP,PF

C-- local vars

INTEGER IOSTA ! unit number of the status file INTEGER GFUNIT ! unit number for internal lib routines INTEGER IOLOG ! unit number log file INTEGER SCREEN ! unit number screen INTEGER IOCNTR ! unit number control file DOUBLE PRECISION XGV(30) ! storage control info INTEGER KGV(30) LOGICAL LGV(30) INTEGER KNV(30) INTEGER DUMMY INTEGER NEEDED ! memory needed INTEGER MEMGOT, MAXMEM ! allocated, available INTEGER ISTART ! first useable position in z INTEGER OBJVAR DOUBLE PRECISION GMINF, GINF INTEGER NLCLEN, NLWLEN LOGICAL CANMIP, CANNLP PARAMETER (CANNLP=.TRUE.,CANMIP=.FALSE.)

C define the unit numbers

IOSTA = 10 IOLOG = 11 GFUNIT = 12 SCREEN = 13 IOCNTR = 14

C initialize and read control file

CALL GFINIT(GFUNIT, IOSTA, SCREEN) CALL GFRCNT(IOCNTR, IOLOG, CANMIP, & CANNLP, XGV, KGV, LGV, KNV, DUMMY)

C open status file

CALL GFOPST()

C write a message to the status file

CALL GFSTCT('STARTC') WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) ' * SUPERNLP, BY SOLVERS INC. *'

Page 149: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

WRITE(IOSTA,*) ' ******************************' WRITE(IOSTA,*) CALL GFSTCT('STOPC')

C extract info

M = KGV(1)+1 ! one extra contraint: objective row N = KGV(2) ! number of columns NZ = KGV(3)+1 ! 1 extra non-zero OBJVAR= KGV(7) ! objective variable GINF = XGV(10) ! GAMS bit pattern for +infinity GMINF = XGV(11) ! GAMS bit patters for -infinity NLCLEN= KNV(4) ! length non-linear code NLWLEN= KNV(5) ! length non-linear work space

C Do a memory estimationC In "real life" add space for basis, lu-factors, eta-vectors,C workspace, etc. All arrays of which the size depends on theC size of the problem should be accomodated within this array.

MA = NZ ! NZ reals are needed to store A MIROW = 1 + (NZ/INTSIZ) ! space needed to store IROW MJCOL = 1 + (N/INTSIZ) ! etc. MJLEN = 1 + (N/INTSIZ) ! etc. MLB = N MUB = N MX = N MRHS = M MISIGN = 1 + (M/INTSIZ) MINS = 1 + (NLCLEN/INTSIZ) ! instructions are stored asinteger*4 MNLW = NLWLEN MSCR = 1 + (N/INTSIZ) ! scratch array MJTYP = 1 + (NZ/INTSIZ) MF = M

CALL MPART(1,NEEDED) ! calculate size of memory needed

CALL GFGETM(Z, ISTART, NEEDED, MEMGOT, MAXMEM) CALL MEMINF(IOSTA,IOLOG,NEEDED,0,MEMGOT,MAXMEM)

IF (MEMGOT.LT.NEEDED) & CALL LPERR(IOLOG,IOSTA,' NOT ENOUGH MEMORY')

CALL MPART(ISTART,DUMMY) ! calculate partitioning

CALL SUB2(IOLOG, IOSTA, M, N, NZ, OBJVAR, GMINF, GINF, & Z(PA),Z(PIROW),Z(PJCOL),Z(PJLEN),Z(PLB), & Z(PUB),Z(PRHS),Z(PISIGN),Z(PX),Z(PF),Z(PJTYP), & Z(PINS),NLCLEN,Z(PNLW),NLWLEN,Z(PSCR),MSCR,Z)

END

Page 150: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

150

C-------------------------------------------------------------------- SUBROUTINE SUB2(IOLOG, IOSTA, M, N, NZ, OBJVAR, GMINF, GINF, & AA, IROW, JCOL, JLEN, LB, UB, RHS, ISIGN, X, & F, JTYP, & INS, LENINS, NLWORK, NLWLEN, SCR, SCRLEN, Z)C--------------------------------------------------------------------

IMPLICIT NONE

C now we can work with "normal" arrays

c-- parms INTEGER IOLOG, IOSTA, M, N, NZ DOUBLE PRECISION AA(NZ), LB(N), UB(N), X(N), RHS(M), F(M) DOUBLE PRECISION GMINF, GINF INTEGER IROW(NZ), JCOL(N), JLEN(N), ISIGN(M), OBJVAR INTEGER JTYP(NZ) INTEGER LENINS, NLWLEN, SCRLEN INTEGER INS(LENINS) DOUBLE PRECISION NLWORK(NLWLEN), SCR(SCRLEN) DOUBLE PRECISION Z(1)c-- locals INTEGER NUMERR ! domain errors in the interpreter

C now read the data file

CALL READAT(IOLOG, IOSTA, ! in case we want to writesomething & M, N, NZ, OBJVAR, GMINF, GINF, & AA, IROW, JCOL, JLEN, LB, UB, RHS, ISIGN, X,JTYP)

c read nl instructions, and set up pointers in JTYP array.

WRITE(IOLOG,900) CALLNLINIT(INS,LENINS,NLWORK,NLWLEN,AA,IROW,JCOL,JLEN,NZ,M,N, & JTYP,SCR,SCRLEN) NUMERR = 0

WRITE(IOLOG,901)

CALL NLEVAL(Z,INS,LENINS,NLWORK,NLWLEN,AA,IROW,JCOL,JLEN, & JTYP,X,F,NZ,M,N,NUMERR)

WRITE(IOLOG,902)

CALL GFCLOS() ! close down the I/O library

Page 151: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

RETURN

900 FORMAT (' READING NON-LINEAR INSTRUCTIONS...') 901 FORMAT (' EVALUATING FUNCTION AND GRADIENTS AT CURRENTPOINT...') 902 FORMAT (' DONE') END

C-------------------------------------------------------------------- SUBROUTINE READAT(IOLOG, IOSTA, M, N, NZ, OBJVAR, GMINF, & GINF, AA, IROW, JCOL, JLEN, LB, UB, RHS, & ISIGN, X, JTYP)C--------------------------------------------------------------------C READ DATA FILE

IMPLICIT NONE

C-- PARAMETERS

INTEGER IOLOG, IOSTA, M, N, NZ DOUBLE PRECISION AA(NZ), LB(N), UB(N), X(N), RHS(M) DOUBLE PRECISION GMINF, GINF INTEGER IROW(NZ), JCOL(N), JLEN(N), ISIGN(M), OBJVAR INTEGER JTYP(NZ)

C-- LOCALS DOUBLE PRECISION X5VEC(5) INTEGER I4VEC(4) INTEGER I, J, NZCOL, NNZ DOUBLE PRECISION HUGE PARAMETER (HUGE=1.0D10)

WRITE(IOLOG,901)

DO 10, I=1,M-1 CALL GFRROWX(X5VEC,I4VEC) RHS(I) = X5VEC(2) ISIGN(I) = I4VEC(1) 10 CONTINUE

C add objective row

RHS(M) = 0.0D0 ISIGN(M) = 3 ! a free row

WRITE(IOLOG,902)

NNZ = 1

DO 20, J=1,N CALL GFRCOLX(X5VEC,I4VEC) LB(J) = X5VEC(1)

Page 152: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

152

IF (LB(J).EQ.GMINF) LB(J) = -HUGE X(J) = X5VEC(2) UB(J) = X5VEC(3) IF (UB(J).EQ.GINF) UB(J) = HUGE NZCOL = I4VEC(1) JCOL(J) = NNZ JLEN(J) = NZCOL DO 30, I=1,NZCOL CALL GFRCOF(AA(NNZ),IROW(NNZ),JTYP(NNZ)) NNZ = NNZ + 1 30 CONTINUE IF (J.EQ.OBJVAR) THEN AA(NNZ) = 1.0D0 IROW(NNZ) = M JTYP(NNZ) = 0 NNZ = NNZ + 1 ENDIF 20 CONTINUE

901 FORMAT(' READING ROWS...') 902 FORMAT(' READING COLUMNS...')

END

C-------------------------------------------------------------------- SUBROUTINE LPERR(IOSTA, IOLOG, MESS)C--------------------------------------------------------------------C write message to status file and log file and terminate

IMPLICIT NONE INTEGER IOSTA, IOLOG CHARACTER*(*) MESS

CALL GFSTCT('SYSOUT')

WRITE(IOSTA,100) MESS WRITE(IOLOG,100) MESS

100 FORMAT(' *** ERROR: ',A80)

STOP

END

C-------------------------------------------------------------------- SUBROUTINE MPART(ISTART,IEND)C--------------------------------------------------------------------C this subroutine partitions the memory where

Page 153: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

C ISTART is the first available REAL*8 slot.C It returns IEND, the last occupied slot.C Use also to esimate memory requirements by callingC it with ISTART=1;

IMPLICIT NONE INTEGER ISTART,IEND

COMMON/NLPMOD/ N,M,NZ, & MA,MIROW,MJCOL,MJLEN,MLB,MUB,MRHS,MISIGN,MX, & MINS,MNLW,MSCR,MJTYP,MF, & PA,PIROW,PJCOL,PJLEN,PLB,PUB,PRHS,PISIGN,PX, & PINS,PNLW,PSCR,PJTYP,PF INTEGER N,M,NZ,MA,MIROW,MJCOL,MJLEN,MLB,MUB,MRHS,MISIGN,MX INTEGER MINS,MNLW,MSCR,MJTYP,MF INTEGER PA,PIROW,PJCOL,PJLEN,PLB,PUB,PRHS,PISIGN,PX INTEGER PINS,PNLW,PSCR,PJTYP,PF

INTEGER INTSIZ

INTSIZ = 2 ! two 4 byte integers fit in one real*8

PA = ISTART PIROW = PA + MA PJCOL = PIROW + MIROW PJLEN = PJCOL + MJCOL PLB = PJLEN + MJLEN PUB = PLB + MLB PX = PUB + MUB PRHS = PX + MX PISIGN = PRHS + MRHS PINS = PISIGN + MISIGN PNLW = PINS + MINS PSCR = PNLW + MNLW PJTYP = PSCR + MSCR PF = PJTYP + MJTYP IEND = PF + MF - 1

END

c-------------------------------------------------------------------- SUBROUTINENLINIT(INSTR,LENGIN,XNLWRK,NLWORK,A,IROW,JCOL,JLEN, & NZ,M,N,NZTYPE,SCRARR,SCRLEN)c--------------------------------------------------------------------cc NLINIT reads the instruction file, patches up the instructionsc such that STORE DERIVATIVE and the STORE (function value)c instructions point to the right places. It also producesc an array that contains the pattern of the non-linearities inc the matrix, which is later on used by NLEVAL.

Page 154: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

154

cc INSTR(LENGIN) is the INTEGER*4 array where the instructionsc are stored. LENGIN can be found in KNV(4) afterc calling GFRCNT. This array should not be altered.c XNLWRK(NLWORK) is a DOUBLE PRECISION array where some non-linearc constants are stored, and space needed by thec interpreter. This array should not be altered.c A(NZ),IROW(NZ),JCOL(N),JLEN(N) describe the matrix. Thestoragec technique is "row index, column pointer", i.e.c columnwise.A contains the non-zero elements. The rowc index of A(K) is IROW(K). JCOL(J) points to theplacec where column J starts, and JLEN(J) contains thelength ofc this column.c NZ,M,N are the counts (non-zeroes, rows, columns).c NZTYPE(NZ) is an INTEGER array containing the nl non-zeropattern.c On input should contain NZTYPE(K) = 0 if A(K) is alinearc nonzero and ZNTYPE(K) = 1 if A(K) is a non-linearc nonzero. On output contains pointers to STOREDERIVATIVEc instructions.c Should not be altered by the user after this call.c This info is provided by GFRCOF.c SCRARR(SCRLEN) is a REAL*8 scratch array. Space can be reusedafterc calling this routine.cc IMPLICIT NONE

c-- params INTEGER N,M,NZ ! counts INTEGER LENGIN ! length instruction array INTEGER INSTR(LENGIN) ! instructions INTEGER NLWORK ! length nl work array DOUBLE PRECISION XNLWRK(NLWORK) ! nl work array DOUBLE PRECISION A(NZ) ! matrix INTEGER IROW(NZ) ! row indices INTEGER JCOL(N) ! column pointers INTEGER JLEN(N) ! length of the columns INTEGER NZTYPE(NZ) ! 0 : linear, >0 : non-linear INTEGER SCRLEN ! length scratch array DOUBLE PRECISION SCRARR(SCRLEN) ! scratch arrayc-- locals INTEGER ISCRLN ! # integer scratch locations INTEGER IMACH(4) ! arguments for GFMACH DOUBLE PRECISION RMACH(6)

c we need to know how much (long) integer we can store in a

Page 155: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

c double precision array of length SCRLEN (see linear IOLIBc docs for information about GFMACH). CALL GFMACH(RMACH,IMACH) ISCRLN = SCRLEN*IMACH(1)

c first read instructions CALL GFRINS(INSTR,LENGIN,XNLWRK,NLWORK)

c set up nztype, so that it points to the STORE DERIVATIVEc instructions CALL GFJTYP(INSTR, LENGIN, IROW, JCOL, JLEN, NZTYPE, & NZ, N, SCRARR, ISCRLN)

c update addresses of STORE DERIVATIVE instructions CALL GFPMJJ(INSTR, LENGIN, IROW, NZTYPE, SCRARR, ISCRLN, NZ )

RETURN END

c-------------------------------------------------------------------- SUBROUTINENLEVAL(Z,INSTR,LENGIN,XNLWRK,NLWORK,A,IROW,JCOL,JLEN, & NZTYPE,X,F,NZ,M,N,NUMERR)c--------------------------------------------------------------------cc NLEVAL evaluates the functions and the gradients in thec current point X.cc Z(1) is the start of the Z array (see the Fortran examplesc in the IOLIB documentation about dynamic memory).c INSTR(LENGIN) is the INTEGER*4 array where the instructionsc are stored. LENGIN can be found in KNV(4) afterc calling GFRCNT. This array should not be altered.c XNLWRK(NLWORK) is a DOUBLE PRECISION array where some non-linearc constants are stored, and space needed by thec interpreter. This array should not be altered.c A(NZ) is the double precision arraywhere the non-zero elementsc are stored.c NZTYPE(NZ) is the integer*4 array with pointers to the STOREc GRADIENT instructions.c F(M) is on output the double precision array that holds thec function values. Both linear and non-linear rowsc are evaluated.C X(N) should on input contain the current values.c NZ,M,N are the counts.c NUMERR should accumulate the number of evaluation errorsc encountered by the interpreter. User shouldc set it to zero before calling this routine forc the first time, and after each call compare

Page 156: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

156

c it with KNV(7) (max. allowed domain errors).c If it exceeds this value, write out solutionc and stop with solution status of 5 (seec documentation on GFWSTA).

IMPLICIT NONE

$include:'gmscom.inc'

C-- PARAMS INTEGER NZ,M,N,NLWORK,LENGIN,NUMERR INTEGER INSTR(LENGIN),NZTYPE(NZ) DOUBLE PRECISION F(M),XNLWRK(NLWORK),X(N),A(NZ),Z(*) ! no problems with bound checking here INTEGER IROW(NZ),JCOL(N),JLEN(N)C-- LOCALS INTEGER I,J,K INTEGER ISEQ ! sequence number of instruction at beginning ! of current equation INTEGER INEXT ! sequence number of instruction at beginningof ! next INTEGER IROSEQ ! number of the non-linear equation ! evaluated by the interpreter

c.tfr INTEGER LINS ! location of next instruction - tfr patch

c.tfr if (gfdbug.gt.0) then call gfdmpa(6,INSTR,LENGIN)

call gfprr8('LEVELS:',X,N,GFSTA) endif

DO 10, I=1, M F(I) = 0.0D0 10 CONTINUE

ISEQ = 1

100 CONTINUE ! ------- LOOP OVER ALL NON-LINEAR EQUATIONS CALL GFNINT(INSTR, ISEQ, INEXT, IROSEQ, LENGIN)c.tfr

IF (INEXT.GT.0) THEN LINS = INEXT ELSE LINS = LENGIN ENDIF

c.tfr Use LINS instead of INEXT in the call:

CALL GFNTRP(X,F(IROSEQ),A,INSTR(ISEQ),XNLWRK, & NUMERR,Z,REFORM,N,NZ,NLWORK,LINS)

Page 157: Don't Panic - UW Computer Sciences User Pagespages.cs.wisc.edu/~swright/635/docs/LinkingSolverToGAMS.pdf · bytes. The floating point ... RESTARTS WITH GAMS If your solver support

IF (INEXT.EQ.0) GOTO 200 ISEQ = INEXT GOTO 100

200 CONTINUE

if (gfdbug.gt.0) CALL GFPRR8('NON LINEAR PART OFF:',F,M,GFSTA)

c now add linear terms

DO 300, J=1,N DO 310, K=JCOL(J), JCOL(J)+JLEN(J)-1 IF (NZTYPE(K).EQ.0) THEN ! LINEAR NON-ZERO I = IROW(K) F(I) = F(I) + A(K)*X(J) ENDIF 310 CONTINUE 300 CONTINUE

c if (gfdbug.gt.0) CALL GFPRR8('TOTAL F:',F,M,GFSTA)

RETURN END