Data Manipulations with Parameters

Introduction

In this chapter we explicitly cover only parameter manipulation, including all aspects of data handling. Much of this material is relevant elsewhere (e.g. to sets), but for specifics related to assignment to sets, to conditions, and to assignments within flow control constructs such as the loop statement, see chapters Dynamic Sets, Conditional Expressions, Assignments and Equations and Programming Flow Control Features respectively.

Once initialized, data often requires manipulation in order to bring it into a form most suitable for use in a model or an application. The assignment statement is the way to do this. All the possible components of the assignment statement except conditions are introduced and discussed in this chapter.

The Assignment Statement

The assignment statement is the fundamental data manipulation statement in GAMS. It may be used to define or alter values associated with sets, parameters, variables or equations.

A simple assignment is written in the style associated with many other computer languages. GAMS uses the traditional symbols for addition (+), subtraction (-), multiplication (*) and division (/). We will use them in the examples that follow, and give more details in section Expressions.

Scalar Assignments

Consider the following artificial sequence:

scalar x / 1.5 /;
x = 1.2;
x = x + 2;

The scalar x is initialized to be 1.5. The second statement changes the value to 1.2, and the third changes it to 3.2. The second and third statements are assignments: each replaces the current value of x with a new one.

Note that the same symbol can be used on the left and right of the = sign. The new value is not available until the calculation is complete, and the operation gives the expected result.

Note
An assignment cannot start with a reserved word. A semicolon is therefore required as a delimiter before all assignments.

Note that extended range identifiers (e.g. INF) and acronyms may also be used in assignment statements. For specific details, see sections Extended Range Arithmetic and Acronym Usage respectively.

Indexed Assignments

The GAMS syntax for performing indexed assignments is extremely powerful. This operation offers what may be thought of as simultaneous or parallel assignments and provides a concise way of specifying large amounts of data. Consider the mathematical statement \( DJ_d = 2.75 \cdot DA_d \) for all elements of \(d\). This means that for every member of the set \(d\), a value is assigned to \(DJ\). This can be written in GAMS as follows:

dj(d) = 2.75*da(d) ;

This assignment is known technically as an indexed assignment and set d as the controlling index or controlling set.

Attention
The index set(s) on the left hand side of an indexed assignment are referred to synonymously as the controlling indices, controlling sets, or controlling domain of the assignment.

The extension to two or more controlling indices should be obvious. There will be an assignment made for each label combination that can be constructed using the indices inside the parentheses. Consider the following example of an assignment to all 100 data elements of the parameter a.

sets  row            / r-1*r-10 /
      col            / c-1*c-10 /
      sro(row)       / r-7*r-10 / ;
parameters  r(row)   /r-1*r-7 4, r-8*r-10 5/
            c(col)   /c-1*c-5 3, c-6*c-10 2/;
parameters  a(row,col);
a(row,col)  =  13.2 + r(row)*c(col)  ;

The calculation in the last statement is carried out for each of the 100 unique two-label combinations that can be formed from the elements of row and col. An explicit formulation of the first of these assignments follows:

a('r-1','c-1') = 13.2 + r('r-1')*c('c-1');

Restricting the Domain in Assignments

Sometimes it is neccessary to make assignments over selected elements of a set instead of over the entire domain. There are several ways to accomplish this: using explicit labels, subsets, conditionals and tuples.

Restricting the Domain: Explicit Labels

The strongest restriction of the domain is assigning a value to just one element. Labels may be used explicitly in the context of assignments to accomplish this. The following example illustrates:

a('r-7','c-4') = -2.36 ;

This statement assigns a constant value to just one element of the parameter a. All other elements of a remain unchanged. Labels must be quoted when used in this way.

Restricting the Domain: Subsets

In general, wherever a set name may occur in an indexed assignment, a subset may be used instead.

Consider the following example:

a(sro,'col-10') = 2.44 -33*r(sro) ;

Since the set sro was declared as a subset of the set row, we can use sro as a controlling index in the assignment above to make the assignment only for the elements of sro.

Restricting the Domain: Conditionals

Conditional assignments are discussed in detail in section Conditional Assignments in chapter Conditional Expressions, Assignments and Equations. For details on the types of logical conditions, see section Logical Conditions. Here we present a simple example to illustrate:

a(row,col)$[a(row,col) >= 100] = INF ;

This assignment has the following effect: all elements of the parameter a whose value was at least 100 are assigned the value INF, while all other elements of a remain unchanged.

Restricting the Domain: Tuples

Tuples or multi-dimensional sets are introduced in section Many-to-Many Mapping. In this simple example we show how they may be used to restrict the domain. The example builds on the first example in this section. We repeat the whole code here for clarity.

sets  row            / r-1*r-10 /
      col            / c-1*c-10 /
      sro(row)       / r-7*r-10 / ;
set tuple(row,col)   /r-1.c-1, r-1.c-10, r-10.c-1, r-10.c-10/;
parameters  r(row)   /r-1*r-7 4, r-8*r-10 5/
            c(col)   /c-1*c-5 3, c-6*c-10 2/;
parameters  a(row,col), b(row,row);
a(row,col)  =  13.2 + r(row)*c(col)  ;
a(tuple(row,col)) = 7 + r(row)*c(col)  ;
a(tuple) = 0.25 * a(tuple)  ;

Note that we have introduced the new set tuple. It is two-dimensional and contains just four elements. As before, the parameter a is first assigned values for all its 100 elements. We then change some of these values using the set tuple as domain. The values of the elements of the parameter a that are not elements of the set tuple remain unchanged.

For a more elaborate example involving tuples, see section Filtering Sets in Assignments.

Issues with Controlling Indices

Attention
The number of controlling indices on the left of the = sign should be at least as large as the number of indices on the right. There should be no index on the right-hand side of the assignment that is not present on the left unless it is operated on by an indexed operator. For more on indexed operators, see section Indexed Operations.

Consider the following statement:

a(row,'col-2') = 22 - c(col) ;

GAMS will flag this statement as an error since col is an index on the right-hand side of the equation but not on the left.

Note that there would be no error here if col were a singleton set. Since there is only one element in a singleton set, the intent and behavior is well-defined even when col is not under control.

Attention
Each set is counted only once to determine the number of controlling indices. If the intent is for a set to appear independently more than once within the controlling domain, the second and subsequent occurrences of the set should be aliases of the original set, so that the number of controlling indices is equal to the number of indices. For details on aliases, see section The Alias Statement: Multiple Names for a Set.

Consider the following statement as an illustration:

b(row,row) = 7.7 - r(row) ;

This statement has only one controlling index, namely row. One element (on the diagonal of b) is assigned for each element of row, for a total of 10 assigned values. None of the off-diagonal elements of b will be changed!

If the intent is to assign values to each element of b, this can be done by introducing an alias rowp for row and using this alias in the second index position. There will then be two controlling indices and GAMS will make assignments over all 100 values of the full Cartesian product. The following example illustrates this method:

alias(row,rowp) ;
b(row,rowp) = 7.7 - (r(row) + r(rowp))/2 ;

Expressions

An expression is an arbitrarily complicated specification for a calculation, with parentheses nested as needed for clarity and intent. In this section the discussion of parameter assignments will continue by showing in more detail the expressions that may be used on the right of the = sign. We will cover standard arithmetic operations and indexed operations here, and functions and extended range arithmetic in the next two sections.

Standard Arithmetic Operations

The standard arithmetic symbols and operations and their order of precedence are given in Table 1. Note that 1 denotes the highest order of precedence and 3 denotes the lowest order of precedence. Parentheses can be used to override the default precedence order in the usual way. Operators (including exponentiation) on the same level are evaluated from left to right.

Operation Symbol Order of Precedence
Exponentiation ** 1
Multiplication * 2
Division / 2
Addition + 3
Subtraction - 3

Table 1: Standard Arithmetic Operations

Note that the full GAMS operator precedence hierarchy also includes logical operators; it is given in section Mixed Logical Conditions. Note further that the symbols for addition, subtraction and multiplication have a different meaning if they are used in the context of sets. For details see sections Set Operations and Lag and Lead Operators.

Attention
The operation x**y is equivalent to the function rPower(x,y) and is calculated internally as \(e^{y \times \log(x)}\). This operation is not defined if \(x\) has a negative value; an error will result in this case. If the possibility of negative values for \(x\) is to be admitted and the exponent is known to be an integer, then the function power(x,n) may be used.
Note
As usual, operations within parentheses or brackets are evaluated before other numerical calculations, where the innermost parentheses are resolved first. Any of the pairs (), [] and {} are allowed.

Consider for example:

x = 5 + 4*3**2;

For clarity, this could have been written as follows:

x = 5 + (4*[3**2]) ;

In both cases the result is 41.

Note
It is often better to use parentheses than to rely on the order of precedence of operators, since this prevents errors and clarifies intentions.

Note that expressions may be freely continued over many lines: an end of line is permissible at any point where a blank may be used. Blanks may be used for readability around identifiers, parentheses and operation symbols. Blanks are not allowed within identifiers or numbers, and are significant inside the quotes used to delimit labels.

Indexed Operations

In addition to the simple operations in Table 1, GAMS also provides the following four indexed operations.

Operation Keyword
Summation sum
Product prod
Minimum valuesmin
Maximum value smax

Table 2: Indexed Operations

These four operations are performed over one or more controlling indices. The syntax in GAMS for these operations is:

indexed_op( (index_list), expression);

Indexed_op is one of the four keywords for indexed operations, index_list is the list of the controlling indices and expession is the expression to be evaluated. If there is only one controlling index, the parentheses around it may be removed. Consider the following simple example adapted from [ANDEAN]:

sets i   plants  / cartagena, callao, moron /
     m   product / nitr-acid, sulf-acid, amm-sulf /;

parameter capacity(i,m) capacity in tons per day
          totcap(m)     total capacity by process ;

totcap(m) = sum(i, capacity(i,m));

The index over which the summation is done, i, is separated from the reserved word sum by a left parenthesis and from the data term capacity(i,m) by a comma. The set i is called the controlling index for this operation. The scope of the control is the pair of parentheses () that start immediately after the sum. Note that using normal mathematical representation the last line could be written as: \(totC_m = \sum_i C_{im}\).

It is also possible to sum simultaneously over the domain of two or more sets as in the first assignment that follows. The second assignment demonstrates the use of a less trivial expression than an identifier within the indexed operation.

count = sum((i,j), a(i,j)) ;
emp = sum(t, l(t)*m(t)) ;

The equivalent mathematical forms are:

\[ count = \sum_i\sum_j A_{ij} \quad \textrm{and} \quad emp = \sum_t L_t M_t. \]

Note that the following alternative notation may be used for the first assignment above:

count = sum(i, sum(j, a(i,j)));

In the context of sets the sum operator may be used to compute the number of elements in a set and for projections. For details see section Projection and Aggregation of Sets.

The smin and smax operations are used to find the largest and smallest values over the domain of the index set or sets. The index for the smin and smax operators is specified in the same manner as in the index for the sum operator. In the following example we want to find the largest capacity:

lrgunit = smax((i,m),capacity(i,m));
Attention
The indexed operations smin and smax may be used in equation definitions only if the corresponding model is of type DNLP. For more on GAMS model types, see GAMS Model Types.
Note
  • In the context of assignment statements, the attributes of variables and equations (e.g. x.up(i,j)) may be used in indexed operations just as scalars and parameters are used. For more on variable and equations attributes, see sections Variable Attributes and Equation Attributes respectively.
  • In the context of equation definitions, scalars, parameters and variables may appear freely in indexed operations. For more on equation definitions, see section Defining Equations.

Sometimes it is necessary to restrict the domain of indexed operations. This may be done with the same techniques as in indexed assignments, see section Restricting the Domain in Assignments for details. See also section Conditional Indexed Operations for more details on conditions in the context of indexed operations.

We now turn to two additional capabilities that are available in GAMS to add power and flexibility to expression calculations: functions and extended range arithmetic.

Functions

Functions play an important role in the GAMS language, especially for nonlinear models. Like other programming languages, GAMS provides a number of built-in or intrinsic functions. GAMS is used in an extremely diverse set of application areas and this creates frequent requests for the addition of new and quite sophisticated or specialized functions. There is a trade-off between satisfying these requests and avoiding a complexity not needed by most users. The GAMS Function Library Facility provides the means for managing this trade-off, see subsection Extrinsic Functions below.

Intrinsic Functions

GAMS provides many functions, ranging from commonly used standard functions like exponentiation, logarithms, and trigonometric functions to utility functions for controlling and querying the running GAMS job or process. The complete list of available functions is given in the following tables: Mathematical Functions, String Manipulation Functions, Logical Functions, Time and Calendar Functions, and GAMS Utility and Performance Functions. For details specific to using these functions in equations, see the section on Expressions in Equation Definitions.

Some of the tables that follow contain an endogenous classification column "End. Classif." that specifies in which models the function may legally appear. In order of least to most restrictive, the choices are DNLP, NLP, any, none. See section Classification of Models for details on model types in GAMS. Note well: functions classified as any are only permitted with exogenous (constant) arguments.

Functions are typically used in assignment statements and equations. In these cases, they are only evaluated at execution time. Some functions can also be used at compile time, e.g. to compute the factorial or square root of a scalar. Some of the tables below contain a column "Compile Time" indicating which functions can be used at compile time.

A word on the notation in the tables below: for function arguments, lower case indicates that an endogenous variable is allowed. For details on endogeneous variables, see section Functions in Equation Definitions. Upper case function arguments indicate that a constant is required. Arguments in square brackets may be omitted: the default values used in such cases are specified in the function description provided.

Mathematical Functions

Mathematical functions may be used as expressions in assignment statements and in equation definitions. We start with some simple examples to illustrate. A list with all mathematical functions available in GAMS is given in Table 3.

Exp(x)

a = exp(t);
b = exp(t+2);

The GAMS function exp(x) returns the exponentional \(e^x\) of its argument. The assignments above set \(a=e^t\) and \(b=e^{t+2}\) respectively.

Log(x)

z(j) = log(y(j));

The GAMS function log(x) returns the natural logarithm of its argument. The assignment above evaluates the logarithm once for each element of the controlling domain j.

Max(x1,x2,x3,...)

x = max(y+2, t, t*t);

The function max returns the maximum of a set of expressions or terms. In the assignment above, x will be assigned the maximum of \(y+2\), \(t\), and \(t \cdot t\).

Round(x[,DECPL])

The function round rounds its argument x to the specified number DECPL of places, where positive values of DECPL indicating rounding to the right of the decimal point. If the argument DECPL is not specified, it defaults to zero, and the function rounds its argument to the nearest integer value. For example,

x = round(q);
y = round(q,d);
z = round(12.432,2);
h = round(515.5,-1);

In the first assignment q is rounded to the nearest integer value, while in the second q is rounded to the number of decimals specified by d. The result of the third assignment is 12.43, while the final assignment results in a value of 520.

Table 3: Mathematical Functions

Function Description End. Classif. Compile Time
abs(x) Absolute value of the argument \(x\). DNLP yes
arccos(x) Inverse cosine of the argument \(x\), where \(x\) is a real number between -1 and 1 and the output is in radians, see MathWorld NLP no
arcsin(x) Inverse sine of the argument \(x\), where \(x\) is a real number between -1 and 1 and the output is in radians, see MathWorld NLP no
arctan(x) Inverse tangent of the argument \(x\), where \(x\) is a real number and the output is in radians, see MathWorld NLP no
arctan2(y,x) Four-quadrant arctan function yielding \( \arctan(\frac{y}{x})\) which is the angle the vector \((x,y) \) makes with (1,0) in radians. NLP no
beta(x,y) Beta function: \( B(x,y) = \frac{\gamma(x)\gamma(y)}{\gamma(x+y)}\), see MathWorld DNLP no
betaReg(x,y,z) Regularized beta function, see MathWorld NLP no
binomial(n,k) (Generalized) Binomial coefficient for \( n > -1\), \( -1 < k < n+1 \).NLP no
ceil(x) Ceiling: returns the smallest integer greater than or equal to \(x\). DNLP yes
centropy(x,y[,Z]) Cross-entropy: \(x \cdot \ln(\frac{x+Z}{y+Z})\). Default \(Z=0\).NLP no
cos(x) Cosine of the argument \(x\), where \(x\) must be in radians, see MathWorld NLP yes
cosh(x) Hyperbolic Cosine of \(x\), where \(x\) must be in radians, see MathWorld NLP no
cvPower(X,y) Real power: returns \( \mathbf{X^{y}}\) for \(X\geq0\). NLP no
div(dividend,divisor) Returns \( \mathbf{\frac{dividend}{divisor}}\), undefined for \(divisor=0\).NLP no
div0(dividend,divisor) Returns \( \mathbf{\frac{dividend}{divisor}}\), returns \(10^{299}\) for \(divisor=0\). NLP no
eDist(x1[,x2,x3,...]) Euclidean or L-2 Norm: \(\sqrt{ x_{1}^{2} + x_{2}^{2} + ... }\).NLP no
entropy(x) Entropy: \(-x\cdot\ln(x)\). NLP no
errorf(x) Integral of the standard normal distribution from negative infinity to \(x\): \(\frac{1}{\sqrt{2\pi}} \int\limits_{-\infty}^x e^{\frac{-t^{2}}{2}}dt\).NLP no
execSeed Reads or resets the seed for the random number generator (RNG). Note that the state of the RNG cannot typically be captured in one seed value; in such cases "reading" the seed involves harvesting a seed from the RNG, resetting the RNG with this seed, and returning the seed. none no
exp(x) Exponential of \(x\): \(e^{x}\), see MathWorld NLP yes
fact(N) Factorial of \(N\), where \(N \geq 0\) is an integer. any yes
floor(x) Floor: greatest integer less than or equal to \(x\).DNLP yes
frac(x) Returns the fractional part of \(x\), s.t. x = trunc(x) + frac(x) DNLP yes
gamma(x) Gamma function : \( \gamma(x)= \int\limits_{0}^{\infty} t^{x-1}e^{-t}dt\), see MathWorld NLP no
gammaReg(x,a) Regularized Gamma function, see MathWorld NLP no
log(x) Natural logarithm: logarithm base \(e\), see MathWorld NLP yes
logBeta(x,y) Log Beta function: \(\log(B(x,y))\). NLP no
logGamma(x) Log Gamma function as discussed in MathWorld NLP no
log10(x) Common logarithm: logarithm base 10, see MathWorld NLP yes
log2(x) Binary logarithm: logarithm base 2, see MathWorld NLP yes
max(x1,x2,x3,...) Maximum value of the arguments, where the number of arguments may vary.DNLP yes
min(x1,x2,x3,...) Minimum value of the arguments, where the number of arguments may vary.DNLP yes
mod(x,y) Remainder of \(x\) divided by \(y\). DNLP yes
ncpCM(x,y,Z) Chen-Mangasarian smoothing: \(x-Z\cdot \ln(1+e^{\frac{x-y}{Z}})\). NLP no
ncpF(x,y[,Z]) Fisher-Burmeister smoothing: \(\sqrt{(x^{2}+y^{2}+2\cdot Z)}-x-y\), \(Z\geq0\). Default \(Z=0\). NLP no
ncpVUpow(r,s[,MU]) NCP Veelken-Ulbrich: smoothed min(r,s)    
result = \( \left\{ \begin{array}{ll}\frac{(r + s - |t|)}{2} & if \ |t| \geq \mu\\ \frac{(r + s - \frac{\mu}{8} \cdot (- (\frac{t}{\mu})^{4}+6(\frac{t}{\mu})^{2} +3))}{2} & otherwise \end{array} \right.\)
where \(t=r-s\). Default \(MU=0\).
NLP no
ncpVUsin(r,s[,MU]) NCP Veelken-Ulbrich: smoothed min(r,s)    
result = \( \left\{ \begin{array}{ll} \frac{(r + s - |t|)}{2} & if \ |t| \geq \mu\\\frac{(r + s - (\frac{2\mu}{\pi} \sin(\frac{\pi}{2\mu} +\frac{3\pi}{2})+\mu))}{2} & otherwise \end{array} \right.\)
where \(t=r-s\). Default \(MU=0\).
NLP no
normal(MEAN,STDDEV) Generate a random number from the normal distribution with mean MEAN and standard deviation STDDEV, see MathWorld none no
pi Value of \( \mathbf{\pi=3.141593...}\). any yes
poly(x,A0,A1,A2[,A3,...]) Returns \(p(x)\), where the polynomial \(p(x) = A_{0}+A_{1}x+A_{2}x^{2}+A_{3}x^{3}+...+A_{20}x^{20}\). By default \(A_{3},...,A_{20}=0\).NLP no
power(x,Y) Returns \( \mathbf{x^Y}\), where \(Y\) must be an integer. NLP no
randBinomial(N,P) Generate a random number from the binomial distribution, where \(N\) is the number of trials and \(P\) the probability of success for each trial, see MathWorld none no
randLinear(LOW,SLOPE,HIGH) Generate a random number between LOW and HIGH with linear distribution, SLOPE must be greater than \(\frac{2}{\mbox{HIGH}-\mbox{LOW}}\) none no
randTriangle(LOW,MID,HIGH) Generate a random number between LOW and HIGH with triangular distribution, MID is the most probable number, see MathWorld none no
round(x[,DECPL]) Round \(x\) to DECPL decimal places. Default DECPL=0 DNLP yes
rPower(x,y) Returns \(x^{y}\) for \(x > 0\) and also for \(x = 0\) and restricted values of \(y\). This function is equivalent to the operation 'x**y', see Standard Arithmetic Operations. NLP no
sigmoid(x) Sigmoid: \(\frac{1}{1+e^{-x}}\), see MathWorld NLP no
sign(x) Sign of \(x\): returns 1 if \(x > 0\), -1 if \(x < 0\), and 0 if \(x = 0\). DNLP yes
signPower(x,Y) Signed power: for \(Y > 0\), returns \(x^{Y}\) if \(x\geq 0\) and \(-1\cdot |x|^{Y}\) if \(x<0\). NLP no
sin(x) Sine of the argument \(x\), where \(x\) must be in radians, see MathWorld NLP yes
sinh(x) Hyperbolic sine of \(x\), where \(x\) must be in radians, see MathWorld NLP no
slexp(x[,S]) Smooth (linear) exponential: result = \( \left\{ \begin{array}{ll} e^{x} & \mbox{if} \ x \leq S \\ e^{x} \cdot (1 + (x - S)) & \mbox{otherwise} \end{array} \right.\ \ \) where \(S<=150\), default \(S=150\).NLP no
sllog10(x[,S]) Smooth (linear) logarithm base 10: result = \( \left\{ \begin{array}{ll} \log_{10}(x) & \mbox{if} \ x \geq S \\ \frac{1}{\ln(10)} \cdot (\ln S + \frac{x - S}{S}) & \mbox{otherwise} \end{array} \right.\ \ \) where \(S>=-150\), default \(S=-150\).NLP no
slrec(x[,S]) Smooth (linear) reciprocal: result = \( \left\{ \begin{array}{ll} \frac{1}{x} & \mbox{if} \ x \geq S \\ \frac{1}{S} - \frac{x - S}{S^2} & \mbox{otherwise} \end{array} \right.\ \ \) where \(S>=10^{-10}\), default \(S=10^{-10}\).NLP no
sqexp(x[,S]) Smooth (quadratic) exponential: result = \( \left\{ \begin{array}{ll} e^{x} & \mbox{if} \ x \leq S \\ e^{x} \cdot (1 + (x - S) + \frac{{(x - S)}^{2}}{2}) & \mbox{otherwise} \end{array} \right.\ \ \) where \(S<=150\), default \(S=150\).NLP no
sqlog10(x[,S]) Smooth (quadratic) logarithm base 10: result = \( \left\{ \begin{array}{ll} \log_{10}(x) & \mbox{if} \ x \geq S \\ \frac{1}{\ln(10)} \cdot (\ln S + \frac{x - S}{S} - \frac{(x - S)^2}{2S^2}) & \mbox{otherwise} \end{array} \right.\ \ \) where \(S>=-150\), default \(S=-150\).NLP no
sqr(x) Square of argument \(x\). NLP yes
sqrec(x[,S]) Smooth (quadratic) reciprocal: result = \( \left\{ \begin{array}{ll} \frac{1}{x} & \mbox{if} \ x \geq S \\ \frac{1}{S} - \frac{x - S}{S^2} + \frac{(x - S)^2}{S^3} & \mbox{otherwise} \end{array} \right.\ \ \) where \(S>=10^{-10}\), default \(S=10^{-10}\).NLP no
sqrt(x) Square root of \(x\), see MathWorld NLP yes
tan(x) Tangent of the argument \(x\), where \(x\) must be in radians, see MathWorld NLP yes
tanh(x) Hyperbolic tangent of \(x\), where \(x\) must be in radians, see MathWorld NLP no
trunc(x) Truncation: returns the integer part of \(x\), truncating towards zero.DNLP yes
uniform(LOW,HIGH) Generates a random number from the uniform distribution between LOW and HIGH, see MathWorld none no
uniformInt(LOW,HIGH) Generates an integer random number from the discrete uniform distribution whose outcomes are the integers between LOW and HIGH, inclusive, see MathWorld none no
vcPower(x,Y) Returns \(x^{Y}\) for \(x\geq0\).NLP no

String Manipulation Functions

GAMS provides some string manipulation capability by extending the card and ord functions to work on strings as well as sets. In Table 4 the extended behavior is described. In this context, the functions take strings and places as arguments, and the numeric places argument must be a constant. This behavior only applies to execution-time usage of these functions.

Table 4: String Manipulation Functions

Function Description
card(STRING)Returns the number of characters in the string.
ord(STRING[,PLACE])Returns the ASCII code number of a character in a position in a string. The optional place entry defaults to 1 if omitted and identifies the character position within the string to be examined (1 for the first, 2 for the second, etc.)

There are four types or sources of strings in this context. A string may be a string literal, i.e. a concatenation of letters and blanks as in "drink it" in the example that follows. It may be the symbol text (aka the explanatory text) associated with any symbol. Or it may be the labels or text associated with the elements of a set. The following table gives an overview:

Table 5: String Types

Notation Description Comments
characters A concatenation of characters and blanks: all legal GAMS characters are allowed, see section Characters for details.The characters must be surrounded by double or single quotes.
symbol_name.ts The string is the explanatory text associated with a symbol name. If the explanatory text is missing, the value of card is 0.
set_name.tl The string is the label for a set element. This string type may be used only when set_name is part of the controlling domain.
set_name.te The string is the explanatory text associated with a set element. This string type may be used only when set_name is part of the controlling domain. If the explanatory text is missing, the value of card is 0.

The string types are illustrated in the following example. Note that the directive in the first line activates the end-of-line comment option, see eolCom.

$oneolcom
variable z 'any symbol can have explanatory text';
set teas "teas available to order"  / black "English Breakfast",  green, peppermint /;
scalar p;

p = card("drink it");      !! result: p=8
p = card(z.ts);            !! result: p=36
p = card(teas.ts);         !! result: p=23

loop{teas,
    p = card(teas.tl)      !! length of set element label from the set "teas": "teas" is the controlling set
    display "length of set element label", p;
    p = card(teas.te)      !! length of set element explanatory text: "teas" is the controlling set
    display "length of set element explanatory text", p;
};

Note that the strings teas.tl and teas.te are used in the context of a loop statement (see section The Loop Statement). This is a typical usage pattern.

Logical Functions

Logical functions may be used as expressions in assignment statements as in the following example.

x = ifthen(tt=2, 3, 4+y);

Here \(x=3\) if \(tt=2\), otherwise \(x=4+y\).

The logical functions available in GAMS are given in Table 6. Note that logical functions may also be used in conditions and logic equations, see sections Logical Conditions and Logic Equations respectively. Most of the logical functions can also be indicated using the familiar operator notation, e.g. (x and y), (x >= y), etc. In such cases, the operator notation is allowed at compile time. Further, note that the inputs and outputs of these functions are often logical/Boolean values, so GAMS does implicit conversions as necessary. As expected, false becomes 0 and true becomes 1 when converting logical values to numeric, and 0 becomes false and nonzero becomes true when numeric values are converted to logicals. For details on behavior when the inputs are special values, see sections Extended Range Arithmetic and Acronym Usage, but note that EPS, +INF, -INF, and acronyms become true when converted to logicals.

Table 6: Logical Functions

Function Alternative Notation 1 Alternative Notation 2 Description Return Values End. Classif. Compile Time
bool_and(x,y)x and y Boolean AND Returns true iff both x and y are true DNLP alt
bool_eqv(x,y) x eqv y x <=> y Boolean equivalence Returns false iff exactly one argument is false DNLP alt
bool_imp(x,y) x imp y x -> y Boolean implication Returns true iff x is false or y is true DNLP alt
bool_not(x) not x Boolean NOT Returns true iff x is false DNLP alt
bool_or(x,y) x or y Boolean OR Returns true iff x is true or y is true DNLP alt
bool_xor(x,y) x xor y Boolean XOR Returns true iff exactly one argument is false DNLP alt
ifThen(cond,iftrue,else) Condition If the logical condition (first argument) is true, the function returns iftrue, else it returns else. See example above. DNLP yes
rel_eq(x,y) x eq y x = y Numeric Relation: Equal Returns true iff \(x=y\) DNLP alt
rel_ge(x,y) x ge y x >= y Numeric Relation: Greater Equal Returns true iff \(x\geq y\) DNLP alt
rel_gt(x,y) x gt y x > y Numeric Relation: Greater Than Returns true iff \(x>y\) DNLP alt
rel_le(x,y) x le y x <= y Numeric Relation: Less Equal Returns true iff \(x\leq y\) DNLP alt
rel_lt(x,y) x lt y x < y Numeric Relation: Less Than Returns true iff \(x<y\) DNLP alt
rel_ne(x,y) x ne y x <> y Numeric Relation: Not Equal Returns true iff \(x\neq y\) DNLP alt

Time and Calendar Functions

GAMS offers several functions that relate to time and dates. The fundamental measurement of time in GAMS is the serial day number beginning with January 1, 1900. This serial day number is a real number whose integer part contains a unique number for each day and whose fractional part contains information about hours, minutes, and seconds. We can think of the serial day number as being a date.time pair. The day information extracted from serial day numbers is based on the Gregorian calendar.

Note
In all functions given in Table 7, serial day 1 is January 1, 1900.

All of the functions in Table 7 can be used at compile time.

Table 7: Time and Calendar Functions

Function Description End. Classif.
gday(SDAY) Returns Gregorian day from a serial day number date.time. any
gdow(SDAY) Returns Gregorian day of week from a serial day number date.time. any
ghour(SDAY) Returns Gregorian hour of day from a serial day number date.time. any
gleap(SDAY) Returns 1 if the year that corresponds to a serial day number date.time, is a leap year, else returns 0. any
gmillisec(SDAY) Returns Gregorian milli second from a serial day number date.time. any
gminute(SDAY) Returns Gregorian minute of hour from a serial day number date.time. any
gmonth(SDAY) Returns Gregorian month from a serial day number date.time. any
gsecond(SDAY) Returns Gregorian second of minute from a serial day number date.time. any
gyear(SDAY) Returns Gregorian year from a serial day number date.time. any
jdate(YEAR,MONTH,DAY) Returns a serial day number. any
jnow Returns the current time as a serial day number. none
jstart Returns the time of the start of the GAMS job as a serial day number. none
jtime(HOUR,MIN,SEC) Returns fraction of a day that corresponds to hour, minute and second. any

GAMS Utility and Performance Functions

GAMS provides several functions that may be used to get (and in some cases set) GAMS system information, for example:

scalar o;
o = heapLimit;
heapLimit = 1024;

Table 8: GAMS Utility and Performance Functions

Function Description End. Classif. Compile Time
embeddedHandle Returns the handle for the last embedded code section executed, see section Syntax in chapter Embedded Code Facility for details. none no
errorLevel Return code of the most recently used command. none yes
execError Get or set the number of execution errors. none no
gamsRelease Returns the release number of the running GAMS system, for example 24.7. none yes
gamsVersion Returns the version number of the running GAMS system, for example 247. none yes
handleCollect(HANDLE) Tests if the solve of the model instance identified by the calling argument HANDLE is done: if so, it loads the solution into GAMS. For details, see Table 1 in section Grid Computing. none no
handleDelete(HANDLE) Deletes the model instance identified by HANDLE. For details, see Table 1 in section Grid Computing. none no
handleStatus(HANDLE) Tests if the solve of the model instance identified by HANDLE is done: if so, it loads the solution into a GDX file. For details, see Table 1 in section Grid Computing. none no
handleSubmit(HANDLE) Resubmits the model instance identified by HANDLE for solution. For details, see Table 1 in section Grid Computing. none no
heapFree Get the amount of free memory in the heap in MB, i.e. memory allocated to the process and available for future use by GAMS. none no
heapLimit Get or set the current heap limit (maximum allowable dynamic memory usage) in Mb. none no
heapSize Get the current heap size in Mb. none no
jobHandle Returns the process ID (PID) of the last job started. none yes
jobKill(PID) Sends a kill signal to the job with process ID PID. The return value is 1 if this was successful, 0 otherwise. none yes
jobStatus(PID) Get the status of the job with process ID PID. Possible return values are:
    0: error (input is not a valid PID or access is denied)
    1: process is still running
    2: process is finished with return code which could be accessed by errorlevel
    3: process not running anymore or was never running, no return code available
none yes
jobTerminate(PID) Sends an interrupt signal to the job with process ID PID. The return value is 1 if this was successful, 0 otherwise. none yes
licenseLevel Get an indicator for the type of license:
    0: demo license, limited to small models
    1: full unlimited developer license
    2: run time license, no new variables or equations can be introduced besides those inherited from a work file
    3: application license, only works with a specific work file which is locked to the license file.
any no
licenseStatus Returns non-zero if a license error has occurred. any no
mapVal(x) Returns an integer value that indicates what special value (if any) is stored in the input \(x\). Possible results:
    0: \(x\) is not a special value
    4: \(x\) is UNDF (undefined)
    5: \(x\) is NA (not available)
    6: \(x\) is INF ( \(\infty\))
    7: \(x\) is -INF ( \(-\infty\))
    8: \(x\) is EPS
    >8: \(x\) is an acronym
any no
maxExecError Get or set the maximum number of execution errors. none no
numCores Get the number of logical CPU cores in the system any yes
readyCollect(HANDLES[,MAXWAIT])Waits until a model solution is ready to be collected. For details, see Table 1 in section Grid Computing. none no
sleep(SEC) Pause or sleep execution for SEC seconds. none yes
timeClose Returns the accumulated closedown time, i.e. the time GAMS uses to save its state to disk prior to a solve. none no
timeComp Returns the compilation time in seconds. none no
timeElapsed Returns the elapsed time since the start of a GAMS run in seconds. none no
timeExec Returns the execution time in seconds. none no
timeStart Returns the accumulated startup time, i.e. the time GAMS uses to restore its state from disk after a solve. none no

Extrinsic Functions

Using the GAMS Function Library Facility, functions may be imported from an external library into a GAMS model. Apart from the import syntax, the imported functions may be used in the same way as intrinsic functions. In particular, they may be used in equation definitions. Some function libraries are included with the standard GAMS software distribution, but GAMS users can also create their own libraries using an open programming interface. The GAMS Test Library instances [TRILIB01], [TRILIB02], [TRILIB03], and [CPPLIB00] are simple examples (in the programming languages C, Delphi, Fortran and C++, respectively) that come with every GAMS system.

For details on using and creating extrinsic function libraries, and on the extrinsic function libraries that are provided with GAMS, see the chapter on Extrinsic Functions.

Function Suffixes

Up to this point, this section has described and discussed functions without mentioning their derivatives. These derivatives are very important, though: most of the nonlinear solvers integrated with GAMS will require first derivatives to solve models, and many will also use or require second derivatives as well. It is sometimes useful (e.g. when testing an extrinsic function) to evaluate the derivatives of GAMS functions instead of the functions themselves. This can be done via function suffixes.

Function suffixes can specify the evaluation of a gradient (i.e. first derivative), a Hessian (i.e. second derivative), a minimum or maximum value of the function over a given range, or the minimum or maximum value of the gradient over a given range. A full list of function suffixes is given in Table 9. For functions whose arguments are constant, the derivatives are zero, so typically func is a mathematical function listed in Table 3 above. Note that function suffixes are not defined for functions without arguments (for example, pi), so specifying something like pi.grad results in a compilation error.

Table 9: Function Suffixes

Function Suffix Description
func.value(x) Value of the function func at x, equals func(x).
func.grad(x) Value of the gradient of the function func at x.
func.gradn(x) Value of the gradient of the function func at x, computed numerically.
func.hess(x) Value of the Hessian of the function func at x.
func.hessn(x) Value of the Hessian of the function func at x, computed numerically.
func.low(x1:x2) Lower bound of the function func(x) on the interval [x1,x2].
func.high(x1:x2) Upper bound of the function func(x) on the interval [x1,x2].
func.gradL(x1:x2) Lower bound of the gradient of the function func(x) on the interval [x1,x2].
func.gradH(x1:x2) Upper bound of the gradient of the function func(x) on the interval [x1,x2].

Consider the following simple example:

scalars g, l, h, gl, gh;

g  = sin.grad(0);
l  = sin.low(pi/3:pi/2);
h  = sin.high(pi/3:pi/2);
gl = sin.gradL(pi/3:pi/2);
gh = sin.gradH(pi/3:pi/2);

display g, l, h, gl, gh;

For univariate functions like sine or cosine, there is no need to specify a variable index when evaluating derivatives. For multivariate functions, the default is to take partial derivatives w.r.t. the first variable. To specify other variables, the colon syntax in the example below is used.

scalars
  x   / 1 /
  ylo / -1 /
  yup / 2 /
  e0, e1, elo, ehi
  e_1, e_2
  e_11, e_22, e_21
  ;
e0 = edist(x,ylo);
e1 = edist(x,yup);
elo = edist.low (x,ylo:x,yup);
ehi = edist.high(x,ylo:x,yup);

e_1 = edist.grad(x,yup);
* e_1 = edist.grad(1:x,yup);  same as above
e_2 = edist.grad(2:x,yup);

e_11 = edist.hess(x,yup);
* e_11 = edist.hess(1:1:x,yup);  same as above
e_22 = edist.hess(2:2:x,yup);
e_21 = edist.hess(2:1:x,yup);

display x, ylo, yup, e0, e1, elo, ehi, e_1, e_2, e_11, e_22, e_21;

For more examples, see model [FUNCS4] in the GAMS Test Library.

Note
  • The function suffixes value, grad, gradn, hess and hessn are also defined for extrinsic functions. When implementing an extrinsic function, be aware that missing derivatives will be computed numerically: see model [TRILIB01] for an example.

To compute derivatives numerically, GAMS uses finite difference approximations. This computation can be controlled with two options: the FDOpt option controls which variant of the finite difference method is used, while the FDDelta option controls the step size.

Extended Range Arithmetic and Error Handling

GAMS uses an extended range arithmetic to handle missing data, the results of undefined operations, infinite values, and zeros that are stored explicitly. The special values used in this arithmetic are listed and described in Table 10 below, along with the value of the mapVal function that corresponds to these values. We can think of special values as any value for which mapVal does not return 0.

Special value Description mapVal
INF Plus infinity. Similar to IEEE plus infinity. Behaves in the expected way in computations, so that e.g. min(x,INF) = x unless x is also special. 6
-INF Minus infinity. Similar to IEEE minus infinity. Behaves in the expected way in computations, so that e.g. max(x,INF) = x unless x is also special. 7
NA Not available - used to indicate missing data. It is a sticky value: e.g. max(x,NA) = NA even for x = INF 5
UNDF Undefined - indicates the result of an undefined or illegal operation. Similar to IEEE NaN. A user cannot directly set a value to UNDF unless the dollar control option onUNDF is active. For details, see the chapter on Dollar Control Options. 4
EPS A stored zero value. If the dollar control option onEPS is active, zeros in a parameter or table statement are treated as EPS. For details on dollar control options, see chapter Dollar Control Options. 8

Table 10: Special Values for Extended Range Arithmetic

Attention
Avoid creating or using numbers with very large (1.0e299 or above) or very small (1.0e-299 or below) magnitudes. Large numbers may be treated by GAMS as undefined (UNDF) or other special values, leading to unpredictable and unusable results. Always use INF (or -INF) explicitly for arbitrarily large (or small) numbers.

GAMS has defined the results of all arithmetic operations and all function evaluations that use these special values. The behavior is designed to both maximize utility and minimize surprise, and is illustrated in the library model [CRAZY]. For example: 1+INF evaluates to INF, 1-EPS to 1, NA * 2 to NA, and EPS*INF to UNDF.

The following table shows a selection of results for exponentiation and division for a variety of input parameters including NA and INF.

a b a**b power(a,b) a/b
2 2 4 4 1
-2 2 UNDF 4 -1
2 2.1 4.28 UNDF .952
NA 2.5 NA NA NA
3 0 1 1 UNDF
INF 2 INF INF INF
2 INF UNDF UNDF 0

Table 11: Extended Range Arithmetic in Exponentiation and Division

Note that most extended range identifiers may be used in assignment statements, as illustrated below.

a(row,'col-3') =  NA;
a(row,'col-4') =  INF;
a(row,'col-5') = -INF;

The values most often used in assignments are NA in incomplete tables and INF for variable bounds.

The special value EPS is numerically equal to zero, so when used in the context of numerical comparisons, it behaves as zero. For example, the logical expressions x > 0 and x > EPS have the same result. However, EPS is a stored zero, so setting a parameter to zero (e.g. a(row,col)=0) results in no values being stored for a, while setting a parameter to EPS (e.g. a(row,col)=EPS) results in the value EPS being stored for every (row,col) tuple. This is sometimes useful, especially if a is used later in loops (see Programming Flow Control Features) or dollar conditions (see Conditional Expressions, Assignments and Equations). For example, consider the statement

a(row,col)$[a(row,col)] = INF ;

In the case where a was originally assigned to be zero, the dollar-condition is always false so no infinities are assigned. If a was originally assigned the value EPS, the dollar-condition is always true and every tuple in a will be set to infinity.

When an attempted arithmetic operation is illegal or has undefined results because of the value of arguments (division by zero is the normal example), an error is reported and the result is set to undefined (UNDF). The error is marked on the output file with a row of four asterisks '****' making this sequence a good search target in the editor. GAMS will also report the line number of the offending statement and give as much detail as possible about the cause. From there on, the resulting UNDF is treated as a proper data value and does not trigger additional error messages. For more on error messages, see chapter GAMS Output.

Note
GAMS will not solve a model if an error has been detected, and it will terminate with an error condition.

It is therefore wise to anticipate and avoid operations like division by zero that will cause errors. This is most easily done with the dollar control, and is discussed in section The Dollar Condition.

Predefined Symbols

GAMS offers several predefined symbols including: sameAs, diag, sortedUels, solvers, licenseCodes, solverCapabilities, componentEDate, componentMDate, and ComponentLicenseOptions. With the exception of sameAs, diag, and sortedUels these predefined symbols are for very special (and mostly internal) purpose, but the way they work is identical.

These symbols can be used in a GAMS program without being declared but work in an idiosyncratic way. For example, the complete program

display solvers, sameAs;

compiles and executes without error and produces the following result in the listing file:

----      1 SET Solvers  Available Solvers
                                                      ( EMPTY )

----      1 SET SameAs  Set Element Comparison Without Checking
                                                      ( EMPTY )

However, if labels have been declared (in any set) that corresponds to a solver name, then set solvers will contain this label. Consider the following example:

Set titles / Lord, Baron, Duke /;
Set greeks / Euclid, Pythagoras, Antigone /;
display solvers, sameAs;

Note that Antigone and Baron are the names of solvers in GAMS and therefore is will be displayed as a member of the set solvers. Also note that the set sameAs contains the diagonal elements for both sets:

----      3 SET Solvers  Available Solvers
Baron   ,    Antigone

----      3 SET SameAs  Set Element Comparison Without Checking
                  Lord       Baron        Duke      Euclid  Pythagoras    Antigone
Lord               YES
Baron                          YES
Duke                                       YES
Euclid                                                 YES
Pythagoras                                                         YES
Antigone                                                                       YES

User defined symbols can have the same name as a predefined symbol. In this case the user symbol hides the predefined symbols as demonstrated in the following example:

Set diag / 1*3 /;
$if setType diag $log diag is a set
$if preType diag $log diag is a predefined type

The log will only contain the line diag is a set. The test $if preType diag fails.

The list of all predefined symbols can be retrieved by declaring and displaying a set using some system data set pre /system.predefinedSymbols/; display pre; which results in

----      1 SET pre  
SameAs                 ,    Diag                   ,    Solvers                
LicenseCodes           ,    SolverCapabilities     ,    SortedUels             
ComponentEDate         ,    ComponentMDate         ,    ComponentLicenseOptions

Summary

GAMS provides powerful facilities for data manipulation with parallel assignment statements, built-in functions and extended range arithmetic.