GAMS [ Home | Support | Sales | Solvers | Documentation | Model Library | Search | Contact Us ]

GAMS FAQ for keyword: GENERAL


Sleep.exe with millisecond resultion
The sleep.exe executable distributed with the Windows GAMS system continues 
running until the specified number of seconds has elapsed. For some 
applications, a finer resolution could be useful. Under UNIX the command 
usleep  sleeps some number of microseconds. Under Windows, the Windows 
Server 2003 Resource Kit Tools (google to locate this) contains a sleep 
executable that works with a millisecond resolution.

How can a GAMS process communicate with another process
Sometimes, you want to exchange data between a running 
GAMS process and some other process.  The following example 
shows how to do that.  Here a GAMS program and a C program 
continuously exchange data (a scalar).  The communication 
is done through ASCII and GDX files and the synchronization 
through some semaphores:

$Title Trivial example of two asynchronous processes 
(one is GAMS) that exchange data through ASCII files

$onechoV > wait.cmd
@echo off
printf "--- Waiting for %1%done"
:loop
if exist %1%done goto finish
printf "."
sleep 5
goto loop
:finish
printf "\n"
rm -f %1%done
$offecho

$onechoV > read.gms
Scalar Ccnt /
$include Ccnt.txt
/
$offecho

* C Program that reads data from GAMS and provides date for a running GAMS job
$onechoV > gc.c
#include 

void main() {
  FILE *fp;
  int  Gcnt=0;

  printf("C - Program started\n");
   
  while (Gcnt<10) {
    system("wait.cmd G");           /* Wait for GAMS to write Gcnt.txt */

    printf("--- Reading Gcnt.txt\n"); /* Read Gcnt.txt */
    fp = fopen("Gcnt.txt","r");
    fscanf(fp,"%d",&Gcnt);
    fclose(fp);

    Gcnt = 2*Gcnt;
    printf("--- Writing Ccnt.txt (%d)\n", Gcnt); /* Write Ccnt.txt */
    fp = fopen("Ccnt.txt","w");
    fprintf(fp,"%d",Gcnt);
    fclose(fp);
    system("touch Cdone"); /* Tell the GAMS program we are done writing */
  }
  printf("C - Program terminated\n");
}
$offecho
* Next line call your favorite C compiler
* $call cl gc.c

* Remove old semaphores 
$call rm -f Cdone Gdone

* Start up the C Program (you can start this also from a different Window)
$call start cmd /K gc.exe

* The GAMS Process
$eolcom //
scalar cnt /3/;
file fx / Gcnt.txt /;

while (cnt < 10,
  cnt=cnt - 1;
  putclose fx cnt:0:0                       // write out the current scalar
  execute 'touch Gdone';                    // Tell the C program GAMS writing is done
  execute 'wait.cmd C';                     // wait for the C program to write out the updated scalar
  execute 'gams read.gms gdx read.gdx lo=2' // From the ASCII file with the scalar create a GDX file
  execute_load 'read', cnt=Ccnt;            // Load the updated scalar from the GDX file
  display cnt;               
); 

* make sure the C program also gets to write out the current scalar
putclose fx cnt:0:0                         
execute 'touch Gdone';

Continuing subsequent solves in a loop after GAMS execution error abort
When having multiple solves in a loop and GAMS aborts due to an execution error, all subsequent solve statements are ignored. Sometimes it may be desirable to continue with subsequent solves even if one solve is aborted by GAMS due to an execution error. This may be the case for example if GAMS detects infeasibilities in a model. [Note that this is different than if the solver detects infeasibilities. If
the sovler detects infeasibilities, subsequent solves in the loop are not affected.]

To continue with subsequent solves, one can do the following:

Use the "execerr" command line option to increase the number of execution errors allowed before GAMS aborts. From the command line one would specify:

>> gams (modelname) execerr=[n]

where [n] is a suitable large number. GAMS will then abort only if [n] execution errors are found during model execution. The default is execerr=0, so that GAMS always aborts if an execution error is found.

If you are using the GAMS/IDE, you can specify

execerr=[n]

in the GAMS/IDE parameter box in the upper right corner.

To entirely ignore execution errors, one can also reset the number of execution errors found after the solve statement. For example, suppose execerr=[n] has been specified during the GAMS call (either from the command line or in the IDE parameter box). One can reset the number of execution errors found during the previous solve to 0 by specifying in the model after the solve statement

execerror = 0;

For example:

loop(numsolves,
  solve model using lp minimizing obj;
  execerr = 0;
);

Solver option file not found (wrong file extension)
Sometimes a solver option file is not found by GAMS because the
file extension is wrong, even if it appears the extension is
.opt. The solver option file must be a text file and must have 
the .opt extension. When saving text files under Windows certain 
programs may in fact add a .txt extension to the options file so 
that the option file is (solver).opt.txt instead of (solver).txt. 

To check if you really have an option file with .opt extension,
open up a DOS command window and move to the appropriate directory.
Type:

>> dir

which will list the full filename with the full extension. If the
option file does have the .opt.txt extension, move the file so
that it has the correct extension:

>> move (solver).opt.txt (solver).opt

You should now have a correct solver option file extension. To 
avoid this you can list complete filename extensions for all files
so that you can immediately tell if a file has an improper extension.

Win NT:
-------
In any folder go to 'View' menu and to 'Options'. Make sure the 
'Hide file extensions for known file types' is not selected.

Win 2000 and XP:
----------------
Go to Settings > Control Panel > Folder Options. Click on the View tab.
Make sure the 'Hide file extensions for known file types' is not
selected.

For other Windows OS this is similar.

Keeping GAMS memory constant for multiple solves in a loop

When utilizing multiple solve statements (e.g. in a loop) the amount of 
memory used by GAMS may increase even though the indiviual model size 
(for the particular solve statement) remains the same. This is due to 
storage of parameters and variables grows, even though they are not 
necessarily used for each solve statement. 
 
In some case there are ways to keep the amount of memory pretty constant.  
They include: 

1) Use "option solveopt=replace" which replaces rather than merges all 
solution values of each GAMS solve.

2) Use "option clear=param" to clean temporary data which is not used 
afterwards.

3) Use put files to store solution values instead of storing in memory.
   Use    file fput /rep.txt/;
          put fput (data);

4) Batch several submodels into fewer but bigger models.

The first two options are simple, the third one might be inconvienient 
(especially if you want to do post solution analysis) whereas the option 
to aggregate the LPs into fewer but bigger models can be quite difficult. 
This option generally is only useful if each submodel to
solve is not dependent on the solution of the previous model. Although 
there may be instances where the addition of a couple of more constraints 
can accomplish this, it is not always possible. 

We shall give examples using the transportation model (trnsport.gms) where 
we have introduced a time series component.

> Set  t      time      / t1*t10 /
> tt(t)       dynamic version of t;
> Parameter   c(i,j)   transport cost in thousands of dollars per case
>             at(i,t), bt(j,t), ct(i,j,t)  "supply, demand, cost by time";
> c(i,j) = f * d(i,j) / 1000 ;
> Variables
> x(i,j,t)  shipment quantities in cases
>
> Equations
> cost          define objective function
> supply(i,t)   observe supply limit at plant i
> demand(j,t)   satisfy demand at market j ;
>
> cost ..           z  =e=  sum((i,j,tt), ct(i,j,tt)*x(i,j,tt)) ;
> supply(i,tt) ..   sum(j, x(i,j,tt))  =l=  at(i,tt) ;
> demand(j,tt) ..   sum(i, x(i,j,tt))  =g=  bt(j,tt) ;
>
> loop(t,
> tt(t) = yes;
>
> ct(i,j,tt(t)) = c(i,j) * ( 1 + 0.25**ord(t));
> at(i,tt(t)) = a(i) * (1 + 0.15**ord(t));
> bt(j,tt(t)) = b(j) * (1 + 0.15**ord(t));
>
> Solve transport using lp minimizing z ;
>
> tt(t) = no;
> );

1) For the solution replace option we add:

> option solveopt=replace;

before the

> loop(t,

statement.

2) For the clear option we can clear the parameters ct, at, and bt, 
since they are only used for the local solve. After

> tt(t) = yes;

we specify

> option clear=ct, clear=at, clear=bt;


3) For the put file option to store solutions, we create a put file 
called frep.put before the loop by:

> file frep

After the solve statement, we write to the put file by:

> put frep / t.tl 'modstat' transport.modelstat
> / t.tl 'slvstat' transport.solvestat
> / t.tl 'obj    ' z.l;


4) In order to aggregate the models we need to change our objective 
function. The model becomes:

> Equations
> defobj
> cost(t)       define objective function
> supply(i,t)   observe supply limit at plant i
> demand(j,t)   satisfy demand at market j ;
>
> defobj ..         obj =e= sum(tt, z(tt));
> cost(tt) ..       z(tt) =e=  sum((i,j), ct(i,j,tt)*x(i,j,tt)) ;
>
> scalar idx /0/, bsize /5/;
> repeat
> tt(t) = no;
>
>*=== Batch 5 single LPs into one larger model:
> loop(t$(ord(t)>(idx*bsize) and ((idx+1)*bsize)>=ord(t)), tt(t) = yes);
>
> ct(i,j,tt(t)) = c(i,j) * ( 1 + 0.25**ord(t));
> at(i,tt(t)) = a(i) * (1 + 0.15**ord(t));
> bt(j,tt(t)) = b(j) * (1 + 0.15**ord(t));
>
> if (card(tt), Solve transport using lp minimizing obj);
>
> idx = idx + 1;
> until card(tt)=0;

The implementation of all four options using the same equations as 
in 4) is:

> File frep;
> Option solveopt=replace;
>
> repeat
>   tt(t) = no;
>   loop(t$(ord(t)>(idx*bsize) and ((idx+1)*bsize)>=ord(t)), tt(t) = yes);
>
>   option clear=ct, clear=at, clear=bt;
>
>   ct(i,j,tt(t)) = c(i,j) * ( 1 + 0.25**ord(t));
>   at(i,tt(t)) = a(i) * (1 + 0.15**ord(t));
>   bt(j,tt(t)) = b(j) * (1 + 0.15**ord(t));
>
>   if (card(tt), Solve transport using lp minimizing obj);
>
>   loop(tt(t),
>     put frep / t.tl 'modstat' transport.modelstat
>              / t.tl 'slvstat' transport.solvestat
>              / t.tl 'obj    ' z.l(t);
>   );
>   idx = idx + 1;
> until card(tt)=0;





How can I access environment variables inside GAMS
> How can I get access to a system environment variable 
> inside GAMS?

Unfortunately, there is no direct way of accessing the
environment variables inside GAMS, but we can create an 
include file on the fly that sets GAMS macros which contain 
the settings of an system environment variable:

For Windows:

$echon '$setglobal WINDIR '  > setwindir
$call echo %WINDIR%         >> setwindir
$include setwindir

display "%windir%";

For Unix:

$echon '$setglobal USER '    > setuser
$call echo $USER            >> setuser
$include setuser

display "%USER%"

Command Line Parameters
> Is it possible to specify commandline arguments in the GAMS call, e.g:
>
>   gams dosomething.gms 10
> 
> and in dosomething.gms then set some scalar to 10 example:
>
> SCALE = $1;

The GAMS user1 to user5 macro will do the job. On the commandline you
can specify user1=10 (or u1=10) and inside the GAMS program you can
refer to the parameter by using %gams.user1%. Note, that this is a
compile time string replacement, so u1 to u5 are not restricted to
numbers. If the string has delimiter character (e.g. space) you quotes
aroung your string. The example from above could be done like this:

  gams dosomething.gms u1=10

SCALE = %gams.user1%;

Note that if user1 is not defined the statement would look like

SCALE =;

which would trigger a compilation error. In order to prevent this, you
might specify a default and overwrite this if user1 is set:

$set myscale 1
$if not %gams.user1% == "" $set myscale %gams.user1%

SCALE = %myscale%;

The Solver Option File
If you want to have a solver use an option file, it is now necessary to
tell this to the solver in the GAMS model. The GAMS statement to do
this is: 

     modelname.OPTFILE = 1 ;

where modelname is the name of the model specified in the MODEL
statement. For example, 

     MODEL M /ALL/ ;
     M.OPTFILE = 1 ;
     SOLVE M USING NLP MAXIMIZING DOLLARS ;

The option file that is being used after this assignment is
solvername.opt, where 'solvername' is the name of the solver that is
specified. For ZOOM, the option file is called zoom.opt; for minos, it is
minos5.opt. The names that you can use are listed in the gamscomp.txt
file. 

If you do not set the .OPTFILE suffix to 1, no option file will be used
even if it exists. 

To allow different option file names for the same solver, the
modelname.OPTFILE parameter can take other values as well.
Formally, the rule is M.OPTFILE = n will use solvename.opt if n=1, and
solvername.opX, solvername.oXX or solvername.XXX, where x's are
the characters representing the value of n, for n>1 and will use no
option file at all for n=0. This scheme implies an upperbound on n of 999.
For example, 

for M.OPTFILE = 2   option file is minos5.op2 
for M.OPTFILE = 26  option file is minos5.o26 
for M.OPTFILE = 345 option file is minos5.345

Special MIP features
Some special features have been added to GAMS to help in simplifying
the modeling of MIP problems 

1. Using Special Order Sets in GAMS 

Special Ordered Sets (SOS) exploit special structures in MIP models
during the solution phase. The precise definition of SOSs differs from
one solver to another and the development of these features has been
driven more by internal algorithmic conside ration than by broader
modelling concepts. GAMS offers a compromise SOS1 and SOS2
feature which incorporates common characteristics. 

 SOS1 
     At most one variable within a set can have a non-zero value.
     For example, only one out of N options can be selected. 
 SOS2 
     At most two variables within a set can have non-zero values.
     The two non-zero values have to be adjacent. For example, a
     non-convex separable function can be linearized using SOS2. 


To use special ordered sets the GAMS model must be a Mixed Integer
model since the SOS conditions are handled by the branch and bound
algorithm in the same way as binary and general integer variables are
handled. Variables arranged in special ordered sets are defined by a
GAMS construct similar to the following examples: 

     SOS1 Variable S1(I), T1(K,J)
     SOS2 Variable S2(I), T2(K,J)

The members of the innermost (the right-most) index belong to the
same set. For example, 

     SOS1 variables x(i,j)     defines i sets with j elements each.
     SOS1 variable  y(j)       defines one SOS1 set
     SOS2 variable  w(i,j,k)   defines (i,j) SOS2 sets with k elements each

The model PRODSCHX in the GAMS model library (SEQ=109) shows
SOS type formulations with binary, SOS1 and SOS2 sets.The default
bounds for SOS variables are 0 to +INF. As with any other variable, the
user may set these bounds to whatever is required. The user must
explicitly provide whatever convexity row that the problem needs (e.g.
an equation that requires the members of the SOS set to add to one).
Any such convexity row would implicitly define bounds on each of the
variables.The use of special ordered sets may not always improve the
performance of the branch and bound algorithm. If there is no natural
'order' the use of binary variables may be a better choice. A good
example of this is the assignment problem. 

WARNING: The precise definition of SOS variables can be different for
various MIP solvers that allow their use, so models may not bee
transferrable between algorithms. And not all MIP solvers allow SOS
variables (e.g. ZOOM). 

2. Setting Priorities for Branching 

The user can specify an order for picking variables to branch on during a
branch and bound search for MIP models through the use of priorities.
Without priorities, the MIP algorithm will determine which variable is
the most suitable to branch on. The GAMS statement to use priorities
for branching during the branch and bound search is: 

     modelname.PRIOROPT = 1 ;

where modelname is the name of the model specified in the model
statement. The default value is 0 in which case priorities will not be
used. 

The priorities of the individual variables are set by using the .PRIOR
suffix like in the following example: 

     Z.PRIOR(I,'small')   = 3 ;
     Z.PRIOR(I,'medium')  = 2 ;
     Z.PRIOR(I,'large')   = 1 ;

Priorities can be set to any real value. The default value is 1.0. The
lower the value given, the higher the priority. In the above example,
Z(I,'large') variables are branched on before Z(I.'small') variables. As
a general rule of thumb, the most important variables should be given
the highest priority. All members of any SOS1 or SOS2 set should be
given the same priority value since it is the set itself which is branched
upon rather than the individual members of the set.

Special NLP features
Some special features have been added to GAMS to help in simplifying
the modeling of MIP problems 

1. The SCALE Option 

The rules for good scaling are exclusively based on algorithmic needs.
GAMS has been developed to increase the efficiency of modellers, and
one of the best ways seems to be to encourage modellers to write their
models using a notation that is as 'natural' as possible. The units of
measurement are one part of this natural notation, and there is
unfortunately a potential conflict between what the modeler thinks is a
good unit and what constitutes a well scaled model. 

To facilitate the translation between a natural model and a well scaled
model, GAMS has introduced the concept of a scale factor, both for
variables and equations. The notations and definitions are quite simple.
First of all, scaling is turned off by default. The GAMS statement to
turn it on is 

     modelname.SCALEOPT = 1 ;

where modelname is the name of the model specified in the model
statement. For example, 

     MODEL M /ALL/ ;
     M.SCALEOPT = 1 ;
     SOLVE M USING NLP MAXIMIZING DOLLARS ;

The statement should be inserted somewhere after the MODEL
statement and before the SOLVE statement. In order to turn scaling off
again, set the modelname.SCALEOPT parameter to 0 before the next
solve. The scale factor of a variable or an equation is referenced with
the suffix ".SCALE", i.e. the scale factor of variable X(I) is referenced
as X.SCALE(I). Note that there is one scale value for each individual
component of a multidimensional variable or equation. Scale factors can
be defined using assignment statements. The default scale factor is
always 1. The scale factor on a variable, Vs, is used to relate the
variable as seen by the user, Vu, to the variable as seen by the
algorithm, Va, as follows: 

     Vu = Va*Vs

Similarly, the scale factor on an equation, Gs, is used to relate the
equation as seen by the user, Gu, to the equation as seen by the
algorithm, Ga, as follows: 

     Gu = Ga*Gs

The derivatives in the scaled model seen by the algorithm, i.e
d(Ga)/d(Va) are related to the derivates in the user's model,
d(Gu)/d(Vu) through the formula: 

     d(Ga)/d(Va) = d(Gu)/d(Vu) * (Vs/Gs)

Upper and lower bounds on variables are automatically scaled in the
same way as the variable itself. Integer and binary variables cannot be
scaled. GAMS scaling is in most respects hidden from the user. The
solution values reported back from a solution algorithm are always
reported in the user's notation. The algorithm's versions of the
equations and variables are only reflected in the derivatives in the
equation and column listings in the GAMS output if the options
LIMROW and LIMCOL are positive, and the debugging output from the
solution algorithm generated with OPTION SYSOUT = ON.

The FOR statement
The FOR statement is used in order to loop over a block of 
statements. 

Syntax

The syntax is: 

     FOR ( i = start TO|DOWNTO end [By incr],
            statements;
           );

Warning: One cannot make declarations or define equations inside 
         a FOR statement. 


Example 1

One can use FOR statements to control the SOLVE statement. For instance,
consider the following bit of GAMS code that randomly searches for a 
global optimum of a nonconvex model: 

     scalar count ;
     for (i = 1 to 1000,
             x.l(j) = uniform(0,1) ;
             option bratio = 1 ;
             solve ml using nlp minimizing obj ;
             if (obj.l le globmin,
                 globmin = obj.l ;
                 globinit(j) = x.l(j) ;
                ) ;
           ) ;

In this example, a non-convex model is solved from 1000 random 
starting points, and the global solution is tracked. 

Example 2

The following GAMS code is illegal since one cannot define equations 
inside a FOR statement. 

     For (s = 1 to 5 by 1,
              eq.. sum(i,x(i)) =g= 2 ;
           );

Example 3

The following GAMS code is illegal since one cannot make declarations 
inside a FOR statement. 

     For (s=1 to 5 by 1,
              scalar y ; y = 5 ;
            );

The WHILE statement
The WHILE statement is used in order to loop over a block of 
statements. 

Syntax

The syntax is: 

     WHILE (condition,
            statements;
           );

Warning: One cannot make declarations or define equations 
         inside a WHILE statement. 


Example 1

One can use WHILE statements to control the SOLVE statement. 
For instance, consider the following bit of GAMS code that randomly 
searches for a global optimum of a nonconvex model: 

     scalar count ;
     count = 0 ;
     while((count le 1000),
             x.l(j) = uniform(0,1) ;
             option bratio = 1 ;
             solve ml using lp minimizing obj ;
             if (obj.l le globmin,
                 globmin = obj.l ;
                 globinit(j) = x.l(j) ;
                ) ;
             count = count + 1 ;
           ) ;

In this example, a non-convex model is solved from 1000 random 
starting points, and the global solution is tracked. 

Example 2

The model PRIME in the model library illustrates the use of 
the WHILE statement through an example where the set of prime 
numbers less than 200 are generated 

Example 3

The following GAMS code is illegal since one cannot define 
equations inside a WHILE statement. 

     While (s GT 0,
              eq.. sum(i,x(i)) =g= 2 ;
           );

Example 4

The following GAMS code is illegal since one cannot make 
declarations inside a WHILE statement. 

     WHILE (s gt 0,
              scalar y ; y = 5 ;
            );

The IF-ELSE statement
The IF-ELSE statement is useful to branch conditionally around 
a group of statements. In some cases this can also be written
as a set of $ conditioned statements, but the IF statement
may be used to make the GAMS code more readable. 

Syntax

An optional ELSE part allows you to formulate traditional 
IF-THEN-ELSE constructs. The syntax is: 

     IF (condition,
            statements;
            .
            .
         ELSE
            statements;
            .
            .
        );

Warning: One cannot make declarations or define equations 
         inside an IF statement. 


Example 1

For instance, 

     P(I)$(F GT 0) = F*P(I) ;
     Q(J)$(F GT 0) = F*Q(J) ;

can also be written as 

     IF (F GT 0,
         P(I) = F*P(I) ;
         Q(J) = F*Q(J) ;
        ) ;

Example 2

One can also use IF statements to control the SOLVE statement. 
For instance, consider the following bit of GAMS code: 

     IF ((ml.modelstat eq 4),
*            model ml was infeasible
*            relax bounds on X and solve again
             x.up(j) = 2*x.up(j) ;
             solve ml using lp minimizing lp ;
         ELSE
            IF ((ml.modelstat ne 1),
                abort "Error solving model ml ;
               );
        );

Example 3

The following GAMS code is illegal since one cannot define 
equations inside an IF statement. 

     If (s GT 0,
         eq.. sum(i,x(i)) =g= 2 ;
        );

Example 4

The following GAMS code is illegal since one cannot make 
declarations inside an IF statement. 

     IF (s gt 0,
         scalar y ; y = 5 ;
        );

What is optca/optcr?
All algorithms in GAMS for solving MIPs are LP based branch-and-bound
algorithms. While the algorithm runs it maintains two very important
numbers: "best estimate" and "best integer". The "best integer" is the
best solution that satisfies all integer requirements found so
far. The "best estimate" provides a bound for the optimal integer
solution.

For example, you have a maximization problem and the algorithms found
an integer solution with objective value 10 (hence "best integer =
10). Moreover the algorithm communicates through the "best estimate",
which is e.g. 15, that the upper bound for the optimal solution of
this problem is 15.

Having those two numbers we can calculate the "quality" of the best
integer. The quality of a solution can be measured as the distance
from the optimal solution. Unfortunately, we don't have the optimal
solution, but we have a bound for the optimal solution ("best
estimate"). Hence an upper bound for the distance between best integer
and optimal solution is "best estimate" - "best integer". This value
is called the absolute gap (GAMS notation OPTCA). By providing the
option OPTCA in a GAMS program you allow the solver to stop if the
absolute gap dropps below OPTCA. In our small example: The absolute
gap is 5 = (15 - 10). If OPTCA>=5 we would stop. The GAMS default for
OPTCA is 0.

The absolute gap depends on the magnitude of the numbers "best
estimate" and "best integer". For example, if "best integer" = 10000
and "best estimate" = 15000 the absolute gap is 5000. In relative
terms the quality of that solution is similar that the solution pair
10/15. For that reason there is the "relative gap" (in GAMS notation
OPTCR) which is ("best estimate"-"best integer)/"best estimate". Hence
the "relative gap" for both example would be 0.33. If the relative gap
drops below OPTCR the algorithm terminates. The GAMS default for OPTCR
is 0.1.

Note, for a general gap calculation you have to be careful about the
signs of your number and the direction of optimization (min/max). Some
of our solver (e.g. CPLEX) divide by the "best integer" to derive the
relative gap.

GAMS/Virus Scanner incompatibility
 > My GAMS is slow and sometimes the solver does not write a solution file.

When Dr. Solomon's anti-virus software or the McAfee ant-virus scanner
is running you could run into these problems.


How can I enumerate all possible subsets of a set
 > How can I enumerate all possible subsets of a set ?

Have a look at the following example program:

* Example showing how to enumerate all possible subsets
* of a set

sets
    I		/ i1 * i3 /,
    J		/ j1 * j2/,
    IJ(I,J),
    cnt		/ 1 * 9999 /;

scalars M, N, pMN, k, l;
M = card(I);
N = card(J);
pMN = power(2,(M*N));
abort$(card(cnt) lt pMN) "cnt set is too small";

loop {cnt$(ord(cnt) le pMN),
    k = ord(cnt) - 1;
    l = M*N;
    IJ(I,J) = NO;
    loop {(I,J),
        IJ(I,J) = mod(k, 2);
	k = floor(k / 2);
    }
    display IJ;
}

A scalar drives the length of a set

> I need my set to be able to changing depending on the value of 
> a scalar. e.g:
> scalar dim /10/; set myset /1*dim/;

In general we do it the other way around:

set 
  myset /1*10/;

scalar dim;
dim = card(myset);

In the GAMS philosophy sets drive the model.

Creating sets based on data (eg scalars) requires the use of dynamic
sets, which are a little bit more difficult to use than static sets.

Here is a fragment that illustrates how you can use dynamic sets:

set univ the universe /1*1000/;

scalar dim /6/;

set myset(univ);

myset(univ)$(ord(univ) <= dim) = yes;

Display myset; 

* declare equations, variables and parameters over the universe set
* but use them over myset
parameter p(univ);
p(myset) = 1;


Adding a constraint to a model and do a warm start

> I was wondering if it were possible to solve a model using gams, and
> then to add a single constraint to the model with out rebuilding the
> entire model.

There are two ways to interpret your question: Can one add a
constraint without regenerating the rest of the model?  Here the
answer is no; the entire model is regenerated, even if only one
parameter (say, an objective coefficient) changes, or indeed if none
change.  "Smart" regeneration has been on our "wish-list" for some
time, but we have not implemented it yet.

However, if you solve a model and add a constraint, the model is
regenerated and the solver starts from the optimum value of the
previous model, so from the solver standpoint, there is likely to be
very little work required in the second solve.  For an LP problem, one
can choose to use dual simplex on the second solve so that a feasible
start is guaranteed and the algorithm will take probably very few
pivots before reaching optimality.


Tabulators in GAMS
> How can I use tabs in GAMS?

The key to putting tabs into GAMS output lies in using the
$ondelim/$offdelim dollar controls to prevent tab expansion.  The small
attached example demonstrates.

* without ondelim the Tabs will be expanded where they appear in the input
* enter Tab directly or stick into a GAMS 'environment'
* tabs are lost (expanded) where they appear outside of $ondelim/offdelim
* the content of %tab% and %losttab% depend on where they are defined, not used

file tab / tab.put /;

$ondelim
display 'tab	tab';
*           ^ tab character 
put tab 'enclosed tab|	|'/;
*                     ^ tab character 
$offdelim
display 'tab	tab';
*           ^ tab character 
put tab 'expanded tab|	|'/;
*                     ^ tab character 



$ondelim
$setglobal tab '	'
*               ^ tab character
$offdelim
$setglobal losttab '	'
*                   ^ tab character

display	'%tab%a%tab%b%tab%';
put tab 'this is a tab|%tab%|'/;
display	'%losttab%a%losttab%b%losttab%';
put tab 'this is a losttab|%losttab%|'/;

How do I reduce the size of my listing (.LST) file?
> My listing file is too large. How do I reduce its size ?
The size of the listing file can be reduced by affecting the following
switches:
- Turning off the SOLPRINT, LIMROW, and LIMCOL options
- Turning on $offsymxref, $offsymlist, and $offlisting
The $offlisting switch turns off the listing of the input file(s) in the
listing file. This can also be done by using the "suppress=1" command
line option. The rest of the options are explained in the GAMS manual.
The following example illustrates the use of these switches to completely
minimize the size of the listing file.

$TITLE    REDUCED
OUTPUT $inlinecom /* */

/* Turn off the listing of the input file */
$offlisting

/* Turn off the listing and cross-reference of the symbols used */
$offsymxref offsymlist

option
    limrow = 0,     /* equations listed per block */
    limcol = 0,     /* variables listed per block */
    solprint = off,     /* solver's solution output printed */
    sysout = off;       /* solver's system output printed */

/*  include your model here */

The "solprint" option can be controlled on a model-by-model basis by a
line of the form
    .solprint = N;

where N = 0, 1, or 2. 0 and 1 correspond to the "off" and "on" settings
for the global solprint option, while 2 eliminates even the abbreviated
solution status information printed in the "off" case.

Sometimes it is tedious to make all the necessary edits.  An
alternative is the command line option "suppress=1" which suppresses
the source file echo print, i.e.

        gams model suppress=1

All display statements, solution listings etc. will appear in the .lst
file, but none of the input text is written there.

Multiple solutions of a MIP
> I was wondering how you would code a Mixed Integer Linear Program,
> so that you would be able to obtain all solutions with an objective
> value less than some predetermined value for a minimisation problem.

Obtaining all solutions (with objective in a particular interval) of a
MIP is not an easy task. If you have continous variables in the MIP
there may be even infinite many optimal solutions.  In this case there
is no efficient general way. You may check books on 'sensitivity
analysis' of LPs and MIP.

If your MIP consists of binary/integer variables only, there is a
possible way for your problem: You solve the original problem in order
to get one optimal solution.  Then you add a new constraint to 'cut
off' the optimal solution and comes up with the next best
solution. You do this loop until the objective of the solution becomes
to small. An example of this 'cutting plane' method can be found in
the model library (model icut)

From the GAMS IDE choose file->Open in GAMS Model Library->Model icut
and run the model (by pressing F9). From a command line (DOS box or
UNIX shell) call 
			gamslib icut 
			gams icut


Linearization of multi dimensional parameter
> I met one index-operation problem. I would like to map
> 
>         B(m)=A(i,j,k)+C(i,j,k)
> where
> 
>     m=i+4*(j-1)+8*(k-1) 
> 
> gives a unique mapping for (i,j,k) to m.

If i,j,k, and m are ordered sets such that the ord() operator works,
one possiblily of the 'linearization' of your matrices A and C could
be formulated with a SUM to control the sets i,j,k. Note that the SUM
consists of one addend only. The following program gives the details:

sets  i /1*5/
      j /1*4/
      k /1*8/
      m /1*160/;

parameter
      A(i,j,k)
      B(m)
      C(i,j,k);

A(i,j,k) = ord(i) + 10 * ord(j) + 100 * ord(k);
C(i,j,k) = 1000*ord(i) + 10000 * ord(j) + 100000 * ord(k);

B(m) = sum((i,j,k)$(ord(m)=(ord(i)+4*(ord(j)-1)+8*(ord(k)-1))),
          A(i,j,k) + C(i,j,k));

display A,C,B;

Static set is not ordered
 > 198  Set used in 'ord' or lag is not ordered

The ordering properties of a set can depend on the data in the set,
and not on use.  I attach an example, with comments, that should make
this clear.

* $ontext
* Here, the set 'big' is not ordered; this is because the
* elements in it have already appeared (in the sets even and odd),
* but appeared in the order 0, 2, 4, 1, 3, 5,
* not 0, 1, 2, 3, 4, 5
SETS
  even  / 0, 2, 4 /,
  odd   / 1, 3, 5 /,
  big   / 0 * 5 /;
* $offtext


$ontext
* Here, the set 'big' is ordered
* and the elements in even and odd occur in this same order,
* so they are ordered as well.
SETS
  big   / 0 * 5 /,
  even  / 0, 2, 4 /,
  odd   / 1, 3, 5 /;
$offtext


parameter oo(big);
oo(big) = ord(big);
display oo;


What is GAMS
> What is GAMS

GAMS stands for General Alegbraic Modeling System and automates the
process of going from a mathematical statement of the problem to the
solution. GAMS transforms the mathematical representation to
representations required by specific solver engines like OSL,CPLEX,..

Random number generator in GAMS
> Is there a random number generator feature in GAMS? 

GAMS has two random number generator functiions:

   num = uniform(low,high)
   num = normal(mean,std);